/src/libspdm/os_stub/cryptlib_mbedtls/pem/pem.c
Line | Count | Source |
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 | | static size_t ascii_str_len(const char *string) |
20 | 0 | { |
21 | 0 | size_t length; |
22 | |
|
23 | 0 | LIBSPDM_ASSERT(string != NULL); |
24 | 0 | if (string == NULL) { |
25 | 0 | return 0; |
26 | 0 | } |
27 | | |
28 | 0 | for (length = 0; *string != '\0'; string++, length++) { |
29 | 0 | ; |
30 | 0 | } |
31 | 0 | return length; |
32 | 0 | } |
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 | | 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 | 152 | { |
57 | 152 | int ret; |
58 | 152 | mbedtls_pk_context pk; |
59 | 152 | mbedtls_rsa_context *rsa; |
60 | 152 | uint8_t *new_pem_data; |
61 | 152 | size_t password_len; |
62 | | |
63 | 152 | if (pem_data == NULL || rsa_context == NULL || pem_size > INT_MAX) { |
64 | 0 | return false; |
65 | 0 | } |
66 | | |
67 | 152 | new_pem_data = NULL; |
68 | 152 | if (pem_data[pem_size - 1] != 0) { |
69 | 152 | new_pem_data = allocate_pool(pem_size + 1); |
70 | 152 | if (new_pem_data == NULL) { |
71 | 0 | return false; |
72 | 0 | } |
73 | 152 | libspdm_copy_mem(new_pem_data, pem_size + 1, pem_data, pem_size); |
74 | 152 | new_pem_data[pem_size] = 0; |
75 | 152 | pem_data = new_pem_data; |
76 | 152 | pem_size += 1; |
77 | 152 | } |
78 | | |
79 | 152 | mbedtls_pk_init(&pk); |
80 | | |
81 | 152 | if (password != NULL) { |
82 | 0 | password_len = ascii_str_len(password); |
83 | 152 | } else { |
84 | 152 | password_len = 0; |
85 | 152 | } |
86 | | |
87 | 152 | ret = mbedtls_pk_parse_key(&pk, pem_data, pem_size, |
88 | 152 | (const uint8_t *)password, password_len, |
89 | 152 | libspdm_myrand, NULL); |
90 | | |
91 | 152 | if (new_pem_data != NULL) { |
92 | 152 | free_pool(new_pem_data); |
93 | 152 | new_pem_data = NULL; |
94 | 152 | } |
95 | | |
96 | 152 | if (ret != 0) { |
97 | 0 | mbedtls_pk_free(&pk); |
98 | 0 | return false; |
99 | 0 | } |
100 | | |
101 | 152 | if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_RSA) { |
102 | 0 | mbedtls_pk_free(&pk); |
103 | 0 | return false; |
104 | 0 | } |
105 | | |
106 | 152 | rsa = libspdm_rsa_new(); |
107 | 152 | if (rsa == NULL) { |
108 | 0 | return false; |
109 | 0 | } |
110 | 152 | ret = mbedtls_rsa_copy(rsa, mbedtls_pk_rsa(pk)); |
111 | 152 | if (ret != 0) { |
112 | 0 | libspdm_rsa_free(rsa); |
113 | 0 | mbedtls_pk_free(&pk); |
114 | 0 | return false; |
115 | 0 | } |
116 | 152 | mbedtls_pk_free(&pk); |
117 | | |
118 | 152 | *rsa_context = rsa; |
119 | 152 | return true; |
120 | 152 | } |
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 | | 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 | 232 | { |
144 | 232 | int ret; |
145 | 232 | mbedtls_pk_context pk; |
146 | 232 | mbedtls_ecdh_context *ecdh; |
147 | 232 | uint8_t *new_pem_data; |
148 | 232 | size_t password_len; |
149 | | |
150 | 232 | if (pem_data == NULL || ec_context == NULL || pem_size > INT_MAX) { |
151 | 0 | return false; |
152 | 0 | } |
153 | | |
154 | 232 | new_pem_data = NULL; |
155 | 232 | if (pem_data[pem_size - 1] != 0) { |
156 | 232 | new_pem_data = allocate_pool(pem_size + 1); |
157 | 232 | if (new_pem_data == NULL) { |
158 | 0 | return false; |
159 | 0 | } |
160 | 232 | libspdm_copy_mem(new_pem_data, pem_size + 1, pem_data, pem_size); |
161 | 232 | new_pem_data[pem_size] = 0; |
162 | 232 | pem_data = new_pem_data; |
163 | 232 | pem_size += 1; |
164 | 232 | } |
165 | | |
166 | 232 | mbedtls_pk_init(&pk); |
167 | | |
168 | 232 | if (password != NULL) { |
169 | 0 | password_len = ascii_str_len(password); |
170 | 232 | } else { |
171 | 232 | password_len = 0; |
172 | 232 | } |
173 | | |
174 | 232 | ret = mbedtls_pk_parse_key(&pk, pem_data, pem_size, |
175 | 232 | (const uint8_t *)password, password_len, |
176 | 232 | libspdm_myrand, NULL); |
177 | | |
178 | 232 | if (new_pem_data != NULL) { |
179 | 232 | free_pool(new_pem_data); |
180 | 232 | new_pem_data = NULL; |
181 | 232 | } |
182 | | |
183 | 232 | if (ret != 0) { |
184 | 0 | mbedtls_pk_free(&pk); |
185 | 0 | return false; |
186 | 0 | } |
187 | | |
188 | 232 | if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_ECKEY) { |
189 | 0 | mbedtls_pk_free(&pk); |
190 | 0 | return false; |
191 | 0 | } |
192 | | |
193 | 232 | ecdh = allocate_zero_pool(sizeof(mbedtls_ecdh_context)); |
194 | 232 | if (ecdh == NULL) { |
195 | 0 | mbedtls_pk_free(&pk); |
196 | 0 | return false; |
197 | 0 | } |
198 | 232 | mbedtls_ecdh_init(ecdh); |
199 | | |
200 | 232 | ret = mbedtls_ecdh_get_params(ecdh, mbedtls_pk_ec(pk), |
201 | 232 | MBEDTLS_ECDH_OURS); |
202 | 232 | 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 | 0 | } |
208 | 232 | mbedtls_pk_free(&pk); |
209 | | |
210 | 232 | *ec_context = ecdh; |
211 | 232 | return true; |
212 | 232 | } |
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 | | 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 | 0 | { |
236 | 0 | return false; |
237 | 0 | } |
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 | | 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 | 0 | { |
261 | | return false; |
262 | 0 | } |