v / thirdparty / mbedtls / library / pkwrite.c
631 lines · 544 sloc · 20.25 KB · 3d9911f887ecec942f9ae2a5be02d064f233b729
Raw
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_ECP_C)
22#include "mbedtls/bignum.h"
23#include "mbedtls/ecp.h"
24#include "mbedtls/platform_util.h"
25#endif
26#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
27#include "pk_internal.h"
28#endif
29#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
30#include "pkwrite.h"
31#endif
32#if defined(MBEDTLS_PEM_WRITE_C)
33#include "mbedtls/pem.h"
34#endif
35#if defined(MBEDTLS_RSA_C)
36#include "rsa_internal.h"
37#endif
38
39#if defined(MBEDTLS_USE_PSA_CRYPTO)
40#include "psa/crypto.h"
41#include "psa_util_internal.h"
42#endif
43#include "mbedtls/platform.h"
44
45/* Helpers for properly sizing buffers aimed at holding public keys or
46 * key-pairs based on build symbols. */
47#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
48#define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
49#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
50#elif defined(MBEDTLS_USE_PSA_CRYPTO)
51#define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
52#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
53#else
54#define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN
55#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES
56#endif
57
58/******************************************************************************
59 * Internal functions for RSA keys.
60 ******************************************************************************/
61#if defined(MBEDTLS_RSA_C)
62static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
63 const mbedtls_pk_context *pk)
64{
65#if defined(MBEDTLS_USE_PSA_CRYPTO)
66 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
67 psa_status_t status;
68 size_t buf_size = (size_t) (*p - buf);
69 size_t key_len = 0;
70
71 status = psa_export_key(pk->priv_id, buf, buf_size, &key_len);
72 if (status == PSA_ERROR_BUFFER_TOO_SMALL) {
73 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
74 } else if (status != PSA_SUCCESS) {
75 return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
76 }
77
78 /* We wrote to the beginning of the buffer while
79 * we were supposed to write to its end. */
80 *p -= key_len;
81 memmove(*p, buf, key_len);
82 mbedtls_platform_zeroize(buf, *p - buf);
83
84 return (int) key_len;
85 }
86#endif /* MBEDTLS_USE_PSA_CRYPTO */
87 return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
88}
89#endif /* MBEDTLS_RSA_C */
90
91/******************************************************************************
92 * Internal functions for EC keys.
93 ******************************************************************************/
94#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
95#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
96static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
97 const mbedtls_pk_context *pk)
98{
99 size_t len = 0;
100 uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
101
102 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
103 if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
104 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
105 }
106 } else {
107 len = pk->pub_raw_len;
108 memcpy(buf, pk->pub_raw, len);
109 }
110
111 if (*p < start || (size_t) (*p - start) < len) {
112 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
113 }
114
115 *p -= len;
116 memcpy(*p, buf, len);
117
118 return (int) len;
119}
120#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
121static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
122 const mbedtls_pk_context *pk)
123{
124 size_t len = 0;
125 unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
126 mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
127 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
128
129#if defined(MBEDTLS_USE_PSA_CRYPTO)
130 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
131 if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
132 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
133 }
134 /* Ensure there's enough space in the provided buffer before copying data into it. */
135 if (len > (size_t) (*p - start)) {
136 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
137 }
138 *p -= len;
139 memcpy(*p, buf, len);
140 return (int) len;
141 } else
142#endif /* MBEDTLS_USE_PSA_CRYPTO */
143 {
144 if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
145 MBEDTLS_ECP_PF_UNCOMPRESSED,
146 &len, buf, sizeof(buf))) != 0) {
147 return ret;
148 }
149 }
150
151 if (*p < start || (size_t) (*p - start) < len) {
152 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
153 }
154
155 *p -= len;
156 memcpy(*p, buf, len);
157
158 return (int) len;
159}
160#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
161
162/*
163 * privateKey OCTET STRING -- always of length ceil(log2(n)/8)
164 */
165#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
166static int pk_write_ec_private(unsigned char **p, unsigned char *start,
167 const mbedtls_pk_context *pk)
168{
169 size_t byte_length;
170 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
171 unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
172 psa_status_t status;
173
174 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
175 status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
176 if (status != PSA_SUCCESS) {
177 ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
178 return ret;
179 }
180 } else {
181 status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
182 if (status != PSA_SUCCESS) {
183 ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
184 goto exit;
185 }
186 }
187
188 ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
189exit:
190 mbedtls_platform_zeroize(tmp, sizeof(tmp));
191 return ret;
192}
193#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
194static int pk_write_ec_private(unsigned char **p, unsigned char *start,
195 const mbedtls_pk_context *pk)
196{
197 size_t byte_length;
198 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
199 unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
200
201#if defined(MBEDTLS_USE_PSA_CRYPTO)
202 psa_status_t status;
203 if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
204 status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
205 if (status != PSA_SUCCESS) {
206 ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
207 return ret;
208 }
209 } else
210#endif /* MBEDTLS_USE_PSA_CRYPTO */
211 {
212 mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
213 byte_length = (ec->grp.pbits + 7) / 8;
214
215 ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));
216 if (ret != 0) {
217 goto exit;
218 }
219 }
220 ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
221exit:
222 mbedtls_platform_zeroize(tmp, sizeof(tmp));
223 return ret;
224}
225#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
226
227/*
228 * ECParameters ::= CHOICE {
229 * namedCurve OBJECT IDENTIFIER
230 * }
231 */
232static int pk_write_ec_param(unsigned char **p, unsigned char *start,
233 mbedtls_ecp_group_id grp_id)
234{
235 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
236 size_t len = 0;
237 const char *oid;
238 size_t oid_len;
239
240 if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
241 return ret;
242 }
243
244 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
245
246 return (int) len;
247}
248
249#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
250/*
251 * RFC8410 section 7
252 *
253 * OneAsymmetricKey ::= SEQUENCE {
254 * version Version,
255 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
256 * privateKey PrivateKey,
257 * attributes [0] IMPLICIT Attributes OPTIONAL,
258 * ...,
259 * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
260 * ...
261 * }
262 * ...
263 * CurvePrivateKey ::= OCTET STRING
264 */
265static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
266 const mbedtls_pk_context *pk)
267{
268 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
269 size_t len = 0;
270 size_t oid_len = 0;
271 const char *oid;
272 mbedtls_ecp_group_id grp_id;
273
274 /* privateKey */
275 MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
276 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
277 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
278
279 grp_id = mbedtls_pk_get_ec_group_id(pk);
280 /* privateKeyAlgorithm */
281 if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
282 return ret;
283 }
284 MBEDTLS_ASN1_CHK_ADD(len,
285 mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
286
287 /* version */
288 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
289
290 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
291 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
292 MBEDTLS_ASN1_SEQUENCE));
293
294 return (int) len;
295}
296#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
297
298/*
299 * RFC 5915, or SEC1 Appendix C.4
300 *
301 * ECPrivateKey ::= SEQUENCE {
302 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
303 * privateKey OCTET STRING,
304 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
305 * publicKey [1] BIT STRING OPTIONAL
306 * }
307 */
308static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
309 const mbedtls_pk_context *pk)
310{
311 size_t len = 0;
312 int ret;
313 size_t pub_len = 0, par_len = 0;
314 mbedtls_ecp_group_id grp_id;
315
316 /* publicKey */
317 MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
318
319 if (*p - buf < 1) {
320 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
321 }
322 (*p)--;
323 **p = 0;
324 pub_len += 1;
325
326 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
327 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
328
329 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
330 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
331 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
332 MBEDTLS_ASN1_CONSTRUCTED | 1));
333 len += pub_len;
334
335 /* parameters */
336 grp_id = mbedtls_pk_get_ec_group_id(pk);
337 MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
338 MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
339 MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
340 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
341 MBEDTLS_ASN1_CONSTRUCTED | 0));
342 len += par_len;
343
344 /* privateKey */
345 MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
346
347 /* version */
348 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
349
350 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
351 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
352 MBEDTLS_ASN1_SEQUENCE));
353
354 return (int) len;
355}
356#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
357
358/******************************************************************************
359 * Internal functions for Opaque keys.
360 ******************************************************************************/
361#if defined(MBEDTLS_USE_PSA_CRYPTO)
362static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
363 const mbedtls_pk_context *pk)
364{
365 size_t buffer_size;
366 size_t len = 0;
367
368 if (*p < start) {
369 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
370 }
371
372 buffer_size = (size_t) (*p - start);
373 if (psa_export_public_key(pk->priv_id, start, buffer_size,
374 &len) != PSA_SUCCESS) {
375 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
376 }
377
378 *p -= len;
379 memmove(*p, start, len);
380
381 return (int) len;
382}
383#endif /* MBEDTLS_USE_PSA_CRYPTO */
384
385/******************************************************************************
386 * Generic helpers
387 ******************************************************************************/
388
389/* Extend the public mbedtls_pk_get_type() by getting key type also in case of
390 * opaque keys. */
391static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk)
392{
393 mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
394
395#if defined(MBEDTLS_USE_PSA_CRYPTO)
396 if (pk_type == MBEDTLS_PK_OPAQUE) {
397 psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
398 psa_key_type_t opaque_key_type;
399
400 if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
401 return MBEDTLS_PK_NONE;
402 }
403 opaque_key_type = psa_get_key_type(&opaque_attrs);
404 psa_reset_key_attributes(&opaque_attrs);
405
406 if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
407 return MBEDTLS_PK_ECKEY;
408 } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
409 return MBEDTLS_PK_RSA;
410 } else {
411 return MBEDTLS_PK_NONE;
412 }
413 } else
414#endif
415 return pk_type;
416}
417
418/******************************************************************************
419 * Public functions for writing private/public DER keys.
420 ******************************************************************************/
421int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
422 const mbedtls_pk_context *key)
423{
424 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
425 size_t len = 0;
426
427#if defined(MBEDTLS_RSA_C)
428 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
429 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
430 } else
431#endif
432#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
433 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
434 MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
435 } else
436#endif
437#if defined(MBEDTLS_USE_PSA_CRYPTO)
438 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
439 MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
440 } else
441#endif /* MBEDTLS_USE_PSA_CRYPTO */
442 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
443
444 return (int) len;
445}
446
447int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
448{
449 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
450 unsigned char *c;
451 int has_par = 1;
452 size_t len = 0, par_len = 0, oid_len = 0;
453 mbedtls_pk_type_t pk_type;
454 const char *oid = NULL;
455
456 if (size == 0) {
457 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
458 }
459
460 c = buf + size;
461
462 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
463
464 if (c - buf < 1) {
465 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
466 }
467
468 /*
469 * SubjectPublicKeyInfo ::= SEQUENCE {
470 * algorithm AlgorithmIdentifier,
471 * subjectPublicKey BIT STRING }
472 */
473 *--c = 0;
474 len += 1;
475
476 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
477 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
478
479 pk_type = pk_get_type_ext(key);
480
481#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
482 if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
483 mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key);
484 if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
485 ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
486 if (ret != 0) {
487 return ret;
488 }
489 has_par = 0;
490 } else {
491 MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
492 }
493 }
494#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
495
496 /* At this point oid_len is not null only for EC Montgomery keys. */
497 if (oid_len == 0) {
498 ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len);
499 if (ret != 0) {
500 return ret;
501 }
502 }
503
504 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
505 par_len, has_par));
506
507 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
508 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
509 MBEDTLS_ASN1_SEQUENCE));
510
511 return (int) len;
512}
513
514int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
515{
516 unsigned char *c;
517
518 if (size == 0) {
519 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
520 }
521
522 c = buf + size;
523
524#if defined(MBEDTLS_RSA_C)
525 if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
526 return pk_write_rsa_der(&c, buf, key);
527 } else
528#endif /* MBEDTLS_RSA_C */
529#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
530 if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
531#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
532 if (mbedtls_pk_is_rfc8410(key)) {
533 return pk_write_ec_rfc8410_der(&c, buf, key);
534 }
535#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
536 return pk_write_ec_der(&c, buf, key);
537 } else
538#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
539 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
540}
541
542/******************************************************************************
543 * Public functions for wrinting private/public PEM keys.
544 ******************************************************************************/
545#if defined(MBEDTLS_PEM_WRITE_C)
546
547#define PUB_DER_MAX_BYTES \
548 (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
549 MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
550#define PRV_DER_MAX_BYTES \
551 (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
552 MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
553
554int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
555{
556 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
557 unsigned char *output_buf = NULL;
558 output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);
559 if (output_buf == NULL) {
560 return MBEDTLS_ERR_PK_ALLOC_FAILED;
561 }
562 size_t olen = 0;
563
564 if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
565 PUB_DER_MAX_BYTES)) < 0) {
566 goto cleanup;
567 }
568
569 if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n",
570 output_buf + PUB_DER_MAX_BYTES - ret,
571 ret, buf, size, &olen)) != 0) {
572 goto cleanup;
573 }
574
575 ret = 0;
576cleanup:
577 mbedtls_free(output_buf);
578 return ret;
579}
580
581int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
582{
583 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
584 unsigned char *output_buf = NULL;
585 output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);
586 if (output_buf == NULL) {
587 return MBEDTLS_ERR_PK_ALLOC_FAILED;
588 }
589 const char *begin, *end;
590 size_t olen = 0;
591
592 if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {
593 goto cleanup;
594 }
595
596#if defined(MBEDTLS_RSA_C)
597 if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
598 begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n";
599 end = PEM_END_PRIVATE_KEY_RSA "\n";
600 } else
601#endif
602#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
603 if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
604 if (mbedtls_pk_is_rfc8410(key)) {
605 begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n";
606 end = PEM_END_PRIVATE_KEY_PKCS8 "\n";
607 } else {
608 begin = PEM_BEGIN_PRIVATE_KEY_EC "\n";
609 end = PEM_END_PRIVATE_KEY_EC "\n";
610 }
611 } else
612#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
613 {
614 ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
615 goto cleanup;
616 }
617
618 if ((ret = mbedtls_pem_write_buffer(begin, end,
619 output_buf + PRV_DER_MAX_BYTES - ret,
620 ret, buf, size, &olen)) != 0) {
621 goto cleanup;
622 }
623
624 ret = 0;
625cleanup:
626 mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES);
627 return ret;
628}
629#endif /* MBEDTLS_PEM_WRITE_C */
630
631#endif /* MBEDTLS_PK_WRITE_C */
632