]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 - 2020, 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 AES for the encrypted PEM.
86 //
87 if (EVP_add_cipher (EVP_aes_128_cbc ()) == 0) {
88 return FALSE;
89 }
90
91 if (EVP_add_cipher (EVP_aes_192_cbc ()) == 0) {
92 return FALSE;
93 }
94
95 if (EVP_add_cipher (EVP_aes_256_cbc ()) == 0) {
96 return FALSE;
97 }
98
99 Status = FALSE;
100
101 //
102 // Read encrypted PEM Data.
103 //
104 PemBio = BIO_new (BIO_s_mem ());
105 if (PemBio == NULL) {
106 goto _Exit;
107 }
108
109 if (BIO_write (PemBio, PemData, (int)PemSize) <= 0) {
110 goto _Exit;
111 }
112
113 //
114 // Retrieve RSA Private Key from encrypted PEM data.
115 //
116 *RsaContext = PEM_read_bio_RSAPrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password);
117 if (*RsaContext != NULL) {
118 Status = TRUE;
119 }
120
121 _Exit:
122 //
123 // Release Resources.
124 //
125 BIO_free (PemBio);
126
127 return Status;
128 }
129
130 /**
131 Retrieve the EC Private Key from the password-protected PEM key data.
132
133 @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
134 @param[in] PemSize Size of the PEM key data in bytes.
135 @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
136 @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
137 EC private key component. Use EcFree() function to free the
138 resource.
139
140 If PemData is NULL, then return FALSE.
141 If EcContext is NULL, then return FALSE.
142
143 @retval TRUE EC Private Key was retrieved successfully.
144 @retval FALSE Invalid PEM key data or incorrect password.
145
146 **/
147 BOOLEAN
148 EFIAPI
149 EcGetPrivateKeyFromPem (
150 IN CONST UINT8 *PemData,
151 IN UINTN PemSize,
152 IN CONST CHAR8 *Password,
153 OUT VOID **EcContext
154 )
155 {
156 BOOLEAN Status;
157 BIO *PemBio;
158
159 //
160 // Check input parameters.
161 //
162 if ((PemData == NULL) || (EcContext == NULL) || (PemSize > INT_MAX)) {
163 return FALSE;
164 }
165
166 //
167 // Add possible block-cipher descriptor for PEM data decryption.
168 // NOTE: Only support most popular ciphers AES for the encrypted PEM.
169 //
170 if (EVP_add_cipher (EVP_aes_128_cbc ()) == 0) {
171 return FALSE;
172 }
173
174 if (EVP_add_cipher (EVP_aes_192_cbc ()) == 0) {
175 return FALSE;
176 }
177
178 if (EVP_add_cipher (EVP_aes_256_cbc ()) == 0) {
179 return FALSE;
180 }
181
182 Status = FALSE;
183
184 //
185 // Read encrypted PEM Data.
186 //
187 PemBio = BIO_new (BIO_s_mem ());
188 if (PemBio == NULL) {
189 goto _Exit;
190 }
191
192 if (BIO_write (PemBio, PemData, (int)PemSize) <= 0) {
193 goto _Exit;
194 }
195
196 //
197 // Retrieve EC Private Key from encrypted PEM data.
198 //
199 *EcContext = PEM_read_bio_ECPrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password);
200 if (*EcContext != NULL) {
201 Status = TRUE;
202 }
203
204 _Exit:
205 //
206 // Release Resources.
207 //
208 BIO_free (PemBio);
209
210 return Status;
211 }