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