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 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 20 #include "common.h" 21 22 #if defined(MBEDTLS_PK_WRITE_C) 23 24 #include "mbedtls/pk.h" 25 #include "mbedtls/asn1write.h" 26 #include "mbedtls/oid.h" 27 #include "mbedtls/platform_util.h" 28 #include "mbedtls/error.h" 29 30 #include <string.h> 31 32 #if defined(MBEDTLS_RSA_C) 33 #include "mbedtls/rsa.h" 34 #endif 35 #if defined(MBEDTLS_ECP_C) 36 #include "mbedtls/bignum.h" 37 #include "mbedtls/ecp.h" 38 #include "mbedtls/platform_util.h" 39 #endif 40 #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) 41 #include "pkwrite.h" 42 #endif 43 #if defined(MBEDTLS_ECDSA_C) 44 #include "mbedtls/ecdsa.h" 45 #endif 46 #if defined(MBEDTLS_PEM_WRITE_C) 47 #include "mbedtls/pem.h" 48 #endif 49 50 #if defined(MBEDTLS_USE_PSA_CRYPTO) 51 #include "psa/crypto.h" 52 #include "mbedtls/psa_util.h" 53 #endif 54 #include "mbedtls/platform.h" 55 56 #if defined(MBEDTLS_RSA_C) 57 /* 58 * RSAPublicKey ::= SEQUENCE { 59 * modulus INTEGER, -- n 60 * publicExponent INTEGER -- e 61 * } 62 */ 63 static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start, 64 mbedtls_rsa_context *rsa) 65 { 66 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 67 size_t len = 0; 68 mbedtls_mpi T; 69 70 mbedtls_mpi_init(&T); 71 72 /* Export E */ 73 if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || 74 (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { 75 goto end_of_export; 76 } 77 len += ret; 78 79 /* Export N */ 80 if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || 81 (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { 82 goto end_of_export; 83 } 84 len += ret; 85 86 end_of_export: 87 88 mbedtls_mpi_free(&T); 89 if (ret < 0) { 90 return ret; 91 } 92 93 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 94 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | 95 MBEDTLS_ASN1_SEQUENCE)); 96 97 return (int) len; 98 } 99 #endif /* MBEDTLS_RSA_C */ 100 101 #if defined(MBEDTLS_ECP_C) 102 /* 103 * EC public key is an EC point 104 */ 105 static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, 106 mbedtls_ecp_keypair *ec) 107 { 108 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 109 size_t len = 0; 110 unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; 111 112 if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, 113 MBEDTLS_ECP_PF_UNCOMPRESSED, 114 &len, buf, sizeof(buf))) != 0) { 115 return ret; 116 } 117 118 if (*p < start || (size_t) (*p - start) < len) { 119 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 120 } 121 122 *p -= len; 123 memcpy(*p, buf, len); 124 125 return (int) len; 126 } 127 128 /* 129 * ECParameters ::= CHOICE { 130 * namedCurve OBJECT IDENTIFIER 131 * } 132 */ 133 static int pk_write_ec_param(unsigned char **p, unsigned char *start, 134 mbedtls_ecp_keypair *ec) 135 { 136 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 137 size_t len = 0; 138 const char *oid; 139 size_t oid_len; 140 141 if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) { 142 return ret; 143 } 144 145 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); 146 147 return (int) len; 148 } 149 150 /* 151 * privateKey OCTET STRING -- always of length ceil(log2(n)/8) 152 */ 153 static int pk_write_ec_private(unsigned char **p, unsigned char *start, 154 mbedtls_ecp_keypair *ec) 155 { 156 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 157 size_t byte_length = (ec->grp.pbits + 7) / 8; 158 unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; 159 160 ret = mbedtls_ecp_write_key(ec, tmp, byte_length); 161 if (ret != 0) { 162 goto exit; 163 } 164 ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); 165 166 exit: 167 mbedtls_platform_zeroize(tmp, byte_length); 168 return ret; 169 } 170 #endif /* MBEDTLS_ECP_C */ 171 172 int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, 173 const mbedtls_pk_context *key) 174 { 175 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 176 size_t len = 0; 177 178 #if defined(MBEDTLS_RSA_C) 179 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { 180 MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key))); 181 } else 182 #endif 183 #if defined(MBEDTLS_ECP_C) 184 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { 185 MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key))); 186 } else 187 #endif 188 #if defined(MBEDTLS_USE_PSA_CRYPTO) 189 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { 190 size_t buffer_size; 191 mbedtls_svc_key_id_t *key_id = (mbedtls_svc_key_id_t *) key->pk_ctx; 192 193 if (*p < start) { 194 return MBEDTLS_ERR_PK_BAD_INPUT_DATA; 195 } 196 197 buffer_size = (size_t) (*p - start); 198 if (psa_export_public_key(*key_id, start, buffer_size, &len) 199 != PSA_SUCCESS) { 200 return MBEDTLS_ERR_PK_BAD_INPUT_DATA; 201 } else { 202 *p -= len; 203 memmove(*p, start, len); 204 } 205 } else 206 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 207 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 208 209 return (int) len; 210 } 211 212 int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) 213 { 214 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 215 unsigned char *c; 216 size_t len = 0, par_len = 0, oid_len; 217 mbedtls_pk_type_t pk_type; 218 const char *oid; 219 220 if (size == 0) { 221 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 222 } 223 224 c = buf + size; 225 226 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key)); 227 228 if (c - buf < 1) { 229 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 230 } 231 232 /* 233 * SubjectPublicKeyInfo ::= SEQUENCE { 234 * algorithm AlgorithmIdentifier, 235 * subjectPublicKey BIT STRING } 236 */ 237 *--c = 0; 238 len += 1; 239 240 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 241 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); 242 243 pk_type = mbedtls_pk_get_type(key); 244 #if defined(MBEDTLS_ECP_C) 245 if (pk_type == MBEDTLS_PK_ECKEY) { 246 MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key))); 247 } 248 #endif 249 #if defined(MBEDTLS_USE_PSA_CRYPTO) 250 if (pk_type == MBEDTLS_PK_OPAQUE) { 251 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 252 psa_key_type_t key_type; 253 mbedtls_svc_key_id_t key_id; 254 psa_ecc_family_t curve; 255 size_t bits; 256 257 key_id = *((mbedtls_svc_key_id_t *) key->pk_ctx); 258 if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) { 259 return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 260 } 261 key_type = psa_get_key_type(&attributes); 262 bits = psa_get_key_bits(&attributes); 263 psa_reset_key_attributes(&attributes); 264 265 if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) { 266 curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type); 267 if (curve == 0) { 268 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 269 } 270 271 ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits, 272 &oid, &oid_len); 273 if (ret != 0) { 274 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 275 } 276 277 /* Write EC algorithm parameters; that's akin 278 * to pk_write_ec_param() above. */ 279 MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_oid(&c, buf, 280 oid, 281 oid_len)); 282 283 /* The rest of the function works as for legacy EC contexts. */ 284 pk_type = MBEDTLS_PK_ECKEY; 285 } else if (PSA_KEY_TYPE_IS_RSA(key_type)) { 286 /* The rest of the function works as for legacy RSA contexts. */ 287 pk_type = MBEDTLS_PK_RSA; 288 } else { 289 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 290 } 291 } 292 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 293 294 if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, 295 &oid_len)) != 0) { 296 return ret; 297 } 298 299 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len, 300 par_len)); 301 302 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 303 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | 304 MBEDTLS_ASN1_SEQUENCE)); 305 306 return (int) len; 307 } 308 309 int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) 310 { 311 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 312 unsigned char *c; 313 size_t len = 0; 314 315 if (size == 0) { 316 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 317 } 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 #define PUB_DER_MAX_BYTES \ 477 (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \ 478 MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) 479 #define PRV_DER_MAX_BYTES \ 480 (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \ 481 MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES) 482 483 int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) 484 { 485 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 486 unsigned char output_buf[PUB_DER_MAX_BYTES]; 487 size_t olen = 0; 488 489 if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, 490 sizeof(output_buf))) < 0) { 491 return ret; 492 } 493 494 if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, 495 output_buf + sizeof(output_buf) - ret, 496 ret, buf, size, &olen)) != 0) { 497 return ret; 498 } 499 500 return 0; 501 } 502 503 int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) 504 { 505 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 506 unsigned char output_buf[PRV_DER_MAX_BYTES]; 507 const char *begin, *end; 508 size_t olen = 0; 509 510 if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) { 511 return ret; 512 } 513 514 #if defined(MBEDTLS_RSA_C) 515 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { 516 begin = PEM_BEGIN_PRIVATE_KEY_RSA; 517 end = PEM_END_PRIVATE_KEY_RSA; 518 } else 519 #endif 520 #if defined(MBEDTLS_ECP_C) 521 if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { 522 begin = PEM_BEGIN_PRIVATE_KEY_EC; 523 end = PEM_END_PRIVATE_KEY_EC; 524 } else 525 #endif 526 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 527 528 if ((ret = mbedtls_pem_write_buffer(begin, end, 529 output_buf + sizeof(output_buf) - ret, 530 ret, buf, size, &olen)) != 0) { 531 return ret; 532 } 533 534 return 0; 535 } 536 #endif /* MBEDTLS_PEM_WRITE_C */ 537 538 #endif /* MBEDTLS_PK_WRITE_C */ 539