]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c
75a133bd0ca057afaa848fa9543aad310c6d8c0a
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pem / CryptPem.c
1 /** @file
2 PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over OpenSSL.
3
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "InternalCryptLib.h"
10 #include <openssl/pem.h>
11
12 /**
13 Callback function for password phrase conversion used for retrieving the encrypted PEM.
14
15 @param[out] Buf Pointer to the buffer to write the passphrase to.
16 @param[in] Size Maximum length of the passphrase (i.e. the size of Buf).
17 @param[in] Flag A flag which is set to 0 when reading and 1 when writing.
18 @param[in] Key Key data to be passed to the callback routine.
19
20 @retval The number of characters in the passphrase or 0 if an error occurred.
21
22 **/
23 INTN
24 PasswordCallback (
25 OUT CHAR8 *Buf,
26 IN INTN Size,
27 IN INTN Flag,
28 IN VOID *Key
29 )
30 {
31 INTN KeyLength;
32
33 ZeroMem ((VOID *) Buf, (UINTN) Size);
34 if (Key != NULL) {
35 //
36 // Duplicate key phrase directly.
37 //
38 KeyLength = (INTN) AsciiStrLen ((CHAR8 *)Key);
39 KeyLength = (KeyLength > Size ) ? Size : KeyLength;
40 CopyMem (Buf, Key, (UINTN) KeyLength);
41 return KeyLength;
42 } else {
43 return 0;
44 }
45 }
46
47 /**
48 Retrieve the RSA Private Key from the password-protected PEM key data.
49
50 @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
51 @param[in] PemSize Size of the PEM key data in bytes.
52 @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
53 @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved
54 RSA private key component. Use RsaFree() function to free the
55 resource.
56
57 If PemData is NULL, then return FALSE.
58 If RsaContext is NULL, then return FALSE.
59
60 @retval TRUE RSA Private Key was retrieved successfully.
61 @retval FALSE Invalid PEM key data or incorrect password.
62
63 **/
64 BOOLEAN
65 EFIAPI
66 RsaGetPrivateKeyFromPem (
67 IN CONST UINT8 *PemData,
68 IN UINTN PemSize,
69 IN CONST CHAR8 *Password,
70 OUT VOID **RsaContext
71 )
72 {
73 BOOLEAN Status;
74 BIO *PemBio;
75
76 //
77 // Check input parameters.
78 //
79 if (PemData == NULL || RsaContext == NULL || PemSize > INT_MAX) {
80 return FALSE;
81 }
82
83 //
84 // Add possible block-cipher descriptor for PEM data decryption.
85 // NOTE: Only support most popular ciphers (3DES, AES) for the encrypted PEM.
86 //
87 if (EVP_add_cipher (EVP_des_ede3_cbc ()) == 0) {
88 return FALSE;
89 }
90 if (EVP_add_cipher (EVP_aes_128_cbc ()) == 0) {
91 return FALSE;
92 }
93 if (EVP_add_cipher (EVP_aes_192_cbc ()) == 0) {
94 return FALSE;
95 }
96 if (EVP_add_cipher (EVP_aes_256_cbc ()) == 0) {
97 return FALSE;
98 }
99
100 Status = FALSE;
101
102 //
103 // Read encrypted PEM Data.
104 //
105 PemBio = BIO_new (BIO_s_mem ());
106 if (PemBio == NULL) {
107 goto _Exit;
108 }
109
110 if (BIO_write (PemBio, PemData, (int) PemSize) <= 0) {
111 goto _Exit;
112 }
113
114 //
115 // Retrieve RSA Private Key from encrypted PEM data.
116 //
117 *RsaContext = PEM_read_bio_RSAPrivateKey (PemBio, NULL, (pem_password_cb *) &PasswordCallback, (void *) Password);
118 if (*RsaContext != NULL) {
119 Status = TRUE;
120 }
121
122 _Exit:
123 //
124 // Release Resources.
125 //
126 BIO_free (PemBio);
127
128 return Status;
129 }