TianoCore EDK2 master
Loading...
Searching...
No Matches
CryptPkcs1Oaep.c
Go to the documentation of this file.
1
11#include "InternalCryptLib.h"
12#include <openssl/objects.h>
13#include <openssl/rsa.h>
14#include <openssl/x509.h>
16
24const
25EVP_MD *
27 IN UINT16 DigestLen
28 )
29{
30 switch (DigestLen) {
32 return EVP_sha1 ();
33 break;
35 return EVP_sha256 ();
36 break;
38 return EVP_sha384 ();
39 break;
41 return EVP_sha512 ();
42 break;
43 default:
44 return NULL;
45 }
46}
47
82BOOLEAN
83EFIAPI
85 EVP_PKEY *Pkey,
86 IN UINT8 *InData,
87 IN UINTN InDataSize,
88 IN CONST UINT8 *PrngSeed OPTIONAL,
89 IN UINTN PrngSeedSize OPTIONAL,
90 IN UINT16 DigestLen OPTIONAL,
91 OUT UINT8 **EncryptedData,
92 OUT UINTN *EncryptedDataSize
93 )
94{
95 BOOLEAN Result;
96 EVP_PKEY_CTX *PkeyCtx;
97 UINT8 *OutData;
98 UINTN OutDataSize;
99 CONST EVP_MD *HashAlg;
100
101 //
102 // Check input parameters.
103 //
104 if ((Pkey == NULL) || (InData == NULL) ||
105 (EncryptedData == NULL) || (EncryptedDataSize == NULL))
106 {
107 return FALSE;
108 }
109
110 *EncryptedData = NULL;
111 *EncryptedDataSize = 0;
112 Result = FALSE;
113 PkeyCtx = NULL;
114 OutData = NULL;
115 OutDataSize = 0;
116
117 //
118 // If it provides a seed then use it.
119 // Ohterwise, we'll seed with fixed values and hope that the PRNG has already been
120 // used enough to generate sufficient entropy.
121 //
122 if (PrngSeed != NULL) {
123 RandomSeed (PrngSeed, PrngSeedSize);
124 } else {
125 RandomSeed (NULL, 0);
126 }
127
128 //
129 // Create a context for the public key operation.
130 //
131 PkeyCtx = EVP_PKEY_CTX_new (Pkey, NULL);
132 if (PkeyCtx == NULL) {
133 //
134 // Fail to create contex.
135 //
136 goto _Exit;
137 }
138
139 //
140 // Initialize the context and set the desired padding.
141 //
142 if ((EVP_PKEY_encrypt_init (PkeyCtx) <= 0) ||
143 (EVP_PKEY_CTX_set_rsa_padding (PkeyCtx, RSA_PKCS1_OAEP_PADDING) <= 0))
144 {
145 //
146 // Fail to initialize the context.
147 //
148 goto _Exit;
149 }
150
151 if (DigestLen != 0) {
152 HashAlg = GetEvpMD (DigestLen);
153 if (HashAlg == NULL) {
154 goto _Exit;
155 }
156
157 if (EVP_PKEY_CTX_set_rsa_oaep_md (PkeyCtx, HashAlg) <= 0) {
158 goto _Exit;
159 }
160
161 if (EVP_PKEY_CTX_set_rsa_mgf1_md (PkeyCtx, HashAlg) <= 0) {
162 goto _Exit;
163 }
164 }
165
166 //
167 // Determine the required buffer length for malloc'ing.
168 //
169 if (EVP_PKEY_encrypt (PkeyCtx, NULL, &OutDataSize, InData, InDataSize) <= 0) {
170 //
171 // Fail to determine output buffer size.
172 //
173 goto _Exit;
174 }
175
176 //
177 // Allocate a buffer for the output data.
178 //
179 OutData = AllocatePool (OutDataSize);
180 if (OutData == NULL) {
181 //
182 // Fail to allocate the output buffer.
183 //
184 goto _Exit;
185 }
186
187 //
188 // Encrypt Data.
189 //
190 if (EVP_PKEY_encrypt (PkeyCtx, OutData, &OutDataSize, InData, InDataSize) <= 0) {
191 //
192 // Fail to encrypt data, need to free the output buffer.
193 //
194 FreePool (OutData);
195 OutData = NULL;
196 OutDataSize = 0;
197 goto _Exit;
198 }
199
200 //
201 // Encrypt done.
202 //
203 *EncryptedData = OutData;
204 *EncryptedDataSize = OutDataSize;
205 Result = TRUE;
206
207_Exit:
208 //
209 // Release Resources
210 //
211 if (PkeyCtx != NULL) {
212 EVP_PKEY_CTX_free (PkeyCtx);
213 }
214
215 return Result;
216}
217
247BOOLEAN
248EFIAPI
250 IN CONST UINT8 *PublicKey,
251 IN UINTN PublicKeySize,
252 IN UINT8 *InData,
253 IN UINTN InDataSize,
254 IN CONST UINT8 *PrngSeed OPTIONAL,
255 IN UINTN PrngSeedSize OPTIONAL,
256 OUT UINT8 **EncryptedData,
257 OUT UINTN *EncryptedDataSize
258 )
259{
260 BOOLEAN Result;
261 CONST UINT8 *TempPointer;
262 X509 *CertData;
263 EVP_PKEY *Pkey;
264
265 //
266 // Check input parameters.
267 //
268 if ((PublicKey == NULL) || (InData == NULL) ||
269 (EncryptedData == NULL) || (EncryptedDataSize == NULL))
270 {
271 return FALSE;
272 }
273
274 //
275 // Check public key size.
276 //
277 if (PublicKeySize > 0xFFFFFFFF) {
278 //
279 // Public key size is too large for implementation.
280 //
281 return FALSE;
282 }
283
284 *EncryptedData = NULL;
285 *EncryptedDataSize = 0;
286 Result = FALSE;
287 TempPointer = NULL;
288 CertData = NULL;
289 Pkey = NULL;
290
291 //
292 // Parse the X509 cert and extract the public key.
293 //
294 TempPointer = PublicKey;
295 CertData = d2i_X509 (&CertData, &TempPointer, (UINT32)PublicKeySize);
296 if (CertData == NULL) {
297 //
298 // Fail to parse X509 cert.
299 //
300 goto _Exit;
301 }
302
303 //
304 // Extract the public key from the x509 cert in a format that
305 // OpenSSL can use.
306 //
307 Pkey = X509_get_pubkey (CertData);
308 if (Pkey == NULL) {
309 //
310 // Fail to extract public key.
311 //
312 goto _Exit;
313 }
314
315 Result = InternalPkcs1v2Encrypt (Pkey, InData, InDataSize, PrngSeed, PrngSeedSize, 0, EncryptedData, EncryptedDataSize);
316
317_Exit:
318 //
319 // Release Resources
320 //
321 if (CertData != NULL) {
322 X509_free (CertData);
323 }
324
325 if (Pkey != NULL) {
326 EVP_PKEY_free (Pkey);
327 }
328
329 return Result;
330}
331
364BOOLEAN
365EFIAPI
367 IN VOID *RsaContext,
368 IN UINT8 *InData,
369 IN UINTN InDataSize,
370 IN CONST UINT8 *PrngSeed OPTIONAL,
371 IN UINTN PrngSeedSize OPTIONAL,
372 IN UINT16 DigestLen OPTIONAL,
373 OUT UINT8 **EncryptedData,
374 OUT UINTN *EncryptedDataSize
375 )
376{
377 BOOLEAN Result;
378 EVP_PKEY *Pkey;
379
380 //
381 // Check input parameters.
382 //
383 if (((RsaContext == NULL) || (InData == NULL)) ||
384 (EncryptedData == NULL) || (EncryptedDataSize == NULL))
385 {
386 return FALSE;
387 }
388
389 *EncryptedData = NULL;
390 *EncryptedDataSize = 0;
391 Result = FALSE;
392 Pkey = NULL;
393
394 Pkey = EVP_PKEY_new ();
395 if (Pkey == NULL) {
396 goto _Exit;
397 }
398
399 if (EVP_PKEY_set1_RSA (Pkey, (RSA *)RsaContext) == 0) {
400 goto _Exit;
401 }
402
403 Result = InternalPkcs1v2Encrypt (Pkey, InData, InDataSize, PrngSeed, PrngSeedSize, DigestLen, EncryptedData, EncryptedDataSize);
404
405_Exit:
406 //
407 // Release Resources
408 //
409 if (Pkey != NULL) {
410 EVP_PKEY_free (Pkey);
411 }
412
413 return Result;
414}
415
442BOOLEAN
443EFIAPI
445 EVP_PKEY *Pkey,
446 IN UINT8 *EncryptedData,
447 IN UINTN EncryptedDataSize,
448 IN UINT16 DigestLen OPTIONAL,
449 OUT UINT8 **OutData,
450 OUT UINTN *OutDataSize
451 )
452{
453 BOOLEAN Result;
454 EVP_PKEY_CTX *PkeyCtx;
455 UINT8 *TempData;
456 UINTN TempDataSize;
457 INTN ReturnCode;
458 CONST EVP_MD *HashAlg;
459
460 //
461 // Check input parameters.
462 //
463 if ((Pkey == NULL) || (EncryptedData == NULL) ||
464 (OutData == NULL) || (OutDataSize == NULL))
465 {
466 return FALSE;
467 }
468
469 Result = FALSE;
470 PkeyCtx = NULL;
471 TempData = NULL;
472 TempDataSize = 0;
473
474 //
475 // Create a context for the decryption operation.
476 //
477 PkeyCtx = EVP_PKEY_CTX_new (Pkey, NULL);
478 if (PkeyCtx == NULL) {
479 //
480 // Fail to create contex.
481 //
482 DEBUG ((DEBUG_ERROR, "[%a] EVP_PKEY_CTK_new() failed\n", __func__));
483 goto _Exit;
484 }
485
486 //
487 // Initialize the context and set the desired padding.
488 //
489 if ((EVP_PKEY_decrypt_init (PkeyCtx) <= 0) ||
490 (EVP_PKEY_CTX_set_rsa_padding (PkeyCtx, RSA_PKCS1_OAEP_PADDING) <= 0))
491 {
492 //
493 // Fail to initialize the context.
494 //
495 DEBUG ((DEBUG_ERROR, "[%a] EVP_PKEY_decrypt_init() failed\n", __func__));
496 goto _Exit;
497 }
498
499 if (DigestLen != 0) {
500 HashAlg = GetEvpMD (DigestLen);
501 if (HashAlg == NULL) {
502 goto _Exit;
503 }
504
505 if (EVP_PKEY_CTX_set_rsa_oaep_md (PkeyCtx, HashAlg) <= 0) {
506 goto _Exit;
507 }
508
509 if (EVP_PKEY_CTX_set_rsa_mgf1_md (PkeyCtx, HashAlg) <= 0) {
510 goto _Exit;
511 }
512 }
513
514 //
515 // Determine the required buffer length for malloc'ing.
516 //
517 ReturnCode = EVP_PKEY_decrypt (PkeyCtx, NULL, &TempDataSize, EncryptedData, EncryptedDataSize);
518 if (ReturnCode <= 0) {
519 //
520 // Fail to determine output buffer size.
521 //
522 DEBUG ((DEBUG_ERROR, "[%a] EVP_PKEY_decrypt() failed to determine output buffer size (rc=%d)\n", __func__, ReturnCode));
523 goto _Exit;
524 }
525
526 //
527 // Allocate a buffer for the output data.
528 //
529 TempData = AllocatePool (TempDataSize);
530 if (TempData == NULL) {
531 //
532 // Fail to allocate the output buffer.
533 //
534 goto _Exit;
535 }
536
537 //
538 // Decrypt Data.
539 //
540 ReturnCode = EVP_PKEY_decrypt (PkeyCtx, TempData, &TempDataSize, EncryptedData, EncryptedDataSize);
541 if (ReturnCode <= 0) {
542 //
543 // Fail to decrypt data, need to free the output buffer.
544 //
545 FreePool (TempData);
546 TempData = NULL;
547 TempDataSize = 0;
548
549 DEBUG ((DEBUG_ERROR, "[%a] EVP_PKEY_decrypt(TempData) failed to decrypt (rc=%d)\n", __func__, ReturnCode));
550 goto _Exit;
551 }
552
553 //
554 // Decrypt done.
555 //
556 *OutData = TempData;
557 *OutDataSize = TempDataSize;
558 Result = TRUE;
559
560_Exit:
561 if (PkeyCtx != NULL) {
562 EVP_PKEY_CTX_free (PkeyCtx);
563 }
564
565 return Result;
566}
567
589BOOLEAN
590EFIAPI
592 IN CONST UINT8 *PrivateKey,
593 IN UINTN PrivateKeySize,
594 IN UINT8 *EncryptedData,
595 IN UINTN EncryptedDataSize,
596 OUT UINT8 **OutData,
597 OUT UINTN *OutDataSize
598 )
599{
600 BOOLEAN Result;
601 EVP_PKEY *Pkey;
602 CONST UINT8 *TempPointer;
603
604 //
605 // Check input parameters.
606 //
607 if ((PrivateKey == NULL) || (EncryptedData == NULL) ||
608 (OutData == NULL) || (OutDataSize == NULL))
609 {
610 return FALSE;
611 }
612
613 Result = FALSE;
614 Pkey = NULL;
615 TempPointer = NULL;
616
617 //
618 // Parse the private key.
619 //
620 TempPointer = PrivateKey;
621 Pkey = d2i_PrivateKey (EVP_PKEY_RSA, &Pkey, &TempPointer, (UINT32)PrivateKeySize);
622 if (Pkey == NULL) {
623 //
624 // Fail to parse private key.
625 //
626 DEBUG ((DEBUG_ERROR, "[%a] d2i_PrivateKey() failed\n", __func__));
627 goto _Exit;
628 }
629
630 Result = InternalPkcs1v2Decrypt (Pkey, EncryptedData, EncryptedDataSize, 0, OutData, OutDataSize);
631
632_Exit:
633 if (Pkey != NULL) {
634 EVP_PKEY_free (Pkey);
635 }
636
637 return Result;
638}
639
667BOOLEAN
668EFIAPI
670 IN VOID *RsaContext,
671 IN UINT8 *EncryptedData,
672 IN UINTN EncryptedDataSize,
673 IN UINT16 DigestLen OPTIONAL,
674 OUT UINT8 **OutData,
675 OUT UINTN *OutDataSize
676 )
677{
678 BOOLEAN Result;
679 EVP_PKEY *Pkey;
680
681 //
682 // Check input parameters.
683 //
684 if ((RsaContext == NULL) || (EncryptedData == NULL) ||
685 (OutData == NULL) || (OutDataSize == NULL))
686 {
687 return FALSE;
688 }
689
690 Result = FALSE;
691 Pkey = NULL;
692
693 //
694 // Create a context for the decryption operation.
695 //
696
697 Pkey = EVP_PKEY_new ();
698 if (Pkey == NULL) {
699 goto _Exit;
700 }
701
702 if (EVP_PKEY_set1_RSA (Pkey, (RSA *)RsaContext) == 0) {
703 goto _Exit;
704 }
705
706 Result = InternalPkcs1v2Decrypt (Pkey, EncryptedData, EncryptedDataSize, DigestLen, OutData, OutDataSize);
707
708_Exit:
709 if (Pkey != NULL) {
710 EVP_PKEY_free (Pkey);
711 }
712
713 return Result;
714}
UINT64 UINTN
INT64 INTN
#define SHA1_DIGEST_SIZE
Definition: BaseCryptLib.h:39
#define SHA512_DIGEST_SIZE
Definition: BaseCryptLib.h:54
#define SHA256_DIGEST_SIZE
Definition: BaseCryptLib.h:44
BOOLEAN EFIAPI RandomSeed(IN CONST UINT8 *Seed OPTIONAL, IN UINTN SeedSize)
Definition: CryptRand.c:36
#define SHA384_DIGEST_SIZE
Definition: BaseCryptLib.h:49
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
BOOLEAN EFIAPI InternalPkcs1v2Decrypt(EVP_PKEY *Pkey, IN UINT8 *EncryptedData, IN UINTN EncryptedDataSize, IN UINT16 DigestLen OPTIONAL, OUT UINT8 **OutData, OUT UINTN *OutDataSize)
BOOLEAN EFIAPI Pkcs1v2Encrypt(IN CONST UINT8 *PublicKey, IN UINTN PublicKeySize, IN UINT8 *InData, IN UINTN InDataSize, IN CONST UINT8 *PrngSeed OPTIONAL, IN UINTN PrngSeedSize OPTIONAL, OUT UINT8 **EncryptedData, OUT UINTN *EncryptedDataSize)
BOOLEAN EFIAPI RsaOaepEncrypt(IN VOID *RsaContext, IN UINT8 *InData, IN UINTN InDataSize, IN CONST UINT8 *PrngSeed OPTIONAL, IN UINTN PrngSeedSize OPTIONAL, IN UINT16 DigestLen OPTIONAL, OUT UINT8 **EncryptedData, OUT UINTN *EncryptedDataSize)
BOOLEAN EFIAPI RsaOaepDecrypt(IN VOID *RsaContext, IN UINT8 *EncryptedData, IN UINTN EncryptedDataSize, IN UINT16 DigestLen OPTIONAL, OUT UINT8 **OutData, OUT UINTN *OutDataSize)
BOOLEAN EFIAPI InternalPkcs1v2Encrypt(EVP_PKEY *Pkey, IN UINT8 *InData, IN UINTN InDataSize, IN CONST UINT8 *PrngSeed OPTIONAL, IN UINTN PrngSeedSize OPTIONAL, IN UINT16 DigestLen OPTIONAL, OUT UINT8 **EncryptedData, OUT UINTN *EncryptedDataSize)
BOOLEAN EFIAPI Pkcs1v2Decrypt(IN CONST UINT8 *PrivateKey, IN UINTN PrivateKeySize, IN UINT8 *EncryptedData, IN UINTN EncryptedDataSize, OUT UINT8 **OutData, OUT UINTN *OutDataSize)
STATIC const EVP_MD * GetEvpMD(IN UINT16 DigestLen)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)