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