2 This file contains UEFI wrapper functions for RSA PKCS1v2 OAEP encryption routines.
4 SPDX-License-Identifier: BSD-2-Clause-Patent
6 Copyright (C) 2016 Microsoft Corporation. All Rights Reserved.
7 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
11 #include "InternalCryptLib.h"
12 #include <openssl/objects.h>
13 #include <openssl/rsa.h>
14 #include <openssl/x509.h>
15 #include <Library/MemoryAllocationLib.h>
18 Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
19 encrypted message in a newly allocated buffer.
21 Things that can cause a failure include:
22 - X509 key size does not match any known key size.
23 - Fail to parse X509 certificate.
24 - Fail to allocate an intermediate buffer.
25 - Null pointer provided for a non-optional parameter.
26 - Data size is too large for the provided key size (max size is a function of key size
27 and hash digest size).
29 @param[in] PublicKey A pointer to the DER-encoded X509 certificate that
30 will be used to encrypt the data.
31 @param[in] PublicKeySize Size of the X509 cert buffer.
32 @param[in] InData Data to be encrypted.
33 @param[in] InDataSize Size of the data buffer.
34 @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer
35 to be used when initializing the PRNG. NULL otherwise.
36 @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer.
38 @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted
40 @param[out] EncryptedDataSize Size of the encrypted message buffer.
42 @retval TRUE Encryption was successful.
43 @retval FALSE Encryption failed.
49 IN CONST UINT8
*PublicKey
,
50 IN UINTN PublicKeySize
,
53 IN CONST UINT8
*PrngSeed OPTIONAL
,
54 IN UINTN PrngSeedSize OPTIONAL
,
55 OUT UINT8
**EncryptedData
,
56 OUT UINTN
*EncryptedDataSize
60 CONST UINT8
*TempPointer
;
62 EVP_PKEY
*InternalPublicKey
;
63 EVP_PKEY_CTX
*PkeyCtx
;
68 // Check input parameters.
70 if ((PublicKey
== NULL
) || (InData
== NULL
) ||
71 (EncryptedData
== NULL
) || (EncryptedDataSize
== NULL
))
77 // Check public key size.
79 if (PublicKeySize
> 0xFFFFFFFF) {
81 // Public key size is too large for implementation.
86 *EncryptedData
= NULL
;
87 *EncryptedDataSize
= 0;
91 InternalPublicKey
= NULL
;
97 // If it provides a seed then use it.
98 // Ohterwise, we'll seed with fixed values and hope that the PRNG has already been
99 // used enough to generate sufficient entropy.
101 if (PrngSeed
!= NULL
) {
102 RandomSeed (PrngSeed
, PrngSeedSize
);
104 RandomSeed (NULL
, 0);
108 // Parse the X509 cert and extract the public key.
110 TempPointer
= PublicKey
;
111 CertData
= d2i_X509 (&CertData
, &TempPointer
, (UINT32
)PublicKeySize
);
112 if (CertData
== NULL
) {
114 // Fail to parse X509 cert.
120 // Extract the public key from the x509 cert in a format that
123 InternalPublicKey
= X509_get_pubkey (CertData
);
124 if (InternalPublicKey
== NULL
) {
126 // Fail to extract public key.
132 // Create a context for the public key operation.
134 PkeyCtx
= EVP_PKEY_CTX_new (InternalPublicKey
, NULL
);
135 if (PkeyCtx
== NULL
) {
137 // Fail to create contex.
143 // Initialize the context and set the desired padding.
145 if ((EVP_PKEY_encrypt_init (PkeyCtx
) <= 0) ||
146 (EVP_PKEY_CTX_set_rsa_padding (PkeyCtx
, RSA_PKCS1_OAEP_PADDING
) <= 0))
149 // Fail to initialize the context.
155 // Determine the required buffer length for malloc'ing.
157 if (EVP_PKEY_encrypt (PkeyCtx
, NULL
, &OutDataSize
, InData
, InDataSize
) <= 0) {
159 // Fail to determine output buffer size.
165 // Allocate a buffer for the output data.
167 OutData
= AllocatePool (OutDataSize
);
168 if (OutData
== NULL
) {
170 // Fail to allocate the output buffer.
178 if (EVP_PKEY_encrypt (PkeyCtx
, OutData
, &OutDataSize
, InData
, InDataSize
) <= 0) {
180 // Fail to encrypt data, need to free the output buffer.
191 *EncryptedData
= OutData
;
192 *EncryptedDataSize
= OutDataSize
;
199 if (CertData
!= NULL
) {
200 X509_free (CertData
);
203 if (InternalPublicKey
!= NULL
) {
204 EVP_PKEY_free (InternalPublicKey
);
207 if (PkeyCtx
!= NULL
) {
208 EVP_PKEY_CTX_free (PkeyCtx
);