From 4a567c9690db97ecbf982e9428727f073bada504 Mon Sep 17 00:00:00 2001 From: qlong Date: Fri, 31 Dec 2010 07:22:48 +0000 Subject: 1. Add new API supports for PEM & X509 key retrieving & verification; 2. Add new MD4 hash supports; 3. Add corresponding test case in Cryptest utility; 4. Fix MACRO definition issue in OpensslLib.inf and parameter checking issues in some wrapper implementations. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11214 6f19259b-4bc3-4df7-8a09-765794883524 --- CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf | 3 + CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c | 177 +++++++++++++ CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c | 6 + CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c | 6 + CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c | 6 + CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c | 6 + .../Library/BaseCryptLib/Hmac/CryptHmacSha1.c | 6 + CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c | 124 +++++++++ CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c | 288 +++++++++++++++++++++ .../Library/BaseCryptLib/SysCall/CrtWrapper.c | 5 + 10 files changed, 627 insertions(+) create mode 100644 CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c create mode 100644 CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c (limited to 'CryptoPkg/Library/BaseCryptLib') diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf index efd28ed120..26ec8c1e79 100644 --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf @@ -28,6 +28,7 @@ [Sources] InternalCryptLib.h + Hash/CryptMd4.c Hash/CryptMd5.c Hash/CryptSha1.c Hash/CryptSha256.c @@ -40,6 +41,8 @@ Pk/CryptRsa.c Pk/CryptPkcs7.c Pk/CryptDh.c + Pk/CryptX509.c + Pem/CryptPem.c SysCall/CrtWrapper.c SysCall/TimerWrapper.c diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c new file mode 100644 index 0000000000..a5769133ed --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c @@ -0,0 +1,177 @@ +/** @file + MD4 Digest Wrapper Implementation over OpenSSL. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+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 "InternalCryptLib.h" +#include + +/** + Retrieves the size, in bytes, of the context buffer required for MD4 hash operations. + + @return The size, in bytes, of the context buffer required for MD4 hash operations. + +**/ +UINTN +EFIAPI +Md4GetContextSize ( + VOID + ) +{ + // + // Retrieves the OpenSSL MD4 Context Size + // + return (UINTN)(sizeof (MD4_CTX)); +} + +/** + Initializes user-supplied memory pointed by Md4Context as MD4 hash context for + subsequent use. + + If Md4Context is NULL, then ASSERT(). + + @param[out] Md4Context Pointer to MD4 context being initialized. + + @retval TRUE MD4 context initialization succeeded. + @retval FALSE MD4 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Md4Init ( + OUT VOID *Md4Context + ) +{ + // + // ASSERT if Md4Context is NULL. + // + ASSERT (Md4Context != NULL); + + // + // OpenSSL MD4 Context Initialization + // + return (BOOLEAN) (MD4_Init ((MD4_CTX *)Md4Context)); +} + +/** + Makes a copy of an existing MD4 context. + + If Md4Context is NULL, then ASSERT(). + If NewMd4Context is NULL, then ASSERT(). + + @param[in] Md4Context Pointer to MD4 context being copied. + @param[out] NewMd4Context Pointer to new MD4 context. + + @retval TRUE MD4 context copy succeeded. + @retval FALSE MD4 context copy failed. + +**/ +BOOLEAN +EFIAPI +Md4Duplicate ( + IN CONST VOID *Md4Context, + OUT VOID *NewMd4Context + ) +{ + // + // ASSERT if Md4Context or NewMd4Context is NULL. + // + ASSERT (Md4Context != NULL); + ASSERT (NewMd4Context != NULL); + + CopyMem (NewMd4Context, Md4Context, sizeof (MD4_CTX)); + + return TRUE; +} + +/** + Digests the input data and updates MD4 context. + + This function performs MD4 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + MD4 context should be already correctly intialized by Md4Init(), and should not be finalized + by Md4Final(). Behavior with invalid context is undefined. + + If Md4Context is NULL, then ASSERT(). + + @param[in, out] Md4Context Pointer to the MD4 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE MD4 data digest succeeded. + @retval FALSE MD4 data digest failed. + +**/ +BOOLEAN +EFIAPI +Md4Update ( + IN OUT VOID *Md4Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // ASSERT if Md4Context is NULL + // + ASSERT (Md4Context != NULL); + + // + // ASSERT if invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL) { + ASSERT (DataSize == 0); + } + + // + // OpenSSL MD4 Hash Update + // + return (BOOLEAN) (MD4_Update ((MD4_CTX *)Md4Context, Data, DataSize)); +} + +/** + Completes computation of the MD4 digest value. + + This function completes MD4 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the MD4 context cannot + be used again. + MD4 context should be already correctly intialized by Md4Init(), and should not be + finalized by Md4Final(). Behavior with invalid MD4 context is undefined. + + If Md4Context is NULL, then ASSERT(). + If HashValue is NULL, then ASSERT(). + + @param[in, out] Md4Context Pointer to the MD4 context. + @param[out] HashValue Pointer to a buffer that receives the MD4 digest + value (16 bytes). + + @retval TRUE MD4 digest computation succeeded. + @retval FALSE MD4 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Md4Final ( + IN OUT VOID *Md4Context, + OUT UINT8 *HashValue + ) +{ + // + // ASSERT if Md4Context is NULL or HashValue is NULL + // + ASSERT (Md4Context != NULL); + ASSERT (HashValue != NULL); + + // + // OpenSSL MD4 Hash Finalization + // + return (BOOLEAN) (MD4_Final (HashValue, (MD4_CTX *)Md4Context)); +} diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c index 73f3d219b0..8d5e6ed89d 100644 --- a/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c @@ -84,6 +84,12 @@ Md5Duplicate ( OUT VOID *NewMd5Context ) { + // + // ASSERT if Md5Context or NewMd5Context is NULL. + // + ASSERT (Md5Context != NULL); + ASSERT (NewMd5Context != NULL); + CopyMem (NewMd5Context, Md5Context, sizeof (MD5_CTX)); return TRUE; diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c index 9a317ec143..27526bcd40 100644 --- a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c @@ -83,6 +83,12 @@ Sha1Duplicate ( OUT VOID *NewSha1Context ) { + // + // ASSERT if Sha1Context or NewSha1Context is NULL. + // + ASSERT (Sha1Context != NULL); + ASSERT (NewSha1Context != NULL); + CopyMem (NewSha1Context, Sha1Context, sizeof (SHA_CTX)); return TRUE; diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c index 7e6c6c691f..3c2f9a1155 100644 --- a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c @@ -82,6 +82,12 @@ Sha256Duplicate ( OUT VOID *NewSha256Context ) { + // + // ASSERT if Sha256Context or NewSha256Context is NULL. + // + ASSERT (Sha256Context != NULL); + ASSERT (NewSha256Context != NULL); + CopyMem (NewSha256Context, Sha256Context, sizeof (SHA256_CTX)); return TRUE; diff --git a/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c b/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c index 1eff5c4978..5386072c38 100644 --- a/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c +++ b/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c @@ -89,6 +89,12 @@ HmacMd5Duplicate ( OUT VOID *NewHmacMd5Context ) { + // + // ASSERT if HmacMd5Context or NewHmacMd5Context is NULL. + // + ASSERT (HmacMd5Context != NULL); + ASSERT (NewHmacMd5Context != NULL); + CopyMem (NewHmacMd5Context, HmacMd5Context, sizeof (HMAC_CTX)); return TRUE; diff --git a/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1.c b/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1.c index 0298b80cc5..ff9377c0d2 100644 --- a/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1.c +++ b/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1.c @@ -89,6 +89,12 @@ HmacSha1Duplicate ( OUT VOID *NewHmacSha1Context ) { + // + // ASSERT if HmacSha1Context or NewHmacSha1Context is NULL. + // + ASSERT (HmacSha1Context != NULL); + ASSERT (NewHmacSha1Context != NULL); + CopyMem (NewHmacSha1Context, HmacSha1Context, sizeof (HMAC_CTX)); return TRUE; diff --git a/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c b/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c new file mode 100644 index 0000000000..e9de39a105 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c @@ -0,0 +1,124 @@ +/** @file + PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over OpenSSL. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+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 "InternalCryptLib.h" +#include + +/** + Callback function for password phrase conversion used for retrieving the encrypted PEM. + + @param[out] Buf Pointer to the buffer to write the passphrase to. + @param[in] Size Maximum length of the passphrase (i.e. the size of Buf). + @param[in] Flag A flag which is set to 0 when reading and 1 when writing. + @param[in] Key Key data to be passed to the callback routine. + + @retval The number of characters in the passphrase or 0 if an error occurred. + +**/ +INTN +PasswordCallback ( + OUT CHAR8 *Buf, + IN INTN Size, + IN INTN Flag, + IN VOID *Key + ) +{ + INTN KeyLength; + + ZeroMem ((VOID *)Buf, (UINTN)Size); + if (Key != NULL) { + // + // Duplicate key phrase directly. + // + KeyLength = AsciiStrLen ((CHAR8 *)Key); + KeyLength = (KeyLength > Size ) ? Size : KeyLength; + CopyMem (Buf, Key, KeyLength); + return KeyLength; + } else { + return 0; + } +} + +/** + Retrieve the RSA Private Key from the password-protected PEM key data. + + @param[in] PemData Pointer to the PEM-encoded key data to be retrieved. + @param[in] PemSize Size of the PEM key data in bytes. + @param[in] Password NULL-terminated passphrase used for encrypted PEM key data. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA private key component. Use RsaFree() function to free the + resource. + + If PemData is NULL, then ASSERT(). + If RsaContext is NULL, then ASSERT(). + + @retval TRUE RSA Private Key was retrieved successfully. + @retval FALSE Invalid PEM key data or incorrect password. + +**/ +BOOLEAN +EFIAPI +RsaGetPrivateKeyFromPem ( + IN CONST UINT8 *PemData, + IN UINTN PemSize, + IN CONST CHAR8 *Password, + OUT VOID **RsaContext + ) +{ + BOOLEAN Status; + BIO *PemBio; + + // + // ASSERT if PemData is NULL or RsaContext is NULL. + // + ASSERT (PemData != NULL); + ASSERT (RsaContext != NULL); + + Status = FALSE; + PemBio = NULL; + + // + // Add possible block-cipher descriptor for PEM data decryption. + // NOTE: Only support most popular ciphers (3DES, AES) for the encrypted PEM. + // + EVP_add_cipher (EVP_des_ede3_cbc()); + EVP_add_cipher (EVP_aes_128_cbc()); + EVP_add_cipher (EVP_aes_192_cbc()); + EVP_add_cipher (EVP_aes_256_cbc()); + + // + // Read encrypted PEM Data. + // + PemBio = BIO_new (BIO_s_mem ()); + BIO_write (PemBio, PemData, (int)PemSize); + if (PemBio == NULL) { + goto _Exit; + } + + // + // Retrieve RSA Private Key from encrypted PEM data. + // + *RsaContext = PEM_read_bio_RSAPrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password); + if (*RsaContext != NULL) { + Status = TRUE; + } + +_Exit: + // + // Release Resources. + // + BIO_free (PemBio); + + return Status; +} diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c new file mode 100644 index 0000000000..6d687c64b6 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c @@ -0,0 +1,288 @@ +/** @file + X.509 Certificate Handler Wrapper Implementation over OpenSSL. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+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 "InternalCryptLib.h" +#include + +/** + Retrieve the subject bytes from one X.509 certificate. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] CertSubject Pointer to the retrieved certificate subject bytes. + @param[in, out] SubjectSize The size in bytes of the CertSubject buffer on input, + and the size of buffer returned CertSubject on output. + + If Cert is NULL, then ASSERT(). + If SubjectSize is NULL, then ASSERT(). + + @retval TRUE The certificate subject retrieved successfully. + @retval FALSE Invalid certificate, or the SubjectSize is too small for the result. + The SubjectSize will be updated with the required size. + +**/ +BOOLEAN +EFIAPI +X509GetSubjectName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 *CertSubject, + IN OUT UINTN *SubjectSize + ) +{ + BOOLEAN Status; + BIO *CertBio; + X509 *X509Cert; + X509_NAME *X509Name; + + // + // ASSERT if Cert is NULL or SubjectSize is NULL. + // + ASSERT (Cert != NULL); + ASSERT (SubjectSize != NULL); + + Status = FALSE; + X509Cert = NULL; + + // + // Read DER-encoded X509 Certificate and Construct X509 object. + // + CertBio = BIO_new (BIO_s_mem ()); + BIO_write (CertBio, Cert, (int)CertSize); + if (CertBio == NULL) { + goto _Exit; + } + X509Cert = d2i_X509_bio (CertBio, NULL); + if (Cert == NULL) { + goto _Exit; + } + + // + // Retrieve subject name from certificate object. + // + X509Name = X509_get_subject_name (X509Cert); + if (*SubjectSize < (UINTN) X509Name->bytes->length) { + *SubjectSize = (UINTN) X509Name->bytes->length; + goto _Exit; + } + *SubjectSize = (UINTN) X509Name->bytes->length; + if (CertSubject != NULL) { + CopyMem (CertSubject, (UINT8 *)X509Name->bytes->data, *SubjectSize); + Status = TRUE; + } + +_Exit: + // + // Release Resources. + // + BIO_free (CertBio); + X509_free (X509Cert); + + return Status; +} + +/** + Retrieve the RSA Public Key from one DER-encoded X509 certificate. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA public key component. Use RsaFree() function to free the + resource. + + If Cert is NULL, then ASSERT(). + If RsaContext is NULL, then ASSERT(). + + @retval TRUE RSA Public Key was retrieved successfully. + @retval FALSE Fail to retrieve RSA public key from X509 certificate. + +**/ +BOOLEAN +EFIAPI +RsaGetPublicKeyFromX509 ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT VOID **RsaContext + ) +{ + BOOLEAN Status; + EVP_PKEY *Pkey; + BIO *CertBio; + X509 *X509Cert; + + // + // ASSERT if Cert is NULL or RsaContext is NULL. + // + ASSERT (Cert != NULL); + ASSERT (RsaContext != NULL); + + Status = FALSE; + Pkey = NULL; + CertBio = NULL; + X509Cert = NULL; + + // + // Read DER-encoded X509 Certificate and Construct X509 object. + // + CertBio = BIO_new (BIO_s_mem ()); + BIO_write (CertBio, Cert, (int)CertSize); + if (CertBio == NULL) { + goto _Exit; + } + X509Cert = d2i_X509_bio (CertBio, NULL); + if (X509Cert == NULL) { + goto _Exit; + } + + // + // Retrieve and check EVP_PKEY data from X509 Certificate. + // + Pkey = X509_get_pubkey (X509Cert); + if ((Pkey == NULL) || (Pkey->type != EVP_PKEY_RSA)) { + goto _Exit; + } + + // + // Duplicate RSA Context from the retrieved EVP_PKEY. + // + if ((*RsaContext = RSAPublicKey_dup (Pkey->pkey.rsa)) != NULL) { + Status = TRUE; + } + +_Exit: + // + // Release Resources. + // + BIO_free (CertBio); + X509_free (X509Cert); + EVP_PKEY_free (Pkey); + + return Status; +} + +/** + Verify one X509 certificate was issued by the trusted CA. + + @param[in] Cert Pointer to the DER-encoded X509 certificate to be verified. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[in] CACert Pointer to the DER-encoded trusted CA certificate. + @param[in] CACertSize Size of the CA Certificate in bytes. + + If Cert is NULL, then ASSERT(). + If CACert is NULL, then ASSERT(). + + @retval TRUE The certificate was issued by the trusted CA. + @retval FALSE Invalid certificate or the certificate was not issued by the given + trusted CA. + +**/ +BOOLEAN +EFIAPI +X509VerifyCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CONST UINT8 *CACert, + IN UINTN CACertSize + ) +{ + BOOLEAN Status; + BIO *BioCert; + BIO *BioCACert; + X509 *X509Cert; + X509 *X509CACert; + X509_STORE *CertStore; + X509_STORE_CTX CertCtx; + + // + // ASSERT if Cert is NULL or CACert is NULL. + // + ASSERT (Cert != NULL); + ASSERT (CACert != NULL); + + Status = FALSE; + BioCert = NULL; + BioCACert = NULL; + X509Cert = NULL; + X509CACert = NULL; + CertStore = NULL; + + // + // Register & Initialize necessary digest algorithms for certificate verification. + // + EVP_add_digest (EVP_md5()); + EVP_add_digest (EVP_sha1()); + EVP_add_digest (EVP_sha256()); + + // + // Read DER-encoded certificate to be verified and Construct X509 object. + // + BioCert = BIO_new (BIO_s_mem ()); + BIO_write (BioCert, Cert, (int)CertSize); + if (BioCert == NULL) { + goto _Exit; + } + X509Cert = d2i_X509_bio (BioCert, NULL); + if (X509Cert == NULL) { + goto _Exit; + } + + // + // Read DER-encoded root certificate and Construct X509 object. + // + BioCACert = BIO_new (BIO_s_mem()); + BIO_write (BioCACert, CACert, (int)CACertSize); + if (BioCert == NULL) { + goto _Exit; + } + X509CACert = d2i_X509_bio (BioCACert, NULL); + if (CACert == NULL) { + goto _Exit; + } + + // + // Set up X509 Store for trusted certificate. + // + CertStore = X509_STORE_new (); + if (CertStore == NULL) { + goto _Exit; + } + if (!(X509_STORE_add_cert (CertStore, X509CACert))) { + goto _Exit; + } + + // + // Set up X509_STORE_CTX for the subsequent verification operation. + // + if (!X509_STORE_CTX_init (&CertCtx, CertStore, X509Cert, NULL)) { + goto _Exit; + } + + // + // X509 Certificate Verification. + // + Status = (BOOLEAN) X509_verify_cert (&CertCtx); + +_Exit: + // + // Release Resources. + // + BIO_free (BioCert); + BIO_free (BioCACert); + X509_free (X509Cert); + X509_free (X509CACert); + X509_STORE_free (CertStore); + X509_STORE_CTX_cleanup (&CertCtx); + + return Status; +} diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c index 1da4452d88..b9daaee0bc 100644 --- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c @@ -293,3 +293,8 @@ int BIO_snprintf(char *buf, size_t n, const char *format, ...) { return 0; } + +void *UI_OpenSSL(void) +{ + return NULL; +} -- cgit v1.2.3