Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2024 DMTF. All rights reserved.
4 : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : **/
6 :
7 : /** @file
8 : * PEM (Privacy Enhanced Mail) format Handler Wrapper Implementation.
9 : **/
10 :
11 : #include "internal_crypt_lib.h"
12 : #include <mbedtls/pem.h>
13 : #include <mbedtls/pk.h>
14 : #include <mbedtls/rsa.h>
15 : #include <mbedtls/ecp.h>
16 : #include <mbedtls/ecdh.h>
17 : #include <mbedtls/ecdsa.h>
18 :
19 0 : static size_t ascii_str_len(const char *string)
20 : {
21 : size_t length;
22 :
23 0 : LIBSPDM_ASSERT(string != NULL);
24 0 : if (string == NULL) {
25 0 : return 0;
26 : }
27 :
28 0 : for (length = 0; *string != '\0'; string++, length++) {
29 : ;
30 : }
31 0 : return length;
32 : }
33 :
34 : #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
35 : /**
36 : * Retrieve the RSA Private key from the password-protected PEM key data.
37 : *
38 : * @param[in] pem_data Pointer to the PEM-encoded key data to be retrieved.
39 : * @param[in] pem_size size of the PEM key data in bytes.
40 : * @param[in] password NULL-terminated passphrase used for encrypted PEM key data.
41 : * @param[out] rsa_context Pointer to newly generated RSA context which contain the retrieved
42 : * RSA private key component. Use libspdm_rsa_free() function to free the
43 : * resource.
44 : *
45 : * If pem_data is NULL, then return false.
46 : * If rsa_context is NULL, then return false.
47 : *
48 : * @retval true RSA Private key was retrieved successfully.
49 : * @retval false Invalid PEM key data or incorrect password.
50 : *
51 : **/
52 36 : bool libspdm_rsa_get_private_key_from_pem(const uint8_t *pem_data,
53 : size_t pem_size,
54 : const char *password,
55 : void **rsa_context)
56 : {
57 : int ret;
58 : mbedtls_pk_context pk;
59 : mbedtls_rsa_context *rsa;
60 : uint8_t *new_pem_data;
61 : size_t password_len;
62 :
63 36 : if (pem_data == NULL || rsa_context == NULL || pem_size > INT_MAX) {
64 0 : return false;
65 : }
66 :
67 36 : new_pem_data = NULL;
68 36 : if (pem_data[pem_size - 1] != 0) {
69 36 : new_pem_data = allocate_pool(pem_size + 1);
70 36 : if (new_pem_data == NULL) {
71 0 : return false;
72 : }
73 36 : libspdm_copy_mem(new_pem_data, pem_size + 1, pem_data, pem_size);
74 36 : new_pem_data[pem_size] = 0;
75 36 : pem_data = new_pem_data;
76 36 : pem_size += 1;
77 : }
78 :
79 36 : mbedtls_pk_init(&pk);
80 :
81 36 : if (password != NULL) {
82 0 : password_len = ascii_str_len(password);
83 : } else {
84 36 : password_len = 0;
85 : }
86 :
87 36 : ret = mbedtls_pk_parse_key(&pk, pem_data, pem_size,
88 : (const uint8_t *)password, password_len,
89 : libspdm_myrand, NULL);
90 :
91 36 : if (new_pem_data != NULL) {
92 36 : free_pool(new_pem_data);
93 36 : new_pem_data = NULL;
94 : }
95 :
96 36 : if (ret != 0) {
97 0 : mbedtls_pk_free(&pk);
98 0 : return false;
99 : }
100 :
101 36 : if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_RSA) {
102 0 : mbedtls_pk_free(&pk);
103 0 : return false;
104 : }
105 :
106 36 : rsa = libspdm_rsa_new();
107 36 : if (rsa == NULL) {
108 0 : return false;
109 : }
110 36 : ret = mbedtls_rsa_copy(rsa, mbedtls_pk_rsa(pk));
111 36 : if (ret != 0) {
112 0 : libspdm_rsa_free(rsa);
113 0 : mbedtls_pk_free(&pk);
114 0 : return false;
115 : }
116 36 : mbedtls_pk_free(&pk);
117 :
118 36 : *rsa_context = rsa;
119 36 : return true;
120 : }
121 : #endif /* (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT) */
122 :
123 : /**
124 : * Retrieve the EC Private key from the password-protected PEM key data.
125 : *
126 : * @param[in] pem_data Pointer to the PEM-encoded key data to be retrieved.
127 : * @param[in] pem_size size of the PEM key data in bytes.
128 : * @param[in] password NULL-terminated passphrase used for encrypted PEM key data.
129 : * @param[out] ec_context Pointer to newly generated EC DSA context which contain the retrieved
130 : * EC private key component. Use libspdm_ec_free() function to free the
131 : * resource.
132 : *
133 : * If pem_data is NULL, then return false.
134 : * If ec_context is NULL, then return false.
135 : *
136 : * @retval true EC Private key was retrieved successfully.
137 : * @retval false Invalid PEM key data or incorrect password.
138 : *
139 : **/
140 145 : bool libspdm_ec_get_private_key_from_pem(const uint8_t *pem_data, size_t pem_size,
141 : const char *password,
142 : void **ec_context)
143 : {
144 : int ret;
145 : mbedtls_pk_context pk;
146 : mbedtls_ecdh_context *ecdh;
147 : uint8_t *new_pem_data;
148 : size_t password_len;
149 :
150 145 : if (pem_data == NULL || ec_context == NULL || pem_size > INT_MAX) {
151 0 : return false;
152 : }
153 :
154 145 : new_pem_data = NULL;
155 145 : if (pem_data[pem_size - 1] != 0) {
156 145 : new_pem_data = allocate_pool(pem_size + 1);
157 145 : if (new_pem_data == NULL) {
158 0 : return false;
159 : }
160 145 : libspdm_copy_mem(new_pem_data, pem_size + 1, pem_data, pem_size);
161 145 : new_pem_data[pem_size] = 0;
162 145 : pem_data = new_pem_data;
163 145 : pem_size += 1;
164 : }
165 :
166 145 : mbedtls_pk_init(&pk);
167 :
168 145 : if (password != NULL) {
169 0 : password_len = ascii_str_len(password);
170 : } else {
171 145 : password_len = 0;
172 : }
173 :
174 145 : ret = mbedtls_pk_parse_key(&pk, pem_data, pem_size,
175 : (const uint8_t *)password, password_len,
176 : libspdm_myrand, NULL);
177 :
178 145 : if (new_pem_data != NULL) {
179 145 : free_pool(new_pem_data);
180 145 : new_pem_data = NULL;
181 : }
182 :
183 145 : if (ret != 0) {
184 0 : mbedtls_pk_free(&pk);
185 0 : return false;
186 : }
187 :
188 145 : if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_ECKEY) {
189 0 : mbedtls_pk_free(&pk);
190 0 : return false;
191 : }
192 :
193 145 : ecdh = allocate_zero_pool(sizeof(mbedtls_ecdh_context));
194 145 : if (ecdh == NULL) {
195 0 : mbedtls_pk_free(&pk);
196 0 : return false;
197 : }
198 145 : mbedtls_ecdh_init(ecdh);
199 :
200 145 : ret = mbedtls_ecdh_get_params(ecdh, mbedtls_pk_ec(pk),
201 : MBEDTLS_ECDH_OURS);
202 145 : if (ret != 0) {
203 0 : mbedtls_ecdh_free(ecdh);
204 0 : free_pool(ecdh);
205 0 : mbedtls_pk_free(&pk);
206 0 : return false;
207 : }
208 145 : mbedtls_pk_free(&pk);
209 :
210 145 : *ec_context = ecdh;
211 145 : return true;
212 : }
213 :
214 : /**
215 : * Retrieve the Ed Private key from the password-protected PEM key data.
216 : *
217 : * @param[in] pem_data Pointer to the PEM-encoded key data to be retrieved.
218 : * @param[in] pem_size size of the PEM key data in bytes.
219 : * @param[in] password NULL-terminated passphrase used for encrypted PEM key data.
220 : * @param[out] ecd_context Pointer to newly generated Ed DSA context which contain the retrieved
221 : * Ed private key component. Use libspdm_ecd_free() function to free the
222 : * resource.
223 : *
224 : * If pem_data is NULL, then return false.
225 : * If ecd_context is NULL, then return false.
226 : *
227 : * @retval true Ed Private key was retrieved successfully.
228 : * @retval false Invalid PEM key data or incorrect password.
229 : *
230 : **/
231 0 : bool libspdm_ecd_get_private_key_from_pem(const uint8_t *pem_data,
232 : size_t pem_size,
233 : const char *password,
234 : void **ecd_context)
235 : {
236 0 : return false;
237 : }
238 :
239 : /**
240 : * Retrieve the sm2 Private key from the password-protected PEM key data.
241 : *
242 : * @param[in] pem_data Pointer to the PEM-encoded key data to be retrieved.
243 : * @param[in] pem_size size of the PEM key data in bytes.
244 : * @param[in] password NULL-terminated passphrase used for encrypted PEM key data.
245 : * @param[out] sm2_context Pointer to newly generated sm2 context which contain the retrieved
246 : * sm2 private key component. Use sm2_free() function to free the
247 : * resource.
248 : *
249 : * If pem_data is NULL, then return false.
250 : * If sm2_context is NULL, then return false.
251 : *
252 : * @retval true sm2 Private key was retrieved successfully.
253 : * @retval false Invalid PEM key data or incorrect password.
254 : *
255 : **/
256 0 : bool libspdm_sm2_get_private_key_from_pem(const uint8_t *pem_data,
257 : size_t pem_size,
258 : const char *password,
259 : void **sm2_context)
260 : {
261 0 : return false;
262 : }
|