]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c
CryptoPkg: Change OPTIONAL keyword usage style
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptPkcs1Oaep.c
CommitLineData
933f1990
BB
1/** @file\r
2 This file contains UEFI wrapper functions for RSA PKCS1v2 OAEP encryption routines.\r
3\r
4 SPDX-License-Identifier: BSD-2-Clause-Patent\r
5\r
6 Copyright (C) 2016 Microsoft Corporation. All Rights Reserved.\r
7 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
8\r
9**/\r
10\r
11#include "InternalCryptLib.h"\r
12#include <openssl/objects.h>\r
13#include <openssl/rsa.h>\r
14#include <openssl/x509.h>\r
15#include <Library/MemoryAllocationLib.h>\r
16\r
17/**\r
18 Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the\r
19 encrypted message in a newly allocated buffer.\r
20\r
21 Things that can cause a failure include:\r
22 - X509 key size does not match any known key size.\r
23 - Fail to parse X509 certificate.\r
24 - Fail to allocate an intermediate buffer.\r
25 - Null pointer provided for a non-optional parameter.\r
26 - Data size is too large for the provided key size (max size is a function of key size\r
27 and hash digest size).\r
28\r
29 @param[in] PublicKey A pointer to the DER-encoded X509 certificate that\r
30 will be used to encrypt the data.\r
31 @param[in] PublicKeySize Size of the X509 cert buffer.\r
32 @param[in] InData Data to be encrypted.\r
33 @param[in] InDataSize Size of the data buffer.\r
34 @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer\r
35 to be used when initializing the PRNG. NULL otherwise.\r
36 @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer.\r
37 0 otherwise.\r
38 @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted\r
39 message.\r
40 @param[out] EncryptedDataSize Size of the encrypted message buffer.\r
41\r
42 @retval TRUE Encryption was successful.\r
43 @retval FALSE Encryption failed.\r
44\r
45**/\r
46BOOLEAN\r
47EFIAPI\r
48Pkcs1v2Encrypt (\r
49 IN CONST UINT8 *PublicKey,\r
50 IN UINTN PublicKeySize,\r
51 IN UINT8 *InData,\r
52 IN UINTN InDataSize,\r
c8f46130
MK
53 IN CONST UINT8 *PrngSeed OPTIONAL,\r
54 IN UINTN PrngSeedSize OPTIONAL,\r
933f1990
BB
55 OUT UINT8 **EncryptedData,\r
56 OUT UINTN *EncryptedDataSize\r
57 )\r
58{\r
59 BOOLEAN Result;\r
60 CONST UINT8 *TempPointer;\r
61 X509 *CertData;\r
62 EVP_PKEY *InternalPublicKey;\r
63 EVP_PKEY_CTX *PkeyCtx;\r
64 UINT8 *OutData;\r
65 UINTN OutDataSize;\r
66\r
67 //\r
68 // Check input parameters.\r
69 //\r
70 if (PublicKey == NULL || InData == NULL ||\r
71 EncryptedData == NULL || EncryptedDataSize == NULL) {\r
72 return FALSE;\r
73 }\r
74\r
75 //\r
76 // Check public key size.\r
77 //\r
78 if (PublicKeySize > 0xFFFFFFFF) {\r
79 //\r
80 // Public key size is too large for implementation.\r
81 //\r
82 return FALSE;\r
83 }\r
84\r
85 *EncryptedData = NULL;\r
86 *EncryptedDataSize = 0;\r
87 Result = FALSE;\r
88 TempPointer = NULL;\r
89 CertData = NULL;\r
90 InternalPublicKey = NULL;\r
91 PkeyCtx = NULL;\r
92 OutData = NULL;\r
93 OutDataSize = 0;\r
94\r
95 //\r
96 // If it provides a seed then use it.\r
97 // Ohterwise, we'll seed with fixed values and hope that the PRNG has already been\r
98 // used enough to generate sufficient entropy.\r
99 //\r
100 if (PrngSeed != NULL) {\r
101 RandomSeed (PrngSeed, PrngSeedSize);\r
102 } else {\r
103 RandomSeed (NULL, 0);\r
104 }\r
105\r
106 //\r
107 // Parse the X509 cert and extract the public key.\r
108 //\r
109 TempPointer = PublicKey;\r
110 CertData = d2i_X509 (&CertData, &TempPointer, (UINT32)PublicKeySize);\r
111 if (CertData == NULL) {\r
112 //\r
113 // Fail to parse X509 cert.\r
114 //\r
115 goto _Exit;\r
116 }\r
117\r
118 //\r
119 // Extract the public key from the x509 cert in a format that\r
120 // OpenSSL can use.\r
121 //\r
122 InternalPublicKey = X509_get_pubkey (CertData);\r
123 if (InternalPublicKey == NULL) {\r
124 //\r
125 // Fail to extract public key.\r
126 //\r
127 goto _Exit;\r
128 }\r
129\r
130 //\r
131 // Create a context for the public key operation.\r
132 //\r
133 PkeyCtx = EVP_PKEY_CTX_new (InternalPublicKey, NULL);\r
134 if (PkeyCtx == NULL) {\r
135 //\r
136 // Fail to create contex.\r
137 //\r
138 goto _Exit;\r
139 }\r
140 //\r
141 // Initialize the context and set the desired padding.\r
142 //\r
143 if (EVP_PKEY_encrypt_init (PkeyCtx) <= 0 ||\r
144 EVP_PKEY_CTX_set_rsa_padding (PkeyCtx, RSA_PKCS1_OAEP_PADDING) <= 0) {\r
145 //\r
146 // Fail to initialize the context.\r
147 //\r
148 goto _Exit;\r
149 }\r
150\r
151 //\r
152 // Determine the required buffer length for malloc'ing.\r
153 //\r
154 if (EVP_PKEY_encrypt (PkeyCtx, NULL, &OutDataSize, InData, InDataSize) <= 0) {\r
155 //\r
156 // Fail to determine output buffer size.\r
157 //\r
158 goto _Exit;\r
159 }\r
160\r
161 //\r
162 // Allocate a buffer for the output data.\r
163 //\r
164 OutData = AllocatePool (OutDataSize);\r
165 if (OutData == NULL) {\r
166 //\r
167 // Fail to allocate the output buffer.\r
168 //\r
169 goto _Exit;\r
170 }\r
171\r
172 //\r
173 // Encrypt Data.\r
174 //\r
175 if (EVP_PKEY_encrypt (PkeyCtx, OutData, &OutDataSize, InData, InDataSize) <= 0) {\r
176 //\r
177 // Fail to encrypt data, need to free the output buffer.\r
178 //\r
179 FreePool (OutData);\r
180 OutData = NULL;\r
181 OutDataSize = 0;\r
182 goto _Exit;\r
183 }\r
184\r
185 //\r
186 // Encrypt done.\r
187 //\r
188 *EncryptedData = OutData;\r
189 *EncryptedDataSize = OutDataSize;\r
190 Result = TRUE;\r
191\r
192_Exit:\r
193 //\r
194 // Release Resources\r
195 //\r
196 if (CertData != NULL) {\r
197 X509_free (CertData );\r
198 }\r
199 if (InternalPublicKey != NULL) {\r
200 EVP_PKEY_free (InternalPublicKey);\r
201 }\r
202 if (PkeyCtx != NULL) {\r
203 EVP_PKEY_CTX_free (PkeyCtx);\r
204 }\r
205\r
206 return Result;\r
207}\r