1 // SPDX-License-Identifier: Apache-2.0 2 /* 3 * Public Key layer for writing key files and structures 4 * 5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may 8 * not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 * This file is part of mbed TLS (https://tls.mbed.org) 20 */ 21 22 #if !defined(MBEDTLS_CONFIG_FILE) 23 #include "mbedtls/config.h" 24 #else 25 #include MBEDTLS_CONFIG_FILE 26 #endif 27 28 #if defined(MBEDTLS_PK_WRITE_C) 29 30 #include "mbedtls/pk.h" 31 #include "mbedtls/asn1write.h" 32 #include "mbedtls/oid.h" 33 #include "mbedtls/platform_util.h" 34 #include "mbedtls/error.h" 35 36 #include <string.h> 37 38 #if defined(MBEDTLS_RSA_C) 39 #include "mbedtls/rsa.h" 40 #endif 41 #if defined(MBEDTLS_ECP_C) 42 #include "mbedtls/bignum.h" 43 #include "mbedtls/ecp.h" 44 #include "mbedtls/platform_util.h" 45 #endif 46 #if defined(MBEDTLS_ECDSA_C) 47 #include "mbedtls/ecdsa.h" 48 #endif 49 #if defined(MBEDTLS_PEM_WRITE_C) 50 #include "mbedtls/pem.h" 51 #endif 52 53 #if defined(MBEDTLS_USE_PSA_CRYPTO) 54 #include "psa/crypto.h" 55 #include "mbedtls/psa_util.h" 56 #endif 57 #if defined(MBEDTLS_PLATFORM_C) 58 #include "mbedtls/platform.h" 59 #else 60 #include <stdlib.h> 61 #define mbedtls_calloc calloc 62 #define mbedtls_free free 63 #endif 64 65 /* Parameter validation macros based on platform_util.h */ 66 #define PK_VALIDATE_RET( cond ) \ 67 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) 68 #define PK_VALIDATE( cond ) \ 69 MBEDTLS_INTERNAL_VALIDATE( cond ) 70 71 #if defined(MBEDTLS_RSA_C) 72 /* 73 * RSAPublicKey ::= SEQUENCE { 74 * modulus INTEGER, -- n 75 * publicExponent INTEGER -- e 76 * } 77 */ 78 static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, 79 mbedtls_rsa_context *rsa ) 80 { 81 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 82 size_t len = 0; 83 mbedtls_mpi T; 84 85 mbedtls_mpi_init( &T ); 86 87 /* Export E */ 88 if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || 89 ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) 90 goto end_of_export; 91 len += ret; 92 93 /* Export N */ 94 if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || 95 ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) 96 goto end_of_export; 97 len += ret; 98 99 end_of_export: 100 101 mbedtls_mpi_free( &T ); 102 if( ret < 0 ) 103 return( ret ); 104 105 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 106 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | 107 MBEDTLS_ASN1_SEQUENCE ) ); 108 109 return( (int) len ); 110 } 111 #endif /* MBEDTLS_RSA_C */ 112 113 #if defined(MBEDTLS_ECP_C) 114 /* 115 * EC public key is an EC point 116 */ 117 static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, 118 mbedtls_ecp_keypair *ec ) 119 { 120 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 121 size_t len = 0; 122 unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; 123 124 if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, 125 MBEDTLS_ECP_PF_UNCOMPRESSED, 126 &len, buf, sizeof( buf ) ) ) != 0 ) 127 { 128 return( ret ); 129 } 130 131 if( *p < start || (size_t)( *p - start ) < len ) 132 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 133 134 *p -= len; 135 memcpy( *p, buf, len ); 136 137 return( (int) len ); 138 } 139 140 /* 141 * ECParameters ::= CHOICE { 142 * namedCurve OBJECT IDENTIFIER 143 * } 144 */ 145 static int pk_write_ec_param( unsigned char **p, unsigned char *start, 146 mbedtls_ecp_keypair *ec ) 147 { 148 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 149 size_t len = 0; 150 const char *oid; 151 size_t oid_len; 152 153 if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) 154 return( ret ); 155 156 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); 157 158 return( (int) len ); 159 } 160 161 /* 162 * privateKey OCTET STRING -- always of length ceil(log2(n)/8) 163 */ 164 static int pk_write_ec_private( unsigned char **p, unsigned char *start, 165 mbedtls_ecp_keypair *ec ) 166 { 167 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 168 size_t byte_length = ( ec->grp.pbits + 7 ) / 8; 169 unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; 170 171 ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length ); 172 if( ret != 0 ) 173 goto exit; 174 ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length ); 175 176 exit: 177 mbedtls_platform_zeroize( tmp, byte_length ); 178 return( ret ); 179 } 180 #endif /* MBEDTLS_ECP_C */ 181 182 int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, 183 const mbedtls_pk_context *key ) 184 { 185 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 186 size_t len = 0; 187 188 PK_VALIDATE_RET( p != NULL ); 189 PK_VALIDATE_RET( *p != NULL ); 190 PK_VALIDATE_RET( start != NULL ); 191 PK_VALIDATE_RET( key != NULL ); 192 193 #if defined(MBEDTLS_RSA_C) 194 if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) 195 MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); 196 else 197 #endif 198 #if defined(MBEDTLS_ECP_C) 199 if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) 200 MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); 201 else 202 #endif 203 #if defined(MBEDTLS_USE_PSA_CRYPTO) 204 if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE ) 205 { 206 size_t buffer_size; 207 psa_key_handle_t* key_slot = (psa_key_handle_t*) key->pk_ctx; 208 209 if ( *p < start ) 210 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); 211 212 buffer_size = (size_t)( *p - start ); 213 if ( psa_export_public_key( *key_slot, start, buffer_size, &len ) 214 != PSA_SUCCESS ) 215 { 216 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); 217 } 218 else 219 { 220 *p -= len; 221 memmove( *p, start, len ); 222 } 223 } 224 else 225 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 226 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); 227 228 return( (int) len ); 229 } 230 231 int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) 232 { 233 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 234 unsigned char *c; 235 size_t len = 0, par_len = 0, oid_len; 236 mbedtls_pk_type_t pk_type; 237 const char *oid; 238 239 PK_VALIDATE_RET( key != NULL ); 240 if( size == 0 ) 241 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 242 PK_VALIDATE_RET( buf != NULL ); 243 244 c = buf + size; 245 246 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); 247 248 if( c - buf < 1 ) 249 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 250 251 /* 252 * SubjectPublicKeyInfo ::= SEQUENCE { 253 * algorithm AlgorithmIdentifier, 254 * subjectPublicKey BIT STRING } 255 */ 256 *--c = 0; 257 len += 1; 258 259 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 260 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); 261 262 pk_type = mbedtls_pk_get_type( key ); 263 #if defined(MBEDTLS_ECP_C) 264 if( pk_type == MBEDTLS_PK_ECKEY ) 265 { 266 MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); 267 } 268 #endif 269 #if defined(MBEDTLS_USE_PSA_CRYPTO) 270 if( pk_type == MBEDTLS_PK_OPAQUE ) 271 { 272 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 273 psa_key_type_t key_type; 274 psa_key_handle_t handle; 275 psa_ecc_curve_t curve; 276 size_t bits; 277 278 handle = *((psa_key_handle_t*) key->pk_ctx ); 279 if( PSA_SUCCESS != psa_get_key_attributes( handle, &attributes ) ) 280 return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); 281 key_type = psa_get_key_type( &attributes ); 282 bits = psa_get_key_bits( &attributes ); 283 psa_reset_key_attributes( &attributes ); 284 285 curve = PSA_KEY_TYPE_GET_CURVE( key_type ); 286 if( curve == 0 ) 287 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); 288 289 ret = mbedtls_psa_get_ecc_oid_from_id( curve, bits, &oid, &oid_len ); 290 if( ret != 0 ) 291 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); 292 293 /* Write EC algorithm parameters; that's akin 294 * to pk_write_ec_param() above. */ 295 MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf, 296 oid, oid_len ) ); 297 298 /* The rest of the function works as for legacy EC contexts. */ 299 pk_type = MBEDTLS_PK_ECKEY; 300 } 301 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 302 303 if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid, 304 &oid_len ) ) != 0 ) 305 { 306 return( ret ); 307 } 308 309 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, 310 par_len ) ); 311 312 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 313 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | 314 MBEDTLS_ASN1_SEQUENCE ) ); 315 316 return( (int) len ); 317 } 318 319 int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) 320 { 321 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 322 unsigned char *c; 323 size_t len = 0; 324 325 PK_VALIDATE_RET( key != NULL ); 326 if( size == 0 ) 327 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 328 PK_VALIDATE_RET( buf != NULL ); 329 330 c = buf + size; 331 332 #if defined(MBEDTLS_RSA_C) 333 if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) 334 { 335 mbedtls_mpi T; /* Temporary holding the exported parameters */ 336 mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); 337 338 /* 339 * Export the parameters one after another to avoid simultaneous copies. 340 */ 341 342 mbedtls_mpi_init( &T ); 343 344 /* Export QP */ 345 if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || 346 ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) 347 goto end_of_export; 348 len += ret; 349 350 /* Export DQ */ 351 if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || 352 ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) 353 goto end_of_export; 354 len += ret; 355 356 /* Export DP */ 357 if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || 358 ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) 359 goto end_of_export; 360 len += ret; 361 362 /* Export Q */ 363 if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, 364 &T, NULL, NULL ) ) != 0 || 365 ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) 366 goto end_of_export; 367 len += ret; 368 369 /* Export P */ 370 if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, 371 NULL, NULL, NULL ) ) != 0 || 372 ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) 373 goto end_of_export; 374 len += ret; 375 376 /* Export D */ 377 if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, 378 NULL, &T, NULL ) ) != 0 || 379 ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) 380 goto end_of_export; 381 len += ret; 382 383 /* Export E */ 384 if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, 385 NULL, NULL, &T ) ) != 0 || 386 ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) 387 goto end_of_export; 388 len += ret; 389 390 /* Export N */ 391 if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, 392 NULL, NULL, NULL ) ) != 0 || 393 ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) 394 goto end_of_export; 395 len += ret; 396 397 end_of_export: 398 399 mbedtls_mpi_free( &T ); 400 if( ret < 0 ) 401 return( ret ); 402 403 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); 404 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 405 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, 406 buf, MBEDTLS_ASN1_CONSTRUCTED | 407 MBEDTLS_ASN1_SEQUENCE ) ); 408 } 409 else 410 #endif /* MBEDTLS_RSA_C */ 411 #if defined(MBEDTLS_ECP_C) 412 if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) 413 { 414 mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); 415 size_t pub_len = 0, par_len = 0; 416 417 /* 418 * RFC 5915, or SEC1 Appendix C.4 419 * 420 * ECPrivateKey ::= SEQUENCE { 421 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), 422 * privateKey OCTET STRING, 423 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, 424 * publicKey [1] BIT STRING OPTIONAL 425 * } 426 */ 427 428 /* publicKey */ 429 MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); 430 431 if( c - buf < 1 ) 432 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 433 *--c = 0; 434 pub_len += 1; 435 436 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); 437 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); 438 439 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); 440 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, 441 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); 442 len += pub_len; 443 444 /* parameters */ 445 MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); 446 447 MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); 448 MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, 449 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); 450 len += par_len; 451 452 /* privateKey */ 453 MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) ); 454 455 /* version */ 456 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); 457 458 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 459 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | 460 MBEDTLS_ASN1_SEQUENCE ) ); 461 } 462 else 463 #endif /* MBEDTLS_ECP_C */ 464 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); 465 466 return( (int) len ); 467 } 468 469 #if defined(MBEDTLS_PEM_WRITE_C) 470 471 #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" 472 #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" 473 474 #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" 475 #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" 476 #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" 477 #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" 478 479 /* 480 * Max sizes of key per types. Shown as tag + len (+ content). 481 */ 482 483 #if defined(MBEDTLS_RSA_C) 484 /* 485 * RSA public keys: 486 * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 487 * algorithm AlgorithmIdentifier, 1 + 1 (sequence) 488 * + 1 + 1 + 9 (rsa oid) 489 * + 1 + 1 (params null) 490 * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) 491 * RSAPublicKey ::= SEQUENCE { 1 + 3 492 * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 493 * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 494 * } 495 */ 496 #define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE 497 498 /* 499 * RSA private keys: 500 * RSAPrivateKey ::= SEQUENCE { 1 + 3 501 * version Version, 1 + 1 + 1 502 * modulus INTEGER, 1 + 3 + MPI_MAX + 1 503 * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 504 * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 505 * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 506 * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 507 * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 508 * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 509 * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 510 * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) 511 * } 512 */ 513 #define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ 514 MBEDTLS_MPI_MAX_SIZE % 2 515 #define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ 516 + 5 * MPI_MAX_SIZE_2 517 518 #else /* MBEDTLS_RSA_C */ 519 520 #define RSA_PUB_DER_MAX_BYTES 0 521 #define RSA_PRV_DER_MAX_BYTES 0 522 523 #endif /* MBEDTLS_RSA_C */ 524 525 #if defined(MBEDTLS_ECP_C) 526 /* 527 * EC public keys: 528 * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 529 * algorithm AlgorithmIdentifier, 1 + 1 (sequence) 530 * + 1 + 1 + 7 (ec oid) 531 * + 1 + 1 + 9 (namedCurve oid) 532 * subjectPublicKey BIT STRING 1 + 2 + 1 [1] 533 * + 1 (point format) [1] 534 * + 2 * ECP_MAX (coords) [1] 535 * } 536 */ 537 #define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES 538 539 /* 540 * EC private keys: 541 * ECPrivateKey ::= SEQUENCE { 1 + 2 542 * version INTEGER , 1 + 1 + 1 543 * privateKey OCTET STRING, 1 + 1 + ECP_MAX 544 * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) 545 * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above 546 * } 547 */ 548 #define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES 549 550 #else /* MBEDTLS_ECP_C */ 551 552 #define ECP_PUB_DER_MAX_BYTES 0 553 #define ECP_PRV_DER_MAX_BYTES 0 554 555 #endif /* MBEDTLS_ECP_C */ 556 557 #define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ 558 RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES 559 #define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ 560 RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES 561 562 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) 563 { 564 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 565 unsigned char output_buf[PUB_DER_MAX_BYTES]; 566 size_t olen = 0; 567 568 PK_VALIDATE_RET( key != NULL ); 569 PK_VALIDATE_RET( buf != NULL || size == 0 ); 570 571 if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, 572 sizeof(output_buf) ) ) < 0 ) 573 { 574 return( ret ); 575 } 576 577 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, 578 output_buf + sizeof(output_buf) - ret, 579 ret, buf, size, &olen ) ) != 0 ) 580 { 581 return( ret ); 582 } 583 584 return( 0 ); 585 } 586 587 int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) 588 { 589 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 590 unsigned char output_buf[PRV_DER_MAX_BYTES]; 591 const char *begin, *end; 592 size_t olen = 0; 593 594 PK_VALIDATE_RET( key != NULL ); 595 PK_VALIDATE_RET( buf != NULL || size == 0 ); 596 597 if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) 598 return( ret ); 599 600 #if defined(MBEDTLS_RSA_C) 601 if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) 602 { 603 begin = PEM_BEGIN_PRIVATE_KEY_RSA; 604 end = PEM_END_PRIVATE_KEY_RSA; 605 } 606 else 607 #endif 608 #if defined(MBEDTLS_ECP_C) 609 if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) 610 { 611 begin = PEM_BEGIN_PRIVATE_KEY_EC; 612 end = PEM_END_PRIVATE_KEY_EC; 613 } 614 else 615 #endif 616 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); 617 618 if( ( ret = mbedtls_pem_write_buffer( begin, end, 619 output_buf + sizeof(output_buf) - ret, 620 ret, buf, size, &olen ) ) != 0 ) 621 { 622 return( ret ); 623 } 624 625 return( 0 ); 626 } 627 #endif /* MBEDTLS_PEM_WRITE_C */ 628 629 #endif /* MBEDTLS_PK_WRITE_C */ 630