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