/work/mbedtls-2.28.8/library/pkwrite.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Public Key layer for writing key files and structures |
3 | | * |
4 | | * Copyright The Mbed TLS Contributors |
5 | | * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later |
6 | | */ |
7 | | |
8 | | #include "common.h" |
9 | | |
10 | | #if defined(MBEDTLS_PK_WRITE_C) |
11 | | |
12 | | #include "mbedtls/pk.h" |
13 | | #include "mbedtls/asn1write.h" |
14 | | #include "mbedtls/oid.h" |
15 | | #include "mbedtls/platform_util.h" |
16 | | #include "mbedtls/error.h" |
17 | | |
18 | | #include <string.h> |
19 | | |
20 | | #if defined(MBEDTLS_RSA_C) |
21 | | #include "mbedtls/rsa.h" |
22 | | #endif |
23 | | #if defined(MBEDTLS_ECP_C) |
24 | | #include "mbedtls/bignum.h" |
25 | | #include "mbedtls/ecp.h" |
26 | | #include "mbedtls/platform_util.h" |
27 | | #endif |
28 | | #if defined(MBEDTLS_ECDSA_C) |
29 | | #include "mbedtls/ecdsa.h" |
30 | | #endif |
31 | | #if defined(MBEDTLS_PEM_WRITE_C) |
32 | | #include "mbedtls/pem.h" |
33 | | #endif |
34 | | |
35 | | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
36 | | #include "psa/crypto.h" |
37 | | #include "mbedtls/psa_util.h" |
38 | | #endif |
39 | | #include "mbedtls/platform.h" |
40 | | |
41 | | /* Parameter validation macros based on platform_util.h */ |
42 | | #define PK_VALIDATE_RET(cond) \ |
43 | 0 | MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA) |
44 | | #define PK_VALIDATE(cond) \ |
45 | | MBEDTLS_INTERNAL_VALIDATE(cond) |
46 | | |
47 | | #if defined(MBEDTLS_RSA_C) |
48 | | /* |
49 | | * RSAPublicKey ::= SEQUENCE { |
50 | | * modulus INTEGER, -- n |
51 | | * publicExponent INTEGER -- e |
52 | | * } |
53 | | */ |
54 | | static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start, |
55 | | mbedtls_rsa_context *rsa) |
56 | 0 | { |
57 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
58 | 0 | size_t len = 0; |
59 | 0 | mbedtls_mpi T; |
60 | |
|
61 | 0 | mbedtls_mpi_init(&T); |
62 | | |
63 | | /* Export E */ |
64 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || |
65 | 0 | (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { |
66 | 0 | goto end_of_export; |
67 | 0 | } |
68 | 0 | len += ret; |
69 | | |
70 | | /* Export N */ |
71 | 0 | if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || |
72 | 0 | (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { |
73 | 0 | goto end_of_export; |
74 | 0 | } |
75 | 0 | len += ret; |
76 | |
|
77 | 0 | end_of_export: |
78 | |
|
79 | 0 | mbedtls_mpi_free(&T); |
80 | 0 | if (ret < 0) { |
81 | 0 | return ret; |
82 | 0 | } |
83 | | |
84 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); |
85 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | |
86 | 0 | MBEDTLS_ASN1_SEQUENCE)); |
87 | | |
88 | 0 | return (int) len; |
89 | 0 | } |
90 | | #endif /* MBEDTLS_RSA_C */ |
91 | | |
92 | | #if defined(MBEDTLS_ECP_C) |
93 | | /* |
94 | | * EC public key is an EC point |
95 | | */ |
96 | | static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, |
97 | | mbedtls_ecp_keypair *ec) |
98 | 0 | { |
99 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
100 | 0 | size_t len = 0; |
101 | 0 | unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; |
102 | |
|
103 | 0 | if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, |
104 | 0 | MBEDTLS_ECP_PF_UNCOMPRESSED, |
105 | 0 | &len, buf, sizeof(buf))) != 0) { |
106 | 0 | return ret; |
107 | 0 | } |
108 | | |
109 | 0 | if (*p < start || (size_t) (*p - start) < len) { |
110 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
111 | 0 | } |
112 | | |
113 | 0 | *p -= len; |
114 | 0 | memcpy(*p, buf, len); |
115 | |
|
116 | 0 | return (int) len; |
117 | 0 | } |
118 | | |
119 | | /* |
120 | | * ECParameters ::= CHOICE { |
121 | | * namedCurve OBJECT IDENTIFIER |
122 | | * } |
123 | | */ |
124 | | static int pk_write_ec_param(unsigned char **p, unsigned char *start, |
125 | | mbedtls_ecp_keypair *ec) |
126 | 0 | { |
127 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
128 | 0 | size_t len = 0; |
129 | 0 | const char *oid; |
130 | 0 | size_t oid_len; |
131 | |
|
132 | 0 | if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) { |
133 | 0 | return ret; |
134 | 0 | } |
135 | | |
136 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); |
137 | | |
138 | 0 | return (int) len; |
139 | 0 | } |
140 | | |
141 | | /* |
142 | | * privateKey OCTET STRING -- always of length ceil(log2(n)/8) |
143 | | */ |
144 | | static int pk_write_ec_private(unsigned char **p, unsigned char *start, |
145 | | mbedtls_ecp_keypair *ec) |
146 | 0 | { |
147 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
148 | 0 | size_t byte_length = (ec->grp.pbits + 7) / 8; |
149 | 0 | unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; |
150 | |
|
151 | 0 | ret = mbedtls_ecp_write_key(ec, tmp, byte_length); |
152 | 0 | if (ret != 0) { |
153 | 0 | goto exit; |
154 | 0 | } |
155 | 0 | ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); |
156 | |
|
157 | 0 | exit: |
158 | 0 | mbedtls_platform_zeroize(tmp, byte_length); |
159 | 0 | return ret; |
160 | 0 | } |
161 | | #endif /* MBEDTLS_ECP_C */ |
162 | | |
163 | | int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, |
164 | | const mbedtls_pk_context *key) |
165 | 0 | { |
166 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
167 | 0 | size_t len = 0; |
168 | |
|
169 | 0 | (void) p; |
170 | 0 | (void) start; |
171 | 0 | (void) key; |
172 | 0 | (void) ret; |
173 | |
|
174 | 0 | PK_VALIDATE_RET(p != NULL); |
175 | 0 | PK_VALIDATE_RET(*p != NULL); |
176 | 0 | PK_VALIDATE_RET(start != NULL); |
177 | 0 | PK_VALIDATE_RET(key != NULL); |
178 | |
|
179 | 0 | #if defined(MBEDTLS_RSA_C) |
180 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { |
181 | 0 | MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key))); |
182 | 0 | } else |
183 | 0 | #endif |
184 | 0 | #if defined(MBEDTLS_ECP_C) |
185 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { |
186 | 0 | MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key))); |
187 | 0 | } else |
188 | 0 | #endif |
189 | | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
190 | | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { |
191 | | size_t buffer_size; |
192 | | psa_key_id_t *key_id = (psa_key_id_t *) key->pk_ctx; |
193 | | |
194 | | if (*p < start) { |
195 | | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
196 | | } |
197 | | |
198 | | buffer_size = (size_t) (*p - start); |
199 | | if (psa_export_public_key(*key_id, start, buffer_size, &len) |
200 | | != PSA_SUCCESS) { |
201 | | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
202 | | } else { |
203 | | *p -= len; |
204 | | memmove(*p, start, len); |
205 | | } |
206 | | } else |
207 | | #endif /* MBEDTLS_USE_PSA_CRYPTO */ |
208 | 0 | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
209 | | |
210 | 0 | return (int) len; |
211 | 0 | } |
212 | | |
213 | | int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *key, unsigned char *buf, size_t size) |
214 | 0 | { |
215 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
216 | 0 | unsigned char *c; |
217 | 0 | size_t len = 0, par_len = 0, oid_len; |
218 | 0 | mbedtls_pk_type_t pk_type; |
219 | 0 | const char *oid; |
220 | |
|
221 | 0 | PK_VALIDATE_RET(key != NULL); |
222 | 0 | if (size == 0) { |
223 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
224 | 0 | } |
225 | 0 | PK_VALIDATE_RET(buf != NULL); |
226 | |
|
227 | 0 | c = buf + size; |
228 | |
|
229 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key)); |
230 | | |
231 | 0 | if (c - buf < 1) { |
232 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
233 | 0 | } |
234 | | |
235 | | /* |
236 | | * SubjectPublicKeyInfo ::= SEQUENCE { |
237 | | * algorithm AlgorithmIdentifier, |
238 | | * subjectPublicKey BIT STRING } |
239 | | */ |
240 | 0 | *--c = 0; |
241 | 0 | len += 1; |
242 | |
|
243 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
244 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); |
245 | | |
246 | 0 | pk_type = mbedtls_pk_get_type(key); |
247 | 0 | #if defined(MBEDTLS_ECP_C) |
248 | 0 | if (pk_type == MBEDTLS_PK_ECKEY) { |
249 | 0 | MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key))); |
250 | 0 | } |
251 | 0 | #endif |
252 | | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
253 | | if (pk_type == MBEDTLS_PK_OPAQUE) { |
254 | | psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
255 | | psa_key_type_t key_type; |
256 | | psa_key_id_t key_id; |
257 | | psa_ecc_family_t curve; |
258 | | size_t bits; |
259 | | |
260 | | key_id = *((psa_key_id_t *) key->pk_ctx); |
261 | | if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) { |
262 | | return MBEDTLS_ERR_PK_HW_ACCEL_FAILED; |
263 | | } |
264 | | key_type = psa_get_key_type(&attributes); |
265 | | bits = psa_get_key_bits(&attributes); |
266 | | psa_reset_key_attributes(&attributes); |
267 | | |
268 | | curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type); |
269 | | if (curve == 0) { |
270 | | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
271 | | } |
272 | | |
273 | | ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits, &oid, &oid_len); |
274 | | if (ret != 0) { |
275 | | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
276 | | } |
277 | | |
278 | | /* Write EC algorithm parameters; that's akin |
279 | | * to pk_write_ec_param() above. */ |
280 | | MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_oid(&c, buf, |
281 | | oid, oid_len)); |
282 | | |
283 | | /* The rest of the function works as for legacy EC contexts. */ |
284 | | pk_type = MBEDTLS_PK_ECKEY; |
285 | | } |
286 | | #endif /* MBEDTLS_USE_PSA_CRYPTO */ |
287 | | |
288 | 0 | if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, |
289 | 0 | &oid_len)) != 0) { |
290 | 0 | return ret; |
291 | 0 | } |
292 | | |
293 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len, |
294 | 0 | par_len)); |
295 | | |
296 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
297 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | |
298 | 0 | MBEDTLS_ASN1_SEQUENCE)); |
299 | | |
300 | 0 | return (int) len; |
301 | 0 | } |
302 | | |
303 | | int mbedtls_pk_write_key_der(mbedtls_pk_context *key, unsigned char *buf, size_t size) |
304 | 0 | { |
305 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
306 | 0 | unsigned char *c; |
307 | 0 | size_t len = 0; |
308 | |
|
309 | 0 | (void) ret; |
310 | 0 | (void) c; |
311 | 0 | (void) key; |
312 | |
|
313 | 0 | PK_VALIDATE_RET(key != NULL); |
314 | 0 | if (size == 0) { |
315 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
316 | 0 | } |
317 | 0 | PK_VALIDATE_RET(buf != NULL); |
318 | |
|
319 | 0 | c = buf + size; |
320 | |
|
321 | 0 | #if defined(MBEDTLS_RSA_C) |
322 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { |
323 | 0 | mbedtls_mpi T; /* Temporary holding the exported parameters */ |
324 | 0 | mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key); |
325 | | |
326 | | /* |
327 | | * Export the parameters one after another to avoid simultaneous copies. |
328 | | */ |
329 | |
|
330 | 0 | mbedtls_mpi_init(&T); |
331 | | |
332 | | /* Export QP */ |
333 | 0 | if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || |
334 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
335 | 0 | goto end_of_export; |
336 | 0 | } |
337 | 0 | len += ret; |
338 | | |
339 | | /* Export DQ */ |
340 | 0 | if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || |
341 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
342 | 0 | goto end_of_export; |
343 | 0 | } |
344 | 0 | len += ret; |
345 | | |
346 | | /* Export DP */ |
347 | 0 | if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || |
348 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
349 | 0 | goto end_of_export; |
350 | 0 | } |
351 | 0 | len += ret; |
352 | | |
353 | | /* Export Q */ |
354 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, |
355 | 0 | &T, NULL, NULL)) != 0 || |
356 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
357 | 0 | goto end_of_export; |
358 | 0 | } |
359 | 0 | len += ret; |
360 | | |
361 | | /* Export P */ |
362 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, &T, |
363 | 0 | NULL, NULL, NULL)) != 0 || |
364 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
365 | 0 | goto end_of_export; |
366 | 0 | } |
367 | 0 | len += ret; |
368 | | |
369 | | /* Export D */ |
370 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, |
371 | 0 | NULL, &T, NULL)) != 0 || |
372 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
373 | 0 | goto end_of_export; |
374 | 0 | } |
375 | 0 | len += ret; |
376 | | |
377 | | /* Export E */ |
378 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, |
379 | 0 | NULL, NULL, &T)) != 0 || |
380 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
381 | 0 | goto end_of_export; |
382 | 0 | } |
383 | 0 | len += ret; |
384 | | |
385 | | /* Export N */ |
386 | 0 | if ((ret = mbedtls_rsa_export(rsa, &T, NULL, |
387 | 0 | NULL, NULL, NULL)) != 0 || |
388 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
389 | 0 | goto end_of_export; |
390 | 0 | } |
391 | 0 | len += ret; |
392 | |
|
393 | 0 | end_of_export: |
394 | |
|
395 | 0 | mbedtls_mpi_free(&T); |
396 | 0 | if (ret < 0) { |
397 | 0 | return ret; |
398 | 0 | } |
399 | | |
400 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); |
401 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
402 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, |
403 | 0 | buf, MBEDTLS_ASN1_CONSTRUCTED | |
404 | 0 | MBEDTLS_ASN1_SEQUENCE)); |
405 | 0 | } else |
406 | 0 | #endif /* MBEDTLS_RSA_C */ |
407 | 0 | #if defined(MBEDTLS_ECP_C) |
408 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { |
409 | 0 | mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key); |
410 | 0 | size_t pub_len = 0, par_len = 0; |
411 | | |
412 | | /* |
413 | | * RFC 5915, or SEC1 Appendix C.4 |
414 | | * |
415 | | * ECPrivateKey ::= SEQUENCE { |
416 | | * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), |
417 | | * privateKey OCTET STRING, |
418 | | * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, |
419 | | * publicKey [1] BIT STRING OPTIONAL |
420 | | * } |
421 | | */ |
422 | | |
423 | | /* publicKey */ |
424 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, ec)); |
425 | | |
426 | 0 | if (c - buf < 1) { |
427 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
428 | 0 | } |
429 | 0 | *--c = 0; |
430 | 0 | pub_len += 1; |
431 | |
|
432 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len)); |
433 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); |
434 | | |
435 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len)); |
436 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, |
437 | 0 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | |
438 | 0 | MBEDTLS_ASN1_CONSTRUCTED | 1)); |
439 | 0 | len += pub_len; |
440 | | |
441 | | /* parameters */ |
442 | 0 | MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec)); |
443 | | |
444 | 0 | MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len)); |
445 | 0 | MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(&c, buf, |
446 | 0 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | |
447 | 0 | MBEDTLS_ASN1_CONSTRUCTED | 0)); |
448 | 0 | len += par_len; |
449 | | |
450 | | /* privateKey */ |
451 | 0 | MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(&c, buf, ec)); |
452 | | |
453 | | /* version */ |
454 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1)); |
455 | | |
456 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
457 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | |
458 | 0 | MBEDTLS_ASN1_SEQUENCE)); |
459 | 0 | } else |
460 | 0 | #endif /* MBEDTLS_ECP_C */ |
461 | 0 | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
462 | | |
463 | 0 | return (int) len; |
464 | 0 | } |
465 | | |
466 | | #if defined(MBEDTLS_PEM_WRITE_C) |
467 | | |
468 | 0 | #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" |
469 | 0 | #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" |
470 | | |
471 | 0 | #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" |
472 | 0 | #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" |
473 | 0 | #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" |
474 | 0 | #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" |
475 | | |
476 | | /* |
477 | | * Max sizes of key per types. Shown as tag + len (+ content). |
478 | | */ |
479 | | |
480 | | #if defined(MBEDTLS_RSA_C) |
481 | | /* |
482 | | * RSA public keys: |
483 | | * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 |
484 | | * algorithm AlgorithmIdentifier, 1 + 1 (sequence) |
485 | | * + 1 + 1 + 9 (rsa oid) |
486 | | * + 1 + 1 (params null) |
487 | | * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) |
488 | | * RSAPublicKey ::= SEQUENCE { 1 + 3 |
489 | | * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 |
490 | | * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 |
491 | | * } |
492 | | */ |
493 | 0 | #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) |
494 | | |
495 | | /* |
496 | | * RSA private keys: |
497 | | * RSAPrivateKey ::= SEQUENCE { 1 + 3 |
498 | | * version Version, 1 + 1 + 1 |
499 | | * modulus INTEGER, 1 + 3 + MPI_MAX + 1 |
500 | | * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 |
501 | | * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 |
502 | | * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
503 | | * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
504 | | * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
505 | | * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
506 | | * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
507 | | * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) |
508 | | * } |
509 | | */ |
510 | 0 | #define MPI_MAX_SIZE_2 (MBEDTLS_MPI_MAX_SIZE / 2 + \ |
511 | 0 | MBEDTLS_MPI_MAX_SIZE % 2) |
512 | 0 | #define RSA_PRV_DER_MAX_BYTES (47 + 3 * MBEDTLS_MPI_MAX_SIZE \ |
513 | 0 | + 5 * MPI_MAX_SIZE_2) |
514 | | |
515 | | #else /* MBEDTLS_RSA_C */ |
516 | | |
517 | | #define RSA_PUB_DER_MAX_BYTES 0 |
518 | | #define RSA_PRV_DER_MAX_BYTES 0 |
519 | | |
520 | | #endif /* MBEDTLS_RSA_C */ |
521 | | |
522 | | #if defined(MBEDTLS_ECP_C) |
523 | | /* |
524 | | * EC public keys: |
525 | | * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 |
526 | | * algorithm AlgorithmIdentifier, 1 + 1 (sequence) |
527 | | * + 1 + 1 + 7 (ec oid) |
528 | | * + 1 + 1 + 9 (namedCurve oid) |
529 | | * subjectPublicKey BIT STRING 1 + 2 + 1 [1] |
530 | | * + 1 (point format) [1] |
531 | | * + 2 * ECP_MAX (coords) [1] |
532 | | * } |
533 | | */ |
534 | 0 | #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) |
535 | | |
536 | | /* |
537 | | * EC private keys: |
538 | | * ECPrivateKey ::= SEQUENCE { 1 + 2 |
539 | | * version INTEGER , 1 + 1 + 1 |
540 | | * privateKey OCTET STRING, 1 + 1 + ECP_MAX |
541 | | * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) |
542 | | * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above |
543 | | * } |
544 | | */ |
545 | 0 | #define ECP_PRV_DER_MAX_BYTES (29 + 3 * MBEDTLS_ECP_MAX_BYTES) |
546 | | |
547 | | #else /* MBEDTLS_ECP_C */ |
548 | | |
549 | | #define ECP_PUB_DER_MAX_BYTES 0 |
550 | | #define ECP_PRV_DER_MAX_BYTES 0 |
551 | | |
552 | | #endif /* MBEDTLS_ECP_C */ |
553 | | |
554 | 0 | #define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ |
555 | 0 | RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) |
556 | 0 | #define PRV_DER_MAX_BYTES (RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ |
557 | 0 | RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES) |
558 | | |
559 | | int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size) |
560 | 0 | { |
561 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
562 | 0 | unsigned char *output_buf = NULL; |
563 | 0 | output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES); |
564 | 0 | if (output_buf == NULL) { |
565 | 0 | return MBEDTLS_ERR_PK_ALLOC_FAILED; |
566 | 0 | } |
567 | 0 | size_t olen = 0; |
568 | |
|
569 | 0 | PK_VALIDATE_RET(key != NULL); |
570 | 0 | PK_VALIDATE_RET(buf != NULL || size == 0); |
571 | |
|
572 | 0 | if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, |
573 | 0 | PUB_DER_MAX_BYTES)) < 0) { |
574 | 0 | goto cleanup; |
575 | 0 | } |
576 | | |
577 | 0 | if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, |
578 | 0 | output_buf + PUB_DER_MAX_BYTES - ret, |
579 | 0 | ret, buf, size, &olen)) != 0) { |
580 | 0 | goto cleanup; |
581 | 0 | } |
582 | | |
583 | 0 | ret = 0; |
584 | 0 | cleanup: |
585 | 0 | mbedtls_free(output_buf); |
586 | 0 | return ret; |
587 | 0 | } |
588 | | |
589 | | int mbedtls_pk_write_key_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size) |
590 | 0 | { |
591 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
592 | 0 | unsigned char *output_buf = NULL; |
593 | 0 | output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES); |
594 | 0 | if (output_buf == NULL) { |
595 | 0 | return MBEDTLS_ERR_PK_ALLOC_FAILED; |
596 | 0 | } |
597 | 0 | const char *begin, *end; |
598 | 0 | size_t olen = 0; |
599 | |
|
600 | 0 | PK_VALIDATE_RET(key != NULL); |
601 | 0 | PK_VALIDATE_RET(buf != NULL || size == 0); |
602 | |
|
603 | 0 | if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) { |
604 | 0 | goto cleanup; |
605 | 0 | } |
606 | | |
607 | 0 | #if defined(MBEDTLS_RSA_C) |
608 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { |
609 | 0 | begin = PEM_BEGIN_PRIVATE_KEY_RSA; |
610 | 0 | end = PEM_END_PRIVATE_KEY_RSA; |
611 | 0 | } else |
612 | 0 | #endif |
613 | 0 | #if defined(MBEDTLS_ECP_C) |
614 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { |
615 | 0 | begin = PEM_BEGIN_PRIVATE_KEY_EC; |
616 | 0 | end = PEM_END_PRIVATE_KEY_EC; |
617 | 0 | } else |
618 | 0 | #endif |
619 | 0 | { |
620 | 0 | ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
621 | 0 | goto cleanup; |
622 | 0 | } |
623 | | |
624 | 0 | if ((ret = mbedtls_pem_write_buffer(begin, end, |
625 | 0 | output_buf + PRV_DER_MAX_BYTES - ret, |
626 | 0 | ret, buf, size, &olen)) != 0) { |
627 | 0 | goto cleanup; |
628 | 0 | } |
629 | | |
630 | 0 | ret = 0; |
631 | 0 | cleanup: |
632 | 0 | mbedtls_platform_zeroize(output_buf, PRV_DER_MAX_BYTES); |
633 | 0 | mbedtls_free(output_buf); |
634 | 0 | return ret; |
635 | 0 | } |
636 | | #endif /* MBEDTLS_PEM_WRITE_C */ |
637 | | |
638 | | #endif /* MBEDTLS_PK_WRITE_C */ |