• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     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  */
pk_write_rsa_pubkey(unsigned char ** p,unsigned char * start,mbedtls_rsa_context * rsa)54 static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
55                                mbedtls_rsa_context *rsa)
56 {
57     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
58     size_t len = 0;
59     mbedtls_mpi T;
60 
61     mbedtls_mpi_init(&T);
62 
63     /* Export E */
64     if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
65         (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
66         goto end_of_export;
67     }
68     len += ret;
69 
70     /* Export N */
71     if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
72         (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
73         goto end_of_export;
74     }
75     len += ret;
76 
77 end_of_export:
78 
79     mbedtls_mpi_free(&T);
80     if (ret < 0) {
81         return ret;
82     }
83 
84     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
85     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
86                                                      MBEDTLS_ASN1_SEQUENCE));
87 
88     return (int) len;
89 }
90 #endif /* MBEDTLS_RSA_C */
91 
92 #if defined(MBEDTLS_ECP_C)
93 /*
94  * EC public key is an EC point
95  */
pk_write_ec_pubkey(unsigned char ** p,unsigned char * start,mbedtls_ecp_keypair * ec)96 static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
97                               mbedtls_ecp_keypair *ec)
98 {
99     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
100     size_t len = 0;
101     unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
102 
103     if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
104                                               MBEDTLS_ECP_PF_UNCOMPRESSED,
105                                               &len, buf, sizeof(buf))) != 0) {
106         return ret;
107     }
108 
109     if (*p < start || (size_t) (*p - start) < len) {
110         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
111     }
112 
113     *p -= len;
114     memcpy(*p, buf, len);
115 
116     return (int) len;
117 }
118 
119 /*
120  * ECParameters ::= CHOICE {
121  *   namedCurve         OBJECT IDENTIFIER
122  * }
123  */
pk_write_ec_param(unsigned char ** p,unsigned char * start,mbedtls_ecp_keypair * ec)124 static int pk_write_ec_param(unsigned char **p, unsigned char *start,
125                              mbedtls_ecp_keypair *ec)
126 {
127     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
128     size_t len = 0;
129     const char *oid;
130     size_t oid_len;
131 
132     if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) {
133         return ret;
134     }
135 
136     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
137 
138     return (int) len;
139 }
140 
141 /*
142  * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
143  */
pk_write_ec_private(unsigned char ** p,unsigned char * start,mbedtls_ecp_keypair * ec)144 static int pk_write_ec_private(unsigned char **p, unsigned char *start,
145                                mbedtls_ecp_keypair *ec)
146 {
147     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
148     size_t byte_length = (ec->grp.pbits + 7) / 8;
149     unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
150 
151     ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
152     if (ret != 0) {
153         goto exit;
154     }
155     ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
156 
157 exit:
158     mbedtls_platform_zeroize(tmp, byte_length);
159     return ret;
160 }
161 #endif /* MBEDTLS_ECP_C */
162 
mbedtls_pk_write_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * key)163 int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
164                             const mbedtls_pk_context *key)
165 {
166     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
167     size_t len = 0;
168 
169     (void) p;
170     (void) start;
171     (void) key;
172     (void) ret;
173 
174     PK_VALIDATE_RET(p != NULL);
175     PK_VALIDATE_RET(*p != NULL);
176     PK_VALIDATE_RET(start != NULL);
177     PK_VALIDATE_RET(key != NULL);
178 
179 #if defined(MBEDTLS_RSA_C)
180     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
181         MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key)));
182     } else
183 #endif
184 #if defined(MBEDTLS_ECP_C)
185     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
186         MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key)));
187     } else
188 #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     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
209 
210     return (int) len;
211 }
212 
mbedtls_pk_write_pubkey_der(mbedtls_pk_context * key,unsigned char * buf,size_t size)213 int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *key, unsigned char *buf, size_t size)
214 {
215     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
216     unsigned char *c;
217     size_t len = 0, par_len = 0, oid_len;
218     mbedtls_pk_type_t pk_type;
219     const char *oid;
220 
221     PK_VALIDATE_RET(key != NULL);
222     if (size == 0) {
223         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
224     }
225     PK_VALIDATE_RET(buf != NULL);
226 
227     c = buf + size;
228 
229     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
230 
231     if (c - buf < 1) {
232         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
233     }
234 
235     /*
236      *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
237      *       algorithm            AlgorithmIdentifier,
238      *       subjectPublicKey     BIT STRING }
239      */
240     *--c = 0;
241     len += 1;
242 
243     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
244     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
245 
246     pk_type = mbedtls_pk_get_type(key);
247 #if defined(MBEDTLS_ECP_C)
248     if (pk_type == MBEDTLS_PK_ECKEY) {
249         MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key)));
250     }
251 #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     if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
289                                              &oid_len)) != 0) {
290         return ret;
291     }
292 
293     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len,
294                                                                       par_len));
295 
296     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
297     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
298                                                      MBEDTLS_ASN1_SEQUENCE));
299 
300     return (int) len;
301 }
302 
mbedtls_pk_write_key_der(mbedtls_pk_context * key,unsigned char * buf,size_t size)303 int mbedtls_pk_write_key_der(mbedtls_pk_context *key, unsigned char *buf, size_t size)
304 {
305     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
306     unsigned char *c;
307     size_t len = 0;
308 
309     (void) ret;
310     (void) c;
311     (void) key;
312 
313     PK_VALIDATE_RET(key != NULL);
314     if (size == 0) {
315         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
316     }
317     PK_VALIDATE_RET(buf != NULL);
318 
319     c = buf + size;
320 
321 #if defined(MBEDTLS_RSA_C)
322     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
323         mbedtls_mpi T; /* Temporary holding the exported parameters */
324         mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key);
325 
326         /*
327          * Export the parameters one after another to avoid simultaneous copies.
328          */
329 
330         mbedtls_mpi_init(&T);
331 
332         /* Export QP */
333         if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
334             (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
335             goto end_of_export;
336         }
337         len += ret;
338 
339         /* Export DQ */
340         if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
341             (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
342             goto end_of_export;
343         }
344         len += ret;
345 
346         /* Export DP */
347         if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
348             (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
349             goto end_of_export;
350         }
351         len += ret;
352 
353         /* Export Q */
354         if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
355                                       &T, NULL, NULL)) != 0 ||
356             (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
357             goto end_of_export;
358         }
359         len += ret;
360 
361         /* Export P */
362         if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
363                                       NULL, NULL, NULL)) != 0 ||
364             (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
365             goto end_of_export;
366         }
367         len += ret;
368 
369         /* Export D */
370         if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
371                                       NULL, &T, NULL)) != 0 ||
372             (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
373             goto end_of_export;
374         }
375         len += ret;
376 
377         /* Export E */
378         if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
379                                       NULL, NULL, &T)) != 0 ||
380             (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
381             goto end_of_export;
382         }
383         len += ret;
384 
385         /* Export N */
386         if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
387                                       NULL, NULL, NULL)) != 0 ||
388             (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
389             goto end_of_export;
390         }
391         len += ret;
392 
393 end_of_export:
394 
395         mbedtls_mpi_free(&T);
396         if (ret < 0) {
397             return ret;
398         }
399 
400         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
401         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
402         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c,
403                                                          buf, MBEDTLS_ASN1_CONSTRUCTED |
404                                                          MBEDTLS_ASN1_SEQUENCE));
405     } else
406 #endif /* MBEDTLS_RSA_C */
407 #if defined(MBEDTLS_ECP_C)
408     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
409         mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
410         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         MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, ec));
425 
426         if (c - buf < 1) {
427             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
428         }
429         *--c = 0;
430         pub_len += 1;
431 
432         MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
433         MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
434 
435         MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
436         MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf,
437                                                              MBEDTLS_ASN1_CONTEXT_SPECIFIC |
438                                                              MBEDTLS_ASN1_CONSTRUCTED | 1));
439         len += pub_len;
440 
441         /* parameters */
442         MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec));
443 
444         MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len));
445         MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(&c, buf,
446                                                              MBEDTLS_ASN1_CONTEXT_SPECIFIC |
447                                                              MBEDTLS_ASN1_CONSTRUCTED | 0));
448         len += par_len;
449 
450         /* privateKey */
451         MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(&c, buf, ec));
452 
453         /* version */
454         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1));
455 
456         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
457         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
458                                                          MBEDTLS_ASN1_SEQUENCE));
459     } else
460 #endif /* MBEDTLS_ECP_C */
461     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
462 
463     return (int) len;
464 }
465 
466 #if defined(MBEDTLS_PEM_WRITE_C)
467 
468 #define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
469 #define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
470 
471 #define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
472 #define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
473 #define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
474 #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 #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 #define MPI_MAX_SIZE_2          (MBEDTLS_MPI_MAX_SIZE / 2 + \
511                                  MBEDTLS_MPI_MAX_SIZE % 2)
512 #define RSA_PRV_DER_MAX_BYTES   (47 + 3 * MBEDTLS_MPI_MAX_SIZE \
513                                  + 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 #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 #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 #define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
555                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
556 #define PRV_DER_MAX_BYTES   (RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
557                              RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES)
558 
mbedtls_pk_write_pubkey_pem(mbedtls_pk_context * key,unsigned char * buf,size_t size)559 int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size)
560 {
561     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
562     unsigned char output_buf[PUB_DER_MAX_BYTES];
563     size_t olen = 0;
564 
565     PK_VALIDATE_RET(key != NULL);
566     PK_VALIDATE_RET(buf != NULL || size == 0);
567 
568     if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
569                                            sizeof(output_buf))) < 0) {
570         return ret;
571     }
572 
573     if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
574                                         output_buf + sizeof(output_buf) - ret,
575                                         ret, buf, size, &olen)) != 0) {
576         return ret;
577     }
578 
579     return 0;
580 }
581 
mbedtls_pk_write_key_pem(mbedtls_pk_context * key,unsigned char * buf,size_t size)582 int mbedtls_pk_write_key_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size)
583 {
584     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
585     unsigned char output_buf[PRV_DER_MAX_BYTES];
586     const char *begin, *end;
587     size_t olen = 0;
588 
589     PK_VALIDATE_RET(key != NULL);
590     PK_VALIDATE_RET(buf != NULL || size == 0);
591 
592     if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) {
593         return ret;
594     }
595 
596 #if defined(MBEDTLS_RSA_C)
597     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
598         begin = PEM_BEGIN_PRIVATE_KEY_RSA;
599         end = PEM_END_PRIVATE_KEY_RSA;
600     } else
601 #endif
602 #if defined(MBEDTLS_ECP_C)
603     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
604         begin = PEM_BEGIN_PRIVATE_KEY_EC;
605         end = PEM_END_PRIVATE_KEY_EC;
606     } else
607 #endif
608     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
609 
610     if ((ret = mbedtls_pem_write_buffer(begin, end,
611                                         output_buf + sizeof(output_buf) - ret,
612                                         ret, buf, size, &olen)) != 0) {
613         return ret;
614     }
615 
616     return 0;
617 }
618 #endif /* MBEDTLS_PEM_WRITE_C */
619 
620 #endif /* MBEDTLS_PK_WRITE_C */
621