2 SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "InternalTlsLib.h"
14 // IANA/IETF defined Cipher Suite ID
18 // OpenSSL-used Cipher Suite String
20 CONST CHAR8
*OpensslCipher
;
22 // Length of OpensslCipher
24 UINTN OpensslCipherLength
;
28 // Create a TLS_CIPHER_MAPPING initializer from IanaCipher and OpensslCipher so
29 // that OpensslCipherLength is filled in automatically. IanaCipher must be an
30 // integer constant expression, and OpensslCipher must be a string literal.
32 #define MAP(IanaCipher, OpensslCipher) \
33 { (IanaCipher), (OpensslCipher), sizeof (OpensslCipher) - 1 }
36 // The mapping table between IANA/IETF Cipher Suite definitions and
37 // OpenSSL-used Cipher Suite name.
39 // Keep the table uniquely sorted by the IanaCipher field, in increasing order.
41 STATIC CONST TLS_CIPHER_MAPPING TlsCipherMappingTable
[] = {
42 MAP (0x0001, "NULL-MD5"), /// TLS_RSA_WITH_NULL_MD5
43 MAP (0x0002, "NULL-SHA"), /// TLS_RSA_WITH_NULL_SHA
44 MAP (0x0004, "RC4-MD5"), /// TLS_RSA_WITH_RC4_128_MD5
45 MAP (0x0005, "RC4-SHA"), /// TLS_RSA_WITH_RC4_128_SHA
46 MAP (0x000A, "DES-CBC3-SHA"), /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
47 MAP (0x0016, "DHE-RSA-DES-CBC3-SHA"), /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
48 MAP (0x002F, "AES128-SHA"), /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2
49 MAP (0x0030, "DH-DSS-AES128-SHA"), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA
50 MAP (0x0031, "DH-RSA-AES128-SHA"), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA
51 MAP (0x0033, "DHE-RSA-AES128-SHA"), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA
52 MAP (0x0035, "AES256-SHA"), /// TLS_RSA_WITH_AES_256_CBC_SHA
53 MAP (0x0036, "DH-DSS-AES256-SHA"), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA
54 MAP (0x0037, "DH-RSA-AES256-SHA"), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA
55 MAP (0x0039, "DHE-RSA-AES256-SHA"), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA
56 MAP (0x003B, "NULL-SHA256"), /// TLS_RSA_WITH_NULL_SHA256
57 MAP (0x003C, "AES128-SHA256"), /// TLS_RSA_WITH_AES_128_CBC_SHA256
58 MAP (0x003D, "AES256-SHA256"), /// TLS_RSA_WITH_AES_256_CBC_SHA256
59 MAP (0x003E, "DH-DSS-AES128-SHA256"), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256
60 MAP (0x003F, "DH-RSA-AES128-SHA256"), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256
61 MAP (0x0067, "DHE-RSA-AES128-SHA256"), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
62 MAP (0x0068, "DH-DSS-AES256-SHA256"), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256
63 MAP (0x0069, "DH-RSA-AES256-SHA256"), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256
64 MAP (0x006B, "DHE-RSA-AES256-SHA256"), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
65 MAP (0x009F, "DHE-RSA-AES256-GCM-SHA384"), /// TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
66 MAP (0xC02B, "ECDHE-ECDSA-AES128-GCM-SHA256"), /// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
67 MAP (0xC02C, "ECDHE-ECDSA-AES256-GCM-SHA384"), /// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
68 MAP (0xC030, "ECDHE-RSA-AES256-GCM-SHA384"), /// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
82 STATIC CONST TLS_ALGO_TO_NAME TlsHashAlgoToName
[] = {
83 { TlsHashAlgoNone
, NULL
},
84 { TlsHashAlgoMd5
, "MD5" },
85 { TlsHashAlgoSha1
, "SHA1" },
86 { TlsHashAlgoSha224
, "SHA224" },
87 { TlsHashAlgoSha256
, "SHA256" },
88 { TlsHashAlgoSha384
, "SHA384" },
89 { TlsHashAlgoSha512
, "SHA512" },
92 STATIC CONST TLS_ALGO_TO_NAME TlsSignatureAlgoToName
[] = {
93 { TlsSignatureAlgoAnonymous
, NULL
},
94 { TlsSignatureAlgoRsa
, "RSA" },
95 { TlsSignatureAlgoDsa
, "DSA" },
96 { TlsSignatureAlgoEcdsa
, "ECDSA" },
100 Gets the OpenSSL cipher suite mapping for the supplied IANA TLS cipher suite.
102 @param[in] CipherId The supplied IANA TLS cipher suite ID.
104 @return The corresponding OpenSSL cipher suite mapping if found,
109 CONST TLS_CIPHER_MAPPING
*
110 TlsGetCipherMapping (
119 // Binary Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation
122 Right
= ARRAY_SIZE (TlsCipherMappingTable
) - 1;
124 while (Right
>= Left
) {
125 Middle
= (Left
+ Right
) / 2;
127 if (CipherId
== TlsCipherMappingTable
[Middle
].IanaCipher
) {
129 // Translate IANA cipher suite ID to OpenSSL name.
131 return &TlsCipherMappingTable
[Middle
];
134 if (CipherId
< TlsCipherMappingTable
[Middle
].IanaCipher
) {
142 // No Cipher Mapping found, return NULL.
148 Set a new TLS/SSL method for a particular TLS object.
150 This function sets a new TLS/SSL method for a particular TLS object.
152 @param[in] Tls Pointer to a TLS object.
153 @param[in] MajorVer Major Version of TLS/SSL Protocol.
154 @param[in] MinorVer Minor Version of TLS/SSL Protocol.
156 @retval EFI_SUCCESS The TLS/SSL method was set successfully.
157 @retval EFI_INVALID_PARAMETER The parameter is invalid.
158 @retval EFI_UNSUPPORTED Unsupported TLS/SSL method.
169 TLS_CONNECTION
*TlsConn
;
172 TlsConn
= (TLS_CONNECTION
*)Tls
;
173 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
)) {
174 return EFI_INVALID_PARAMETER
;
177 ProtoVersion
= (MajorVer
<< 8) | MinorVer
;
180 // Bound TLS method to the particular specified version.
182 switch (ProtoVersion
) {
187 SSL_set_min_proto_version (TlsConn
->Ssl
, TLS1_VERSION
);
188 SSL_set_max_proto_version (TlsConn
->Ssl
, TLS1_VERSION
);
194 SSL_set_min_proto_version (TlsConn
->Ssl
, TLS1_1_VERSION
);
195 SSL_set_max_proto_version (TlsConn
->Ssl
, TLS1_1_VERSION
);
201 SSL_set_min_proto_version (TlsConn
->Ssl
, TLS1_2_VERSION
);
202 SSL_set_max_proto_version (TlsConn
->Ssl
, TLS1_2_VERSION
);
206 // Unsupported Protocol Version
208 return EFI_UNSUPPORTED
;
215 Set TLS object to work in client or server mode.
217 This function prepares a TLS object to work in client or server mode.
219 @param[in] Tls Pointer to a TLS object.
220 @param[in] IsServer Work in server mode.
222 @retval EFI_SUCCESS The TLS/SSL work mode was set successfully.
223 @retval EFI_INVALID_PARAMETER The parameter is invalid.
224 @retval EFI_UNSUPPORTED Unsupported TLS/SSL work mode.
229 TlsSetConnectionEnd (
234 TLS_CONNECTION
*TlsConn
;
236 TlsConn
= (TLS_CONNECTION
*)Tls
;
237 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
)) {
238 return EFI_INVALID_PARAMETER
;
243 // Set TLS to work in Client mode.
245 SSL_set_connect_state (TlsConn
->Ssl
);
248 // Set TLS to work in Server mode.
249 // It is unsupported for UEFI version currently.
251 // SSL_set_accept_state (TlsConn->Ssl);
252 return EFI_UNSUPPORTED
;
259 Set the ciphers list to be used by the TLS object.
261 This function sets the ciphers for use by a specified TLS object.
263 @param[in] Tls Pointer to a TLS object.
264 @param[in] CipherId Array of UINT16 cipher identifiers. Each UINT16
265 cipher identifier comes from the TLS Cipher Suite
266 Registry of the IANA, interpreting Byte1 and Byte2
267 in network (big endian) byte order.
268 @param[in] CipherNum The number of cipher in the list.
270 @retval EFI_SUCCESS The ciphers list was set successfully.
271 @retval EFI_INVALID_PARAMETER The parameter is invalid.
272 @retval EFI_UNSUPPORTED No supported TLS cipher was found in CipherId.
273 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
284 TLS_CONNECTION
*TlsConn
;
286 CONST TLS_CIPHER_MAPPING
**MappedCipher
;
287 UINTN MappedCipherBytes
;
288 UINTN MappedCipherCount
;
289 UINTN CipherStringSize
;
291 CONST TLS_CIPHER_MAPPING
*Mapping
;
293 CHAR8
*CipherStringPosition
;
295 TlsConn
= (TLS_CONNECTION
*)Tls
;
296 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (CipherId
== NULL
)) {
297 return EFI_INVALID_PARAMETER
;
301 // Allocate the MappedCipher array for recording the mappings that we find
302 // for the input IANA identifiers in CipherId.
304 Status
= SafeUintnMult (
306 sizeof (*MappedCipher
),
309 if (EFI_ERROR (Status
)) {
310 return EFI_OUT_OF_RESOURCES
;
313 MappedCipher
= AllocatePool (MappedCipherBytes
);
314 if (MappedCipher
== NULL
) {
315 return EFI_OUT_OF_RESOURCES
;
319 // Map the cipher IDs, and count the number of bytes for the full
322 MappedCipherCount
= 0;
323 CipherStringSize
= 0;
324 for (Index
= 0; Index
< CipherNum
; Index
++) {
326 // Look up the IANA-to-OpenSSL mapping.
328 Mapping
= TlsGetCipherMapping (CipherId
[Index
]);
329 if (Mapping
== NULL
) {
332 "%a:%a: skipping CipherId=0x%04x\n",
338 // Skipping the cipher is valid because CipherId is an ordered
339 // preference list of ciphers, thus we can filter it as long as we
340 // don't change the relative order of elements on it.
346 // Accumulate Mapping->OpensslCipherLength into CipherStringSize. If this
347 // is not the first successful mapping, account for a colon (":") prefix
350 if (MappedCipherCount
> 0) {
351 Status
= SafeUintnAdd (CipherStringSize
, 1, &CipherStringSize
);
352 if (EFI_ERROR (Status
)) {
353 Status
= EFI_OUT_OF_RESOURCES
;
354 goto FreeMappedCipher
;
358 Status
= SafeUintnAdd (
360 Mapping
->OpensslCipherLength
,
363 if (EFI_ERROR (Status
)) {
364 Status
= EFI_OUT_OF_RESOURCES
;
365 goto FreeMappedCipher
;
369 // Record the mapping.
371 MappedCipher
[MappedCipherCount
++] = Mapping
;
375 // Verify that at least one IANA cipher ID could be mapped; account for the
376 // terminating NUL character in CipherStringSize; allocate CipherString.
378 if (MappedCipherCount
== 0) {
381 "%a:%a: no CipherId could be mapped\n",
385 Status
= EFI_UNSUPPORTED
;
386 goto FreeMappedCipher
;
389 Status
= SafeUintnAdd (CipherStringSize
, 1, &CipherStringSize
);
390 if (EFI_ERROR (Status
)) {
391 Status
= EFI_OUT_OF_RESOURCES
;
392 goto FreeMappedCipher
;
395 CipherString
= AllocatePool (CipherStringSize
);
396 if (CipherString
== NULL
) {
397 Status
= EFI_OUT_OF_RESOURCES
;
398 goto FreeMappedCipher
;
402 // Go over the collected mappings and populate CipherString.
404 CipherStringPosition
= CipherString
;
405 for (Index
= 0; Index
< MappedCipherCount
; Index
++) {
406 Mapping
= MappedCipher
[Index
];
408 // Append the colon (":") prefix except for the first mapping, then append
409 // Mapping->OpensslCipher.
412 *(CipherStringPosition
++) = ':';
416 CipherStringPosition
,
417 Mapping
->OpensslCipher
,
418 Mapping
->OpensslCipherLength
420 CipherStringPosition
+= Mapping
->OpensslCipherLength
;
424 // NUL-terminate CipherString.
426 *(CipherStringPosition
++) = '\0';
427 ASSERT (CipherStringPosition
== CipherString
+ CipherStringSize
);
430 // Log CipherString for debugging. CipherString can be very long if the
431 // caller provided a large CipherId array, so log CipherString in segments of
432 // 79 non-newline characters. (MAX_DEBUG_MESSAGE_LENGTH is usually 0x100 in
433 // DebugLib instances.)
439 FullLength
= CipherStringSize
- 1;
442 "%a:%a: CipherString={\n",
446 for (CipherStringPosition
= CipherString
;
447 CipherStringPosition
< CipherString
+ FullLength
;
448 CipherStringPosition
+= SegmentLength
)
450 SegmentLength
= FullLength
- (CipherStringPosition
- CipherString
);
451 if (SegmentLength
> 79) {
455 DEBUG ((DEBUG_VERBOSE
, "%.*a\n", SegmentLength
, CipherStringPosition
));
458 DEBUG ((DEBUG_VERBOSE
, "}\n"));
460 // Restore the pre-debug value of CipherStringPosition by skipping over the
463 CipherStringPosition
++;
464 ASSERT (CipherStringPosition
== CipherString
+ CipherStringSize
);
468 // Sets the ciphers for use by the Tls object.
470 if (SSL_set_cipher_list (TlsConn
->Ssl
, CipherString
) <= 0) {
471 Status
= EFI_UNSUPPORTED
;
472 goto FreeCipherString
;
475 Status
= EFI_SUCCESS
;
478 FreePool (CipherString
);
481 FreePool ((VOID
*)MappedCipher
);
487 Set the compression method for TLS/SSL operations.
489 This function handles TLS/SSL integrated compression methods.
491 @param[in] CompMethod The compression method ID.
493 @retval EFI_SUCCESS The compression method for the communication was
495 @retval EFI_UNSUPPORTED Unsupported compression method.
500 TlsSetCompressionMethod (
510 if (CompMethod
== 0) {
512 // TLS defines one standard compression method, CompressionMethod.null (0),
513 // which specifies that data exchanged via the record protocol will not be compressed.
514 // So, return EFI_SUCCESS directly (RFC 3749).
517 } else if (CompMethod
== 1) {
520 return EFI_UNSUPPORTED
;
524 // Adds the compression method to the list of available
525 // compression methods.
527 Ret
= SSL_COMP_add_compression_method (CompMethod
, Cm
);
529 return EFI_UNSUPPORTED
;
536 Set peer certificate verification mode for the TLS connection.
538 This function sets the verification mode flags for the TLS connection.
540 @param[in] Tls Pointer to the TLS object.
541 @param[in] VerifyMode A set of logically or'ed verification mode flags.
551 TLS_CONNECTION
*TlsConn
;
553 TlsConn
= (TLS_CONNECTION
*)Tls
;
554 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
)) {
559 // Set peer certificate verification parameters with NULL callback.
561 SSL_set_verify (TlsConn
->Ssl
, VerifyMode
, NULL
);
565 Set the specified host name to be verified.
567 @param[in] Tls Pointer to the TLS object.
568 @param[in] Flags The setting flags during the validation.
569 @param[in] HostName The specified host name to be verified.
571 @retval EFI_SUCCESS The HostName setting was set successfully.
572 @retval EFI_INVALID_PARAMETER The parameter is invalid.
573 @retval EFI_ABORTED Invalid HostName setting.
584 TLS_CONNECTION
*TlsConn
;
585 X509_VERIFY_PARAM
*VerifyParam
;
586 UINTN BinaryAddressSize
;
587 UINT8 BinaryAddress
[MAX (NS_INADDRSZ
, NS_IN6ADDRSZ
)];
590 TlsConn
= (TLS_CONNECTION
*)Tls
;
591 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (HostName
== NULL
)) {
592 return EFI_INVALID_PARAMETER
;
595 SSL_set_hostflags (TlsConn
->Ssl
, Flags
);
597 VerifyParam
= SSL_get0_param (TlsConn
->Ssl
);
598 ASSERT (VerifyParam
!= NULL
);
600 BinaryAddressSize
= 0;
601 if (inet_pton (AF_INET6
, HostName
, BinaryAddress
) == 1) {
602 BinaryAddressSize
= NS_IN6ADDRSZ
;
603 } else if (inet_pton (AF_INET
, HostName
, BinaryAddress
) == 1) {
604 BinaryAddressSize
= NS_INADDRSZ
;
607 if (BinaryAddressSize
> 0) {
610 "%a:%a: parsed \"%a\" as an IPv%c address "
615 (UINTN
)((BinaryAddressSize
== NS_IN6ADDRSZ
) ? '6' : '4')
617 ParamStatus
= X509_VERIFY_PARAM_set1_ip (
623 ParamStatus
= X509_VERIFY_PARAM_set1_host (VerifyParam
, HostName
, 0);
626 return (ParamStatus
== 1) ? EFI_SUCCESS
: EFI_ABORTED
;
630 Sets a TLS/SSL session ID to be used during TLS/SSL connect.
632 This function sets a session ID to be used when the TLS/SSL connection is
635 @param[in] Tls Pointer to the TLS object.
636 @param[in] SessionId Session ID data used for session resumption.
637 @param[in] SessionIdLen Length of Session ID in bytes.
639 @retval EFI_SUCCESS Session ID was set successfully.
640 @retval EFI_INVALID_PARAMETER The parameter is invalid.
641 @retval EFI_UNSUPPORTED No available session for ID setting.
649 IN UINT16 SessionIdLen
652 TLS_CONNECTION
*TlsConn
;
653 SSL_SESSION
*Session
;
655 TlsConn
= (TLS_CONNECTION
*)Tls
;
658 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (SessionId
== NULL
)) {
659 return EFI_INVALID_PARAMETER
;
662 Session
= SSL_get_session (TlsConn
->Ssl
);
663 if (Session
== NULL
) {
664 return EFI_UNSUPPORTED
;
667 SSL_SESSION_set1_id (Session
, (const unsigned char *)SessionId
, SessionIdLen
);
673 Adds the CA to the cert store when requesting Server or Client authentication.
675 This function adds the CA certificate to the list of CAs when requesting
676 Server or Client authentication for the chosen TLS connection.
678 @param[in] Tls Pointer to the TLS object.
679 @param[in] Data Pointer to the data buffer of a DER-encoded binary
680 X.509 certificate or PEM-encoded X.509 certificate.
681 @param[in] DataSize The size of data buffer in bytes.
683 @retval EFI_SUCCESS The operation succeeded.
684 @retval EFI_INVALID_PARAMETER The parameter is invalid.
685 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
686 @retval EFI_ABORTED Invalid X.509 certificate.
691 TlsSetCaCertificate (
699 X509_STORE
*X509Store
;
701 TLS_CONNECTION
*TlsConn
;
709 Status
= EFI_SUCCESS
;
710 TlsConn
= (TLS_CONNECTION
*)Tls
;
713 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (Data
== NULL
) || (DataSize
== 0)) {
714 return EFI_INVALID_PARAMETER
;
718 // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
719 // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
721 Cert
= d2i_X509 (NULL
, (const unsigned char **)&Data
, (long)DataSize
);
724 // Certificate is from PEM encoding.
726 BioCert
= BIO_new (BIO_s_mem ());
727 if (BioCert
== NULL
) {
728 Status
= EFI_OUT_OF_RESOURCES
;
732 if (BIO_write (BioCert
, Data
, (UINT32
)DataSize
) <= 0) {
733 Status
= EFI_ABORTED
;
737 Cert
= PEM_read_bio_X509 (BioCert
, NULL
, NULL
, NULL
);
739 Status
= EFI_ABORTED
;
744 SslCtx
= SSL_get_SSL_CTX (TlsConn
->Ssl
);
745 X509Store
= SSL_CTX_get_cert_store (SslCtx
);
746 if (X509Store
== NULL
) {
747 Status
= EFI_ABORTED
;
752 // Add certificate to X509 store
754 Ret
= X509_STORE_add_cert (X509Store
, Cert
);
756 ErrorCode
= ERR_peek_last_error ();
758 // Ignore "already in table" errors
760 if (!((ERR_GET_FUNC (ErrorCode
) == X509_F_X509_STORE_ADD_CERT
) &&
761 (ERR_GET_REASON (ErrorCode
) == X509_R_CERT_ALREADY_IN_HASH_TABLE
)))
763 Status
= EFI_ABORTED
;
769 if (BioCert
!= NULL
) {
781 Loads the local public certificate into the specified TLS object.
783 This function loads the X.509 certificate into the specified TLS object
786 @param[in] Tls Pointer to the TLS object.
787 @param[in] Data Pointer to the data buffer of a DER-encoded binary
788 X.509 certificate or PEM-encoded X.509 certificate.
789 @param[in] DataSize The size of data buffer in bytes.
791 @retval EFI_SUCCESS The operation succeeded.
792 @retval EFI_INVALID_PARAMETER The parameter is invalid.
793 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
794 @retval EFI_ABORTED Invalid X.509 certificate.
799 TlsSetHostPublicCert (
808 TLS_CONNECTION
*TlsConn
;
812 Status
= EFI_SUCCESS
;
813 TlsConn
= (TLS_CONNECTION
*)Tls
;
815 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (Data
== NULL
) || (DataSize
== 0)) {
816 return EFI_INVALID_PARAMETER
;
820 // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
821 // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
823 Cert
= d2i_X509 (NULL
, (const unsigned char **)&Data
, (long)DataSize
);
826 // Certificate is from PEM encoding.
828 BioCert
= BIO_new (BIO_s_mem ());
829 if (BioCert
== NULL
) {
830 Status
= EFI_OUT_OF_RESOURCES
;
834 if (BIO_write (BioCert
, Data
, (UINT32
)DataSize
) <= 0) {
835 Status
= EFI_ABORTED
;
839 Cert
= PEM_read_bio_X509 (BioCert
, NULL
, NULL
, NULL
);
841 Status
= EFI_ABORTED
;
846 if (SSL_use_certificate (TlsConn
->Ssl
, Cert
) != 1) {
847 Status
= EFI_ABORTED
;
852 if (BioCert
!= NULL
) {
864 Adds the local private key to the specified TLS object.
866 This function adds the local private key (DER-encoded or PEM-encoded or PKCS#8 private
867 key) into the specified TLS object for TLS negotiation.
869 @param[in] Tls Pointer to the TLS object.
870 @param[in] Data Pointer to the data buffer of a DER-encoded or PEM-encoded
871 or PKCS#8 private key.
872 @param[in] DataSize The size of data buffer in bytes.
873 @param[in] Password Pointer to NULL-terminated private key password, set it to NULL
874 if private key not encrypted.
876 @retval EFI_SUCCESS The operation succeeded.
877 @retval EFI_UNSUPPORTED This function is not supported.
878 @retval EFI_ABORTED Invalid private key data.
883 TlsSetHostPrivateKeyEx (
887 IN VOID
*Password OPTIONAL
890 TLS_CONNECTION
*TlsConn
;
895 TlsConn
= (TLS_CONNECTION
*)Tls
;
897 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (Data
== NULL
) || (DataSize
== 0)) {
898 return EFI_INVALID_PARAMETER
;
901 // Try to parse the private key in DER format or un-encrypted PKC#8
902 if (SSL_use_PrivateKey_ASN1 (
912 if (SSL_use_PrivateKey_ASN1 (
922 if (SSL_use_PrivateKey_ASN1 (
932 // Try to parse the private key in PEM format or encrypted PKC#8
933 Bio
= BIO_new_mem_buf (Data
, (int)DataSize
);
936 Pkey
= PEM_read_bio_PrivateKey (Bio
, NULL
, NULL
, Password
);
937 if ((Pkey
!= NULL
) && (SSL_use_PrivateKey (TlsConn
->Ssl
, Pkey
) == 1)) {
941 EVP_PKEY_free (Pkey
);
952 if (SSL_check_private_key (TlsConn
->Ssl
) == 1) {
960 Adds the local private key to the specified TLS object.
962 This function adds the local private key (DER-encoded or PEM-encoded or PKCS#8 private
963 key) into the specified TLS object for TLS negotiation.
965 @param[in] Tls Pointer to the TLS object.
966 @param[in] Data Pointer to the data buffer of a DER-encoded or PEM-encoded
967 or PKCS#8 private key.
968 @param[in] DataSize The size of data buffer in bytes.
970 @retval EFI_SUCCESS The operation succeeded.
971 @retval EFI_UNSUPPORTED This function is not supported.
972 @retval EFI_ABORTED Invalid private key data.
977 TlsSetHostPrivateKey (
983 return TlsSetHostPrivateKeyEx (Tls
, Data
, DataSize
, NULL
);
987 Adds the CA-supplied certificate revocation list for certificate validation.
989 This function adds the CA-supplied certificate revocation list data for
990 certificate validity checking.
992 @param[in] Data Pointer to the data buffer of a DER-encoded CRL data.
993 @param[in] DataSize The size of data buffer in bytes.
995 @retval EFI_SUCCESS The operation succeeded.
996 @retval EFI_UNSUPPORTED This function is not supported.
997 @retval EFI_ABORTED Invalid CRL data.
1002 TlsSetCertRevocationList (
1007 return EFI_UNSUPPORTED
;
1011 Set the signature algorithm list to used by the TLS object.
1013 This function sets the signature algorithms for use by a specified TLS object.
1015 @param[in] Tls Pointer to a TLS object.
1016 @param[in] Data Array of UINT8 of signature algorithms. The array consists of
1017 pairs of the hash algorithm and the signature algorithm as defined
1019 @param[in] DataSize The length the SignatureAlgoList. Must be divisible by 2.
1021 @retval EFI_SUCCESS The signature algorithm list was set successfully.
1022 @retval EFI_INVALID_PARAMETER The parameters are invalid.
1023 @retval EFI_UNSUPPORTED No supported TLS signature algorithm was found in SignatureAlgoList
1024 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1029 TlsSetSignatureAlgoList (
1035 TLS_CONNECTION
*TlsConn
;
1037 UINTN SignAlgoStrSize
;
1040 UINT8
*SignatureAlgoList
;
1043 TlsConn
= (TLS_CONNECTION
*)Tls
;
1045 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (Data
== NULL
) || (DataSize
< 3) ||
1046 ((DataSize
% 2) == 0) || (Data
[0] != DataSize
- 1))
1048 return EFI_INVALID_PARAMETER
;
1051 SignatureAlgoList
= Data
+ 1;
1052 SignAlgoStrSize
= 0;
1053 for (Index
= 0; Index
< Data
[0]; Index
+= 2) {
1056 if (SignatureAlgoList
[Index
] >= ARRAY_SIZE (TlsHashAlgoToName
)) {
1057 return EFI_INVALID_PARAMETER
;
1060 Tmp
= TlsHashAlgoToName
[SignatureAlgoList
[Index
]].Name
;
1062 return EFI_INVALID_PARAMETER
;
1065 // Add 1 for the '+'
1066 SignAlgoStrSize
+= AsciiStrLen (Tmp
) + 1;
1068 if (SignatureAlgoList
[Index
+ 1] >= ARRAY_SIZE (TlsSignatureAlgoToName
)) {
1069 return EFI_INVALID_PARAMETER
;
1072 Tmp
= TlsSignatureAlgoToName
[SignatureAlgoList
[Index
+ 1]].Name
;
1074 return EFI_INVALID_PARAMETER
;
1077 // Add 1 for the ':' or for the NULL terminator
1078 SignAlgoStrSize
+= AsciiStrLen (Tmp
) + 1;
1081 if (!SignAlgoStrSize
) {
1082 return EFI_UNSUPPORTED
;
1085 SignAlgoStr
= AllocatePool (SignAlgoStrSize
);
1086 if (SignAlgoStr
== NULL
) {
1087 return EFI_OUT_OF_RESOURCES
;
1091 for (Index
= 0; Index
< Data
[0]; Index
+= 2) {
1094 Tmp
= TlsHashAlgoToName
[SignatureAlgoList
[Index
]].Name
;
1095 CopyMem (Pos
, Tmp
, AsciiStrLen (Tmp
));
1096 Pos
+= AsciiStrLen (Tmp
);
1099 Tmp
= TlsSignatureAlgoToName
[SignatureAlgoList
[Index
+ 1]].Name
;
1100 CopyMem (Pos
, Tmp
, AsciiStrLen (Tmp
));
1101 Pos
+= AsciiStrLen (Tmp
);
1107 if (SSL_set1_sigalgs_list (TlsConn
->Ssl
, SignAlgoStr
) < 1) {
1108 Status
= EFI_INVALID_PARAMETER
;
1110 Status
= EFI_SUCCESS
;
1113 FreePool (SignAlgoStr
);
1118 Set the EC curve to be used for TLS flows
1120 This function sets the EC curve to be used for TLS flows.
1122 @param[in] Tls Pointer to a TLS object.
1123 @param[in] Data An EC named curve as defined in section 5.1.1 of RFC 4492.
1124 @param[in] DataSize Size of Data, it should be sizeof (UINT32)
1126 @retval EFI_SUCCESS The EC curve was set successfully.
1127 @retval EFI_INVALID_PARAMETER The parameters are invalid.
1128 @retval EFI_UNSUPPORTED The requested TLS EC curve is not supported
1139 TLS_CONNECTION
*TlsConn
;
1144 TlsConn
= (TLS_CONNECTION
*)Tls
;
1146 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (Data
== NULL
) || (DataSize
!= sizeof (UINT32
))) {
1147 return EFI_INVALID_PARAMETER
;
1150 switch (*((UINT32
*)Data
)) {
1151 case TlsEcNamedCurveSecp256r1
:
1152 return EFI_UNSUPPORTED
;
1153 case TlsEcNamedCurveSecp384r1
:
1154 Nid
= NID_secp384r1
;
1156 case TlsEcNamedCurveSecp521r1
:
1157 Nid
= NID_secp521r1
;
1159 case TlsEcNamedCurveX25519
:
1162 case TlsEcNamedCurveX448
:
1166 return EFI_UNSUPPORTED
;
1169 if (SSL_set1_curves (TlsConn
->Ssl
, &Nid
, 1) != 1) {
1170 return EFI_UNSUPPORTED
;
1173 EcKey
= EC_KEY_new_by_curve_name (Nid
);
1174 if (EcKey
== NULL
) {
1175 return EFI_UNSUPPORTED
;
1178 Ret
= SSL_set_tmp_ecdh (TlsConn
->Ssl
, EcKey
);
1179 EC_KEY_free (EcKey
);
1182 return EFI_UNSUPPORTED
;
1189 Gets the protocol version used by the specified TLS connection.
1191 This function returns the protocol version used by the specified TLS
1194 If Tls is NULL, then ASSERT().
1196 @param[in] Tls Pointer to the TLS object.
1198 @return The protocol version of the specified TLS connection.
1207 TLS_CONNECTION
*TlsConn
;
1209 TlsConn
= (TLS_CONNECTION
*)Tls
;
1211 ASSERT (TlsConn
!= NULL
);
1213 return (UINT16
)(SSL_version (TlsConn
->Ssl
));
1217 Gets the connection end of the specified TLS connection.
1219 This function returns the connection end (as client or as server) used by
1220 the specified TLS connection.
1222 If Tls is NULL, then ASSERT().
1224 @param[in] Tls Pointer to the TLS object.
1226 @return The connection end used by the specified TLS connection.
1231 TlsGetConnectionEnd (
1235 TLS_CONNECTION
*TlsConn
;
1237 TlsConn
= (TLS_CONNECTION
*)Tls
;
1239 ASSERT (TlsConn
!= NULL
);
1241 return (UINT8
)SSL_is_server (TlsConn
->Ssl
);
1245 Gets the cipher suite used by the specified TLS connection.
1247 This function returns current cipher suite used by the specified
1250 @param[in] Tls Pointer to the TLS object.
1251 @param[in,out] CipherId The cipher suite used by the TLS object.
1253 @retval EFI_SUCCESS The cipher suite was returned successfully.
1254 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1255 @retval EFI_UNSUPPORTED Unsupported cipher suite.
1260 TlsGetCurrentCipher (
1262 IN OUT UINT16
*CipherId
1265 TLS_CONNECTION
*TlsConn
;
1266 CONST SSL_CIPHER
*Cipher
;
1268 TlsConn
= (TLS_CONNECTION
*)Tls
;
1271 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (CipherId
== NULL
)) {
1272 return EFI_INVALID_PARAMETER
;
1275 Cipher
= SSL_get_current_cipher (TlsConn
->Ssl
);
1276 if (Cipher
== NULL
) {
1277 return EFI_UNSUPPORTED
;
1280 *CipherId
= (SSL_CIPHER_get_id (Cipher
)) & 0xFFFF;
1286 Gets the compression methods used by the specified TLS connection.
1288 This function returns current integrated compression methods used by
1289 the specified TLS connection.
1291 @param[in] Tls Pointer to the TLS object.
1292 @param[in,out] CompressionId The current compression method used by
1295 @retval EFI_SUCCESS The compression method was returned successfully.
1296 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1297 @retval EFI_ABORTED Invalid Compression method.
1298 @retval EFI_UNSUPPORTED This function is not supported.
1303 TlsGetCurrentCompressionId (
1305 IN OUT UINT8
*CompressionId
1308 return EFI_UNSUPPORTED
;
1312 Gets the verification mode currently set in the TLS connection.
1314 This function returns the peer verification mode currently set in the
1315 specified TLS connection.
1317 If Tls is NULL, then ASSERT().
1319 @param[in] Tls Pointer to the TLS object.
1321 @return The verification mode set in the specified TLS connection.
1330 TLS_CONNECTION
*TlsConn
;
1332 TlsConn
= (TLS_CONNECTION
*)Tls
;
1334 ASSERT (TlsConn
!= NULL
);
1336 return SSL_get_verify_mode (TlsConn
->Ssl
);
1340 Gets the session ID used by the specified TLS connection.
1342 This function returns the TLS/SSL session ID currently used by the
1343 specified TLS connection.
1345 @param[in] Tls Pointer to the TLS object.
1346 @param[in,out] SessionId Buffer to contain the returned session ID.
1347 @param[in,out] SessionIdLen The length of Session ID in bytes.
1349 @retval EFI_SUCCESS The Session ID was returned successfully.
1350 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1351 @retval EFI_UNSUPPORTED Invalid TLS/SSL session.
1358 IN OUT UINT8
*SessionId
,
1359 IN OUT UINT16
*SessionIdLen
1362 TLS_CONNECTION
*TlsConn
;
1363 SSL_SESSION
*Session
;
1364 CONST UINT8
*SslSessionId
;
1366 TlsConn
= (TLS_CONNECTION
*)Tls
;
1369 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (SessionId
== NULL
) || (SessionIdLen
== NULL
)) {
1370 return EFI_INVALID_PARAMETER
;
1373 Session
= SSL_get_session (TlsConn
->Ssl
);
1374 if (Session
== NULL
) {
1375 return EFI_UNSUPPORTED
;
1378 SslSessionId
= SSL_SESSION_get_id (Session
, (unsigned int *)SessionIdLen
);
1379 CopyMem (SessionId
, SslSessionId
, *SessionIdLen
);
1385 Gets the client random data used in the specified TLS connection.
1387 This function returns the TLS/SSL client random data currently used in
1388 the specified TLS connection.
1390 @param[in] Tls Pointer to the TLS object.
1391 @param[in,out] ClientRandom Buffer to contain the returned client
1392 random data (32 bytes).
1397 TlsGetClientRandom (
1399 IN OUT UINT8
*ClientRandom
1402 TLS_CONNECTION
*TlsConn
;
1404 TlsConn
= (TLS_CONNECTION
*)Tls
;
1406 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (ClientRandom
== NULL
)) {
1410 SSL_get_client_random (TlsConn
->Ssl
, ClientRandom
, SSL3_RANDOM_SIZE
);
1414 Gets the server random data used in the specified TLS connection.
1416 This function returns the TLS/SSL server random data currently used in
1417 the specified TLS connection.
1419 @param[in] Tls Pointer to the TLS object.
1420 @param[in,out] ServerRandom Buffer to contain the returned server
1421 random data (32 bytes).
1426 TlsGetServerRandom (
1428 IN OUT UINT8
*ServerRandom
1431 TLS_CONNECTION
*TlsConn
;
1433 TlsConn
= (TLS_CONNECTION
*)Tls
;
1435 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (ServerRandom
== NULL
)) {
1439 SSL_get_server_random (TlsConn
->Ssl
, ServerRandom
, SSL3_RANDOM_SIZE
);
1443 Gets the master key data used in the specified TLS connection.
1445 This function returns the TLS/SSL master key material currently used in
1446 the specified TLS connection.
1448 @param[in] Tls Pointer to the TLS object.
1449 @param[in,out] KeyMaterial Buffer to contain the returned key material.
1451 @retval EFI_SUCCESS Key material was returned successfully.
1452 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1453 @retval EFI_UNSUPPORTED Invalid TLS/SSL session.
1460 IN OUT UINT8
*KeyMaterial
1463 TLS_CONNECTION
*TlsConn
;
1464 SSL_SESSION
*Session
;
1466 TlsConn
= (TLS_CONNECTION
*)Tls
;
1469 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (KeyMaterial
== NULL
)) {
1470 return EFI_INVALID_PARAMETER
;
1473 Session
= SSL_get_session (TlsConn
->Ssl
);
1475 if (Session
== NULL
) {
1476 return EFI_UNSUPPORTED
;
1479 SSL_SESSION_get_master_key (Session
, KeyMaterial
, SSL3_MASTER_SECRET_SIZE
);
1485 Gets the CA Certificate from the cert store.
1487 This function returns the CA certificate for the chosen
1490 @param[in] Tls Pointer to the TLS object.
1491 @param[out] Data Pointer to the data buffer to receive the CA
1492 certificate data sent to the client.
1493 @param[in,out] DataSize The size of data buffer in bytes.
1495 @retval EFI_SUCCESS The operation succeeded.
1496 @retval EFI_UNSUPPORTED This function is not supported.
1497 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
1502 TlsGetCaCertificate (
1505 IN OUT UINTN
*DataSize
1508 return EFI_UNSUPPORTED
;
1512 Gets the local public Certificate set in the specified TLS object.
1514 This function returns the local public certificate which was currently set
1515 in the specified TLS object.
1517 @param[in] Tls Pointer to the TLS object.
1518 @param[out] Data Pointer to the data buffer to receive the local
1520 @param[in,out] DataSize The size of data buffer in bytes.
1522 @retval EFI_SUCCESS The operation succeeded.
1523 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1524 @retval EFI_NOT_FOUND The certificate is not found.
1525 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
1530 TlsGetHostPublicCert (
1533 IN OUT UINTN
*DataSize
1537 TLS_CONNECTION
*TlsConn
;
1540 TlsConn
= (TLS_CONNECTION
*)Tls
;
1542 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
1543 return EFI_INVALID_PARAMETER
;
1546 Cert
= SSL_get_certificate (TlsConn
->Ssl
);
1548 return EFI_NOT_FOUND
;
1552 // Only DER encoding is supported currently.
1554 if (*DataSize
< (UINTN
)i2d_X509 (Cert
, NULL
)) {
1555 *DataSize
= (UINTN
)i2d_X509 (Cert
, NULL
);
1556 return EFI_BUFFER_TOO_SMALL
;
1559 *DataSize
= (UINTN
)i2d_X509 (Cert
, (unsigned char **)&Data
);
1565 Gets the local private key set in the specified TLS object.
1567 This function returns the local private key data which was currently set
1568 in the specified TLS object.
1570 @param[in] Tls Pointer to the TLS object.
1571 @param[out] Data Pointer to the data buffer to receive the local
1573 @param[in,out] DataSize The size of data buffer in bytes.
1575 @retval EFI_SUCCESS The operation succeeded.
1576 @retval EFI_UNSUPPORTED This function is not supported.
1577 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
1582 TlsGetHostPrivateKey (
1585 IN OUT UINTN
*DataSize
1588 return EFI_UNSUPPORTED
;
1592 Gets the CA-supplied certificate revocation list data set in the specified
1595 This function returns the CA-supplied certificate revocation list data which
1596 was currently set in the specified TLS object.
1598 @param[out] Data Pointer to the data buffer to receive the CRL data.
1599 @param[in,out] DataSize The size of data buffer in bytes.
1601 @retval EFI_SUCCESS The operation succeeded.
1602 @retval EFI_UNSUPPORTED This function is not supported.
1603 @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
1608 TlsGetCertRevocationList (
1610 IN OUT UINTN
*DataSize
1613 return EFI_UNSUPPORTED
;
1617 Derive keying material from a TLS connection.
1619 This function exports keying material using the mechanism described in RFC
1622 @param[in] Tls Pointer to the TLS object
1623 @param[in] Label Description of the key for the PRF function
1624 @param[in] Context Optional context
1625 @param[in] ContextLen The length of the context value in bytes
1626 @param[out] KeyBuffer Buffer to hold the output of the TLS-PRF
1627 @param[in] KeyBufferLen The length of the KeyBuffer
1629 @retval EFI_SUCCESS The operation succeeded.
1630 @retval EFI_INVALID_PARAMETER The TLS object is invalid.
1631 @retval EFI_PROTOCOL_ERROR Some other error occurred.
1638 IN CONST VOID
*Label
,
1639 IN CONST VOID
*Context
,
1640 IN UINTN ContextLen
,
1641 OUT VOID
*KeyBuffer
,
1642 IN UINTN KeyBufferLen
1645 TLS_CONNECTION
*TlsConn
;
1647 TlsConn
= (TLS_CONNECTION
*)Tls
;
1649 if ((TlsConn
== NULL
) || (TlsConn
->Ssl
== NULL
)) {
1650 return EFI_INVALID_PARAMETER
;
1653 return SSL_export_keying_material (
1658 AsciiStrLen (Label
),
1663 EFI_SUCCESS
: EFI_PROTOCOL_ERROR
;