-/** @file
- SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.
-
-Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "InternalTlsLib.h"
-
-typedef struct {
- //
- // IANA/IETF defined Cipher Suite ID
- //
- UINT16 IanaCipher;
- //
- // OpenSSL-used Cipher Suite String
- //
- CONST CHAR8 *OpensslCipher;
-} TLS_CIPHER_PAIR;
-
-//
-// The mapping table between IANA/IETF Cipher Suite definitions and
-// OpenSSL-used Cipher Suite name.
-//
-STATIC CONST TLS_CIPHER_PAIR TlsCipherMappingTable[] = {
- { 0x0001, "NULL-MD5" }, /// TLS_RSA_WITH_NULL_MD5
- { 0x0002, "NULL-SHA" }, /// TLS_RSA_WITH_NULL_SHA
- { 0x0004, "RC4-MD5" }, /// TLS_RSA_WITH_RC4_128_MD5
- { 0x0005, "RC4-SHA" }, /// TLS_RSA_WITH_RC4_128_SHA
- { 0x000A, "DES-CBC3-SHA" }, /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
- { 0x0016, "DHE-RSA-DES-CBC3-SHA" }, /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- { 0x002F, "AES128-SHA" }, /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2
- { 0x0030, "DH-DSS-AES128-SHA" }, /// TLS_DH_DSS_WITH_AES_128_CBC_SHA
- { 0x0031, "DH-RSA-AES128-SHA" }, /// TLS_DH_RSA_WITH_AES_128_CBC_SHA
- { 0x0033, "DHE-RSA-AES128-SHA" }, /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- { 0x0035, "AES256-SHA" }, /// TLS_RSA_WITH_AES_256_CBC_SHA
- { 0x0036, "DH-DSS-AES256-SHA" }, /// TLS_DH_DSS_WITH_AES_256_CBC_SHA
- { 0x0037, "DH-RSA-AES256-SHA" }, /// TLS_DH_RSA_WITH_AES_256_CBC_SHA
- { 0x0039, "DHE-RSA-AES256-SHA" }, /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- { 0x003B, "NULL-SHA256" }, /// TLS_RSA_WITH_NULL_SHA256
- { 0x003C, "AES128-SHA256" }, /// TLS_RSA_WITH_AES_128_CBC_SHA256
- { 0x003D, "AES256-SHA256" }, /// TLS_RSA_WITH_AES_256_CBC_SHA256
- { 0x003E, "DH-DSS-AES128-SHA256" }, /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256
- { 0x003F, "DH-RSA-AES128-SHA256" }, /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256
- { 0x0067, "DHE-RSA-AES128-SHA256" }, /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- { 0x0068, "DH-DSS-AES256-SHA256" }, /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256
- { 0x0069, "DH-RSA-AES256-SHA256" }, /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256
- { 0x006B, "DHE-RSA-AES256-SHA256" } /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
-};
-
-/**
- Gets the OpenSSL cipher suite string for the supplied IANA TLS cipher suite.
-
- @param[in] CipherId The supplied IANA TLS cipher suite ID.
-
- @return The corresponding OpenSSL cipher suite string if found,
- NULL otherwise.
-
-**/
-STATIC
-CONST CHAR8 *
-TlsGetCipherString (
- IN UINT16 CipherId
- )
-{
- CONST TLS_CIPHER_PAIR *CipherEntry;
- UINTN TableSize;
- UINTN Index;
-
- CipherEntry = TlsCipherMappingTable;
- TableSize = sizeof (TlsCipherMappingTable) / sizeof (TLS_CIPHER_PAIR);
-
- //
- // Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation
- //
- for (Index = 0; Index < TableSize; Index++, CipherEntry++) {
- //
- // Translate IANA cipher suite name to OpenSSL name.
- //
- if (CipherEntry->IanaCipher == CipherId) {
- return CipherEntry->OpensslCipher;
- }
- }
-
- //
- // No Cipher Mapping found, return NULL.
- //
- return NULL;
-}
-
-/**
- Set a new TLS/SSL method for a particular TLS object.
-
- This function sets a new TLS/SSL method for a particular TLS object.
-
- @param[in] Tls Pointer to a TLS object.
- @param[in] MajorVer Major Version of TLS/SSL Protocol.
- @param[in] MinorVer Minor Version of TLS/SSL Protocol.
-
- @retval EFI_SUCCESS The TLS/SSL method was set successfully.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_UNSUPPORTED Unsupported TLS/SSL method.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetVersion (
- IN VOID *Tls,
- IN UINT8 MajorVer,
- IN UINT8 MinorVer
- )
-{
- TLS_CONNECTION *TlsConn;
- UINT16 ProtoVersion;
-
- TlsConn = (TLS_CONNECTION *)Tls;
- if (TlsConn == NULL || TlsConn->Ssl == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- ProtoVersion = (MajorVer << 8) | MinorVer;
-
- //
- // Bound TLS method to the particular specified version.
- //
- switch (ProtoVersion) {
- case TLS1_VERSION:
- //
- // TLS 1.0
- //
- SSL_set_min_proto_version (TlsConn->Ssl, TLS1_VERSION);
- SSL_set_max_proto_version (TlsConn->Ssl, TLS1_VERSION);
- break;
- case TLS1_1_VERSION:
- //
- // TLS 1.1
- //
- SSL_set_min_proto_version (TlsConn->Ssl, TLS1_1_VERSION);
- SSL_set_max_proto_version (TlsConn->Ssl, TLS1_1_VERSION);
- break;
- case TLS1_2_VERSION:
- //
- // TLS 1.2
- //
- SSL_set_min_proto_version (TlsConn->Ssl, TLS1_2_VERSION);
- SSL_set_max_proto_version (TlsConn->Ssl, TLS1_2_VERSION);
- break;
- default:
- //
- // Unsupported Protocol Version
- //
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;;
-}
-
-/**
- Set TLS object to work in client or server mode.
-
- This function prepares a TLS object to work in client or server mode.
-
- @param[in] Tls Pointer to a TLS object.
- @param[in] IsServer Work in server mode.
-
- @retval EFI_SUCCESS The TLS/SSL work mode was set successfully.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_UNSUPPORTED Unsupported TLS/SSL work mode.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetConnectionEnd (
- IN VOID *Tls,
- IN BOOLEAN IsServer
- )
-{
- TLS_CONNECTION *TlsConn;
-
- TlsConn = (TLS_CONNECTION *) Tls;
- if (TlsConn == NULL || TlsConn->Ssl == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsServer) {
- //
- // Set TLS to work in Client mode.
- //
- SSL_set_connect_state (TlsConn->Ssl);
- } else {
- //
- // Set TLS to work in Server mode.
- // It is unsupported for UEFI version currently.
- //
- //SSL_set_accept_state (TlsConn->Ssl);
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Set the ciphers list to be used by the TLS object.
-
- This function sets the ciphers for use by a specified TLS object.
-
- @param[in] Tls Pointer to a TLS object.
- @param[in] CipherId Pointer to a UINT16 cipher Id.
- @param[in] CipherNum The number of cipher in the list.
-
- @retval EFI_SUCCESS The ciphers list was set successfully.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_UNSUPPORTED Unsupported TLS cipher in the list.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetCipherList (
- IN VOID *Tls,
- IN UINT16 *CipherId,
- IN UINTN CipherNum
- )
-{
- TLS_CONNECTION *TlsConn;
- UINTN Index;
- CONST CHAR8 *MappingName;
- CHAR8 CipherString[500];
-
- TlsConn = (TLS_CONNECTION *) Tls;
- if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- MappingName = NULL;
-
- memset (CipherString, 0, sizeof (CipherString));
-
- for (Index = 0; Index < CipherNum; Index++) {
- //
- // Handling OpenSSL / RFC Cipher name mapping.
- //
- MappingName = TlsGetCipherString (*(CipherId + Index));
- if (MappingName == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- if (Index != 0) {
- //
- // The ciphers were separated by a colon.
- //
- AsciiStrCatS (CipherString, sizeof (CipherString), ":");
- }
-
- AsciiStrCatS (CipherString, sizeof (CipherString), MappingName);
- }
-
- AsciiStrCatS (CipherString, sizeof (CipherString), ":@STRENGTH");
-
- //
- // Sets the ciphers for use by the Tls object.
- //
- if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) {
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Set the compression method for TLS/SSL operations.
-
- This function handles TLS/SSL integrated compression methods.
-
- @param[in] CompMethod The compression method ID.
-
- @retval EFI_SUCCESS The compression method for the communication was
- set successfully.
- @retval EFI_UNSUPPORTED Unsupported compression method.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetCompressionMethod (
- IN UINT8 CompMethod
- )
-{
- COMP_METHOD *Cm;
- INTN Ret;
-
- Cm = NULL;
- Ret = 0;
-
- if (CompMethod == 0) {
- //
- // TLS defines one standard compression method, CompressionMethod.null (0),
- // which specifies that data exchanged via the record protocol will not be compressed.
- // So, return EFI_SUCCESS directly (RFC 3749).
- //
- return EFI_SUCCESS;
- } else if (CompMethod == 1) {
- Cm = COMP_zlib();
- } else {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Adds the compression method to the list of available
- // compression methods.
- //
- Ret = SSL_COMP_add_compression_method (CompMethod, Cm);
- if (Ret != 0) {
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Set peer certificate verification mode for the TLS connection.
-
- This function sets the verification mode flags for the TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in] VerifyMode A set of logically or'ed verification mode flags.
-
-**/
-VOID
-EFIAPI
-TlsSetVerify (
- IN VOID *Tls,
- IN UINT32 VerifyMode
- )
-{
- TLS_CONNECTION *TlsConn;
-
- TlsConn = (TLS_CONNECTION *) Tls;
- if (TlsConn == NULL || TlsConn->Ssl == NULL) {
- return;
- }
-
- //
- // Set peer certificate verification parameters with NULL callback.
- //
- SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL);
-}
-
-/**
- Sets a TLS/SSL session ID to be used during TLS/SSL connect.
-
- This function sets a session ID to be used when the TLS/SSL connection is
- to be established.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in] SessionId Session ID data used for session resumption.
- @param[in] SessionIdLen Length of Session ID in bytes.
-
- @retval EFI_SUCCESS Session ID was set successfully.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_UNSUPPORTED No available session for ID setting.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetSessionId (
- IN VOID *Tls,
- IN UINT8 *SessionId,
- IN UINT16 SessionIdLen
- )
-{
- TLS_CONNECTION *TlsConn;
- SSL_SESSION *Session;
-
- TlsConn = (TLS_CONNECTION *) Tls;
- Session = NULL;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Session = SSL_get_session (TlsConn->Ssl);
- if (Session == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- SSL_SESSION_set1_id (Session, (const unsigned char *)SessionId, SessionIdLen);
-
- return EFI_SUCCESS;
-}
-
-/**
- Adds the CA to the cert store when requesting Server or Client authentication.
-
- This function adds the CA certificate to the list of CAs when requesting
- Server or Client authentication for the chosen TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in] Data Pointer to the data buffer of a DER-encoded binary
- X.509 certificate or PEM-encoded X.509 certificate.
- @param[in] DataSize The size of data buffer in bytes.
-
- @retval EFI_SUCCESS The operation succeeded.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
- @retval EFI_ABORTED Invalid X.509 certificate.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetCaCertificate (
- IN VOID *Tls,
- IN VOID *Data,
- IN UINTN DataSize
- )
-{
- BIO *BioCert;
- X509 *Cert;
- X509_STORE *X509Store;
- EFI_STATUS Status;
- TLS_CONNECTION *TlsConn;
- SSL_CTX *SslCtx;
- INTN Ret;
- UINTN ErrorCode;
-
- BioCert = NULL;
- Cert = NULL;
- X509Store = NULL;
- Status = EFI_SUCCESS;
- TlsConn = (TLS_CONNECTION *) Tls;
- Ret = 0;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
- // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
- //
- Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
- if (Cert == NULL) {
- //
- // Certificate is from PEM encoding.
- //
- BioCert = BIO_new (BIO_s_mem ());
- if (BioCert == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
- Status = EFI_ABORTED;
- goto ON_EXIT;
- }
-
- Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
- if (Cert == NULL) {
- Status = EFI_ABORTED;
- goto ON_EXIT;
- }
- }
-
- SslCtx = SSL_get_SSL_CTX (TlsConn->Ssl);
- X509Store = SSL_CTX_get_cert_store (SslCtx);
- if (X509Store == NULL) {
- Status = EFI_ABORTED;
- goto ON_EXIT;
- }
-
- //
- // Add certificate to X509 store
- //
- Ret = X509_STORE_add_cert (X509Store, Cert);
- if (Ret != 1) {
- ErrorCode = ERR_peek_last_error ();
- //
- // Ignore "already in table" errors
- //
- if (!(ERR_GET_FUNC (ErrorCode) == X509_F_X509_STORE_ADD_CERT &&
- ERR_GET_REASON (ErrorCode) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
- Status = EFI_ABORTED;
- goto ON_EXIT;
- }
- }
-
-ON_EXIT:
- if (BioCert != NULL) {
- BIO_free (BioCert);
- }
-
- if (Cert != NULL) {
- X509_free (Cert);
- }
-
- return Status;
-}
-
-/**
- Loads the local public certificate into the specified TLS object.
-
- This function loads the X.509 certificate into the specified TLS object
- for TLS negotiation.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in] Data Pointer to the data buffer of a DER-encoded binary
- X.509 certificate or PEM-encoded X.509 certificate.
- @param[in] DataSize The size of data buffer in bytes.
-
- @retval EFI_SUCCESS The operation succeeded.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
- @retval EFI_ABORTED Invalid X.509 certificate.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetHostPublicCert (
- IN VOID *Tls,
- IN VOID *Data,
- IN UINTN DataSize
- )
-{
- BIO *BioCert;
- X509 *Cert;
- EFI_STATUS Status;
- TLS_CONNECTION *TlsConn;
-
- BioCert = NULL;
- Cert = NULL;
- Status = EFI_SUCCESS;
- TlsConn = (TLS_CONNECTION *) Tls;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
- // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
- //
- Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
- if (Cert == NULL) {
- //
- // Certificate is from PEM encoding.
- //
- BioCert = BIO_new (BIO_s_mem ());
- if (BioCert == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
- Status = EFI_ABORTED;
- goto ON_EXIT;
- }
-
- Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
- if (Cert == NULL) {
- Status = EFI_ABORTED;
- goto ON_EXIT;
- }
- }
-
- if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) {
- Status = EFI_ABORTED;
- goto ON_EXIT;
- }
-
-ON_EXIT:
- if (BioCert != NULL) {
- BIO_free (BioCert);
- }
-
- if (Cert != NULL) {
- X509_free (Cert);
- }
-
- return Status;
-}
-
-/**
- Adds the local private key to the specified TLS object.
-
- This function adds the local private key (PEM-encoded RSA or PKCS#8 private
- key) into the specified TLS object for TLS negotiation.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in] Data Pointer to the data buffer of a PEM-encoded RSA
- or PKCS#8 private key.
- @param[in] DataSize The size of data buffer in bytes.
-
- @retval EFI_SUCCESS The operation succeeded.
- @retval EFI_UNSUPPORTED This function is not supported.
- @retval EFI_ABORTED Invalid private key data.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetHostPrivateKey (
- IN VOID *Tls,
- IN VOID *Data,
- IN UINTN DataSize
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Adds the CA-supplied certificate revocation list for certificate validation.
-
- This function adds the CA-supplied certificate revocation list data for
- certificate validity checking.
-
- @param[in] Data Pointer to the data buffer of a DER-encoded CRL data.
- @param[in] DataSize The size of data buffer in bytes.
-
- @retval EFI_SUCCESS The operation succeeded.
- @retval EFI_UNSUPPORTED This function is not supported.
- @retval EFI_ABORTED Invalid CRL data.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsSetCertRevocationList (
- IN VOID *Data,
- IN UINTN DataSize
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Gets the protocol version used by the specified TLS connection.
-
- This function returns the protocol version used by the specified TLS
- connection.
-
- @param[in] Tls Pointer to the TLS object.
-
- @return The protocol version of the specified TLS connection.
-
-**/
-UINT16
-EFIAPI
-TlsGetVersion (
- IN VOID *Tls
- )
-{
- TLS_CONNECTION *TlsConn;
-
- TlsConn = (TLS_CONNECTION *) Tls;
-
- ASSERT (TlsConn != NULL);
-
- return (UINT16)(SSL_version (TlsConn->Ssl));
-}
-
-/**
- Gets the connection end of the specified TLS connection.
-
- This function returns the connection end (as client or as server) used by
- the specified TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
-
- @return The connection end used by the specified TLS connection.
-
-**/
-UINT8
-EFIAPI
-TlsGetConnectionEnd (
- IN VOID *Tls
- )
-{
- TLS_CONNECTION *TlsConn;
-
- TlsConn = (TLS_CONNECTION *) Tls;
-
- ASSERT (TlsConn != NULL);
-
- return (UINT8)SSL_is_server (TlsConn->Ssl);
-}
-
-/**
- Gets the cipher suite used by the specified TLS connection.
-
- This function returns current cipher suite used by the specified
- TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in,out] CipherId The cipher suite used by the TLS object.
-
- @retval EFI_SUCCESS The cipher suite was returned successfully.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_UNSUPPORTED Unsupported cipher suite.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsGetCurrentCipher (
- IN VOID *Tls,
- IN OUT UINT16 *CipherId
- )
-{
- TLS_CONNECTION *TlsConn;
- CONST SSL_CIPHER *Cipher;
-
- TlsConn = (TLS_CONNECTION *) Tls;
- Cipher = NULL;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Cipher = SSL_get_current_cipher (TlsConn->Ssl);
- if (Cipher == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF;
-
- return EFI_SUCCESS;
-}
-
-/**
- Gets the compression methods used by the specified TLS connection.
-
- This function returns current integrated compression methods used by
- the specified TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in,out] CompressionId The current compression method used by
- the TLS object.
-
- @retval EFI_SUCCESS The compression method was returned successfully.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_ABORTED Invalid Compression method.
- @retval EFI_UNSUPPORTED This function is not supported.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsGetCurrentCompressionId (
- IN VOID *Tls,
- IN OUT UINT8 *CompressionId
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Gets the verification mode currently set in the TLS connection.
-
- This function returns the peer verification mode currently set in the
- specified TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
-
- @return The verification mode set in the specified TLS connection.
-
-**/
-UINT32
-EFIAPI
-TlsGetVerify (
- IN VOID *Tls
- )
-{
- TLS_CONNECTION *TlsConn;
-
- TlsConn = (TLS_CONNECTION *) Tls;
-
- ASSERT (TlsConn != NULL);
-
- return SSL_get_verify_mode (TlsConn->Ssl);
-}
-
-/**
- Gets the session ID used by the specified TLS connection.
-
- This function returns the TLS/SSL session ID currently used by the
- specified TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in,out] SessionId Buffer to contain the returned session ID.
- @param[in,out] SessionIdLen The length of Session ID in bytes.
-
- @retval EFI_SUCCESS The Session ID was returned successfully.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_UNSUPPORTED Invalid TLS/SSL session.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsGetSessionId (
- IN VOID *Tls,
- IN OUT UINT8 *SessionId,
- IN OUT UINT16 *SessionIdLen
- )
-{
- TLS_CONNECTION *TlsConn;
- SSL_SESSION *Session;
- CONST UINT8 *SslSessionId;
-
- TlsConn = (TLS_CONNECTION *) Tls;
- Session = NULL;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL || SessionIdLen == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Session = SSL_get_session (TlsConn->Ssl);
- if (Session == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- SslSessionId = SSL_SESSION_get_id (Session, (unsigned int *)SessionIdLen);
- CopyMem (SessionId, SslSessionId, *SessionIdLen);
-
- return EFI_SUCCESS;
-}
-
-/**
- Gets the client random data used in the specified TLS connection.
-
- This function returns the TLS/SSL client random data currently used in
- the specified TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in,out] ClientRandom Buffer to contain the returned client
- random data (32 bytes).
-
-**/
-VOID
-EFIAPI
-TlsGetClientRandom (
- IN VOID *Tls,
- IN OUT UINT8 *ClientRandom
- )
-{
- TLS_CONNECTION *TlsConn;
-
- TlsConn = (TLS_CONNECTION *) Tls;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || ClientRandom == NULL) {
- return;
- }
-
- SSL_get_client_random (TlsConn->Ssl, ClientRandom, SSL3_RANDOM_SIZE);
-}
-
-/**
- Gets the server random data used in the specified TLS connection.
-
- This function returns the TLS/SSL server random data currently used in
- the specified TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in,out] ServerRandom Buffer to contain the returned server
- random data (32 bytes).
-
-**/
-VOID
-EFIAPI
-TlsGetServerRandom (
- IN VOID *Tls,
- IN OUT UINT8 *ServerRandom
- )
-{
- TLS_CONNECTION *TlsConn;
-
- TlsConn = (TLS_CONNECTION *) Tls;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || ServerRandom == NULL) {
- return;
- }
-
- SSL_get_server_random (TlsConn->Ssl, ServerRandom, SSL3_RANDOM_SIZE);
-}
-
-/**
- Gets the master key data used in the specified TLS connection.
-
- This function returns the TLS/SSL master key material currently used in
- the specified TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[in,out] KeyMaterial Buffer to contain the returned key material.
-
- @retval EFI_SUCCESS Key material was returned successfully.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_UNSUPPORTED Invalid TLS/SSL session.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsGetKeyMaterial (
- IN VOID *Tls,
- IN OUT UINT8 *KeyMaterial
- )
-{
- TLS_CONNECTION *TlsConn;
- SSL_SESSION *Session;
-
- TlsConn = (TLS_CONNECTION *) Tls;
- Session = NULL;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || KeyMaterial == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Session = SSL_get_session (TlsConn->Ssl);
-
- if (Session == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- SSL_SESSION_get_master_key (Session, KeyMaterial, SSL3_MASTER_SECRET_SIZE);
-
- return EFI_SUCCESS;
-}
-
-/**
- Gets the CA Certificate from the cert store.
-
- This function returns the CA certificate for the chosen
- TLS connection.
-
- @param[in] Tls Pointer to the TLS object.
- @param[out] Data Pointer to the data buffer to receive the CA
- certificate data sent to the client.
- @param[in,out] DataSize The size of data buffer in bytes.
-
- @retval EFI_SUCCESS The operation succeeded.
- @retval EFI_UNSUPPORTED This function is not supported.
- @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsGetCaCertificate (
- IN VOID *Tls,
- OUT VOID *Data,
- IN OUT UINTN *DataSize
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Gets the local public Certificate set in the specified TLS object.
-
- This function returns the local public certificate which was currently set
- in the specified TLS object.
-
- @param[in] Tls Pointer to the TLS object.
- @param[out] Data Pointer to the data buffer to receive the local
- public certificate.
- @param[in,out] DataSize The size of data buffer in bytes.
-
- @retval EFI_SUCCESS The operation succeeded.
- @retval EFI_INVALID_PARAMETER The parameter is invalid.
- @retval EFI_NOT_FOUND The certificate is not found.
- @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsGetHostPublicCert (
- IN VOID *Tls,
- OUT VOID *Data,
- IN OUT UINTN *DataSize
- )
-{
- X509 *Cert;
- TLS_CONNECTION *TlsConn;
-
- Cert = NULL;
- TlsConn = (TLS_CONNECTION *) Tls;
-
- if (TlsConn == NULL || TlsConn->Ssl == NULL || DataSize == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Cert = SSL_get_certificate(TlsConn->Ssl);
- if (Cert == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Only DER encoding is supported currently.
- //
- if (*DataSize < (UINTN) i2d_X509 (Cert, NULL)) {
- *DataSize = (UINTN) i2d_X509 (Cert, NULL);
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *DataSize = (UINTN) i2d_X509 (Cert, (unsigned char **) &Data);
-
- return EFI_SUCCESS;
-}
-
-/**
- Gets the local private key set in the specified TLS object.
-
- This function returns the local private key data which was currently set
- in the specified TLS object.
-
- @param[in] Tls Pointer to the TLS object.
- @param[out] Data Pointer to the data buffer to receive the local
- private key data.
- @param[in,out] DataSize The size of data buffer in bytes.
-
- @retval EFI_SUCCESS The operation succeeded.
- @retval EFI_UNSUPPORTED This function is not supported.
- @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsGetHostPrivateKey (
- IN VOID *Tls,
- OUT VOID *Data,
- IN OUT UINTN *DataSize
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Gets the CA-supplied certificate revocation list data set in the specified
- TLS object.
-
- This function returns the CA-supplied certificate revocation list data which
- was currently set in the specified TLS object.
-
- @param[out] Data Pointer to the data buffer to receive the CRL data.
- @param[in,out] DataSize The size of data buffer in bytes.
-
- @retval EFI_SUCCESS The operation succeeded.
- @retval EFI_UNSUPPORTED This function is not supported.
- @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.
-
-**/
-EFI_STATUS
-EFIAPI
-TlsGetCertRevocationList (
- OUT VOID *Data,
- IN OUT UINTN *DataSize
- )
-{
- return EFI_UNSUPPORTED;
-}
+/** @file\r
+ SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.\r
+\r
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "InternalTlsLib.h"\r
+\r
+typedef struct {\r
+ //\r
+ // IANA/IETF defined Cipher Suite ID\r
+ //\r
+ UINT16 IanaCipher;\r
+ //\r
+ // OpenSSL-used Cipher Suite String\r
+ //\r
+ CONST CHAR8 *OpensslCipher;\r
+ //\r
+ // Length of OpensslCipher\r
+ //\r
+ UINTN OpensslCipherLength;\r
+} TLS_CIPHER_MAPPING;\r
+\r
+//\r
+// Create a TLS_CIPHER_MAPPING initializer from IanaCipher and OpensslCipher so\r
+// that OpensslCipherLength is filled in automatically. IanaCipher must be an\r
+// integer constant expression, and OpensslCipher must be a string literal.\r
+//\r
+#define MAP(IanaCipher, OpensslCipher) \\r
+ { (IanaCipher), (OpensslCipher), sizeof (OpensslCipher) - 1 }\r
+\r
+//\r
+// The mapping table between IANA/IETF Cipher Suite definitions and\r
+// OpenSSL-used Cipher Suite name.\r
+//\r
+// Keep the table uniquely sorted by the IanaCipher field, in increasing order.\r
+//\r
+STATIC CONST TLS_CIPHER_MAPPING TlsCipherMappingTable[] = {\r
+ MAP (0x0001, "NULL-MD5"), /// TLS_RSA_WITH_NULL_MD5\r
+ MAP (0x0002, "NULL-SHA"), /// TLS_RSA_WITH_NULL_SHA\r
+ MAP (0x0004, "RC4-MD5"), /// TLS_RSA_WITH_RC4_128_MD5\r
+ MAP (0x0005, "RC4-SHA"), /// TLS_RSA_WITH_RC4_128_SHA\r
+ MAP (0x000A, "DES-CBC3-SHA"), /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1\r
+ MAP (0x0016, "DHE-RSA-DES-CBC3-SHA"), /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA\r
+ MAP (0x002F, "AES128-SHA"), /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2\r
+ MAP (0x0030, "DH-DSS-AES128-SHA"), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA\r
+ MAP (0x0031, "DH-RSA-AES128-SHA"), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA\r
+ MAP (0x0033, "DHE-RSA-AES128-SHA"), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA\r
+ MAP (0x0035, "AES256-SHA"), /// TLS_RSA_WITH_AES_256_CBC_SHA\r
+ MAP (0x0036, "DH-DSS-AES256-SHA"), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA\r
+ MAP (0x0037, "DH-RSA-AES256-SHA"), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA\r
+ MAP (0x0039, "DHE-RSA-AES256-SHA"), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA\r
+ MAP (0x003B, "NULL-SHA256"), /// TLS_RSA_WITH_NULL_SHA256\r
+ MAP (0x003C, "AES128-SHA256"), /// TLS_RSA_WITH_AES_128_CBC_SHA256\r
+ MAP (0x003D, "AES256-SHA256"), /// TLS_RSA_WITH_AES_256_CBC_SHA256\r
+ MAP (0x003E, "DH-DSS-AES128-SHA256"), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256\r
+ MAP (0x003F, "DH-RSA-AES128-SHA256"), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256\r
+ MAP (0x0067, "DHE-RSA-AES128-SHA256"), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\r
+ MAP (0x0068, "DH-DSS-AES256-SHA256"), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256\r
+ MAP (0x0069, "DH-RSA-AES256-SHA256"), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256\r
+ MAP (0x006B, "DHE-RSA-AES256-SHA256"), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\r
+};\r
+\r
+/**\r
+ Gets the OpenSSL cipher suite mapping for the supplied IANA TLS cipher suite.\r
+\r
+ @param[in] CipherId The supplied IANA TLS cipher suite ID.\r
+\r
+ @return The corresponding OpenSSL cipher suite mapping if found,\r
+ NULL otherwise.\r
+\r
+**/\r
+STATIC\r
+CONST TLS_CIPHER_MAPPING *\r
+TlsGetCipherMapping (\r
+ IN UINT16 CipherId\r
+ )\r
+{\r
+ INTN Left;\r
+ INTN Right;\r
+ INTN Middle;\r
+\r
+ //\r
+ // Binary Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation\r
+ //\r
+ Left = 0;\r
+ Right = ARRAY_SIZE (TlsCipherMappingTable) - 1;\r
+\r
+ while (Right >= Left) {\r
+ Middle = (Left + Right) / 2;\r
+\r
+ if (CipherId == TlsCipherMappingTable[Middle].IanaCipher) {\r
+ //\r
+ // Translate IANA cipher suite ID to OpenSSL name.\r
+ //\r
+ return &TlsCipherMappingTable[Middle];\r
+ }\r
+\r
+ if (CipherId < TlsCipherMappingTable[Middle].IanaCipher) {\r
+ Right = Middle - 1;\r
+ } else {\r
+ Left = Middle + 1;\r
+ }\r
+ }\r
+\r
+ //\r
+ // No Cipher Mapping found, return NULL.\r
+ //\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Set a new TLS/SSL method for a particular TLS object.\r
+\r
+ This function sets a new TLS/SSL method for a particular TLS object.\r
+\r
+ @param[in] Tls Pointer to a TLS object.\r
+ @param[in] MajorVer Major Version of TLS/SSL Protocol.\r
+ @param[in] MinorVer Minor Version of TLS/SSL Protocol.\r
+\r
+ @retval EFI_SUCCESS The TLS/SSL method was set successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_UNSUPPORTED Unsupported TLS/SSL method.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetVersion (\r
+ IN VOID *Tls,\r
+ IN UINT8 MajorVer,\r
+ IN UINT8 MinorVer\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ UINT16 ProtoVersion;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ProtoVersion = (MajorVer << 8) | MinorVer;\r
+\r
+ //\r
+ // Bound TLS method to the particular specified version.\r
+ //\r
+ switch (ProtoVersion) {\r
+ case TLS1_VERSION:\r
+ //\r
+ // TLS 1.0\r
+ //\r
+ SSL_set_min_proto_version (TlsConn->Ssl, TLS1_VERSION);\r
+ SSL_set_max_proto_version (TlsConn->Ssl, TLS1_VERSION);\r
+ break;\r
+ case TLS1_1_VERSION:\r
+ //\r
+ // TLS 1.1\r
+ //\r
+ SSL_set_min_proto_version (TlsConn->Ssl, TLS1_1_VERSION);\r
+ SSL_set_max_proto_version (TlsConn->Ssl, TLS1_1_VERSION);\r
+ break;\r
+ case TLS1_2_VERSION:\r
+ //\r
+ // TLS 1.2\r
+ //\r
+ SSL_set_min_proto_version (TlsConn->Ssl, TLS1_2_VERSION);\r
+ SSL_set_max_proto_version (TlsConn->Ssl, TLS1_2_VERSION);\r
+ break;\r
+ default:\r
+ //\r
+ // Unsupported Protocol Version\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set TLS object to work in client or server mode.\r
+\r
+ This function prepares a TLS object to work in client or server mode.\r
+\r
+ @param[in] Tls Pointer to a TLS object.\r
+ @param[in] IsServer Work in server mode.\r
+\r
+ @retval EFI_SUCCESS The TLS/SSL work mode was set successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_UNSUPPORTED Unsupported TLS/SSL work mode.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetConnectionEnd (\r
+ IN VOID *Tls,\r
+ IN BOOLEAN IsServer\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsServer) {\r
+ //\r
+ // Set TLS to work in Client mode.\r
+ //\r
+ SSL_set_connect_state (TlsConn->Ssl);\r
+ } else {\r
+ //\r
+ // Set TLS to work in Server mode.\r
+ // It is unsupported for UEFI version currently.\r
+ //\r
+ // SSL_set_accept_state (TlsConn->Ssl);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set the ciphers list to be used by the TLS object.\r
+\r
+ This function sets the ciphers for use by a specified TLS object.\r
+\r
+ @param[in] Tls Pointer to a TLS object.\r
+ @param[in] CipherId Array of UINT16 cipher identifiers. Each UINT16\r
+ cipher identifier comes from the TLS Cipher Suite\r
+ Registry of the IANA, interpreting Byte1 and Byte2\r
+ in network (big endian) byte order.\r
+ @param[in] CipherNum The number of cipher in the list.\r
+\r
+ @retval EFI_SUCCESS The ciphers list was set successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_UNSUPPORTED No supported TLS cipher was found in CipherId.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetCipherList (\r
+ IN VOID *Tls,\r
+ IN UINT16 *CipherId,\r
+ IN UINTN CipherNum\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ EFI_STATUS Status;\r
+ CONST TLS_CIPHER_MAPPING **MappedCipher;\r
+ UINTN MappedCipherBytes;\r
+ UINTN MappedCipherCount;\r
+ UINTN CipherStringSize;\r
+ UINTN Index;\r
+ CONST TLS_CIPHER_MAPPING *Mapping;\r
+ CHAR8 *CipherString;\r
+ CHAR8 *CipherStringPosition;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (CipherId == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Allocate the MappedCipher array for recording the mappings that we find\r
+ // for the input IANA identifiers in CipherId.\r
+ //\r
+ Status = SafeUintnMult (\r
+ CipherNum,\r
+ sizeof (*MappedCipher),\r
+ &MappedCipherBytes\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ MappedCipher = AllocatePool (MappedCipherBytes);\r
+ if (MappedCipher == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Map the cipher IDs, and count the number of bytes for the full\r
+ // CipherString.\r
+ //\r
+ MappedCipherCount = 0;\r
+ CipherStringSize = 0;\r
+ for (Index = 0; Index < CipherNum; Index++) {\r
+ //\r
+ // Look up the IANA-to-OpenSSL mapping.\r
+ //\r
+ Mapping = TlsGetCipherMapping (CipherId[Index]);\r
+ if (Mapping == NULL) {\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ "%a:%a: skipping CipherId=0x%04x\n",\r
+ gEfiCallerBaseName,\r
+ __FUNCTION__,\r
+ CipherId[Index]\r
+ ));\r
+ //\r
+ // Skipping the cipher is valid because CipherId is an ordered\r
+ // preference list of ciphers, thus we can filter it as long as we\r
+ // don't change the relative order of elements on it.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Accumulate Mapping->OpensslCipherLength into CipherStringSize. If this\r
+ // is not the first successful mapping, account for a colon (":") prefix\r
+ // too.\r
+ //\r
+ if (MappedCipherCount > 0) {\r
+ Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto FreeMappedCipher;\r
+ }\r
+ }\r
+\r
+ Status = SafeUintnAdd (\r
+ CipherStringSize,\r
+ Mapping->OpensslCipherLength,\r
+ &CipherStringSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto FreeMappedCipher;\r
+ }\r
+\r
+ //\r
+ // Record the mapping.\r
+ //\r
+ MappedCipher[MappedCipherCount++] = Mapping;\r
+ }\r
+\r
+ //\r
+ // Verify that at least one IANA cipher ID could be mapped; account for the\r
+ // terminating NUL character in CipherStringSize; allocate CipherString.\r
+ //\r
+ if (MappedCipherCount == 0) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "%a:%a: no CipherId could be mapped\n",\r
+ gEfiCallerBaseName,\r
+ __FUNCTION__\r
+ ));\r
+ Status = EFI_UNSUPPORTED;\r
+ goto FreeMappedCipher;\r
+ }\r
+\r
+ Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto FreeMappedCipher;\r
+ }\r
+\r
+ CipherString = AllocatePool (CipherStringSize);\r
+ if (CipherString == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto FreeMappedCipher;\r
+ }\r
+\r
+ //\r
+ // Go over the collected mappings and populate CipherString.\r
+ //\r
+ CipherStringPosition = CipherString;\r
+ for (Index = 0; Index < MappedCipherCount; Index++) {\r
+ Mapping = MappedCipher[Index];\r
+ //\r
+ // Append the colon (":") prefix except for the first mapping, then append\r
+ // Mapping->OpensslCipher.\r
+ //\r
+ if (Index > 0) {\r
+ *(CipherStringPosition++) = ':';\r
+ }\r
+\r
+ CopyMem (\r
+ CipherStringPosition,\r
+ Mapping->OpensslCipher,\r
+ Mapping->OpensslCipherLength\r
+ );\r
+ CipherStringPosition += Mapping->OpensslCipherLength;\r
+ }\r
+\r
+ //\r
+ // NUL-terminate CipherString.\r
+ //\r
+ *(CipherStringPosition++) = '\0';\r
+ ASSERT (CipherStringPosition == CipherString + CipherStringSize);\r
+\r
+ //\r
+ // Log CipherString for debugging. CipherString can be very long if the\r
+ // caller provided a large CipherId array, so log CipherString in segments of\r
+ // 79 non-newline characters. (MAX_DEBUG_MESSAGE_LENGTH is usually 0x100 in\r
+ // DebugLib instances.)\r
+ //\r
+ DEBUG_CODE_BEGIN ();\r
+ UINTN FullLength;\r
+ UINTN SegmentLength;\r
+\r
+ FullLength = CipherStringSize - 1;\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ "%a:%a: CipherString={\n",\r
+ gEfiCallerBaseName,\r
+ __FUNCTION__\r
+ ));\r
+ for (CipherStringPosition = CipherString;\r
+ CipherStringPosition < CipherString + FullLength;\r
+ CipherStringPosition += SegmentLength)\r
+ {\r
+ SegmentLength = FullLength - (CipherStringPosition - CipherString);\r
+ if (SegmentLength > 79) {\r
+ SegmentLength = 79;\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "%.*a\n", SegmentLength, CipherStringPosition));\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "}\n"));\r
+ //\r
+ // Restore the pre-debug value of CipherStringPosition by skipping over the\r
+ // trailing NUL.\r
+ //\r
+ CipherStringPosition++;\r
+ ASSERT (CipherStringPosition == CipherString + CipherStringSize);\r
+ DEBUG_CODE_END ();\r
+\r
+ //\r
+ // Sets the ciphers for use by the Tls object.\r
+ //\r
+ if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto FreeCipherString;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+FreeCipherString:\r
+ FreePool (CipherString);\r
+\r
+FreeMappedCipher:\r
+ FreePool (MappedCipher);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set the compression method for TLS/SSL operations.\r
+\r
+ This function handles TLS/SSL integrated compression methods.\r
+\r
+ @param[in] CompMethod The compression method ID.\r
+\r
+ @retval EFI_SUCCESS The compression method for the communication was\r
+ set successfully.\r
+ @retval EFI_UNSUPPORTED Unsupported compression method.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetCompressionMethod (\r
+ IN UINT8 CompMethod\r
+ )\r
+{\r
+ COMP_METHOD *Cm;\r
+ INTN Ret;\r
+\r
+ Cm = NULL;\r
+ Ret = 0;\r
+\r
+ if (CompMethod == 0) {\r
+ //\r
+ // TLS defines one standard compression method, CompressionMethod.null (0),\r
+ // which specifies that data exchanged via the record protocol will not be compressed.\r
+ // So, return EFI_SUCCESS directly (RFC 3749).\r
+ //\r
+ return EFI_SUCCESS;\r
+ } else if (CompMethod == 1) {\r
+ Cm = COMP_zlib ();\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Adds the compression method to the list of available\r
+ // compression methods.\r
+ //\r
+ Ret = SSL_COMP_add_compression_method (CompMethod, Cm);\r
+ if (Ret != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set peer certificate verification mode for the TLS connection.\r
+\r
+ This function sets the verification mode flags for the TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in] VerifyMode A set of logically or'ed verification mode flags.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+TlsSetVerify (\r
+ IN VOID *Tls,\r
+ IN UINT32 VerifyMode\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Set peer certificate verification parameters with NULL callback.\r
+ //\r
+ SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL);\r
+}\r
+\r
+/**\r
+ Set the specified host name to be verified.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in] Flags The setting flags during the validation.\r
+ @param[in] HostName The specified host name to be verified.\r
+\r
+ @retval EFI_SUCCESS The HostName setting was set successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_ABORTED Invalid HostName setting.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetVerifyHost (\r
+ IN VOID *Tls,\r
+ IN UINT32 Flags,\r
+ IN CHAR8 *HostName\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ X509_VERIFY_PARAM *VerifyParam;\r
+ UINTN BinaryAddressSize;\r
+ UINT8 BinaryAddress[MAX (NS_INADDRSZ, NS_IN6ADDRSZ)];\r
+ INTN ParamStatus;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (HostName == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ SSL_set_hostflags (TlsConn->Ssl, Flags);\r
+\r
+ VerifyParam = SSL_get0_param (TlsConn->Ssl);\r
+ ASSERT (VerifyParam != NULL);\r
+\r
+ BinaryAddressSize = 0;\r
+ if (inet_pton (AF_INET6, HostName, BinaryAddress) == 1) {\r
+ BinaryAddressSize = NS_IN6ADDRSZ;\r
+ } else if (inet_pton (AF_INET, HostName, BinaryAddress) == 1) {\r
+ BinaryAddressSize = NS_INADDRSZ;\r
+ }\r
+\r
+ if (BinaryAddressSize > 0) {\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ "%a:%a: parsed \"%a\" as an IPv%c address "\r
+ "literal\n",\r
+ gEfiCallerBaseName,\r
+ __FUNCTION__,\r
+ HostName,\r
+ (UINTN)((BinaryAddressSize == NS_IN6ADDRSZ) ? '6' : '4')\r
+ ));\r
+ ParamStatus = X509_VERIFY_PARAM_set1_ip (\r
+ VerifyParam,\r
+ BinaryAddress,\r
+ BinaryAddressSize\r
+ );\r
+ } else {\r
+ ParamStatus = X509_VERIFY_PARAM_set1_host (VerifyParam, HostName, 0);\r
+ }\r
+\r
+ return (ParamStatus == 1) ? EFI_SUCCESS : EFI_ABORTED;\r
+}\r
+\r
+/**\r
+ Sets a TLS/SSL session ID to be used during TLS/SSL connect.\r
+\r
+ This function sets a session ID to be used when the TLS/SSL connection is\r
+ to be established.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in] SessionId Session ID data used for session resumption.\r
+ @param[in] SessionIdLen Length of Session ID in bytes.\r
+\r
+ @retval EFI_SUCCESS Session ID was set successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_UNSUPPORTED No available session for ID setting.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetSessionId (\r
+ IN VOID *Tls,\r
+ IN UINT8 *SessionId,\r
+ IN UINT16 SessionIdLen\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ SSL_SESSION *Session;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ Session = NULL;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (SessionId == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Session = SSL_get_session (TlsConn->Ssl);\r
+ if (Session == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SSL_SESSION_set1_id (Session, (const unsigned char *)SessionId, SessionIdLen);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Adds the CA to the cert store when requesting Server or Client authentication.\r
+\r
+ This function adds the CA certificate to the list of CAs when requesting\r
+ Server or Client authentication for the chosen TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in] Data Pointer to the data buffer of a DER-encoded binary\r
+ X.509 certificate or PEM-encoded X.509 certificate.\r
+ @param[in] DataSize The size of data buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The operation succeeded.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.\r
+ @retval EFI_ABORTED Invalid X.509 certificate.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetCaCertificate (\r
+ IN VOID *Tls,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ BIO *BioCert;\r
+ X509 *Cert;\r
+ X509_STORE *X509Store;\r
+ EFI_STATUS Status;\r
+ TLS_CONNECTION *TlsConn;\r
+ SSL_CTX *SslCtx;\r
+ INTN Ret;\r
+ UINTN ErrorCode;\r
+\r
+ BioCert = NULL;\r
+ Cert = NULL;\r
+ X509Store = NULL;\r
+ Status = EFI_SUCCESS;\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ Ret = 0;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize == 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.\r
+ // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.\r
+ //\r
+ Cert = d2i_X509 (NULL, (const unsigned char **)&Data, (long)DataSize);\r
+ if (Cert == NULL) {\r
+ //\r
+ // Certificate is from PEM encoding.\r
+ //\r
+ BioCert = BIO_new (BIO_s_mem ());\r
+ if (BioCert == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (BIO_write (BioCert, Data, (UINT32)DataSize) <= 0) {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);\r
+ if (Cert == NULL) {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+\r
+ SslCtx = SSL_get_SSL_CTX (TlsConn->Ssl);\r
+ X509Store = SSL_CTX_get_cert_store (SslCtx);\r
+ if (X509Store == NULL) {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Add certificate to X509 store\r
+ //\r
+ Ret = X509_STORE_add_cert (X509Store, Cert);\r
+ if (Ret != 1) {\r
+ ErrorCode = ERR_peek_last_error ();\r
+ //\r
+ // Ignore "already in table" errors\r
+ //\r
+ if (!((ERR_GET_FUNC (ErrorCode) == X509_F_X509_STORE_ADD_CERT) &&\r
+ (ERR_GET_REASON (ErrorCode) == X509_R_CERT_ALREADY_IN_HASH_TABLE)))\r
+ {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+\r
+ON_EXIT:\r
+ if (BioCert != NULL) {\r
+ BIO_free (BioCert);\r
+ }\r
+\r
+ if (Cert != NULL) {\r
+ X509_free (Cert);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Loads the local public certificate into the specified TLS object.\r
+\r
+ This function loads the X.509 certificate into the specified TLS object\r
+ for TLS negotiation.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in] Data Pointer to the data buffer of a DER-encoded binary\r
+ X.509 certificate or PEM-encoded X.509 certificate.\r
+ @param[in] DataSize The size of data buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The operation succeeded.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.\r
+ @retval EFI_ABORTED Invalid X.509 certificate.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetHostPublicCert (\r
+ IN VOID *Tls,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ BIO *BioCert;\r
+ X509 *Cert;\r
+ EFI_STATUS Status;\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ BioCert = NULL;\r
+ Cert = NULL;\r
+ Status = EFI_SUCCESS;\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize == 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.\r
+ // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.\r
+ //\r
+ Cert = d2i_X509 (NULL, (const unsigned char **)&Data, (long)DataSize);\r
+ if (Cert == NULL) {\r
+ //\r
+ // Certificate is from PEM encoding.\r
+ //\r
+ BioCert = BIO_new (BIO_s_mem ());\r
+ if (BioCert == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (BIO_write (BioCert, Data, (UINT32)DataSize) <= 0) {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);\r
+ if (Cert == NULL) {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+\r
+ if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ON_EXIT:\r
+ if (BioCert != NULL) {\r
+ BIO_free (BioCert);\r
+ }\r
+\r
+ if (Cert != NULL) {\r
+ X509_free (Cert);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Adds the local private key to the specified TLS object.\r
+\r
+ This function adds the local private key (PEM-encoded RSA or PKCS#8 private\r
+ key) into the specified TLS object for TLS negotiation.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in] Data Pointer to the data buffer of a PEM-encoded RSA\r
+ or PKCS#8 private key.\r
+ @param[in] DataSize The size of data buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The operation succeeded.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+ @retval EFI_ABORTED Invalid private key data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetHostPrivateKey (\r
+ IN VOID *Tls,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Adds the CA-supplied certificate revocation list for certificate validation.\r
+\r
+ This function adds the CA-supplied certificate revocation list data for\r
+ certificate validity checking.\r
+\r
+ @param[in] Data Pointer to the data buffer of a DER-encoded CRL data.\r
+ @param[in] DataSize The size of data buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The operation succeeded.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+ @retval EFI_ABORTED Invalid CRL data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetCertRevocationList (\r
+ IN VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Gets the protocol version used by the specified TLS connection.\r
+\r
+ This function returns the protocol version used by the specified TLS\r
+ connection.\r
+\r
+ If Tls is NULL, then ASSERT().\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+\r
+ @return The protocol version of the specified TLS connection.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+TlsGetVersion (\r
+ IN VOID *Tls\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ ASSERT (TlsConn != NULL);\r
+\r
+ return (UINT16)(SSL_version (TlsConn->Ssl));\r
+}\r
+\r
+/**\r
+ Gets the connection end of the specified TLS connection.\r
+\r
+ This function returns the connection end (as client or as server) used by\r
+ the specified TLS connection.\r
+\r
+ If Tls is NULL, then ASSERT().\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+\r
+ @return The connection end used by the specified TLS connection.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+TlsGetConnectionEnd (\r
+ IN VOID *Tls\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ ASSERT (TlsConn != NULL);\r
+\r
+ return (UINT8)SSL_is_server (TlsConn->Ssl);\r
+}\r
+\r
+/**\r
+ Gets the cipher suite used by the specified TLS connection.\r
+\r
+ This function returns current cipher suite used by the specified\r
+ TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in,out] CipherId The cipher suite used by the TLS object.\r
+\r
+ @retval EFI_SUCCESS The cipher suite was returned successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_UNSUPPORTED Unsupported cipher suite.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetCurrentCipher (\r
+ IN VOID *Tls,\r
+ IN OUT UINT16 *CipherId\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ CONST SSL_CIPHER *Cipher;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ Cipher = NULL;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (CipherId == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Cipher = SSL_get_current_cipher (TlsConn->Ssl);\r
+ if (Cipher == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Gets the compression methods used by the specified TLS connection.\r
+\r
+ This function returns current integrated compression methods used by\r
+ the specified TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in,out] CompressionId The current compression method used by\r
+ the TLS object.\r
+\r
+ @retval EFI_SUCCESS The compression method was returned successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_ABORTED Invalid Compression method.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetCurrentCompressionId (\r
+ IN VOID *Tls,\r
+ IN OUT UINT8 *CompressionId\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Gets the verification mode currently set in the TLS connection.\r
+\r
+ This function returns the peer verification mode currently set in the\r
+ specified TLS connection.\r
+\r
+ If Tls is NULL, then ASSERT().\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+\r
+ @return The verification mode set in the specified TLS connection.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+TlsGetVerify (\r
+ IN VOID *Tls\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ ASSERT (TlsConn != NULL);\r
+\r
+ return SSL_get_verify_mode (TlsConn->Ssl);\r
+}\r
+\r
+/**\r
+ Gets the session ID used by the specified TLS connection.\r
+\r
+ This function returns the TLS/SSL session ID currently used by the\r
+ specified TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in,out] SessionId Buffer to contain the returned session ID.\r
+ @param[in,out] SessionIdLen The length of Session ID in bytes.\r
+\r
+ @retval EFI_SUCCESS The Session ID was returned successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_UNSUPPORTED Invalid TLS/SSL session.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetSessionId (\r
+ IN VOID *Tls,\r
+ IN OUT UINT8 *SessionId,\r
+ IN OUT UINT16 *SessionIdLen\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ SSL_SESSION *Session;\r
+ CONST UINT8 *SslSessionId;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ Session = NULL;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (SessionId == NULL) || (SessionIdLen == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Session = SSL_get_session (TlsConn->Ssl);\r
+ if (Session == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SslSessionId = SSL_SESSION_get_id (Session, (unsigned int *)SessionIdLen);\r
+ CopyMem (SessionId, SslSessionId, *SessionIdLen);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Gets the client random data used in the specified TLS connection.\r
+\r
+ This function returns the TLS/SSL client random data currently used in\r
+ the specified TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in,out] ClientRandom Buffer to contain the returned client\r
+ random data (32 bytes).\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+TlsGetClientRandom (\r
+ IN VOID *Tls,\r
+ IN OUT UINT8 *ClientRandom\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (ClientRandom == NULL)) {\r
+ return;\r
+ }\r
+\r
+ SSL_get_client_random (TlsConn->Ssl, ClientRandom, SSL3_RANDOM_SIZE);\r
+}\r
+\r
+/**\r
+ Gets the server random data used in the specified TLS connection.\r
+\r
+ This function returns the TLS/SSL server random data currently used in\r
+ the specified TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in,out] ServerRandom Buffer to contain the returned server\r
+ random data (32 bytes).\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+TlsGetServerRandom (\r
+ IN VOID *Tls,\r
+ IN OUT UINT8 *ServerRandom\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (ServerRandom == NULL)) {\r
+ return;\r
+ }\r
+\r
+ SSL_get_server_random (TlsConn->Ssl, ServerRandom, SSL3_RANDOM_SIZE);\r
+}\r
+\r
+/**\r
+ Gets the master key data used in the specified TLS connection.\r
+\r
+ This function returns the TLS/SSL master key material currently used in\r
+ the specified TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[in,out] KeyMaterial Buffer to contain the returned key material.\r
+\r
+ @retval EFI_SUCCESS Key material was returned successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_UNSUPPORTED Invalid TLS/SSL session.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetKeyMaterial (\r
+ IN VOID *Tls,\r
+ IN OUT UINT8 *KeyMaterial\r
+ )\r
+{\r
+ TLS_CONNECTION *TlsConn;\r
+ SSL_SESSION *Session;\r
+\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+ Session = NULL;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (KeyMaterial == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Session = SSL_get_session (TlsConn->Ssl);\r
+\r
+ if (Session == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SSL_SESSION_get_master_key (Session, KeyMaterial, SSL3_MASTER_SECRET_SIZE);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Gets the CA Certificate from the cert store.\r
+\r
+ This function returns the CA certificate for the chosen\r
+ TLS connection.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[out] Data Pointer to the data buffer to receive the CA\r
+ certificate data sent to the client.\r
+ @param[in,out] DataSize The size of data buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The operation succeeded.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+ @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetCaCertificate (\r
+ IN VOID *Tls,\r
+ OUT VOID *Data,\r
+ IN OUT UINTN *DataSize\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Gets the local public Certificate set in the specified TLS object.\r
+\r
+ This function returns the local public certificate which was currently set\r
+ in the specified TLS object.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[out] Data Pointer to the data buffer to receive the local\r
+ public certificate.\r
+ @param[in,out] DataSize The size of data buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The operation succeeded.\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_NOT_FOUND The certificate is not found.\r
+ @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetHostPublicCert (\r
+ IN VOID *Tls,\r
+ OUT VOID *Data,\r
+ IN OUT UINTN *DataSize\r
+ )\r
+{\r
+ X509 *Cert;\r
+ TLS_CONNECTION *TlsConn;\r
+\r
+ Cert = NULL;\r
+ TlsConn = (TLS_CONNECTION *)Tls;\r
+\r
+ if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Cert = SSL_get_certificate (TlsConn->Ssl);\r
+ if (Cert == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Only DER encoding is supported currently.\r
+ //\r
+ if (*DataSize < (UINTN)i2d_X509 (Cert, NULL)) {\r
+ *DataSize = (UINTN)i2d_X509 (Cert, NULL);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *DataSize = (UINTN)i2d_X509 (Cert, (unsigned char **)&Data);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Gets the local private key set in the specified TLS object.\r
+\r
+ This function returns the local private key data which was currently set\r
+ in the specified TLS object.\r
+\r
+ @param[in] Tls Pointer to the TLS object.\r
+ @param[out] Data Pointer to the data buffer to receive the local\r
+ private key data.\r
+ @param[in,out] DataSize The size of data buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The operation succeeded.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+ @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetHostPrivateKey (\r
+ IN VOID *Tls,\r
+ OUT VOID *Data,\r
+ IN OUT UINTN *DataSize\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Gets the CA-supplied certificate revocation list data set in the specified\r
+ TLS object.\r
+\r
+ This function returns the CA-supplied certificate revocation list data which\r
+ was currently set in the specified TLS object.\r
+\r
+ @param[out] Data Pointer to the data buffer to receive the CRL data.\r
+ @param[in,out] DataSize The size of data buffer in bytes.\r
+\r
+ @retval EFI_SUCCESS The operation succeeded.\r
+ @retval EFI_UNSUPPORTED This function is not supported.\r
+ @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetCertRevocationList (\r
+ OUT VOID *Data,\r
+ IN OUT UINTN *DataSize\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r