1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * Public Key layer for parsing key files and structures 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6a8e1175bSopenharmony_ci */ 7a8e1175bSopenharmony_ci 8a8e1175bSopenharmony_ci#include "common.h" 9a8e1175bSopenharmony_ci 10a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_PARSE_C) 11a8e1175bSopenharmony_ci 12a8e1175bSopenharmony_ci#include "mbedtls/pk.h" 13a8e1175bSopenharmony_ci#include "mbedtls/asn1.h" 14a8e1175bSopenharmony_ci#include "mbedtls/oid.h" 15a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h" 16a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 17a8e1175bSopenharmony_ci#include "mbedtls/error.h" 18a8e1175bSopenharmony_ci#include "mbedtls/ecp.h" 19a8e1175bSopenharmony_ci#include "pk_internal.h" 20a8e1175bSopenharmony_ci 21a8e1175bSopenharmony_ci#include <string.h> 22a8e1175bSopenharmony_ci 23a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO) 24a8e1175bSopenharmony_ci#include "mbedtls/psa_util.h" 25a8e1175bSopenharmony_ci#include "psa/crypto.h" 26a8e1175bSopenharmony_ci#endif 27a8e1175bSopenharmony_ci 28a8e1175bSopenharmony_ci/* Key types */ 29a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 30a8e1175bSopenharmony_ci#include "mbedtls/rsa.h" 31a8e1175bSopenharmony_ci#include "rsa_internal.h" 32a8e1175bSopenharmony_ci#endif 33a8e1175bSopenharmony_ci 34a8e1175bSopenharmony_ci/* Extended formats */ 35a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C) 36a8e1175bSopenharmony_ci#include "mbedtls/pem.h" 37a8e1175bSopenharmony_ci#endif 38a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS5_C) 39a8e1175bSopenharmony_ci#include "mbedtls/pkcs5.h" 40a8e1175bSopenharmony_ci#endif 41a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) 42a8e1175bSopenharmony_ci#include "mbedtls/pkcs12.h" 43a8e1175bSopenharmony_ci#endif 44a8e1175bSopenharmony_ci 45a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) 46a8e1175bSopenharmony_ci 47a8e1175bSopenharmony_ci/*********************************************************************** 48a8e1175bSopenharmony_ci * 49a8e1175bSopenharmony_ci * Low-level ECC parsing: optional support for SpecifiedECDomain 50a8e1175bSopenharmony_ci * 51a8e1175bSopenharmony_ci * There are two functions here that are used by the rest of the code: 52a8e1175bSopenharmony_ci * - pk_ecc_tag_is_speficied_ec_domain() 53a8e1175bSopenharmony_ci * - pk_ecc_group_id_from_specified() 54a8e1175bSopenharmony_ci * 55a8e1175bSopenharmony_ci * All the other functions are internal to this section. 56a8e1175bSopenharmony_ci * 57a8e1175bSopenharmony_ci * The two "public" functions have a dummy variant provided 58a8e1175bSopenharmony_ci * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an 59a8e1175bSopenharmony_ci * abstraction layer for this macro, which should not appear outside 60a8e1175bSopenharmony_ci * this section. 61a8e1175bSopenharmony_ci * 62a8e1175bSopenharmony_ci **********************************************************************/ 63a8e1175bSopenharmony_ci 64a8e1175bSopenharmony_ci#if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED) 65a8e1175bSopenharmony_ci/* See the "real" version for documentation */ 66a8e1175bSopenharmony_cistatic int pk_ecc_tag_is_specified_ec_domain(int tag) 67a8e1175bSopenharmony_ci{ 68a8e1175bSopenharmony_ci (void) tag; 69a8e1175bSopenharmony_ci return 0; 70a8e1175bSopenharmony_ci} 71a8e1175bSopenharmony_ci 72a8e1175bSopenharmony_ci/* See the "real" version for documentation */ 73a8e1175bSopenharmony_cistatic int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, 74a8e1175bSopenharmony_ci mbedtls_ecp_group_id *grp_id) 75a8e1175bSopenharmony_ci{ 76a8e1175bSopenharmony_ci (void) params; 77a8e1175bSopenharmony_ci (void) grp_id; 78a8e1175bSopenharmony_ci return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; 79a8e1175bSopenharmony_ci} 80a8e1175bSopenharmony_ci#else /* MBEDTLS_PK_PARSE_EC_EXTENDED */ 81a8e1175bSopenharmony_ci/* 82a8e1175bSopenharmony_ci * Tell if the passed tag might be the start of SpecifiedECDomain 83a8e1175bSopenharmony_ci * (that is, a sequence). 84a8e1175bSopenharmony_ci */ 85a8e1175bSopenharmony_cistatic int pk_ecc_tag_is_specified_ec_domain(int tag) 86a8e1175bSopenharmony_ci{ 87a8e1175bSopenharmony_ci return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); 88a8e1175bSopenharmony_ci} 89a8e1175bSopenharmony_ci 90a8e1175bSopenharmony_ci/* 91a8e1175bSopenharmony_ci * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. 92a8e1175bSopenharmony_ci * WARNING: the resulting group should only be used with 93a8e1175bSopenharmony_ci * pk_ecc_group_id_from_specified(), since its base point may not be set correctly 94a8e1175bSopenharmony_ci * if it was encoded compressed. 95a8e1175bSopenharmony_ci * 96a8e1175bSopenharmony_ci * SpecifiedECDomain ::= SEQUENCE { 97a8e1175bSopenharmony_ci * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), 98a8e1175bSopenharmony_ci * fieldID FieldID {{FieldTypes}}, 99a8e1175bSopenharmony_ci * curve Curve, 100a8e1175bSopenharmony_ci * base ECPoint, 101a8e1175bSopenharmony_ci * order INTEGER, 102a8e1175bSopenharmony_ci * cofactor INTEGER OPTIONAL, 103a8e1175bSopenharmony_ci * hash HashAlgorithm OPTIONAL, 104a8e1175bSopenharmony_ci * ... 105a8e1175bSopenharmony_ci * } 106a8e1175bSopenharmony_ci * 107a8e1175bSopenharmony_ci * We only support prime-field as field type, and ignore hash and cofactor. 108a8e1175bSopenharmony_ci */ 109a8e1175bSopenharmony_cistatic int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) 110a8e1175bSopenharmony_ci{ 111a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 112a8e1175bSopenharmony_ci unsigned char *p = params->p; 113a8e1175bSopenharmony_ci const unsigned char *const end = params->p + params->len; 114a8e1175bSopenharmony_ci const unsigned char *end_field, *end_curve; 115a8e1175bSopenharmony_ci size_t len; 116a8e1175bSopenharmony_ci int ver; 117a8e1175bSopenharmony_ci 118a8e1175bSopenharmony_ci /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ 119a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) { 120a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 121a8e1175bSopenharmony_ci } 122a8e1175bSopenharmony_ci 123a8e1175bSopenharmony_ci if (ver < 1 || ver > 3) { 124a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 125a8e1175bSopenharmony_ci } 126a8e1175bSopenharmony_ci 127a8e1175bSopenharmony_ci /* 128a8e1175bSopenharmony_ci * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field 129a8e1175bSopenharmony_ci * fieldType FIELD-ID.&id({IOSet}), 130a8e1175bSopenharmony_ci * parameters FIELD-ID.&Type({IOSet}{@fieldType}) 131a8e1175bSopenharmony_ci * } 132a8e1175bSopenharmony_ci */ 133a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 134a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 135a8e1175bSopenharmony_ci return ret; 136a8e1175bSopenharmony_ci } 137a8e1175bSopenharmony_ci 138a8e1175bSopenharmony_ci end_field = p + len; 139a8e1175bSopenharmony_ci 140a8e1175bSopenharmony_ci /* 141a8e1175bSopenharmony_ci * FIELD-ID ::= TYPE-IDENTIFIER 142a8e1175bSopenharmony_ci * FieldTypes FIELD-ID ::= { 143a8e1175bSopenharmony_ci * { Prime-p IDENTIFIED BY prime-field } | 144a8e1175bSopenharmony_ci * { Characteristic-two IDENTIFIED BY characteristic-two-field } 145a8e1175bSopenharmony_ci * } 146a8e1175bSopenharmony_ci * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } 147a8e1175bSopenharmony_ci */ 148a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) { 149a8e1175bSopenharmony_ci return ret; 150a8e1175bSopenharmony_ci } 151a8e1175bSopenharmony_ci 152a8e1175bSopenharmony_ci if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) || 153a8e1175bSopenharmony_ci memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) { 154a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 155a8e1175bSopenharmony_ci } 156a8e1175bSopenharmony_ci 157a8e1175bSopenharmony_ci p += len; 158a8e1175bSopenharmony_ci 159a8e1175bSopenharmony_ci /* Prime-p ::= INTEGER -- Field of size p. */ 160a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) { 161a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 162a8e1175bSopenharmony_ci } 163a8e1175bSopenharmony_ci 164a8e1175bSopenharmony_ci grp->pbits = mbedtls_mpi_bitlen(&grp->P); 165a8e1175bSopenharmony_ci 166a8e1175bSopenharmony_ci if (p != end_field) { 167a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 168a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 169a8e1175bSopenharmony_ci } 170a8e1175bSopenharmony_ci 171a8e1175bSopenharmony_ci /* 172a8e1175bSopenharmony_ci * Curve ::= SEQUENCE { 173a8e1175bSopenharmony_ci * a FieldElement, 174a8e1175bSopenharmony_ci * b FieldElement, 175a8e1175bSopenharmony_ci * seed BIT STRING OPTIONAL 176a8e1175bSopenharmony_ci * -- Shall be present if used in SpecifiedECDomain 177a8e1175bSopenharmony_ci * -- with version equal to ecdpVer2 or ecdpVer3 178a8e1175bSopenharmony_ci * } 179a8e1175bSopenharmony_ci */ 180a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 181a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 182a8e1175bSopenharmony_ci return ret; 183a8e1175bSopenharmony_ci } 184a8e1175bSopenharmony_ci 185a8e1175bSopenharmony_ci end_curve = p + len; 186a8e1175bSopenharmony_ci 187a8e1175bSopenharmony_ci /* 188a8e1175bSopenharmony_ci * FieldElement ::= OCTET STRING 189a8e1175bSopenharmony_ci * containing an integer in the case of a prime field 190a8e1175bSopenharmony_ci */ 191a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || 192a8e1175bSopenharmony_ci (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) { 193a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 194a8e1175bSopenharmony_ci } 195a8e1175bSopenharmony_ci 196a8e1175bSopenharmony_ci p += len; 197a8e1175bSopenharmony_ci 198a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || 199a8e1175bSopenharmony_ci (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) { 200a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 201a8e1175bSopenharmony_ci } 202a8e1175bSopenharmony_ci 203a8e1175bSopenharmony_ci p += len; 204a8e1175bSopenharmony_ci 205a8e1175bSopenharmony_ci /* Ignore seed BIT STRING OPTIONAL */ 206a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) { 207a8e1175bSopenharmony_ci p += len; 208a8e1175bSopenharmony_ci } 209a8e1175bSopenharmony_ci 210a8e1175bSopenharmony_ci if (p != end_curve) { 211a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 212a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 213a8e1175bSopenharmony_ci } 214a8e1175bSopenharmony_ci 215a8e1175bSopenharmony_ci /* 216a8e1175bSopenharmony_ci * ECPoint ::= OCTET STRING 217a8e1175bSopenharmony_ci */ 218a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 219a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 220a8e1175bSopenharmony_ci } 221a8e1175bSopenharmony_ci 222a8e1175bSopenharmony_ci if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G, 223a8e1175bSopenharmony_ci (const unsigned char *) p, len)) != 0) { 224a8e1175bSopenharmony_ci /* 225a8e1175bSopenharmony_ci * If we can't read the point because it's compressed, cheat by 226a8e1175bSopenharmony_ci * reading only the X coordinate and the parity bit of Y. 227a8e1175bSopenharmony_ci */ 228a8e1175bSopenharmony_ci if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || 229a8e1175bSopenharmony_ci (p[0] != 0x02 && p[0] != 0x03) || 230a8e1175bSopenharmony_ci len != mbedtls_mpi_size(&grp->P) + 1 || 231a8e1175bSopenharmony_ci mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 || 232a8e1175bSopenharmony_ci mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 || 233a8e1175bSopenharmony_ci mbedtls_mpi_lset(&grp->G.Z, 1) != 0) { 234a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 235a8e1175bSopenharmony_ci } 236a8e1175bSopenharmony_ci } 237a8e1175bSopenharmony_ci 238a8e1175bSopenharmony_ci p += len; 239a8e1175bSopenharmony_ci 240a8e1175bSopenharmony_ci /* 241a8e1175bSopenharmony_ci * order INTEGER 242a8e1175bSopenharmony_ci */ 243a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) { 244a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 245a8e1175bSopenharmony_ci } 246a8e1175bSopenharmony_ci 247a8e1175bSopenharmony_ci grp->nbits = mbedtls_mpi_bitlen(&grp->N); 248a8e1175bSopenharmony_ci 249a8e1175bSopenharmony_ci /* 250a8e1175bSopenharmony_ci * Allow optional elements by purposefully not enforcing p == end here. 251a8e1175bSopenharmony_ci */ 252a8e1175bSopenharmony_ci 253a8e1175bSopenharmony_ci return 0; 254a8e1175bSopenharmony_ci} 255a8e1175bSopenharmony_ci 256a8e1175bSopenharmony_ci/* 257a8e1175bSopenharmony_ci * Find the group id associated with an (almost filled) group as generated by 258a8e1175bSopenharmony_ci * pk_group_from_specified(), or return an error if unknown. 259a8e1175bSopenharmony_ci */ 260a8e1175bSopenharmony_cistatic int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id) 261a8e1175bSopenharmony_ci{ 262a8e1175bSopenharmony_ci int ret = 0; 263a8e1175bSopenharmony_ci mbedtls_ecp_group ref; 264a8e1175bSopenharmony_ci const mbedtls_ecp_group_id *id; 265a8e1175bSopenharmony_ci 266a8e1175bSopenharmony_ci mbedtls_ecp_group_init(&ref); 267a8e1175bSopenharmony_ci 268a8e1175bSopenharmony_ci for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) { 269a8e1175bSopenharmony_ci /* Load the group associated to that id */ 270a8e1175bSopenharmony_ci mbedtls_ecp_group_free(&ref); 271a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id)); 272a8e1175bSopenharmony_ci 273a8e1175bSopenharmony_ci /* Compare to the group we were given, starting with easy tests */ 274a8e1175bSopenharmony_ci if (grp->pbits == ref.pbits && grp->nbits == ref.nbits && 275a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 && 276a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 && 277a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 && 278a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 && 279a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 && 280a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 && 281a8e1175bSopenharmony_ci /* For Y we may only know the parity bit, so compare only that */ 282a8e1175bSopenharmony_ci mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { 283a8e1175bSopenharmony_ci break; 284a8e1175bSopenharmony_ci } 285a8e1175bSopenharmony_ci } 286a8e1175bSopenharmony_ci 287a8e1175bSopenharmony_cicleanup: 288a8e1175bSopenharmony_ci mbedtls_ecp_group_free(&ref); 289a8e1175bSopenharmony_ci 290a8e1175bSopenharmony_ci *grp_id = *id; 291a8e1175bSopenharmony_ci 292a8e1175bSopenharmony_ci if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) { 293a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; 294a8e1175bSopenharmony_ci } 295a8e1175bSopenharmony_ci 296a8e1175bSopenharmony_ci return ret; 297a8e1175bSopenharmony_ci} 298a8e1175bSopenharmony_ci 299a8e1175bSopenharmony_ci/* 300a8e1175bSopenharmony_ci * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID 301a8e1175bSopenharmony_ci */ 302a8e1175bSopenharmony_cistatic int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, 303a8e1175bSopenharmony_ci mbedtls_ecp_group_id *grp_id) 304a8e1175bSopenharmony_ci{ 305a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 306a8e1175bSopenharmony_ci mbedtls_ecp_group grp; 307a8e1175bSopenharmony_ci 308a8e1175bSopenharmony_ci mbedtls_ecp_group_init(&grp); 309a8e1175bSopenharmony_ci 310a8e1175bSopenharmony_ci if ((ret = pk_group_from_specified(params, &grp)) != 0) { 311a8e1175bSopenharmony_ci goto cleanup; 312a8e1175bSopenharmony_ci } 313a8e1175bSopenharmony_ci 314a8e1175bSopenharmony_ci ret = pk_group_id_from_group(&grp, grp_id); 315a8e1175bSopenharmony_ci 316a8e1175bSopenharmony_cicleanup: 317a8e1175bSopenharmony_ci /* The API respecting lifecycle for mbedtls_ecp_group struct is 318a8e1175bSopenharmony_ci * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the 319a8e1175bSopenharmony_ci * temporary grp breaks that flow and it's members are populated 320a8e1175bSopenharmony_ci * by pk_group_id_from_group(). As such mbedtls_ecp_group_free() 321a8e1175bSopenharmony_ci * which is assuming a group populated by _setup() may not clean-up 322a8e1175bSopenharmony_ci * properly -> Manually free it's members. 323a8e1175bSopenharmony_ci */ 324a8e1175bSopenharmony_ci mbedtls_mpi_free(&grp.N); 325a8e1175bSopenharmony_ci mbedtls_mpi_free(&grp.P); 326a8e1175bSopenharmony_ci mbedtls_mpi_free(&grp.A); 327a8e1175bSopenharmony_ci mbedtls_mpi_free(&grp.B); 328a8e1175bSopenharmony_ci mbedtls_ecp_point_free(&grp.G); 329a8e1175bSopenharmony_ci 330a8e1175bSopenharmony_ci return ret; 331a8e1175bSopenharmony_ci} 332a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ 333a8e1175bSopenharmony_ci 334a8e1175bSopenharmony_ci/*********************************************************************** 335a8e1175bSopenharmony_ci * 336a8e1175bSopenharmony_ci * Unsorted (yet!) from this point on until the next section header 337a8e1175bSopenharmony_ci * 338a8e1175bSopenharmony_ci **********************************************************************/ 339a8e1175bSopenharmony_ci 340a8e1175bSopenharmony_ci/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf 341a8e1175bSopenharmony_ci * 342a8e1175bSopenharmony_ci * ECParameters ::= CHOICE { 343a8e1175bSopenharmony_ci * namedCurve OBJECT IDENTIFIER 344a8e1175bSopenharmony_ci * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } 345a8e1175bSopenharmony_ci * -- implicitCurve NULL 346a8e1175bSopenharmony_ci * } 347a8e1175bSopenharmony_ci */ 348a8e1175bSopenharmony_cistatic int pk_get_ecparams(unsigned char **p, const unsigned char *end, 349a8e1175bSopenharmony_ci mbedtls_asn1_buf *params) 350a8e1175bSopenharmony_ci{ 351a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 352a8e1175bSopenharmony_ci 353a8e1175bSopenharmony_ci if (end - *p < 1) { 354a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 355a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_OUT_OF_DATA); 356a8e1175bSopenharmony_ci } 357a8e1175bSopenharmony_ci 358a8e1175bSopenharmony_ci /* Acceptable tags: OID for namedCurve, or specifiedECDomain */ 359a8e1175bSopenharmony_ci params->tag = **p; 360a8e1175bSopenharmony_ci if (params->tag != MBEDTLS_ASN1_OID && 361a8e1175bSopenharmony_ci !pk_ecc_tag_is_specified_ec_domain(params->tag)) { 362a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 363a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 364a8e1175bSopenharmony_ci } 365a8e1175bSopenharmony_ci 366a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { 367a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 368a8e1175bSopenharmony_ci } 369a8e1175bSopenharmony_ci 370a8e1175bSopenharmony_ci params->p = *p; 371a8e1175bSopenharmony_ci *p += params->len; 372a8e1175bSopenharmony_ci 373a8e1175bSopenharmony_ci if (*p != end) { 374a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 375a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 376a8e1175bSopenharmony_ci } 377a8e1175bSopenharmony_ci 378a8e1175bSopenharmony_ci return 0; 379a8e1175bSopenharmony_ci} 380a8e1175bSopenharmony_ci 381a8e1175bSopenharmony_ci/* 382a8e1175bSopenharmony_ci * Use EC parameters to initialise an EC group 383a8e1175bSopenharmony_ci * 384a8e1175bSopenharmony_ci * ECParameters ::= CHOICE { 385a8e1175bSopenharmony_ci * namedCurve OBJECT IDENTIFIER 386a8e1175bSopenharmony_ci * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } 387a8e1175bSopenharmony_ci * -- implicitCurve NULL 388a8e1175bSopenharmony_ci */ 389a8e1175bSopenharmony_cistatic int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk) 390a8e1175bSopenharmony_ci{ 391a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 392a8e1175bSopenharmony_ci mbedtls_ecp_group_id grp_id; 393a8e1175bSopenharmony_ci 394a8e1175bSopenharmony_ci if (params->tag == MBEDTLS_ASN1_OID) { 395a8e1175bSopenharmony_ci if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) { 396a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE; 397a8e1175bSopenharmony_ci } 398a8e1175bSopenharmony_ci } else { 399a8e1175bSopenharmony_ci ret = pk_ecc_group_id_from_specified(params, &grp_id); 400a8e1175bSopenharmony_ci if (ret != 0) { 401a8e1175bSopenharmony_ci return ret; 402a8e1175bSopenharmony_ci } 403a8e1175bSopenharmony_ci } 404a8e1175bSopenharmony_ci 405a8e1175bSopenharmony_ci return mbedtls_pk_ecc_set_group(pk, grp_id); 406a8e1175bSopenharmony_ci} 407a8e1175bSopenharmony_ci 408a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) 409a8e1175bSopenharmony_ci 410a8e1175bSopenharmony_ci/* 411a8e1175bSopenharmony_ci * Load an RFC8410 EC key, which doesn't have any parameters 412a8e1175bSopenharmony_ci */ 413a8e1175bSopenharmony_cistatic int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params, 414a8e1175bSopenharmony_ci mbedtls_ecp_group_id grp_id, 415a8e1175bSopenharmony_ci mbedtls_pk_context *pk) 416a8e1175bSopenharmony_ci{ 417a8e1175bSopenharmony_ci if (params->tag != 0 || params->len != 0) { 418a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 419a8e1175bSopenharmony_ci } 420a8e1175bSopenharmony_ci 421a8e1175bSopenharmony_ci return mbedtls_pk_ecc_set_group(pk, grp_id); 422a8e1175bSopenharmony_ci} 423a8e1175bSopenharmony_ci 424a8e1175bSopenharmony_ci/* 425a8e1175bSopenharmony_ci * Parse an RFC 8410 encoded private EC key 426a8e1175bSopenharmony_ci * 427a8e1175bSopenharmony_ci * CurvePrivateKey ::= OCTET STRING 428a8e1175bSopenharmony_ci */ 429a8e1175bSopenharmony_cistatic int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk, 430a8e1175bSopenharmony_ci unsigned char *key, size_t keylen, const unsigned char *end, 431a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 432a8e1175bSopenharmony_ci{ 433a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 434a8e1175bSopenharmony_ci size_t len; 435a8e1175bSopenharmony_ci 436a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 437a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 438a8e1175bSopenharmony_ci } 439a8e1175bSopenharmony_ci 440a8e1175bSopenharmony_ci if (key + len != end) { 441a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 442a8e1175bSopenharmony_ci } 443a8e1175bSopenharmony_ci 444a8e1175bSopenharmony_ci /* 445a8e1175bSopenharmony_ci * Load the private key 446a8e1175bSopenharmony_ci */ 447a8e1175bSopenharmony_ci ret = mbedtls_pk_ecc_set_key(pk, key, len); 448a8e1175bSopenharmony_ci if (ret != 0) { 449a8e1175bSopenharmony_ci return ret; 450a8e1175bSopenharmony_ci } 451a8e1175bSopenharmony_ci 452a8e1175bSopenharmony_ci /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys, 453a8e1175bSopenharmony_ci * which never contain a public key. As such, derive the public key 454a8e1175bSopenharmony_ci * unconditionally. */ 455a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) { 456a8e1175bSopenharmony_ci return ret; 457a8e1175bSopenharmony_ci } 458a8e1175bSopenharmony_ci 459a8e1175bSopenharmony_ci return 0; 460a8e1175bSopenharmony_ci} 461a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ 462a8e1175bSopenharmony_ci 463a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 464a8e1175bSopenharmony_ci 465a8e1175bSopenharmony_ci/* Get a PK algorithm identifier 466a8e1175bSopenharmony_ci * 467a8e1175bSopenharmony_ci * AlgorithmIdentifier ::= SEQUENCE { 468a8e1175bSopenharmony_ci * algorithm OBJECT IDENTIFIER, 469a8e1175bSopenharmony_ci * parameters ANY DEFINED BY algorithm OPTIONAL } 470a8e1175bSopenharmony_ci */ 471a8e1175bSopenharmony_cistatic int pk_get_pk_alg(unsigned char **p, 472a8e1175bSopenharmony_ci const unsigned char *end, 473a8e1175bSopenharmony_ci mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params, 474a8e1175bSopenharmony_ci mbedtls_ecp_group_id *ec_grp_id) 475a8e1175bSopenharmony_ci{ 476a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 477a8e1175bSopenharmony_ci mbedtls_asn1_buf alg_oid; 478a8e1175bSopenharmony_ci 479a8e1175bSopenharmony_ci memset(params, 0, sizeof(mbedtls_asn1_buf)); 480a8e1175bSopenharmony_ci 481a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) { 482a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret); 483a8e1175bSopenharmony_ci } 484a8e1175bSopenharmony_ci 485a8e1175bSopenharmony_ci ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg); 486a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) 487a8e1175bSopenharmony_ci if (ret == MBEDTLS_ERR_OID_NOT_FOUND) { 488a8e1175bSopenharmony_ci ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id); 489a8e1175bSopenharmony_ci if (ret == 0) { 490a8e1175bSopenharmony_ci *pk_alg = MBEDTLS_PK_ECKEY; 491a8e1175bSopenharmony_ci } 492a8e1175bSopenharmony_ci } 493a8e1175bSopenharmony_ci#else 494a8e1175bSopenharmony_ci (void) ec_grp_id; 495a8e1175bSopenharmony_ci#endif 496a8e1175bSopenharmony_ci if (ret != 0) { 497a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 498a8e1175bSopenharmony_ci } 499a8e1175bSopenharmony_ci 500a8e1175bSopenharmony_ci /* 501a8e1175bSopenharmony_ci * No parameters with RSA (only for EC) 502a8e1175bSopenharmony_ci */ 503a8e1175bSopenharmony_ci if (*pk_alg == MBEDTLS_PK_RSA && 504a8e1175bSopenharmony_ci ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) || 505a8e1175bSopenharmony_ci params->len != 0)) { 506a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_INVALID_ALG; 507a8e1175bSopenharmony_ci } 508a8e1175bSopenharmony_ci 509a8e1175bSopenharmony_ci return 0; 510a8e1175bSopenharmony_ci} 511a8e1175bSopenharmony_ci 512a8e1175bSopenharmony_ci/* 513a8e1175bSopenharmony_ci * SubjectPublicKeyInfo ::= SEQUENCE { 514a8e1175bSopenharmony_ci * algorithm AlgorithmIdentifier, 515a8e1175bSopenharmony_ci * subjectPublicKey BIT STRING } 516a8e1175bSopenharmony_ci */ 517a8e1175bSopenharmony_ciint mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, 518a8e1175bSopenharmony_ci mbedtls_pk_context *pk) 519a8e1175bSopenharmony_ci{ 520a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 521a8e1175bSopenharmony_ci size_t len; 522a8e1175bSopenharmony_ci mbedtls_asn1_buf alg_params; 523a8e1175bSopenharmony_ci mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; 524a8e1175bSopenharmony_ci mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; 525a8e1175bSopenharmony_ci const mbedtls_pk_info_t *pk_info; 526a8e1175bSopenharmony_ci 527a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(p, end, &len, 528a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 529a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 530a8e1175bSopenharmony_ci } 531a8e1175bSopenharmony_ci 532a8e1175bSopenharmony_ci end = *p + len; 533a8e1175bSopenharmony_ci 534a8e1175bSopenharmony_ci if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) { 535a8e1175bSopenharmony_ci return ret; 536a8e1175bSopenharmony_ci } 537a8e1175bSopenharmony_ci 538a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { 539a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); 540a8e1175bSopenharmony_ci } 541a8e1175bSopenharmony_ci 542a8e1175bSopenharmony_ci if (*p + len != end) { 543a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, 544a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 545a8e1175bSopenharmony_ci } 546a8e1175bSopenharmony_ci 547a8e1175bSopenharmony_ci if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { 548a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 549a8e1175bSopenharmony_ci } 550a8e1175bSopenharmony_ci 551a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { 552a8e1175bSopenharmony_ci return ret; 553a8e1175bSopenharmony_ci } 554a8e1175bSopenharmony_ci 555a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 556a8e1175bSopenharmony_ci if (pk_alg == MBEDTLS_PK_RSA) { 557a8e1175bSopenharmony_ci ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p)); 558a8e1175bSopenharmony_ci if (ret == 0) { 559a8e1175bSopenharmony_ci /* On success all the input has been consumed by the parsing function. */ 560a8e1175bSopenharmony_ci *p += end - *p; 561a8e1175bSopenharmony_ci } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) && 562a8e1175bSopenharmony_ci (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) { 563a8e1175bSopenharmony_ci /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */ 564a8e1175bSopenharmony_ci ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); 565a8e1175bSopenharmony_ci } else { 566a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_PK_INVALID_PUBKEY; 567a8e1175bSopenharmony_ci } 568a8e1175bSopenharmony_ci } else 569a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */ 570a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) 571a8e1175bSopenharmony_ci if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { 572a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) 573a8e1175bSopenharmony_ci if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { 574a8e1175bSopenharmony_ci ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk); 575a8e1175bSopenharmony_ci } else 576a8e1175bSopenharmony_ci#endif 577a8e1175bSopenharmony_ci { 578a8e1175bSopenharmony_ci ret = pk_use_ecparams(&alg_params, pk); 579a8e1175bSopenharmony_ci } 580a8e1175bSopenharmony_ci if (ret == 0) { 581a8e1175bSopenharmony_ci ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p)); 582a8e1175bSopenharmony_ci *p += end - *p; 583a8e1175bSopenharmony_ci } 584a8e1175bSopenharmony_ci } else 585a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 586a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 587a8e1175bSopenharmony_ci 588a8e1175bSopenharmony_ci if (ret == 0 && *p != end) { 589a8e1175bSopenharmony_ci ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, 590a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 591a8e1175bSopenharmony_ci } 592a8e1175bSopenharmony_ci 593a8e1175bSopenharmony_ci if (ret != 0) { 594a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 595a8e1175bSopenharmony_ci } 596a8e1175bSopenharmony_ci 597a8e1175bSopenharmony_ci return ret; 598a8e1175bSopenharmony_ci} 599a8e1175bSopenharmony_ci 600a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) 601a8e1175bSopenharmony_ci/* 602a8e1175bSopenharmony_ci * Parse a SEC1 encoded private EC key 603a8e1175bSopenharmony_ci */ 604a8e1175bSopenharmony_cistatic int pk_parse_key_sec1_der(mbedtls_pk_context *pk, 605a8e1175bSopenharmony_ci const unsigned char *key, size_t keylen, 606a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 607a8e1175bSopenharmony_ci{ 608a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 609a8e1175bSopenharmony_ci int version, pubkey_done; 610a8e1175bSopenharmony_ci size_t len, d_len; 611a8e1175bSopenharmony_ci mbedtls_asn1_buf params = { 0, 0, NULL }; 612a8e1175bSopenharmony_ci unsigned char *p = (unsigned char *) key; 613a8e1175bSopenharmony_ci unsigned char *d; 614a8e1175bSopenharmony_ci unsigned char *end = p + keylen; 615a8e1175bSopenharmony_ci unsigned char *end2; 616a8e1175bSopenharmony_ci 617a8e1175bSopenharmony_ci /* 618a8e1175bSopenharmony_ci * RFC 5915, or SEC1 Appendix C.4 619a8e1175bSopenharmony_ci * 620a8e1175bSopenharmony_ci * ECPrivateKey ::= SEQUENCE { 621a8e1175bSopenharmony_ci * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), 622a8e1175bSopenharmony_ci * privateKey OCTET STRING, 623a8e1175bSopenharmony_ci * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, 624a8e1175bSopenharmony_ci * publicKey [1] BIT STRING OPTIONAL 625a8e1175bSopenharmony_ci * } 626a8e1175bSopenharmony_ci */ 627a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 628a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 629a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 630a8e1175bSopenharmony_ci } 631a8e1175bSopenharmony_ci 632a8e1175bSopenharmony_ci end = p + len; 633a8e1175bSopenharmony_ci 634a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { 635a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 636a8e1175bSopenharmony_ci } 637a8e1175bSopenharmony_ci 638a8e1175bSopenharmony_ci if (version != 1) { 639a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; 640a8e1175bSopenharmony_ci } 641a8e1175bSopenharmony_ci 642a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 643a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 644a8e1175bSopenharmony_ci } 645a8e1175bSopenharmony_ci 646a8e1175bSopenharmony_ci /* Keep a reference to the position fo the private key. It will be used 647a8e1175bSopenharmony_ci * later in this function. */ 648a8e1175bSopenharmony_ci d = p; 649a8e1175bSopenharmony_ci d_len = len; 650a8e1175bSopenharmony_ci 651a8e1175bSopenharmony_ci p += len; 652a8e1175bSopenharmony_ci 653a8e1175bSopenharmony_ci pubkey_done = 0; 654a8e1175bSopenharmony_ci if (p != end) { 655a8e1175bSopenharmony_ci /* 656a8e1175bSopenharmony_ci * Is 'parameters' present? 657a8e1175bSopenharmony_ci */ 658a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 659a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 660a8e1175bSopenharmony_ci 0)) == 0) { 661a8e1175bSopenharmony_ci if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || 662a8e1175bSopenharmony_ci (ret = pk_use_ecparams(¶ms, pk)) != 0) { 663a8e1175bSopenharmony_ci return ret; 664a8e1175bSopenharmony_ci } 665a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 666a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 667a8e1175bSopenharmony_ci } 668a8e1175bSopenharmony_ci } 669a8e1175bSopenharmony_ci 670a8e1175bSopenharmony_ci /* 671a8e1175bSopenharmony_ci * Load the private key 672a8e1175bSopenharmony_ci */ 673a8e1175bSopenharmony_ci ret = mbedtls_pk_ecc_set_key(pk, d, d_len); 674a8e1175bSopenharmony_ci if (ret != 0) { 675a8e1175bSopenharmony_ci return ret; 676a8e1175bSopenharmony_ci } 677a8e1175bSopenharmony_ci 678a8e1175bSopenharmony_ci if (p != end) { 679a8e1175bSopenharmony_ci /* 680a8e1175bSopenharmony_ci * Is 'publickey' present? If not, or if we can't read it (eg because it 681a8e1175bSopenharmony_ci * is compressed), create it from the private key. 682a8e1175bSopenharmony_ci */ 683a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 684a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 685a8e1175bSopenharmony_ci 1)) == 0) { 686a8e1175bSopenharmony_ci end2 = p + len; 687a8e1175bSopenharmony_ci 688a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) { 689a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 690a8e1175bSopenharmony_ci } 691a8e1175bSopenharmony_ci 692a8e1175bSopenharmony_ci if (p + len != end2) { 693a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 694a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 695a8e1175bSopenharmony_ci } 696a8e1175bSopenharmony_ci 697a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) { 698a8e1175bSopenharmony_ci pubkey_done = 1; 699a8e1175bSopenharmony_ci } else { 700a8e1175bSopenharmony_ci /* 701a8e1175bSopenharmony_ci * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above 702a8e1175bSopenharmony_ci * is if the point format is not recognized. 703a8e1175bSopenharmony_ci */ 704a8e1175bSopenharmony_ci if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { 705a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 706a8e1175bSopenharmony_ci } 707a8e1175bSopenharmony_ci } 708a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 709a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 710a8e1175bSopenharmony_ci } 711a8e1175bSopenharmony_ci } 712a8e1175bSopenharmony_ci 713a8e1175bSopenharmony_ci if (!pubkey_done) { 714a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) { 715a8e1175bSopenharmony_ci return ret; 716a8e1175bSopenharmony_ci } 717a8e1175bSopenharmony_ci } 718a8e1175bSopenharmony_ci 719a8e1175bSopenharmony_ci return 0; 720a8e1175bSopenharmony_ci} 721a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 722a8e1175bSopenharmony_ci 723a8e1175bSopenharmony_ci/*********************************************************************** 724a8e1175bSopenharmony_ci * 725a8e1175bSopenharmony_ci * PKCS#8 parsing functions 726a8e1175bSopenharmony_ci * 727a8e1175bSopenharmony_ci **********************************************************************/ 728a8e1175bSopenharmony_ci 729a8e1175bSopenharmony_ci/* 730a8e1175bSopenharmony_ci * Parse an unencrypted PKCS#8 encoded private key 731a8e1175bSopenharmony_ci * 732a8e1175bSopenharmony_ci * Notes: 733a8e1175bSopenharmony_ci * 734a8e1175bSopenharmony_ci * - This function does not own the key buffer. It is the 735a8e1175bSopenharmony_ci * responsibility of the caller to take care of zeroizing 736a8e1175bSopenharmony_ci * and freeing it after use. 737a8e1175bSopenharmony_ci * 738a8e1175bSopenharmony_ci * - The function is responsible for freeing the provided 739a8e1175bSopenharmony_ci * PK context on failure. 740a8e1175bSopenharmony_ci * 741a8e1175bSopenharmony_ci */ 742a8e1175bSopenharmony_cistatic int pk_parse_key_pkcs8_unencrypted_der( 743a8e1175bSopenharmony_ci mbedtls_pk_context *pk, 744a8e1175bSopenharmony_ci const unsigned char *key, size_t keylen, 745a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 746a8e1175bSopenharmony_ci{ 747a8e1175bSopenharmony_ci int ret, version; 748a8e1175bSopenharmony_ci size_t len; 749a8e1175bSopenharmony_ci mbedtls_asn1_buf params; 750a8e1175bSopenharmony_ci unsigned char *p = (unsigned char *) key; 751a8e1175bSopenharmony_ci unsigned char *end = p + keylen; 752a8e1175bSopenharmony_ci mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; 753a8e1175bSopenharmony_ci mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; 754a8e1175bSopenharmony_ci const mbedtls_pk_info_t *pk_info; 755a8e1175bSopenharmony_ci 756a8e1175bSopenharmony_ci#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) 757a8e1175bSopenharmony_ci (void) f_rng; 758a8e1175bSopenharmony_ci (void) p_rng; 759a8e1175bSopenharmony_ci#endif 760a8e1175bSopenharmony_ci 761a8e1175bSopenharmony_ci /* 762a8e1175bSopenharmony_ci * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) 763a8e1175bSopenharmony_ci * 764a8e1175bSopenharmony_ci * PrivateKeyInfo ::= SEQUENCE { 765a8e1175bSopenharmony_ci * version Version, 766a8e1175bSopenharmony_ci * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, 767a8e1175bSopenharmony_ci * privateKey PrivateKey, 768a8e1175bSopenharmony_ci * attributes [0] IMPLICIT Attributes OPTIONAL } 769a8e1175bSopenharmony_ci * 770a8e1175bSopenharmony_ci * Version ::= INTEGER 771a8e1175bSopenharmony_ci * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier 772a8e1175bSopenharmony_ci * PrivateKey ::= OCTET STRING 773a8e1175bSopenharmony_ci * 774a8e1175bSopenharmony_ci * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey 775a8e1175bSopenharmony_ci */ 776a8e1175bSopenharmony_ci 777a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 778a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 779a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 780a8e1175bSopenharmony_ci } 781a8e1175bSopenharmony_ci 782a8e1175bSopenharmony_ci end = p + len; 783a8e1175bSopenharmony_ci 784a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { 785a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 786a8e1175bSopenharmony_ci } 787a8e1175bSopenharmony_ci 788a8e1175bSopenharmony_ci if (version != 0) { 789a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret); 790a8e1175bSopenharmony_ci } 791a8e1175bSopenharmony_ci 792a8e1175bSopenharmony_ci if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms, &ec_grp_id)) != 0) { 793a8e1175bSopenharmony_ci return ret; 794a8e1175bSopenharmony_ci } 795a8e1175bSopenharmony_ci 796a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 797a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 798a8e1175bSopenharmony_ci } 799a8e1175bSopenharmony_ci 800a8e1175bSopenharmony_ci if (len < 1) { 801a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 802a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_OUT_OF_DATA); 803a8e1175bSopenharmony_ci } 804a8e1175bSopenharmony_ci 805a8e1175bSopenharmony_ci if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { 806a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 807a8e1175bSopenharmony_ci } 808a8e1175bSopenharmony_ci 809a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { 810a8e1175bSopenharmony_ci return ret; 811a8e1175bSopenharmony_ci } 812a8e1175bSopenharmony_ci 813a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 814a8e1175bSopenharmony_ci if (pk_alg == MBEDTLS_PK_RSA) { 815a8e1175bSopenharmony_ci if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) { 816a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 817a8e1175bSopenharmony_ci return ret; 818a8e1175bSopenharmony_ci } 819a8e1175bSopenharmony_ci } else 820a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */ 821a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) 822a8e1175bSopenharmony_ci if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { 823a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) 824a8e1175bSopenharmony_ci if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { 825a8e1175bSopenharmony_ci if ((ret = 826a8e1175bSopenharmony_ci pk_use_ecparams_rfc8410(¶ms, ec_grp_id, pk)) != 0 || 827a8e1175bSopenharmony_ci (ret = 828a8e1175bSopenharmony_ci pk_parse_key_rfc8410_der(pk, p, len, end, f_rng, 829a8e1175bSopenharmony_ci p_rng)) != 0) { 830a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 831a8e1175bSopenharmony_ci return ret; 832a8e1175bSopenharmony_ci } 833a8e1175bSopenharmony_ci } else 834a8e1175bSopenharmony_ci#endif 835a8e1175bSopenharmony_ci { 836a8e1175bSopenharmony_ci if ((ret = pk_use_ecparams(¶ms, pk)) != 0 || 837a8e1175bSopenharmony_ci (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) { 838a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 839a8e1175bSopenharmony_ci return ret; 840a8e1175bSopenharmony_ci } 841a8e1175bSopenharmony_ci } 842a8e1175bSopenharmony_ci } else 843a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 844a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 845a8e1175bSopenharmony_ci 846a8e1175bSopenharmony_ci end = p + len; 847a8e1175bSopenharmony_ci if (end != (key + keylen)) { 848a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 849a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 850a8e1175bSopenharmony_ci } 851a8e1175bSopenharmony_ci 852a8e1175bSopenharmony_ci return 0; 853a8e1175bSopenharmony_ci} 854a8e1175bSopenharmony_ci 855a8e1175bSopenharmony_ci/* 856a8e1175bSopenharmony_ci * Parse an encrypted PKCS#8 encoded private key 857a8e1175bSopenharmony_ci * 858a8e1175bSopenharmony_ci * To save space, the decryption happens in-place on the given key buffer. 859a8e1175bSopenharmony_ci * Also, while this function may modify the keybuffer, it doesn't own it, 860a8e1175bSopenharmony_ci * and instead it is the responsibility of the caller to zeroize and properly 861a8e1175bSopenharmony_ci * free it after use. 862a8e1175bSopenharmony_ci * 863a8e1175bSopenharmony_ci */ 864a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 865a8e1175bSopenharmony_ciMBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( 866a8e1175bSopenharmony_ci mbedtls_pk_context *pk, 867a8e1175bSopenharmony_ci unsigned char *key, size_t keylen, 868a8e1175bSopenharmony_ci const unsigned char *pwd, size_t pwdlen, 869a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 870a8e1175bSopenharmony_ci{ 871a8e1175bSopenharmony_ci int ret, decrypted = 0; 872a8e1175bSopenharmony_ci size_t len; 873a8e1175bSopenharmony_ci unsigned char *buf; 874a8e1175bSopenharmony_ci unsigned char *p, *end; 875a8e1175bSopenharmony_ci mbedtls_asn1_buf pbe_alg_oid, pbe_params; 876a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) 877a8e1175bSopenharmony_ci mbedtls_cipher_type_t cipher_alg; 878a8e1175bSopenharmony_ci mbedtls_md_type_t md_alg; 879a8e1175bSopenharmony_ci#endif 880a8e1175bSopenharmony_ci size_t outlen = 0; 881a8e1175bSopenharmony_ci 882a8e1175bSopenharmony_ci p = key; 883a8e1175bSopenharmony_ci end = p + keylen; 884a8e1175bSopenharmony_ci 885a8e1175bSopenharmony_ci if (pwdlen == 0) { 886a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; 887a8e1175bSopenharmony_ci } 888a8e1175bSopenharmony_ci 889a8e1175bSopenharmony_ci /* 890a8e1175bSopenharmony_ci * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) 891a8e1175bSopenharmony_ci * 892a8e1175bSopenharmony_ci * EncryptedPrivateKeyInfo ::= SEQUENCE { 893a8e1175bSopenharmony_ci * encryptionAlgorithm EncryptionAlgorithmIdentifier, 894a8e1175bSopenharmony_ci * encryptedData EncryptedData 895a8e1175bSopenharmony_ci * } 896a8e1175bSopenharmony_ci * 897a8e1175bSopenharmony_ci * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 898a8e1175bSopenharmony_ci * 899a8e1175bSopenharmony_ci * EncryptedData ::= OCTET STRING 900a8e1175bSopenharmony_ci * 901a8e1175bSopenharmony_ci * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo 902a8e1175bSopenharmony_ci * 903a8e1175bSopenharmony_ci */ 904a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 905a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 906a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 907a8e1175bSopenharmony_ci } 908a8e1175bSopenharmony_ci 909a8e1175bSopenharmony_ci end = p + len; 910a8e1175bSopenharmony_ci 911a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) { 912a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 913a8e1175bSopenharmony_ci } 914a8e1175bSopenharmony_ci 915a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 916a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 917a8e1175bSopenharmony_ci } 918a8e1175bSopenharmony_ci 919a8e1175bSopenharmony_ci buf = p; 920a8e1175bSopenharmony_ci 921a8e1175bSopenharmony_ci /* 922a8e1175bSopenharmony_ci * Decrypt EncryptedData with appropriate PBE 923a8e1175bSopenharmony_ci */ 924a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) 925a8e1175bSopenharmony_ci if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { 926a8e1175bSopenharmony_ci if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, 927a8e1175bSopenharmony_ci cipher_alg, md_alg, 928a8e1175bSopenharmony_ci pwd, pwdlen, p, len, buf, len, &outlen)) != 0) { 929a8e1175bSopenharmony_ci if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) { 930a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; 931a8e1175bSopenharmony_ci } 932a8e1175bSopenharmony_ci 933a8e1175bSopenharmony_ci return ret; 934a8e1175bSopenharmony_ci } 935a8e1175bSopenharmony_ci 936a8e1175bSopenharmony_ci decrypted = 1; 937a8e1175bSopenharmony_ci } else 938a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */ 939a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) 940a8e1175bSopenharmony_ci if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { 941a8e1175bSopenharmony_ci if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, 942a8e1175bSopenharmony_ci p, len, buf, len, &outlen)) != 0) { 943a8e1175bSopenharmony_ci if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) { 944a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; 945a8e1175bSopenharmony_ci } 946a8e1175bSopenharmony_ci 947a8e1175bSopenharmony_ci return ret; 948a8e1175bSopenharmony_ci } 949a8e1175bSopenharmony_ci 950a8e1175bSopenharmony_ci decrypted = 1; 951a8e1175bSopenharmony_ci } else 952a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */ 953a8e1175bSopenharmony_ci { 954a8e1175bSopenharmony_ci ((void) pwd); 955a8e1175bSopenharmony_ci } 956a8e1175bSopenharmony_ci 957a8e1175bSopenharmony_ci if (decrypted == 0) { 958a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 959a8e1175bSopenharmony_ci } 960a8e1175bSopenharmony_ci return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng); 961a8e1175bSopenharmony_ci} 962a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 963a8e1175bSopenharmony_ci 964a8e1175bSopenharmony_ci/*********************************************************************** 965a8e1175bSopenharmony_ci * 966a8e1175bSopenharmony_ci * Top-level functions, with format auto-discovery 967a8e1175bSopenharmony_ci * 968a8e1175bSopenharmony_ci **********************************************************************/ 969a8e1175bSopenharmony_ci 970a8e1175bSopenharmony_ci/* 971a8e1175bSopenharmony_ci * Parse a private key 972a8e1175bSopenharmony_ci */ 973a8e1175bSopenharmony_ciint mbedtls_pk_parse_key(mbedtls_pk_context *pk, 974a8e1175bSopenharmony_ci const unsigned char *key, size_t keylen, 975a8e1175bSopenharmony_ci const unsigned char *pwd, size_t pwdlen, 976a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 977a8e1175bSopenharmony_ci{ 978a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 979a8e1175bSopenharmony_ci const mbedtls_pk_info_t *pk_info; 980a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C) 981a8e1175bSopenharmony_ci size_t len; 982a8e1175bSopenharmony_ci mbedtls_pem_context pem; 983a8e1175bSopenharmony_ci#endif 984a8e1175bSopenharmony_ci 985a8e1175bSopenharmony_ci if (keylen == 0) { 986a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 987a8e1175bSopenharmony_ci } 988a8e1175bSopenharmony_ci 989a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C) 990a8e1175bSopenharmony_ci mbedtls_pem_init(&pem); 991a8e1175bSopenharmony_ci 992a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 993a8e1175bSopenharmony_ci /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 994a8e1175bSopenharmony_ci if (key[keylen - 1] != '\0') { 995a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 996a8e1175bSopenharmony_ci } else { 997a8e1175bSopenharmony_ci ret = mbedtls_pem_read_buffer(&pem, 998a8e1175bSopenharmony_ci PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA, 999a8e1175bSopenharmony_ci key, pwd, pwdlen, &len); 1000a8e1175bSopenharmony_ci } 1001a8e1175bSopenharmony_ci 1002a8e1175bSopenharmony_ci if (ret == 0) { 1003a8e1175bSopenharmony_ci pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); 1004a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || 1005a8e1175bSopenharmony_ci (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), 1006a8e1175bSopenharmony_ci pem.buf, pem.buflen)) != 0) { 1007a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 1008a8e1175bSopenharmony_ci } 1009a8e1175bSopenharmony_ci 1010a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1011a8e1175bSopenharmony_ci return ret; 1012a8e1175bSopenharmony_ci } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { 1013a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; 1014a8e1175bSopenharmony_ci } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { 1015a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; 1016a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1017a8e1175bSopenharmony_ci return ret; 1018a8e1175bSopenharmony_ci } 1019a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */ 1020a8e1175bSopenharmony_ci 1021a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) 1022a8e1175bSopenharmony_ci /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1023a8e1175bSopenharmony_ci if (key[keylen - 1] != '\0') { 1024a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1025a8e1175bSopenharmony_ci } else { 1026a8e1175bSopenharmony_ci ret = mbedtls_pem_read_buffer(&pem, 1027a8e1175bSopenharmony_ci PEM_BEGIN_PRIVATE_KEY_EC, 1028a8e1175bSopenharmony_ci PEM_END_PRIVATE_KEY_EC, 1029a8e1175bSopenharmony_ci key, pwd, pwdlen, &len); 1030a8e1175bSopenharmony_ci } 1031a8e1175bSopenharmony_ci if (ret == 0) { 1032a8e1175bSopenharmony_ci pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); 1033a8e1175bSopenharmony_ci 1034a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || 1035a8e1175bSopenharmony_ci (ret = pk_parse_key_sec1_der(pk, 1036a8e1175bSopenharmony_ci pem.buf, pem.buflen, 1037a8e1175bSopenharmony_ci f_rng, p_rng)) != 0) { 1038a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 1039a8e1175bSopenharmony_ci } 1040a8e1175bSopenharmony_ci 1041a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1042a8e1175bSopenharmony_ci return ret; 1043a8e1175bSopenharmony_ci } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { 1044a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; 1045a8e1175bSopenharmony_ci } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { 1046a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; 1047a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1048a8e1175bSopenharmony_ci return ret; 1049a8e1175bSopenharmony_ci } 1050a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 1051a8e1175bSopenharmony_ci 1052a8e1175bSopenharmony_ci /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1053a8e1175bSopenharmony_ci if (key[keylen - 1] != '\0') { 1054a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1055a8e1175bSopenharmony_ci } else { 1056a8e1175bSopenharmony_ci ret = mbedtls_pem_read_buffer(&pem, 1057a8e1175bSopenharmony_ci PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8, 1058a8e1175bSopenharmony_ci key, NULL, 0, &len); 1059a8e1175bSopenharmony_ci } 1060a8e1175bSopenharmony_ci if (ret == 0) { 1061a8e1175bSopenharmony_ci if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, 1062a8e1175bSopenharmony_ci pem.buf, pem.buflen, f_rng, p_rng)) != 0) { 1063a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 1064a8e1175bSopenharmony_ci } 1065a8e1175bSopenharmony_ci 1066a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1067a8e1175bSopenharmony_ci return ret; 1068a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1069a8e1175bSopenharmony_ci return ret; 1070a8e1175bSopenharmony_ci } 1071a8e1175bSopenharmony_ci 1072a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 1073a8e1175bSopenharmony_ci /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1074a8e1175bSopenharmony_ci if (key[keylen - 1] != '\0') { 1075a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1076a8e1175bSopenharmony_ci } else { 1077a8e1175bSopenharmony_ci ret = mbedtls_pem_read_buffer(&pem, 1078a8e1175bSopenharmony_ci PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8, 1079a8e1175bSopenharmony_ci PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8, 1080a8e1175bSopenharmony_ci key, NULL, 0, &len); 1081a8e1175bSopenharmony_ci } 1082a8e1175bSopenharmony_ci if (ret == 0) { 1083a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, 1084a8e1175bSopenharmony_ci pwd, pwdlen, f_rng, p_rng)) != 0) { 1085a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 1086a8e1175bSopenharmony_ci } 1087a8e1175bSopenharmony_ci 1088a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1089a8e1175bSopenharmony_ci return ret; 1090a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1091a8e1175bSopenharmony_ci return ret; 1092a8e1175bSopenharmony_ci } 1093a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 1094a8e1175bSopenharmony_ci#else 1095a8e1175bSopenharmony_ci ((void) pwd); 1096a8e1175bSopenharmony_ci ((void) pwdlen); 1097a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_PARSE_C */ 1098a8e1175bSopenharmony_ci 1099a8e1175bSopenharmony_ci /* 1100a8e1175bSopenharmony_ci * At this point we only know it's not a PEM formatted key. Could be any 1101a8e1175bSopenharmony_ci * of the known DER encoded private key formats 1102a8e1175bSopenharmony_ci * 1103a8e1175bSopenharmony_ci * We try the different DER format parsers to see if one passes without 1104a8e1175bSopenharmony_ci * error 1105a8e1175bSopenharmony_ci */ 1106a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 1107a8e1175bSopenharmony_ci if (pwdlen != 0) { 1108a8e1175bSopenharmony_ci unsigned char *key_copy; 1109a8e1175bSopenharmony_ci 1110a8e1175bSopenharmony_ci if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) { 1111a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_ALLOC_FAILED; 1112a8e1175bSopenharmony_ci } 1113a8e1175bSopenharmony_ci 1114a8e1175bSopenharmony_ci memcpy(key_copy, key, keylen); 1115a8e1175bSopenharmony_ci 1116a8e1175bSopenharmony_ci ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, 1117a8e1175bSopenharmony_ci pwd, pwdlen, f_rng, p_rng); 1118a8e1175bSopenharmony_ci 1119a8e1175bSopenharmony_ci mbedtls_zeroize_and_free(key_copy, keylen); 1120a8e1175bSopenharmony_ci } 1121a8e1175bSopenharmony_ci 1122a8e1175bSopenharmony_ci if (ret == 0) { 1123a8e1175bSopenharmony_ci return 0; 1124a8e1175bSopenharmony_ci } 1125a8e1175bSopenharmony_ci 1126a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 1127a8e1175bSopenharmony_ci mbedtls_pk_init(pk); 1128a8e1175bSopenharmony_ci 1129a8e1175bSopenharmony_ci if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { 1130a8e1175bSopenharmony_ci return ret; 1131a8e1175bSopenharmony_ci } 1132a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 1133a8e1175bSopenharmony_ci 1134a8e1175bSopenharmony_ci ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng); 1135a8e1175bSopenharmony_ci if (ret == 0) { 1136a8e1175bSopenharmony_ci return 0; 1137a8e1175bSopenharmony_ci } 1138a8e1175bSopenharmony_ci 1139a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 1140a8e1175bSopenharmony_ci mbedtls_pk_init(pk); 1141a8e1175bSopenharmony_ci 1142a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 1143a8e1175bSopenharmony_ci 1144a8e1175bSopenharmony_ci pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); 1145a8e1175bSopenharmony_ci if (mbedtls_pk_setup(pk, pk_info) == 0 && 1146a8e1175bSopenharmony_ci mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) { 1147a8e1175bSopenharmony_ci return 0; 1148a8e1175bSopenharmony_ci } 1149a8e1175bSopenharmony_ci 1150a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 1151a8e1175bSopenharmony_ci mbedtls_pk_init(pk); 1152a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */ 1153a8e1175bSopenharmony_ci 1154a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) 1155a8e1175bSopenharmony_ci pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); 1156a8e1175bSopenharmony_ci if (mbedtls_pk_setup(pk, pk_info) == 0 && 1157a8e1175bSopenharmony_ci pk_parse_key_sec1_der(pk, 1158a8e1175bSopenharmony_ci key, keylen, f_rng, p_rng) == 0) { 1159a8e1175bSopenharmony_ci return 0; 1160a8e1175bSopenharmony_ci } 1161a8e1175bSopenharmony_ci mbedtls_pk_free(pk); 1162a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 1163a8e1175bSopenharmony_ci 1164a8e1175bSopenharmony_ci /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't, 1165a8e1175bSopenharmony_ci * it is ok to leave the PK context initialized but not 1166a8e1175bSopenharmony_ci * freed: It is the caller's responsibility to call pk_init() 1167a8e1175bSopenharmony_ci * before calling this function, and to call pk_free() 1168a8e1175bSopenharmony_ci * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C 1169a8e1175bSopenharmony_ci * isn't, this leads to mbedtls_pk_free() being called 1170a8e1175bSopenharmony_ci * twice, once here and once by the caller, but this is 1171a8e1175bSopenharmony_ci * also ok and in line with the mbedtls_pk_free() calls 1172a8e1175bSopenharmony_ci * on failed PEM parsing attempts. */ 1173a8e1175bSopenharmony_ci 1174a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 1175a8e1175bSopenharmony_ci} 1176a8e1175bSopenharmony_ci 1177a8e1175bSopenharmony_ci/* 1178a8e1175bSopenharmony_ci * Parse a public key 1179a8e1175bSopenharmony_ci */ 1180a8e1175bSopenharmony_ciint mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, 1181a8e1175bSopenharmony_ci const unsigned char *key, size_t keylen) 1182a8e1175bSopenharmony_ci{ 1183a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1184a8e1175bSopenharmony_ci unsigned char *p; 1185a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 1186a8e1175bSopenharmony_ci const mbedtls_pk_info_t *pk_info; 1187a8e1175bSopenharmony_ci#endif 1188a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C) 1189a8e1175bSopenharmony_ci size_t len; 1190a8e1175bSopenharmony_ci mbedtls_pem_context pem; 1191a8e1175bSopenharmony_ci#endif 1192a8e1175bSopenharmony_ci 1193a8e1175bSopenharmony_ci if (keylen == 0) { 1194a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 1195a8e1175bSopenharmony_ci } 1196a8e1175bSopenharmony_ci 1197a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C) 1198a8e1175bSopenharmony_ci mbedtls_pem_init(&pem); 1199a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 1200a8e1175bSopenharmony_ci /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1201a8e1175bSopenharmony_ci if (key[keylen - 1] != '\0') { 1202a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1203a8e1175bSopenharmony_ci } else { 1204a8e1175bSopenharmony_ci ret = mbedtls_pem_read_buffer(&pem, 1205a8e1175bSopenharmony_ci PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA, 1206a8e1175bSopenharmony_ci key, NULL, 0, &len); 1207a8e1175bSopenharmony_ci } 1208a8e1175bSopenharmony_ci 1209a8e1175bSopenharmony_ci if (ret == 0) { 1210a8e1175bSopenharmony_ci p = pem.buf; 1211a8e1175bSopenharmony_ci if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { 1212a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1213a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 1214a8e1175bSopenharmony_ci } 1215a8e1175bSopenharmony_ci 1216a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { 1217a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1218a8e1175bSopenharmony_ci return ret; 1219a8e1175bSopenharmony_ci } 1220a8e1175bSopenharmony_ci 1221a8e1175bSopenharmony_ci if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) { 1222a8e1175bSopenharmony_ci mbedtls_pk_free(ctx); 1223a8e1175bSopenharmony_ci } 1224a8e1175bSopenharmony_ci 1225a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1226a8e1175bSopenharmony_ci return ret; 1227a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1228a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1229a8e1175bSopenharmony_ci return ret; 1230a8e1175bSopenharmony_ci } 1231a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */ 1232a8e1175bSopenharmony_ci 1233a8e1175bSopenharmony_ci /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1234a8e1175bSopenharmony_ci if (key[keylen - 1] != '\0') { 1235a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1236a8e1175bSopenharmony_ci } else { 1237a8e1175bSopenharmony_ci ret = mbedtls_pem_read_buffer(&pem, 1238a8e1175bSopenharmony_ci PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, 1239a8e1175bSopenharmony_ci key, NULL, 0, &len); 1240a8e1175bSopenharmony_ci } 1241a8e1175bSopenharmony_ci 1242a8e1175bSopenharmony_ci if (ret == 0) { 1243a8e1175bSopenharmony_ci /* 1244a8e1175bSopenharmony_ci * Was PEM encoded 1245a8e1175bSopenharmony_ci */ 1246a8e1175bSopenharmony_ci p = pem.buf; 1247a8e1175bSopenharmony_ci 1248a8e1175bSopenharmony_ci ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); 1249a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1250a8e1175bSopenharmony_ci return ret; 1251a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1252a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1253a8e1175bSopenharmony_ci return ret; 1254a8e1175bSopenharmony_ci } 1255a8e1175bSopenharmony_ci mbedtls_pem_free(&pem); 1256a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_PARSE_C */ 1257a8e1175bSopenharmony_ci 1258a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 1259a8e1175bSopenharmony_ci if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { 1260a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 1261a8e1175bSopenharmony_ci } 1262a8e1175bSopenharmony_ci 1263a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { 1264a8e1175bSopenharmony_ci return ret; 1265a8e1175bSopenharmony_ci } 1266a8e1175bSopenharmony_ci 1267a8e1175bSopenharmony_ci p = (unsigned char *) key; 1268a8e1175bSopenharmony_ci ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen); 1269a8e1175bSopenharmony_ci if (ret == 0) { 1270a8e1175bSopenharmony_ci return ret; 1271a8e1175bSopenharmony_ci } 1272a8e1175bSopenharmony_ci mbedtls_pk_free(ctx); 1273a8e1175bSopenharmony_ci if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 1274a8e1175bSopenharmony_ci return ret; 1275a8e1175bSopenharmony_ci } 1276a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */ 1277a8e1175bSopenharmony_ci p = (unsigned char *) key; 1278a8e1175bSopenharmony_ci 1279a8e1175bSopenharmony_ci ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx); 1280a8e1175bSopenharmony_ci 1281a8e1175bSopenharmony_ci return ret; 1282a8e1175bSopenharmony_ci} 1283a8e1175bSopenharmony_ci 1284a8e1175bSopenharmony_ci/*********************************************************************** 1285a8e1175bSopenharmony_ci * 1286a8e1175bSopenharmony_ci * Top-level functions, with filesystem support 1287a8e1175bSopenharmony_ci * 1288a8e1175bSopenharmony_ci **********************************************************************/ 1289a8e1175bSopenharmony_ci 1290a8e1175bSopenharmony_ci#if defined(MBEDTLS_FS_IO) 1291a8e1175bSopenharmony_ci/* 1292a8e1175bSopenharmony_ci * Load all data from a file into a given buffer. 1293a8e1175bSopenharmony_ci * 1294a8e1175bSopenharmony_ci * The file is expected to contain either PEM or DER encoded data. 1295a8e1175bSopenharmony_ci * A terminating null byte is always appended. It is included in the announced 1296a8e1175bSopenharmony_ci * length only if the data looks like it is PEM encoded. 1297a8e1175bSopenharmony_ci */ 1298a8e1175bSopenharmony_ciint mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) 1299a8e1175bSopenharmony_ci{ 1300a8e1175bSopenharmony_ci FILE *f; 1301a8e1175bSopenharmony_ci long size; 1302a8e1175bSopenharmony_ci 1303a8e1175bSopenharmony_ci if ((f = fopen(path, "rb")) == NULL) { 1304a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_FILE_IO_ERROR; 1305a8e1175bSopenharmony_ci } 1306a8e1175bSopenharmony_ci 1307a8e1175bSopenharmony_ci /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ 1308a8e1175bSopenharmony_ci mbedtls_setbuf(f, NULL); 1309a8e1175bSopenharmony_ci 1310a8e1175bSopenharmony_ci fseek(f, 0, SEEK_END); 1311a8e1175bSopenharmony_ci if ((size = ftell(f)) == -1) { 1312a8e1175bSopenharmony_ci fclose(f); 1313a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_FILE_IO_ERROR; 1314a8e1175bSopenharmony_ci } 1315a8e1175bSopenharmony_ci fseek(f, 0, SEEK_SET); 1316a8e1175bSopenharmony_ci 1317a8e1175bSopenharmony_ci *n = (size_t) size; 1318a8e1175bSopenharmony_ci 1319a8e1175bSopenharmony_ci if (*n + 1 == 0 || 1320a8e1175bSopenharmony_ci (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { 1321a8e1175bSopenharmony_ci fclose(f); 1322a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_ALLOC_FAILED; 1323a8e1175bSopenharmony_ci } 1324a8e1175bSopenharmony_ci 1325a8e1175bSopenharmony_ci if (fread(*buf, 1, *n, f) != *n) { 1326a8e1175bSopenharmony_ci fclose(f); 1327a8e1175bSopenharmony_ci 1328a8e1175bSopenharmony_ci mbedtls_zeroize_and_free(*buf, *n); 1329a8e1175bSopenharmony_ci 1330a8e1175bSopenharmony_ci return MBEDTLS_ERR_PK_FILE_IO_ERROR; 1331a8e1175bSopenharmony_ci } 1332a8e1175bSopenharmony_ci 1333a8e1175bSopenharmony_ci fclose(f); 1334a8e1175bSopenharmony_ci 1335a8e1175bSopenharmony_ci (*buf)[*n] = '\0'; 1336a8e1175bSopenharmony_ci 1337a8e1175bSopenharmony_ci if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { 1338a8e1175bSopenharmony_ci ++*n; 1339a8e1175bSopenharmony_ci } 1340a8e1175bSopenharmony_ci 1341a8e1175bSopenharmony_ci return 0; 1342a8e1175bSopenharmony_ci} 1343a8e1175bSopenharmony_ci 1344a8e1175bSopenharmony_ci/* 1345a8e1175bSopenharmony_ci * Load and parse a private key 1346a8e1175bSopenharmony_ci */ 1347a8e1175bSopenharmony_ciint mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, 1348a8e1175bSopenharmony_ci const char *path, const char *pwd, 1349a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 1350a8e1175bSopenharmony_ci{ 1351a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1352a8e1175bSopenharmony_ci size_t n; 1353a8e1175bSopenharmony_ci unsigned char *buf; 1354a8e1175bSopenharmony_ci 1355a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { 1356a8e1175bSopenharmony_ci return ret; 1357a8e1175bSopenharmony_ci } 1358a8e1175bSopenharmony_ci 1359a8e1175bSopenharmony_ci if (pwd == NULL) { 1360a8e1175bSopenharmony_ci ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng); 1361a8e1175bSopenharmony_ci } else { 1362a8e1175bSopenharmony_ci ret = mbedtls_pk_parse_key(ctx, buf, n, 1363a8e1175bSopenharmony_ci (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng); 1364a8e1175bSopenharmony_ci } 1365a8e1175bSopenharmony_ci 1366a8e1175bSopenharmony_ci mbedtls_zeroize_and_free(buf, n); 1367a8e1175bSopenharmony_ci 1368a8e1175bSopenharmony_ci return ret; 1369a8e1175bSopenharmony_ci} 1370a8e1175bSopenharmony_ci 1371a8e1175bSopenharmony_ci/* 1372a8e1175bSopenharmony_ci * Load and parse a public key 1373a8e1175bSopenharmony_ci */ 1374a8e1175bSopenharmony_ciint mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) 1375a8e1175bSopenharmony_ci{ 1376a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1377a8e1175bSopenharmony_ci size_t n; 1378a8e1175bSopenharmony_ci unsigned char *buf; 1379a8e1175bSopenharmony_ci 1380a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { 1381a8e1175bSopenharmony_ci return ret; 1382a8e1175bSopenharmony_ci } 1383a8e1175bSopenharmony_ci 1384a8e1175bSopenharmony_ci ret = mbedtls_pk_parse_public_key(ctx, buf, n); 1385a8e1175bSopenharmony_ci 1386a8e1175bSopenharmony_ci mbedtls_zeroize_and_free(buf, n); 1387a8e1175bSopenharmony_ci 1388a8e1175bSopenharmony_ci return ret; 1389a8e1175bSopenharmony_ci} 1390a8e1175bSopenharmony_ci#endif /* MBEDTLS_FS_IO */ 1391a8e1175bSopenharmony_ci 1392a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_PARSE_C */ 1393