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 #include "pk_internal.h"
18
19 #include <string.h>
20
21 #if defined(MBEDTLS_RSA_C)
22 #include "mbedtls/rsa.h"
23 #endif
24 #if defined(MBEDTLS_ECP_C)
25 #include "mbedtls/bignum.h"
26 #include "mbedtls/ecp.h"
27 #include "mbedtls/platform_util.h"
28 #endif
29 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
30 #include "pk_internal.h"
31 #endif
32 #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
33 #include "pkwrite.h"
34 #endif
35 #if defined(MBEDTLS_ECDSA_C)
36 #include "mbedtls/ecdsa.h"
37 #endif
38 #if defined(MBEDTLS_PEM_WRITE_C)
39 #include "mbedtls/pem.h"
40 #endif
41
42 #if defined(MBEDTLS_USE_PSA_CRYPTO)
43 #include "psa/crypto.h"
44 #include "psa_util_internal.h"
45 #endif
46 #include "mbedtls/platform.h"
47
48 /* Helper for Montgomery curves */
49 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
50 #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
mbedtls_pk_is_rfc8410(const mbedtls_pk_context * pk)51 static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk)
52 {
53 mbedtls_ecp_group_id id = mbedtls_pk_get_group_id(pk);
54
55 #if defined(MBEDTLS_ECP_HAVE_CURVE25519)
56 if (id == MBEDTLS_ECP_DP_CURVE25519) {
57 return 1;
58 }
59 #endif
60 #if defined(MBEDTLS_ECP_HAVE_CURVE448)
61 if (id == MBEDTLS_ECP_DP_CURVE448) {
62 return 1;
63 }
64 #endif
65 return 0;
66 }
67
68 #if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PEM_WRITE_C)
69 /* It is assumed that the input key is opaque */
pk_get_opaque_ec_family(const mbedtls_pk_context * pk)70 static psa_ecc_family_t pk_get_opaque_ec_family(const mbedtls_pk_context *pk)
71 {
72 psa_ecc_family_t ec_family = 0;
73 psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
74
75 if (psa_get_key_attributes(pk->priv_id, &key_attrs) != PSA_SUCCESS) {
76 return 0;
77 }
78 ec_family = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attrs));
79 psa_reset_key_attributes(&key_attrs);
80
81 return ec_family;
82 }
83 #endif /* MBETLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C */
84 #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
85 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
86
87 #if defined(MBEDTLS_USE_PSA_CRYPTO)
88 /* It is assumed that the input key is opaque */
pk_get_opaque_key_type(const mbedtls_pk_context * pk)89 static psa_key_type_t pk_get_opaque_key_type(const mbedtls_pk_context *pk)
90 {
91 psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
92 psa_key_type_t opaque_key_type;
93
94 if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
95 return 0;
96 }
97 opaque_key_type = psa_get_key_type(&opaque_attrs);
98 psa_reset_key_attributes(&opaque_attrs);
99
100 return opaque_key_type;
101 }
102 #endif /* MBETLS_USE_PSA_CRYPTO */
103
104 #if defined(MBEDTLS_RSA_C)
105 /*
106 * RSAPublicKey ::= SEQUENCE {
107 * modulus INTEGER, -- n
108 * publicExponent INTEGER -- e
109 * }
110 */
pk_write_rsa_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)111 static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
112 const mbedtls_pk_context *pk)
113 {
114 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
115 size_t len = 0;
116 mbedtls_mpi T;
117 mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
118
119 mbedtls_mpi_init(&T);
120
121 /* Export E */
122 if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
123 (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
124 goto end_of_export;
125 }
126 len += ret;
127
128 /* Export N */
129 if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
130 (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
131 goto end_of_export;
132 }
133 len += ret;
134
135 end_of_export:
136
137 mbedtls_mpi_free(&T);
138 if (ret < 0) {
139 return ret;
140 }
141
142 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
143 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
144 MBEDTLS_ASN1_SEQUENCE));
145
146 return (int) len;
147 }
148 #endif /* MBEDTLS_RSA_C */
149
150 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
151 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
pk_write_ec_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)152 static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
153 const mbedtls_pk_context *pk)
154 {
155 size_t len = 0;
156 uint8_t buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
157
158 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
159 if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
160 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
161 }
162 } else {
163 len = pk->pub_raw_len;
164 memcpy(buf, pk->pub_raw, len);
165 }
166
167 if (*p < start || (size_t) (*p - start) < len) {
168 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
169 }
170
171 *p -= len;
172 memcpy(*p, buf, len);
173
174 return (int) len;
175 }
176 #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
pk_write_ec_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)177 static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
178 const mbedtls_pk_context *pk)
179 {
180 size_t len = 0;
181 #if defined(MBEDTLS_USE_PSA_CRYPTO)
182 uint8_t buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
183 #else
184 unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
185 #endif /* MBEDTLS_USE_PSA_CRYPTO */
186 mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
187 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
188
189 #if defined(MBEDTLS_USE_PSA_CRYPTO)
190 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
191 if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
192 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
193 }
194 *p -= len;
195 memcpy(*p, buf, len);
196 return (int) len;
197 } else
198 #endif /* MBEDTLS_USE_PSA_CRYPTO */
199 {
200 if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
201 MBEDTLS_ECP_PF_UNCOMPRESSED,
202 &len, buf, sizeof(buf))) != 0) {
203 return ret;
204 }
205 }
206
207 if (*p < start || (size_t) (*p - start) < len) {
208 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
209 }
210
211 *p -= len;
212 memcpy(*p, buf, len);
213
214 return (int) len;
215 }
216 #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
217
218 /*
219 * ECParameters ::= CHOICE {
220 * namedCurve OBJECT IDENTIFIER
221 * }
222 */
pk_write_ec_param(unsigned char ** p,unsigned char * start,mbedtls_ecp_group_id grp_id)223 static int pk_write_ec_param(unsigned char **p, unsigned char *start,
224 mbedtls_ecp_group_id grp_id)
225 {
226 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
227 size_t len = 0;
228 const char *oid;
229 size_t oid_len;
230
231 if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
232 return ret;
233 }
234
235 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
236
237 return (int) len;
238 }
239
240 /*
241 * privateKey OCTET STRING -- always of length ceil(log2(n)/8)
242 */
243 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
pk_write_ec_private(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)244 static int pk_write_ec_private(unsigned char **p, unsigned char *start,
245 const mbedtls_pk_context *pk)
246 {
247 size_t byte_length;
248 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
249 unsigned char tmp[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
250 psa_status_t status;
251
252 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
253 status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
254 if (status != PSA_SUCCESS) {
255 ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
256 return ret;
257 }
258 } else {
259 status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
260 if (status != PSA_SUCCESS) {
261 ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
262 goto exit;
263 }
264 }
265
266 ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
267 exit:
268 mbedtls_platform_zeroize(tmp, sizeof(tmp));
269 return ret;
270 }
271 #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
pk_write_ec_private(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)272 static int pk_write_ec_private(unsigned char **p, unsigned char *start,
273 const mbedtls_pk_context *pk)
274 {
275 size_t byte_length;
276 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
277 #if defined(MBEDTLS_USE_PSA_CRYPTO)
278 unsigned char tmp[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
279 psa_status_t status;
280 #else
281 unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
282 #endif /* MBEDTLS_USE_PSA_CRYPTO */
283
284 #if defined(MBEDTLS_USE_PSA_CRYPTO)
285 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
286 status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
287 if (status != PSA_SUCCESS) {
288 ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
289 return ret;
290 }
291 } else
292 #endif /* MBEDTLS_USE_PSA_CRYPTO */
293 {
294 mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
295 byte_length = (ec->grp.pbits + 7) / 8;
296
297 ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
298 if (ret != 0) {
299 goto exit;
300 }
301 }
302 ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
303 exit:
304 mbedtls_platform_zeroize(tmp, sizeof(tmp));
305 return ret;
306 }
307 #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
308 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
309
310 #if defined(MBEDTLS_USE_PSA_CRYPTO)
pk_write_opaque_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)311 static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
312 const mbedtls_pk_context *pk)
313 {
314 size_t buffer_size;
315 size_t len = 0;
316
317 if (*p < start) {
318 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
319 }
320
321 buffer_size = (size_t) (*p - start);
322 if (psa_export_public_key(pk->priv_id, start, buffer_size,
323 &len) != PSA_SUCCESS) {
324 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
325 }
326
327 *p -= len;
328 memmove(*p, start, len);
329
330 return (int) len;
331 }
332 #endif /* MBEDTLS_USE_PSA_CRYPTO */
333
mbedtls_pk_write_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * key)334 int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
335 const mbedtls_pk_context *key)
336 {
337 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
338 size_t len = 0;
339
340 #if defined(MBEDTLS_RSA_C)
341 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
342 MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, key));
343 } else
344 #endif
345 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
346 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
347 MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
348 } else
349 #endif
350 #if defined(MBEDTLS_USE_PSA_CRYPTO)
351 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
352 MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
353 } else
354 #endif /* MBEDTLS_USE_PSA_CRYPTO */
355 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
356
357 return (int) len;
358 }
359
mbedtls_pk_write_pubkey_der(const mbedtls_pk_context * key,unsigned char * buf,size_t size)360 int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
361 {
362 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
363 unsigned char *c;
364 int has_par = 1;
365 size_t len = 0, par_len = 0, oid_len = 0;
366 mbedtls_pk_type_t pk_type;
367 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
368 mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
369 #endif
370 const char *oid = NULL;
371
372 if (size == 0) {
373 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
374 }
375
376 c = buf + size;
377
378 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
379
380 if (c - buf < 1) {
381 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
382 }
383
384 /*
385 * SubjectPublicKeyInfo ::= SEQUENCE {
386 * algorithm AlgorithmIdentifier,
387 * subjectPublicKey BIT STRING }
388 */
389 *--c = 0;
390 len += 1;
391
392 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
393 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
394
395 pk_type = mbedtls_pk_get_type(key);
396 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
397 if (pk_type == MBEDTLS_PK_ECKEY) {
398 ec_grp_id = mbedtls_pk_get_group_id(key);
399 }
400 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
401 #if defined(MBEDTLS_USE_PSA_CRYPTO)
402 if (pk_type == MBEDTLS_PK_OPAQUE) {
403 psa_key_type_t opaque_key_type = pk_get_opaque_key_type(key);
404 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
405 if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
406 pk_type = MBEDTLS_PK_ECKEY;
407 ec_grp_id = mbedtls_pk_get_group_id(key);
408 } else
409 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
410 if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
411 /* The rest of the function works as for legacy RSA contexts. */
412 pk_type = MBEDTLS_PK_RSA;
413 }
414 }
415 /* `pk_type` will have been changed to non-opaque by here if this function can handle it */
416 if (pk_type == MBEDTLS_PK_OPAQUE) {
417 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
418 }
419 #endif /* MBEDTLS_USE_PSA_CRYPTO */
420
421 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
422 if (pk_type == MBEDTLS_PK_ECKEY) {
423 /* Some groups have their own AlgorithmIdentifier OID, others are handled
424 * by mbedtls_oid_get_oid_by_pk_alg() below */
425 ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
426
427 if (ret == 0) {
428 /* Currently, none of the supported algorithms that have their own
429 * AlgorithmIdentifier OID have any parameters */
430 has_par = 0;
431 } else if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
432 MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
433 } else {
434 return ret;
435 }
436 }
437 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
438
439 if (oid_len == 0) {
440 if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
441 &oid_len)) != 0) {
442 return ret;
443 }
444 }
445
446 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
447 par_len, has_par));
448
449 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
450 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
451 MBEDTLS_ASN1_SEQUENCE));
452
453 return (int) len;
454 }
455
456 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
457 #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
458 /*
459 * RFC8410 section 7
460 *
461 * OneAsymmetricKey ::= SEQUENCE {
462 * version Version,
463 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
464 * privateKey PrivateKey,
465 * attributes [0] IMPLICIT Attributes OPTIONAL,
466 * ...,
467 * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
468 * ...
469 * }
470 * ...
471 * CurvePrivateKey ::= OCTET STRING
472 */
pk_write_ec_rfc8410_der(unsigned char ** p,unsigned char * buf,const mbedtls_pk_context * pk)473 static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
474 const mbedtls_pk_context *pk)
475 {
476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
477 size_t len = 0;
478 size_t oid_len = 0;
479 const char *oid;
480 mbedtls_ecp_group_id grp_id;
481
482 /* privateKey */
483 MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
484 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
485 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
486
487 grp_id = mbedtls_pk_get_group_id(pk);
488 /* privateKeyAlgorithm */
489 if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
490 return ret;
491 }
492 MBEDTLS_ASN1_CHK_ADD(len,
493 mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
494
495 /* version */
496 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
497
498 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
499 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
500 MBEDTLS_ASN1_SEQUENCE));
501
502 return (int) len;
503 }
504 #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
505
506 /*
507 * RFC 5915, or SEC1 Appendix C.4
508 *
509 * ECPrivateKey ::= SEQUENCE {
510 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
511 * privateKey OCTET STRING,
512 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
513 * publicKey [1] BIT STRING OPTIONAL
514 * }
515 */
pk_write_ec_der(unsigned char ** p,unsigned char * buf,const mbedtls_pk_context * pk)516 static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
517 const mbedtls_pk_context *pk)
518 {
519 size_t len = 0;
520 int ret;
521 size_t pub_len = 0, par_len = 0;
522 mbedtls_ecp_group_id grp_id;
523
524 /* publicKey */
525 MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
526
527 if (*p - buf < 1) {
528 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
529 }
530 (*p)--;
531 **p = 0;
532 pub_len += 1;
533
534 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
535 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
536
537 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
538 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
539 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
540 MBEDTLS_ASN1_CONSTRUCTED | 1));
541 len += pub_len;
542
543 /* parameters */
544 grp_id = mbedtls_pk_get_group_id(pk);
545 MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
546 MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
547 MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
548 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
549 MBEDTLS_ASN1_CONSTRUCTED | 0));
550 len += par_len;
551
552 /* privateKey */
553 MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
554
555 /* version */
556 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
557
558 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
559 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
560 MBEDTLS_ASN1_SEQUENCE));
561
562 return (int) len;
563 }
564 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
565
566 #if defined(MBEDTLS_RSA_C)
pk_write_rsa_der(unsigned char ** p,unsigned char * buf,const mbedtls_pk_context * pk)567 static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
568 const mbedtls_pk_context *pk)
569 {
570 size_t len = 0;
571 int ret;
572
573 #if defined(MBEDTLS_USE_PSA_CRYPTO)
574 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
575 uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
576 size_t tmp_len = 0;
577
578 if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
579 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
580 }
581 *p -= tmp_len;
582 memcpy(*p, tmp, tmp_len);
583 len += tmp_len;
584 mbedtls_platform_zeroize(tmp, sizeof(tmp));
585 } else
586 #endif /* MBEDTLS_USE_PSA_CRYPTO */
587 {
588 mbedtls_mpi T; /* Temporary holding the exported parameters */
589 mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
590
591 /*
592 * Export the parameters one after another to avoid simultaneous copies.
593 */
594
595 mbedtls_mpi_init(&T);
596
597 /* Export QP */
598 if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
599 (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
600 goto end_of_export;
601 }
602 len += ret;
603
604 /* Export DQ */
605 if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
606 (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
607 goto end_of_export;
608 }
609 len += ret;
610
611 /* Export DP */
612 if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
613 (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
614 goto end_of_export;
615 }
616 len += ret;
617
618 /* Export Q */
619 if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
620 &T, NULL, NULL)) != 0 ||
621 (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
622 goto end_of_export;
623 }
624 len += ret;
625
626 /* Export P */
627 if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
628 NULL, NULL, NULL)) != 0 ||
629 (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
630 goto end_of_export;
631 }
632 len += ret;
633
634 /* Export D */
635 if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
636 NULL, &T, NULL)) != 0 ||
637 (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
638 goto end_of_export;
639 }
640 len += ret;
641
642 /* Export E */
643 if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
644 NULL, NULL, &T)) != 0 ||
645 (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
646 goto end_of_export;
647 }
648 len += ret;
649
650 /* Export N */
651 if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
652 NULL, NULL, NULL)) != 0 ||
653 (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
654 goto end_of_export;
655 }
656 len += ret;
657
658 end_of_export:
659
660 mbedtls_mpi_free(&T);
661 if (ret < 0) {
662 return ret;
663 }
664
665 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
666 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
667 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p,
668 buf, MBEDTLS_ASN1_CONSTRUCTED |
669 MBEDTLS_ASN1_SEQUENCE));
670 }
671
672 return (int) len;
673 }
674 #endif /* MBEDTLS_RSA_C */
675
mbedtls_pk_write_key_der(const mbedtls_pk_context * key,unsigned char * buf,size_t size)676 int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
677 {
678 unsigned char *c;
679 #if defined(MBEDTLS_RSA_C)
680 int is_rsa_opaque = 0;
681 #endif /* MBEDTLS_RSA_C */
682 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
683 int is_ec_opaque = 0;
684 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
685 #if defined(MBEDTLS_USE_PSA_CRYPTO)
686 psa_key_type_t opaque_key_type;
687 #endif /* MBEDTLS_USE_PSA_CRYPTO */
688
689 if (size == 0) {
690 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
691 }
692
693 c = buf + size;
694
695 #if defined(MBEDTLS_USE_PSA_CRYPTO)
696 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
697 opaque_key_type = pk_get_opaque_key_type(key);
698 #if defined(MBEDTLS_RSA_C)
699 is_rsa_opaque = PSA_KEY_TYPE_IS_RSA(opaque_key_type);
700 #endif /* MBEDTLS_RSA_C */
701 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
702 is_ec_opaque = PSA_KEY_TYPE_IS_ECC(opaque_key_type);
703 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
704 }
705 #endif /* MBEDTLS_USE_PSA_CRYPTO */
706
707 #if defined(MBEDTLS_RSA_C)
708 if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) || is_rsa_opaque) {
709 return pk_write_rsa_der(&c, buf, key);
710 } else
711 #endif /* MBEDTLS_RSA_C */
712 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
713 if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) || is_ec_opaque) {
714 #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
715 if (mbedtls_pk_is_rfc8410(key)) {
716 return pk_write_ec_rfc8410_der(&c, buf, key);
717 }
718 #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
719 return pk_write_ec_der(&c, buf, key);
720 } else
721 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
722 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
723 }
724
725 #if defined(MBEDTLS_PEM_WRITE_C)
726
727 #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
728 #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
729
730 #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n"
731 #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n"
732 #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n"
733 #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n"
734 #define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----\n"
735 #define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----\n"
736
737 #define PUB_DER_MAX_BYTES \
738 (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
739 MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
740 #define PRV_DER_MAX_BYTES \
741 (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
742 MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
743
mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context * key,unsigned char * buf,size_t size)744 int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
745 {
746 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
747 unsigned char output_buf[PUB_DER_MAX_BYTES];
748 size_t olen = 0;
749
750 if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
751 sizeof(output_buf))) < 0) {
752 return ret;
753 }
754
755 if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
756 output_buf + sizeof(output_buf) - ret,
757 ret, buf, size, &olen)) != 0) {
758 return ret;
759 }
760
761 return 0;
762 }
763
mbedtls_pk_write_key_pem(const mbedtls_pk_context * key,unsigned char * buf,size_t size)764 int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
765 {
766 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
767 unsigned char output_buf[PRV_DER_MAX_BYTES];
768 const char *begin, *end;
769 size_t olen = 0;
770 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
771 int is_ec_opaque = 0;
772 #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
773 int is_montgomery_opaque = 0;
774 #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
775 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
776 #if defined(MBEDTLS_RSA_C)
777 int is_rsa_opaque = 0;
778 #endif
779
780 if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) {
781 return ret;
782 }
783
784 #if defined(MBEDTLS_USE_PSA_CRYPTO)
785 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
786 psa_key_type_t opaque_key_type = pk_get_opaque_key_type(key);
787
788 #if defined(MBEDTLS_RSA_C)
789 is_rsa_opaque = PSA_KEY_TYPE_IS_RSA(opaque_key_type);
790 #endif
791 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
792 is_ec_opaque = PSA_KEY_TYPE_IS_ECC(opaque_key_type);
793 #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
794 if (pk_get_opaque_ec_family(key) == PSA_ECC_FAMILY_MONTGOMERY) {
795 is_montgomery_opaque = 1;
796 }
797 #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
798 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
799 }
800 #endif /* MBEDTLS_USE_PSA_CRYPTO */
801
802 #if defined(MBEDTLS_RSA_C)
803 if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) || is_rsa_opaque) {
804 begin = PEM_BEGIN_PRIVATE_KEY_RSA;
805 end = PEM_END_PRIVATE_KEY_RSA;
806 } else
807 #endif
808 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
809 if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) || is_ec_opaque) {
810 #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
811 if (is_montgomery_opaque ||
812 ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) &&
813 (mbedtls_pk_is_rfc8410(key)))) {
814 begin = PEM_BEGIN_PRIVATE_KEY_PKCS8;
815 end = PEM_END_PRIVATE_KEY_PKCS8;
816 } else
817 #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
818 {
819 begin = PEM_BEGIN_PRIVATE_KEY_EC;
820 end = PEM_END_PRIVATE_KEY_EC;
821 }
822 } else
823 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
824 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
825
826 if ((ret = mbedtls_pem_write_buffer(begin, end,
827 output_buf + sizeof(output_buf) - ret,
828 ret, buf, size, &olen)) != 0) {
829 return ret;
830 }
831
832 return 0;
833 }
834 #endif /* MBEDTLS_PEM_WRITE_C */
835
836 #endif /* MBEDTLS_PK_WRITE_C */
837