1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * Public Key layer for parsing key files and structures 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 57901324dSJerome Forissier * SPDX-License-Identifier: Apache-2.0 6817466cbSJens Wiklander * 7817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8817466cbSJens Wiklander * not use this file except in compliance with the License. 9817466cbSJens Wiklander * You may obtain a copy of the License at 10817466cbSJens Wiklander * 11817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12817466cbSJens Wiklander * 13817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16817466cbSJens Wiklander * See the License for the specific language governing permissions and 17817466cbSJens Wiklander * limitations under the License. 18817466cbSJens Wiklander */ 19817466cbSJens Wiklander 207901324dSJerome Forissier #include "common.h" 21817466cbSJens Wiklander 22817466cbSJens Wiklander #if defined(MBEDTLS_PK_PARSE_C) 23817466cbSJens Wiklander 24817466cbSJens Wiklander #include "mbedtls/pk.h" 25817466cbSJens Wiklander #include "mbedtls/asn1.h" 26817466cbSJens Wiklander #include "mbedtls/oid.h" 273d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 2811fa71b9SJerome Forissier #include "mbedtls/error.h" 29817466cbSJens Wiklander 30817466cbSJens Wiklander #include <string.h> 31817466cbSJens Wiklander 32817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 33817466cbSJens Wiklander #include "mbedtls/rsa.h" 34817466cbSJens Wiklander #endif 35817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 36817466cbSJens Wiklander #include "mbedtls/ecp.h" 37817466cbSJens Wiklander #endif 38817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C) 39817466cbSJens Wiklander #include "mbedtls/ecdsa.h" 40817466cbSJens Wiklander #endif 41817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 42817466cbSJens Wiklander #include "mbedtls/pem.h" 43817466cbSJens Wiklander #endif 44817466cbSJens Wiklander #if defined(MBEDTLS_PKCS5_C) 45817466cbSJens Wiklander #include "mbedtls/pkcs5.h" 46817466cbSJens Wiklander #endif 47817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) 48817466cbSJens Wiklander #include "mbedtls/pkcs12.h" 49817466cbSJens Wiklander #endif 50817466cbSJens Wiklander 51817466cbSJens Wiklander #include "mbedtls/platform.h" 52817466cbSJens Wiklander 533d3b0591SJens Wiklander #if defined(MBEDTLS_FS_IO) 54817466cbSJens Wiklander /* 55817466cbSJens Wiklander * Load all data from a file into a given buffer. 56817466cbSJens Wiklander * 57817466cbSJens Wiklander * The file is expected to contain either PEM or DER encoded data. 58817466cbSJens Wiklander * A terminating null byte is always appended. It is included in the announced 59817466cbSJens Wiklander * length only if the data looks like it is PEM encoded. 60817466cbSJens Wiklander */ 61817466cbSJens Wiklander int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) 62817466cbSJens Wiklander { 63817466cbSJens Wiklander FILE *f; 64817466cbSJens Wiklander long size; 65817466cbSJens Wiklander 66*32b31808SJens Wiklander if ((f = fopen(path, "rb")) == NULL) { 67*32b31808SJens Wiklander return MBEDTLS_ERR_PK_FILE_IO_ERROR; 68*32b31808SJens Wiklander } 693d3b0591SJens Wiklander 70*32b31808SJens Wiklander /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ 71*32b31808SJens Wiklander mbedtls_setbuf(f, NULL); 72817466cbSJens Wiklander 73817466cbSJens Wiklander fseek(f, 0, SEEK_END); 74*32b31808SJens Wiklander if ((size = ftell(f)) == -1) { 75817466cbSJens Wiklander fclose(f); 76*32b31808SJens Wiklander return MBEDTLS_ERR_PK_FILE_IO_ERROR; 77817466cbSJens Wiklander } 78817466cbSJens Wiklander fseek(f, 0, SEEK_SET); 79817466cbSJens Wiklander 80817466cbSJens Wiklander *n = (size_t) size; 81817466cbSJens Wiklander 82817466cbSJens Wiklander if (*n + 1 == 0 || 83*32b31808SJens Wiklander (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { 84817466cbSJens Wiklander fclose(f); 85*32b31808SJens Wiklander return MBEDTLS_ERR_PK_ALLOC_FAILED; 86817466cbSJens Wiklander } 87817466cbSJens Wiklander 88*32b31808SJens Wiklander if (fread(*buf, 1, *n, f) != *n) { 89817466cbSJens Wiklander fclose(f); 903d3b0591SJens Wiklander 913d3b0591SJens Wiklander mbedtls_platform_zeroize(*buf, *n); 92817466cbSJens Wiklander mbedtls_free(*buf); 933d3b0591SJens Wiklander 94*32b31808SJens Wiklander return MBEDTLS_ERR_PK_FILE_IO_ERROR; 95817466cbSJens Wiklander } 96817466cbSJens Wiklander 97817466cbSJens Wiklander fclose(f); 98817466cbSJens Wiklander 99817466cbSJens Wiklander (*buf)[*n] = '\0'; 100817466cbSJens Wiklander 101*32b31808SJens Wiklander if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { 102817466cbSJens Wiklander ++*n; 103*32b31808SJens Wiklander } 104817466cbSJens Wiklander 105*32b31808SJens Wiklander return 0; 106817466cbSJens Wiklander } 107817466cbSJens Wiklander 108817466cbSJens Wiklander /* 109817466cbSJens Wiklander * Load and parse a private key 110817466cbSJens Wiklander */ 111817466cbSJens Wiklander int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, 112*32b31808SJens Wiklander const char *path, const char *pwd, 113*32b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 114817466cbSJens Wiklander { 11511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 116817466cbSJens Wiklander size_t n; 117817466cbSJens Wiklander unsigned char *buf; 118817466cbSJens Wiklander 119*32b31808SJens Wiklander if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { 120*32b31808SJens Wiklander return ret; 121*32b31808SJens Wiklander } 1223d3b0591SJens Wiklander 123*32b31808SJens Wiklander if (pwd == NULL) { 124*32b31808SJens Wiklander ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng); 125*32b31808SJens Wiklander } else { 126817466cbSJens Wiklander ret = mbedtls_pk_parse_key(ctx, buf, n, 127*32b31808SJens Wiklander (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng); 128*32b31808SJens Wiklander } 129817466cbSJens Wiklander 1303d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, n); 131817466cbSJens Wiklander mbedtls_free(buf); 132817466cbSJens Wiklander 133*32b31808SJens Wiklander return ret; 134817466cbSJens Wiklander } 135817466cbSJens Wiklander 136817466cbSJens Wiklander /* 137817466cbSJens Wiklander * Load and parse a public key 138817466cbSJens Wiklander */ 139817466cbSJens Wiklander int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) 140817466cbSJens Wiklander { 14111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 142817466cbSJens Wiklander size_t n; 143817466cbSJens Wiklander unsigned char *buf; 144817466cbSJens Wiklander 145*32b31808SJens Wiklander if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { 146*32b31808SJens Wiklander return ret; 147*32b31808SJens Wiklander } 148817466cbSJens Wiklander 149817466cbSJens Wiklander ret = mbedtls_pk_parse_public_key(ctx, buf, n); 150817466cbSJens Wiklander 1513d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, n); 152817466cbSJens Wiklander mbedtls_free(buf); 153817466cbSJens Wiklander 154*32b31808SJens Wiklander return ret; 155817466cbSJens Wiklander } 156817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 157817466cbSJens Wiklander 158817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 159817466cbSJens Wiklander /* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf 160817466cbSJens Wiklander * 161817466cbSJens Wiklander * ECParameters ::= CHOICE { 162817466cbSJens Wiklander * namedCurve OBJECT IDENTIFIER 163817466cbSJens Wiklander * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } 164817466cbSJens Wiklander * -- implicitCurve NULL 165817466cbSJens Wiklander * } 166817466cbSJens Wiklander */ 167817466cbSJens Wiklander static int pk_get_ecparams(unsigned char **p, const unsigned char *end, 168817466cbSJens Wiklander mbedtls_asn1_buf *params) 169817466cbSJens Wiklander { 17011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 171817466cbSJens Wiklander 172*32b31808SJens Wiklander if (end - *p < 1) { 173*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 174*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA); 175*32b31808SJens Wiklander } 1763d3b0591SJens Wiklander 177817466cbSJens Wiklander /* Tag may be either OID or SEQUENCE */ 178817466cbSJens Wiklander params->tag = **p; 179817466cbSJens Wiklander if (params->tag != MBEDTLS_ASN1_OID 180817466cbSJens Wiklander #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) 181817466cbSJens Wiklander && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) 182817466cbSJens Wiklander #endif 183*32b31808SJens Wiklander ) { 184*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 185*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 186817466cbSJens Wiklander } 187817466cbSJens Wiklander 188*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { 189*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 190817466cbSJens Wiklander } 191817466cbSJens Wiklander 192817466cbSJens Wiklander params->p = *p; 193817466cbSJens Wiklander *p += params->len; 194817466cbSJens Wiklander 195*32b31808SJens Wiklander if (*p != end) { 196*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 197*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 198*32b31808SJens Wiklander } 199817466cbSJens Wiklander 200*32b31808SJens Wiklander return 0; 201817466cbSJens Wiklander } 202817466cbSJens Wiklander 203817466cbSJens Wiklander #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) 204817466cbSJens Wiklander /* 205817466cbSJens Wiklander * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. 206817466cbSJens Wiklander * WARNING: the resulting group should only be used with 207817466cbSJens Wiklander * pk_group_id_from_specified(), since its base point may not be set correctly 208817466cbSJens Wiklander * if it was encoded compressed. 209817466cbSJens Wiklander * 210817466cbSJens Wiklander * SpecifiedECDomain ::= SEQUENCE { 211817466cbSJens Wiklander * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), 212817466cbSJens Wiklander * fieldID FieldID {{FieldTypes}}, 213817466cbSJens Wiklander * curve Curve, 214817466cbSJens Wiklander * base ECPoint, 215817466cbSJens Wiklander * order INTEGER, 216817466cbSJens Wiklander * cofactor INTEGER OPTIONAL, 217817466cbSJens Wiklander * hash HashAlgorithm OPTIONAL, 218817466cbSJens Wiklander * ... 219817466cbSJens Wiklander * } 220817466cbSJens Wiklander * 221817466cbSJens Wiklander * We only support prime-field as field type, and ignore hash and cofactor. 222817466cbSJens Wiklander */ 223817466cbSJens Wiklander static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) 224817466cbSJens Wiklander { 22511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 226817466cbSJens Wiklander unsigned char *p = params->p; 227817466cbSJens Wiklander const unsigned char * const end = params->p + params->len; 228817466cbSJens Wiklander const unsigned char *end_field, *end_curve; 229817466cbSJens Wiklander size_t len; 230817466cbSJens Wiklander int ver; 231817466cbSJens Wiklander 232817466cbSJens Wiklander /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ 233*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) { 234*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 235*32b31808SJens Wiklander } 236817466cbSJens Wiklander 237*32b31808SJens Wiklander if (ver < 1 || ver > 3) { 238*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 239*32b31808SJens Wiklander } 240817466cbSJens Wiklander 241817466cbSJens Wiklander /* 242817466cbSJens Wiklander * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field 243817466cbSJens Wiklander * fieldType FIELD-ID.&id({IOSet}), 244817466cbSJens Wiklander * parameters FIELD-ID.&Type({IOSet}{@fieldType}) 245817466cbSJens Wiklander * } 246817466cbSJens Wiklander */ 247817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 248*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 249*32b31808SJens Wiklander return ret; 250*32b31808SJens Wiklander } 251817466cbSJens Wiklander 252817466cbSJens Wiklander end_field = p + len; 253817466cbSJens Wiklander 254817466cbSJens Wiklander /* 255817466cbSJens Wiklander * FIELD-ID ::= TYPE-IDENTIFIER 256817466cbSJens Wiklander * FieldTypes FIELD-ID ::= { 257817466cbSJens Wiklander * { Prime-p IDENTIFIED BY prime-field } | 258817466cbSJens Wiklander * { Characteristic-two IDENTIFIED BY characteristic-two-field } 259817466cbSJens Wiklander * } 260817466cbSJens Wiklander * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } 261817466cbSJens Wiklander */ 262*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) { 263*32b31808SJens Wiklander return ret; 264*32b31808SJens Wiklander } 265817466cbSJens Wiklander 266817466cbSJens Wiklander if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) || 267*32b31808SJens Wiklander memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) { 268*32b31808SJens Wiklander return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 269817466cbSJens Wiklander } 270817466cbSJens Wiklander 271817466cbSJens Wiklander p += len; 272817466cbSJens Wiklander 273817466cbSJens Wiklander /* Prime-p ::= INTEGER -- Field of size p. */ 274*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) { 275*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 276*32b31808SJens Wiklander } 277817466cbSJens Wiklander 278817466cbSJens Wiklander grp->pbits = mbedtls_mpi_bitlen(&grp->P); 279817466cbSJens Wiklander 280*32b31808SJens Wiklander if (p != end_field) { 281*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 282*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 283*32b31808SJens Wiklander } 284817466cbSJens Wiklander 285817466cbSJens Wiklander /* 286817466cbSJens Wiklander * Curve ::= SEQUENCE { 287817466cbSJens Wiklander * a FieldElement, 288817466cbSJens Wiklander * b FieldElement, 289817466cbSJens Wiklander * seed BIT STRING OPTIONAL 290817466cbSJens Wiklander * -- Shall be present if used in SpecifiedECDomain 291817466cbSJens Wiklander * -- with version equal to ecdpVer2 or ecdpVer3 292817466cbSJens Wiklander * } 293817466cbSJens Wiklander */ 294817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 295*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 296*32b31808SJens Wiklander return ret; 297*32b31808SJens Wiklander } 298817466cbSJens Wiklander 299817466cbSJens Wiklander end_curve = p + len; 300817466cbSJens Wiklander 301817466cbSJens Wiklander /* 302817466cbSJens Wiklander * FieldElement ::= OCTET STRING 303817466cbSJens Wiklander * containing an integer in the case of a prime field 304817466cbSJens Wiklander */ 305817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || 306*32b31808SJens Wiklander (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) { 307*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 308817466cbSJens Wiklander } 309817466cbSJens Wiklander 310817466cbSJens Wiklander p += len; 311817466cbSJens Wiklander 312817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || 313*32b31808SJens Wiklander (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) { 314*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 315817466cbSJens Wiklander } 316817466cbSJens Wiklander 317817466cbSJens Wiklander p += len; 318817466cbSJens Wiklander 319817466cbSJens Wiklander /* Ignore seed BIT STRING OPTIONAL */ 320*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) { 321817466cbSJens Wiklander p += len; 322*32b31808SJens Wiklander } 323817466cbSJens Wiklander 324*32b31808SJens Wiklander if (p != end_curve) { 325*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 326*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 327*32b31808SJens Wiklander } 328817466cbSJens Wiklander 329817466cbSJens Wiklander /* 330817466cbSJens Wiklander * ECPoint ::= OCTET STRING 331817466cbSJens Wiklander */ 332*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 333*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 334*32b31808SJens Wiklander } 335817466cbSJens Wiklander 336817466cbSJens Wiklander if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G, 337*32b31808SJens Wiklander (const unsigned char *) p, len)) != 0) { 338817466cbSJens Wiklander /* 339817466cbSJens Wiklander * If we can't read the point because it's compressed, cheat by 340817466cbSJens Wiklander * reading only the X coordinate and the parity bit of Y. 341817466cbSJens Wiklander */ 342817466cbSJens Wiklander if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || 343817466cbSJens Wiklander (p[0] != 0x02 && p[0] != 0x03) || 344817466cbSJens Wiklander len != mbedtls_mpi_size(&grp->P) + 1 || 345817466cbSJens Wiklander mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 || 346817466cbSJens Wiklander mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 || 347*32b31808SJens Wiklander mbedtls_mpi_lset(&grp->G.Z, 1) != 0) { 348*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 349817466cbSJens Wiklander } 350817466cbSJens Wiklander } 351817466cbSJens Wiklander 352817466cbSJens Wiklander p += len; 353817466cbSJens Wiklander 354817466cbSJens Wiklander /* 355817466cbSJens Wiklander * order INTEGER 356817466cbSJens Wiklander */ 357*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) { 358*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 359*32b31808SJens Wiklander } 360817466cbSJens Wiklander 361817466cbSJens Wiklander grp->nbits = mbedtls_mpi_bitlen(&grp->N); 362817466cbSJens Wiklander 363817466cbSJens Wiklander /* 364817466cbSJens Wiklander * Allow optional elements by purposefully not enforcing p == end here. 365817466cbSJens Wiklander */ 366817466cbSJens Wiklander 367*32b31808SJens Wiklander return 0; 368817466cbSJens Wiklander } 369817466cbSJens Wiklander 370817466cbSJens Wiklander /* 371817466cbSJens Wiklander * Find the group id associated with an (almost filled) group as generated by 372817466cbSJens Wiklander * pk_group_from_specified(), or return an error if unknown. 373817466cbSJens Wiklander */ 374817466cbSJens Wiklander static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id) 375817466cbSJens Wiklander { 376817466cbSJens Wiklander int ret = 0; 377817466cbSJens Wiklander mbedtls_ecp_group ref; 378817466cbSJens Wiklander const mbedtls_ecp_group_id *id; 379817466cbSJens Wiklander 380817466cbSJens Wiklander mbedtls_ecp_group_init(&ref); 381817466cbSJens Wiklander 382*32b31808SJens Wiklander for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) { 383817466cbSJens Wiklander /* Load the group associated to that id */ 384817466cbSJens Wiklander mbedtls_ecp_group_free(&ref); 385817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id)); 386817466cbSJens Wiklander 387817466cbSJens Wiklander /* Compare to the group we were given, starting with easy tests */ 388817466cbSJens Wiklander if (grp->pbits == ref.pbits && grp->nbits == ref.nbits && 389817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 && 390817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 && 391817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 && 392817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 && 393817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 && 394817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 && 395817466cbSJens Wiklander /* For Y we may only know the parity bit, so compare only that */ 396*32b31808SJens Wiklander mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { 397817466cbSJens Wiklander break; 398817466cbSJens Wiklander } 399817466cbSJens Wiklander 400817466cbSJens Wiklander } 401817466cbSJens Wiklander 402817466cbSJens Wiklander cleanup: 403817466cbSJens Wiklander mbedtls_ecp_group_free(&ref); 404817466cbSJens Wiklander 405817466cbSJens Wiklander *grp_id = *id; 406817466cbSJens Wiklander 407*32b31808SJens Wiklander if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) { 408817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; 409*32b31808SJens Wiklander } 410817466cbSJens Wiklander 411*32b31808SJens Wiklander return ret; 412817466cbSJens Wiklander } 413817466cbSJens Wiklander 414817466cbSJens Wiklander /* 415817466cbSJens Wiklander * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID 416817466cbSJens Wiklander */ 417817466cbSJens Wiklander static int pk_group_id_from_specified(const mbedtls_asn1_buf *params, 418817466cbSJens Wiklander mbedtls_ecp_group_id *grp_id) 419817466cbSJens Wiklander { 42011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 421817466cbSJens Wiklander mbedtls_ecp_group grp; 422817466cbSJens Wiklander 423817466cbSJens Wiklander mbedtls_ecp_group_init(&grp); 424817466cbSJens Wiklander 425*32b31808SJens Wiklander if ((ret = pk_group_from_specified(params, &grp)) != 0) { 426817466cbSJens Wiklander goto cleanup; 427*32b31808SJens Wiklander } 428817466cbSJens Wiklander 429817466cbSJens Wiklander ret = pk_group_id_from_group(&grp, grp_id); 430817466cbSJens Wiklander 431817466cbSJens Wiklander cleanup: 432*32b31808SJens Wiklander /* The API respecting lifecycle for mbedtls_ecp_group struct is 433*32b31808SJens Wiklander * _init(), _load() and _free(). In pk_group_id_from_specified() the 434*32b31808SJens Wiklander * temporary grp breaks that flow and it's members are populated 435*32b31808SJens Wiklander * by pk_group_id_from_group(). As such mbedtls_ecp_group_free() 436*32b31808SJens Wiklander * which is assuming a group populated by _setup() may not clean-up 437*32b31808SJens Wiklander * properly -> Manually free it's members. 438*32b31808SJens Wiklander */ 439*32b31808SJens Wiklander mbedtls_mpi_free(&grp.N); 440*32b31808SJens Wiklander mbedtls_mpi_free(&grp.P); 441*32b31808SJens Wiklander mbedtls_mpi_free(&grp.A); 442*32b31808SJens Wiklander mbedtls_mpi_free(&grp.B); 443*32b31808SJens Wiklander mbedtls_ecp_point_free(&grp.G); 444817466cbSJens Wiklander 445*32b31808SJens Wiklander return ret; 446817466cbSJens Wiklander } 447817466cbSJens Wiklander #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ 448817466cbSJens Wiklander 449817466cbSJens Wiklander /* 450817466cbSJens Wiklander * Use EC parameters to initialise an EC group 451817466cbSJens Wiklander * 452817466cbSJens Wiklander * ECParameters ::= CHOICE { 453817466cbSJens Wiklander * namedCurve OBJECT IDENTIFIER 454817466cbSJens Wiklander * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } 455817466cbSJens Wiklander * -- implicitCurve NULL 456817466cbSJens Wiklander */ 457817466cbSJens Wiklander static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) 458817466cbSJens Wiklander { 45911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 460817466cbSJens Wiklander mbedtls_ecp_group_id grp_id; 461817466cbSJens Wiklander 462*32b31808SJens Wiklander if (params->tag == MBEDTLS_ASN1_OID) { 463*32b31808SJens Wiklander if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) { 464*32b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE; 465817466cbSJens Wiklander } 466*32b31808SJens Wiklander } else { 467817466cbSJens Wiklander #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) 468*32b31808SJens Wiklander if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) { 469*32b31808SJens Wiklander return ret; 470*32b31808SJens Wiklander } 471817466cbSJens Wiklander #else 472*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 473817466cbSJens Wiklander #endif 474817466cbSJens Wiklander } 475817466cbSJens Wiklander 476817466cbSJens Wiklander /* 477039e02dfSJerome Forissier * grp may already be initialized; if so, make sure IDs match 478817466cbSJens Wiklander */ 479*32b31808SJens Wiklander if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id) { 480*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 481*32b31808SJens Wiklander } 482817466cbSJens Wiklander 483*32b31808SJens Wiklander if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0) { 484*32b31808SJens Wiklander return ret; 485*32b31808SJens Wiklander } 486817466cbSJens Wiklander 487*32b31808SJens Wiklander return 0; 488817466cbSJens Wiklander } 489817466cbSJens Wiklander 490817466cbSJens Wiklander /* 491817466cbSJens Wiklander * EC public key is an EC point 492817466cbSJens Wiklander * 493817466cbSJens Wiklander * The caller is responsible for clearing the structure upon failure if 494817466cbSJens Wiklander * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE 495817466cbSJens Wiklander * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. 496817466cbSJens Wiklander */ 497817466cbSJens Wiklander static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end, 498817466cbSJens Wiklander mbedtls_ecp_keypair *key) 499817466cbSJens Wiklander { 50011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 501817466cbSJens Wiklander 502817466cbSJens Wiklander if ((ret = mbedtls_ecp_point_read_binary(&key->grp, &key->Q, 503*32b31808SJens Wiklander (const unsigned char *) *p, end - *p)) == 0) { 504817466cbSJens Wiklander ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q); 505817466cbSJens Wiklander } 506817466cbSJens Wiklander 507817466cbSJens Wiklander /* 508817466cbSJens Wiklander * We know mbedtls_ecp_point_read_binary consumed all bytes or failed 509817466cbSJens Wiklander */ 510817466cbSJens Wiklander *p = (unsigned char *) end; 511817466cbSJens Wiklander 512*32b31808SJens Wiklander return ret; 513817466cbSJens Wiklander } 514817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 515817466cbSJens Wiklander 516817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 517817466cbSJens Wiklander /* 518817466cbSJens Wiklander * RSAPublicKey ::= SEQUENCE { 519817466cbSJens Wiklander * modulus INTEGER, -- n 520817466cbSJens Wiklander * publicExponent INTEGER -- e 521817466cbSJens Wiklander * } 522817466cbSJens Wiklander */ 523817466cbSJens Wiklander static int pk_get_rsapubkey(unsigned char **p, 524817466cbSJens Wiklander const unsigned char *end, 525817466cbSJens Wiklander mbedtls_rsa_context *rsa) 526817466cbSJens Wiklander { 52711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 528817466cbSJens Wiklander size_t len; 529817466cbSJens Wiklander 530817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(p, end, &len, 531*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 532*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); 533*32b31808SJens Wiklander } 534817466cbSJens Wiklander 535*32b31808SJens Wiklander if (*p + len != end) { 536*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, 537*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 538*32b31808SJens Wiklander } 539817466cbSJens Wiklander 5403d3b0591SJens Wiklander /* Import N */ 541*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { 542*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); 543*32b31808SJens Wiklander } 544817466cbSJens Wiklander 5453d3b0591SJens Wiklander if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0, 546*32b31808SJens Wiklander NULL, 0, NULL, 0)) != 0) { 547*32b31808SJens Wiklander return MBEDTLS_ERR_PK_INVALID_PUBKEY; 548*32b31808SJens Wiklander } 5493d3b0591SJens Wiklander 5503d3b0591SJens Wiklander *p += len; 5513d3b0591SJens Wiklander 5523d3b0591SJens Wiklander /* Import E */ 553*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { 554*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); 555*32b31808SJens Wiklander } 5563d3b0591SJens Wiklander 5573d3b0591SJens Wiklander if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, 558*32b31808SJens Wiklander NULL, 0, *p, len)) != 0) { 559*32b31808SJens Wiklander return MBEDTLS_ERR_PK_INVALID_PUBKEY; 560*32b31808SJens Wiklander } 5613d3b0591SJens Wiklander 5623d3b0591SJens Wiklander *p += len; 5633d3b0591SJens Wiklander 5643d3b0591SJens Wiklander if (mbedtls_rsa_complete(rsa) != 0 || 565*32b31808SJens Wiklander mbedtls_rsa_check_pubkey(rsa) != 0) { 566*32b31808SJens Wiklander return MBEDTLS_ERR_PK_INVALID_PUBKEY; 5673d3b0591SJens Wiklander } 5683d3b0591SJens Wiklander 569*32b31808SJens Wiklander if (*p != end) { 570*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, 571*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 572*32b31808SJens Wiklander } 573817466cbSJens Wiklander 574*32b31808SJens Wiklander return 0; 575817466cbSJens Wiklander } 576817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 577817466cbSJens Wiklander 578817466cbSJens Wiklander /* Get a PK algorithm identifier 579817466cbSJens Wiklander * 580817466cbSJens Wiklander * AlgorithmIdentifier ::= SEQUENCE { 581817466cbSJens Wiklander * algorithm OBJECT IDENTIFIER, 582817466cbSJens Wiklander * parameters ANY DEFINED BY algorithm OPTIONAL } 583817466cbSJens Wiklander */ 584817466cbSJens Wiklander static int pk_get_pk_alg(unsigned char **p, 585817466cbSJens Wiklander const unsigned char *end, 586817466cbSJens Wiklander mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params) 587817466cbSJens Wiklander { 58811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 589817466cbSJens Wiklander mbedtls_asn1_buf alg_oid; 590817466cbSJens Wiklander 591817466cbSJens Wiklander memset(params, 0, sizeof(mbedtls_asn1_buf)); 592817466cbSJens Wiklander 593*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) { 594*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret); 595*32b31808SJens Wiklander } 596817466cbSJens Wiklander 597*32b31808SJens Wiklander if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0) { 598*32b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 599*32b31808SJens Wiklander } 600817466cbSJens Wiklander 601817466cbSJens Wiklander /* 602817466cbSJens Wiklander * No parameters with RSA (only for EC) 603817466cbSJens Wiklander */ 604817466cbSJens Wiklander if (*pk_alg == MBEDTLS_PK_RSA && 605817466cbSJens Wiklander ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) || 606*32b31808SJens Wiklander params->len != 0)) { 607*32b31808SJens Wiklander return MBEDTLS_ERR_PK_INVALID_ALG; 608817466cbSJens Wiklander } 609817466cbSJens Wiklander 610*32b31808SJens Wiklander return 0; 611817466cbSJens Wiklander } 612817466cbSJens Wiklander 613817466cbSJens Wiklander /* 614817466cbSJens Wiklander * SubjectPublicKeyInfo ::= SEQUENCE { 615817466cbSJens Wiklander * algorithm AlgorithmIdentifier, 616817466cbSJens Wiklander * subjectPublicKey BIT STRING } 617817466cbSJens Wiklander */ 618817466cbSJens Wiklander int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, 619817466cbSJens Wiklander mbedtls_pk_context *pk) 620817466cbSJens Wiklander { 62111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 622817466cbSJens Wiklander size_t len; 623817466cbSJens Wiklander mbedtls_asn1_buf alg_params; 624817466cbSJens Wiklander mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; 625817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info; 626817466cbSJens Wiklander 627817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(p, end, &len, 628*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 629*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 630817466cbSJens Wiklander } 631817466cbSJens Wiklander 632817466cbSJens Wiklander end = *p + len; 633817466cbSJens Wiklander 634*32b31808SJens Wiklander if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0) { 635*32b31808SJens Wiklander return ret; 636*32b31808SJens Wiklander } 637817466cbSJens Wiklander 638*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { 639*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); 640*32b31808SJens Wiklander } 641817466cbSJens Wiklander 642*32b31808SJens Wiklander if (*p + len != end) { 643*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, 644*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 645*32b31808SJens Wiklander } 646817466cbSJens Wiklander 647*32b31808SJens Wiklander if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { 648*32b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 649*32b31808SJens Wiklander } 650817466cbSJens Wiklander 651*32b31808SJens Wiklander if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { 652*32b31808SJens Wiklander return ret; 653*32b31808SJens Wiklander } 654817466cbSJens Wiklander 655817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 656*32b31808SJens Wiklander if (pk_alg == MBEDTLS_PK_RSA) { 657817466cbSJens Wiklander ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk)); 658817466cbSJens Wiklander } else 659817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 660817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 661*32b31808SJens Wiklander if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { 662817466cbSJens Wiklander ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp); 663*32b31808SJens Wiklander if (ret == 0) { 664817466cbSJens Wiklander ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk)); 665*32b31808SJens Wiklander } 666817466cbSJens Wiklander } else 667817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 668817466cbSJens Wiklander ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 669817466cbSJens Wiklander 670*32b31808SJens Wiklander if (ret == 0 && *p != end) { 6717901324dSJerome Forissier ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, 6727901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 673*32b31808SJens Wiklander } 674817466cbSJens Wiklander 675*32b31808SJens Wiklander if (ret != 0) { 676817466cbSJens Wiklander mbedtls_pk_free(pk); 677*32b31808SJens Wiklander } 678817466cbSJens Wiklander 679*32b31808SJens Wiklander return ret; 680817466cbSJens Wiklander } 681817466cbSJens Wiklander 682817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 683817466cbSJens Wiklander /* 6845b25c76aSJerome Forissier * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. 6855b25c76aSJerome Forissier * 6865b25c76aSJerome Forissier * The value zero is: 6875b25c76aSJerome Forissier * - never a valid value for an RSA parameter 6885b25c76aSJerome Forissier * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). 6895b25c76aSJerome Forissier * 6905b25c76aSJerome Forissier * Since values can't be omitted in PKCS#1, passing a zero value to 6915b25c76aSJerome Forissier * rsa_complete() would be incorrect, so reject zero values early. 6925b25c76aSJerome Forissier */ 6935b25c76aSJerome Forissier static int asn1_get_nonzero_mpi(unsigned char **p, 6945b25c76aSJerome Forissier const unsigned char *end, 6955b25c76aSJerome Forissier mbedtls_mpi *X) 6965b25c76aSJerome Forissier { 6975b25c76aSJerome Forissier int ret; 6985b25c76aSJerome Forissier 6995b25c76aSJerome Forissier ret = mbedtls_asn1_get_mpi(p, end, X); 700*32b31808SJens Wiklander if (ret != 0) { 701*32b31808SJens Wiklander return ret; 702*32b31808SJens Wiklander } 7035b25c76aSJerome Forissier 704*32b31808SJens Wiklander if (mbedtls_mpi_cmp_int(X, 0) == 0) { 705*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 706*32b31808SJens Wiklander } 7075b25c76aSJerome Forissier 708*32b31808SJens Wiklander return 0; 7095b25c76aSJerome Forissier } 7105b25c76aSJerome Forissier 7115b25c76aSJerome Forissier /* 712817466cbSJens Wiklander * Parse a PKCS#1 encoded private RSA key 713817466cbSJens Wiklander */ 714817466cbSJens Wiklander static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa, 715817466cbSJens Wiklander const unsigned char *key, 716817466cbSJens Wiklander size_t keylen) 717817466cbSJens Wiklander { 7183d3b0591SJens Wiklander int ret, version; 719817466cbSJens Wiklander size_t len; 720817466cbSJens Wiklander unsigned char *p, *end; 721817466cbSJens Wiklander 7223d3b0591SJens Wiklander mbedtls_mpi T; 7233d3b0591SJens Wiklander mbedtls_mpi_init(&T); 7243d3b0591SJens Wiklander 725817466cbSJens Wiklander p = (unsigned char *) key; 726817466cbSJens Wiklander end = p + keylen; 727817466cbSJens Wiklander 728817466cbSJens Wiklander /* 729817466cbSJens Wiklander * This function parses the RSAPrivateKey (PKCS#1) 730817466cbSJens Wiklander * 731817466cbSJens Wiklander * RSAPrivateKey ::= SEQUENCE { 732817466cbSJens Wiklander * version Version, 733817466cbSJens Wiklander * modulus INTEGER, -- n 734817466cbSJens Wiklander * publicExponent INTEGER, -- e 735817466cbSJens Wiklander * privateExponent INTEGER, -- d 736817466cbSJens Wiklander * prime1 INTEGER, -- p 737817466cbSJens Wiklander * prime2 INTEGER, -- q 738817466cbSJens Wiklander * exponent1 INTEGER, -- d mod (p-1) 739817466cbSJens Wiklander * exponent2 INTEGER, -- d mod (q-1) 740817466cbSJens Wiklander * coefficient INTEGER, -- (inverse of q) mod p 741817466cbSJens Wiklander * otherPrimeInfos OtherPrimeInfos OPTIONAL 742817466cbSJens Wiklander * } 743817466cbSJens Wiklander */ 744817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 745*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 746*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 747817466cbSJens Wiklander } 748817466cbSJens Wiklander 749817466cbSJens Wiklander end = p + len; 750817466cbSJens Wiklander 751*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { 752*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 753817466cbSJens Wiklander } 754817466cbSJens Wiklander 755*32b31808SJens Wiklander if (version != 0) { 756*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; 757817466cbSJens Wiklander } 758817466cbSJens Wiklander 7593d3b0591SJens Wiklander /* Import N */ 7605b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 7615b25c76aSJerome Forissier (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, 762*32b31808SJens Wiklander NULL, NULL)) != 0) { 7633d3b0591SJens Wiklander goto cleanup; 764*32b31808SJens Wiklander } 765817466cbSJens Wiklander 7663d3b0591SJens Wiklander /* Import E */ 7675b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 7685b25c76aSJerome Forissier (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, 769*32b31808SJens Wiklander NULL, &T)) != 0) { 7703d3b0591SJens Wiklander goto cleanup; 771*32b31808SJens Wiklander } 7723d3b0591SJens Wiklander 7733d3b0591SJens Wiklander /* Import D */ 7745b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 7755b25c76aSJerome Forissier (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, 776*32b31808SJens Wiklander &T, NULL)) != 0) { 7773d3b0591SJens Wiklander goto cleanup; 778*32b31808SJens Wiklander } 7793d3b0591SJens Wiklander 7803d3b0591SJens Wiklander /* Import P */ 7815b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 7825b25c76aSJerome Forissier (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, 783*32b31808SJens Wiklander NULL, NULL)) != 0) { 7843d3b0591SJens Wiklander goto cleanup; 785*32b31808SJens Wiklander } 7863d3b0591SJens Wiklander 7873d3b0591SJens Wiklander /* Import Q */ 7885b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 7895b25c76aSJerome Forissier (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, 790*32b31808SJens Wiklander NULL, NULL)) != 0) { 7913d3b0591SJens Wiklander goto cleanup; 792*32b31808SJens Wiklander } 7933d3b0591SJens Wiklander 7945b25c76aSJerome Forissier #if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) 7955b25c76aSJerome Forissier /* 7965b25c76aSJerome Forissier * The RSA CRT parameters DP, DQ and QP are nominally redundant, in 7975b25c76aSJerome Forissier * that they can be easily recomputed from D, P and Q. However by 7985b25c76aSJerome Forissier * parsing them from the PKCS1 structure it is possible to avoid 7995b25c76aSJerome Forissier * recalculating them which both reduces the overhead of loading 8005b25c76aSJerome Forissier * RSA private keys into memory and also avoids side channels which 8015b25c76aSJerome Forissier * can arise when computing those values, since all of D, P, and Q 8025b25c76aSJerome Forissier * are secret. See https://eprint.iacr.org/2020/055 for a 8035b25c76aSJerome Forissier * description of one such attack. 8045b25c76aSJerome Forissier */ 8055b25c76aSJerome Forissier 8065b25c76aSJerome Forissier /* Import DP */ 8075b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 808*32b31808SJens Wiklander (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) { 8093d3b0591SJens Wiklander goto cleanup; 810*32b31808SJens Wiklander } 811817466cbSJens Wiklander 8125b25c76aSJerome Forissier /* Import DQ */ 8135b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 814*32b31808SJens Wiklander (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) { 8155b25c76aSJerome Forissier goto cleanup; 816*32b31808SJens Wiklander } 8175b25c76aSJerome Forissier 8185b25c76aSJerome Forissier /* Import QP */ 8195b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 820*32b31808SJens Wiklander (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) { 8215b25c76aSJerome Forissier goto cleanup; 822*32b31808SJens Wiklander } 8235b25c76aSJerome Forissier 8245b25c76aSJerome Forissier #else 825039e02dfSJerome Forissier /* Verify existence of the CRT params */ 8265b25c76aSJerome Forissier if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 8275b25c76aSJerome Forissier (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || 828*32b31808SJens Wiklander (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) { 8295b25c76aSJerome Forissier goto cleanup; 830*32b31808SJens Wiklander } 8315b25c76aSJerome Forissier #endif 8325b25c76aSJerome Forissier 8335b25c76aSJerome Forissier /* rsa_complete() doesn't complete anything with the default 8345b25c76aSJerome Forissier * implementation but is still called: 8355b25c76aSJerome Forissier * - for the benefit of alternative implementation that may want to 8365b25c76aSJerome Forissier * pre-compute stuff beyond what's provided (eg Montgomery factors) 8375b25c76aSJerome Forissier * - as is also sanity-checks the key 8385b25c76aSJerome Forissier * 8395b25c76aSJerome Forissier * Furthermore, we also check the public part for consistency with 8405b25c76aSJerome Forissier * mbedtls_pk_parse_pubkey(), as it includes size minima for example. 8415b25c76aSJerome Forissier */ 8425b25c76aSJerome Forissier if ((ret = mbedtls_rsa_complete(rsa)) != 0 || 843*32b31808SJens Wiklander (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) { 8445b25c76aSJerome Forissier goto cleanup; 8455b25c76aSJerome Forissier } 8465b25c76aSJerome Forissier 847*32b31808SJens Wiklander if (p != end) { 8487901324dSJerome Forissier ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 8497901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 850817466cbSJens Wiklander } 851817466cbSJens Wiklander 8523d3b0591SJens Wiklander cleanup: 8533d3b0591SJens Wiklander 8543d3b0591SJens Wiklander mbedtls_mpi_free(&T); 8553d3b0591SJens Wiklander 856*32b31808SJens Wiklander if (ret != 0) { 8573d3b0591SJens Wiklander /* Wrap error code if it's coming from a lower level */ 858*32b31808SJens Wiklander if ((ret & 0xff80) == 0) { 8597901324dSJerome Forissier ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 860*32b31808SJens Wiklander } else { 8613d3b0591SJens Wiklander ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 862*32b31808SJens Wiklander } 8633d3b0591SJens Wiklander 864817466cbSJens Wiklander mbedtls_rsa_free(rsa); 865817466cbSJens Wiklander } 866817466cbSJens Wiklander 867*32b31808SJens Wiklander return ret; 868817466cbSJens Wiklander } 869817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 870817466cbSJens Wiklander 871817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 872817466cbSJens Wiklander /* 873817466cbSJens Wiklander * Parse a SEC1 encoded private EC key 874817466cbSJens Wiklander */ 875817466cbSJens Wiklander static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, 876*32b31808SJens Wiklander const unsigned char *key, size_t keylen, 877*32b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 878817466cbSJens Wiklander { 87911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 880817466cbSJens Wiklander int version, pubkey_done; 881817466cbSJens Wiklander size_t len; 882*32b31808SJens Wiklander mbedtls_asn1_buf params = { 0, 0, NULL }; 883817466cbSJens Wiklander unsigned char *p = (unsigned char *) key; 884817466cbSJens Wiklander unsigned char *end = p + keylen; 885817466cbSJens Wiklander unsigned char *end2; 886817466cbSJens Wiklander 887817466cbSJens Wiklander /* 888817466cbSJens Wiklander * RFC 5915, or SEC1 Appendix C.4 889817466cbSJens Wiklander * 890817466cbSJens Wiklander * ECPrivateKey ::= SEQUENCE { 891817466cbSJens Wiklander * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), 892817466cbSJens Wiklander * privateKey OCTET STRING, 893817466cbSJens Wiklander * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, 894817466cbSJens Wiklander * publicKey [1] BIT STRING OPTIONAL 895817466cbSJens Wiklander * } 896817466cbSJens Wiklander */ 897817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 898*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 899*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 900817466cbSJens Wiklander } 901817466cbSJens Wiklander 902817466cbSJens Wiklander end = p + len; 903817466cbSJens Wiklander 904*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { 905*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 906*32b31808SJens Wiklander } 907817466cbSJens Wiklander 908*32b31808SJens Wiklander if (version != 1) { 909*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; 910*32b31808SJens Wiklander } 911817466cbSJens Wiklander 912*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 913*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 914*32b31808SJens Wiklander } 915817466cbSJens Wiklander 916*32b31808SJens Wiklander if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) { 917817466cbSJens Wiklander mbedtls_ecp_keypair_free(eck); 918*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 919817466cbSJens Wiklander } 920817466cbSJens Wiklander 921817466cbSJens Wiklander p += len; 922817466cbSJens Wiklander 923817466cbSJens Wiklander pubkey_done = 0; 924*32b31808SJens Wiklander if (p != end) { 925817466cbSJens Wiklander /* 926817466cbSJens Wiklander * Is 'parameters' present? 927817466cbSJens Wiklander */ 928817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 929*32b31808SJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 930*32b31808SJens Wiklander 0)) == 0) { 931817466cbSJens Wiklander if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || 932*32b31808SJens Wiklander (ret = pk_use_ecparams(¶ms, &eck->grp)) != 0) { 933817466cbSJens Wiklander mbedtls_ecp_keypair_free(eck); 934*32b31808SJens Wiklander return ret; 935817466cbSJens Wiklander } 936*32b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 937817466cbSJens Wiklander mbedtls_ecp_keypair_free(eck); 938*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 939817466cbSJens Wiklander } 9403d3b0591SJens Wiklander } 941817466cbSJens Wiklander 942*32b31808SJens Wiklander if (p != end) { 943817466cbSJens Wiklander /* 944817466cbSJens Wiklander * Is 'publickey' present? If not, or if we can't read it (eg because it 945817466cbSJens Wiklander * is compressed), create it from the private key. 946817466cbSJens Wiklander */ 947817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 948*32b31808SJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 949*32b31808SJens Wiklander 1)) == 0) { 950817466cbSJens Wiklander end2 = p + len; 951817466cbSJens Wiklander 952*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) { 953*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 954*32b31808SJens Wiklander } 955817466cbSJens Wiklander 956*32b31808SJens Wiklander if (p + len != end2) { 957*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 958*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 959*32b31808SJens Wiklander } 960817466cbSJens Wiklander 961*32b31808SJens Wiklander if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) { 962817466cbSJens Wiklander pubkey_done = 1; 963*32b31808SJens Wiklander } else { 964817466cbSJens Wiklander /* 965817466cbSJens Wiklander * The only acceptable failure mode of pk_get_ecpubkey() above 966817466cbSJens Wiklander * is if the point format is not recognized. 967817466cbSJens Wiklander */ 968*32b31808SJens Wiklander if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { 969*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 970817466cbSJens Wiklander } 971817466cbSJens Wiklander } 972*32b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 973817466cbSJens Wiklander mbedtls_ecp_keypair_free(eck); 974*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 975817466cbSJens Wiklander } 976817466cbSJens Wiklander } 977817466cbSJens Wiklander 978817466cbSJens Wiklander if (!pubkey_done && 979817466cbSJens Wiklander (ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, 980*32b31808SJens Wiklander f_rng, p_rng)) != 0) { 981817466cbSJens Wiklander mbedtls_ecp_keypair_free(eck); 982*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 983817466cbSJens Wiklander } 984817466cbSJens Wiklander 985*32b31808SJens Wiklander if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) { 986817466cbSJens Wiklander mbedtls_ecp_keypair_free(eck); 987*32b31808SJens Wiklander return ret; 988817466cbSJens Wiklander } 989817466cbSJens Wiklander 990*32b31808SJens Wiklander return 0; 991817466cbSJens Wiklander } 992817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 993817466cbSJens Wiklander 994817466cbSJens Wiklander /* 995817466cbSJens Wiklander * Parse an unencrypted PKCS#8 encoded private key 9963d3b0591SJens Wiklander * 9973d3b0591SJens Wiklander * Notes: 9983d3b0591SJens Wiklander * 9993d3b0591SJens Wiklander * - This function does not own the key buffer. It is the 10003d3b0591SJens Wiklander * responsibility of the caller to take care of zeroizing 10013d3b0591SJens Wiklander * and freeing it after use. 10023d3b0591SJens Wiklander * 10033d3b0591SJens Wiklander * - The function is responsible for freeing the provided 10043d3b0591SJens Wiklander * PK context on failure. 10053d3b0591SJens Wiklander * 1006817466cbSJens Wiklander */ 1007817466cbSJens Wiklander static int pk_parse_key_pkcs8_unencrypted_der( 1008817466cbSJens Wiklander mbedtls_pk_context *pk, 1009*32b31808SJens Wiklander const unsigned char *key, size_t keylen, 1010*32b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 1011817466cbSJens Wiklander { 1012817466cbSJens Wiklander int ret, version; 1013817466cbSJens Wiklander size_t len; 1014817466cbSJens Wiklander mbedtls_asn1_buf params; 1015817466cbSJens Wiklander unsigned char *p = (unsigned char *) key; 1016817466cbSJens Wiklander unsigned char *end = p + keylen; 1017817466cbSJens Wiklander mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; 1018817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info; 1019817466cbSJens Wiklander 1020*32b31808SJens Wiklander #if !defined(MBEDTLS_ECP_C) 1021*32b31808SJens Wiklander (void) f_rng; 1022*32b31808SJens Wiklander (void) p_rng; 1023*32b31808SJens Wiklander #endif 1024*32b31808SJens Wiklander 1025817466cbSJens Wiklander /* 10263d3b0591SJens Wiklander * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) 1027817466cbSJens Wiklander * 1028817466cbSJens Wiklander * PrivateKeyInfo ::= SEQUENCE { 1029817466cbSJens Wiklander * version Version, 1030817466cbSJens Wiklander * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, 1031817466cbSJens Wiklander * privateKey PrivateKey, 1032817466cbSJens Wiklander * attributes [0] IMPLICIT Attributes OPTIONAL } 1033817466cbSJens Wiklander * 1034817466cbSJens Wiklander * Version ::= INTEGER 1035817466cbSJens Wiklander * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier 1036817466cbSJens Wiklander * PrivateKey ::= OCTET STRING 1037817466cbSJens Wiklander * 1038817466cbSJens Wiklander * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey 1039817466cbSJens Wiklander */ 1040817466cbSJens Wiklander 1041817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1042*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 1043*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 1044817466cbSJens Wiklander } 1045817466cbSJens Wiklander 1046817466cbSJens Wiklander end = p + len; 1047817466cbSJens Wiklander 1048*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { 1049*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 10507901324dSJerome Forissier } 1051817466cbSJens Wiklander 1052*32b31808SJens Wiklander if (version != 0) { 1053*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret); 1054*32b31808SJens Wiklander } 1055817466cbSJens Wiklander 1056*32b31808SJens Wiklander if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms)) != 0) { 1057*32b31808SJens Wiklander return ret; 1058*32b31808SJens Wiklander } 1059817466cbSJens Wiklander 1060*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 1061*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 1062*32b31808SJens Wiklander } 1063817466cbSJens Wiklander 1064*32b31808SJens Wiklander if (len < 1) { 1065*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 1066*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA); 1067*32b31808SJens Wiklander } 1068*32b31808SJens Wiklander 1069*32b31808SJens Wiklander if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { 1070*32b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 1071*32b31808SJens Wiklander } 1072*32b31808SJens Wiklander 1073*32b31808SJens Wiklander if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { 1074*32b31808SJens Wiklander return ret; 1075*32b31808SJens Wiklander } 1076817466cbSJens Wiklander 1077817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 1078*32b31808SJens Wiklander if (pk_alg == MBEDTLS_PK_RSA) { 1079*32b31808SJens Wiklander if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) { 1080817466cbSJens Wiklander mbedtls_pk_free(pk); 1081*32b31808SJens Wiklander return ret; 1082817466cbSJens Wiklander } 1083817466cbSJens Wiklander } else 1084817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 1085817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 1086*32b31808SJens Wiklander if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { 1087817466cbSJens Wiklander if ((ret = pk_use_ecparams(¶ms, &mbedtls_pk_ec(*pk)->grp)) != 0 || 1088*32b31808SJens Wiklander (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len, f_rng, p_rng)) != 0) { 1089817466cbSJens Wiklander mbedtls_pk_free(pk); 1090*32b31808SJens Wiklander return ret; 1091817466cbSJens Wiklander } 1092817466cbSJens Wiklander } else 1093817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 1094*32b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 1095817466cbSJens Wiklander 1096*32b31808SJens Wiklander return 0; 1097817466cbSJens Wiklander } 1098817466cbSJens Wiklander 1099817466cbSJens Wiklander /* 1100817466cbSJens Wiklander * Parse an encrypted PKCS#8 encoded private key 11013d3b0591SJens Wiklander * 11023d3b0591SJens Wiklander * To save space, the decryption happens in-place on the given key buffer. 11033d3b0591SJens Wiklander * Also, while this function may modify the keybuffer, it doesn't own it, 11043d3b0591SJens Wiklander * and instead it is the responsibility of the caller to zeroize and properly 11053d3b0591SJens Wiklander * free it after use. 11063d3b0591SJens Wiklander * 1107817466cbSJens Wiklander */ 1108817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 1109817466cbSJens Wiklander static int pk_parse_key_pkcs8_encrypted_der( 1110817466cbSJens Wiklander mbedtls_pk_context *pk, 11113d3b0591SJens Wiklander unsigned char *key, size_t keylen, 1112*32b31808SJens Wiklander const unsigned char *pwd, size_t pwdlen, 1113*32b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 1114817466cbSJens Wiklander { 1115817466cbSJens Wiklander int ret, decrypted = 0; 1116817466cbSJens Wiklander size_t len; 11173d3b0591SJens Wiklander unsigned char *buf; 1118817466cbSJens Wiklander unsigned char *p, *end; 1119817466cbSJens Wiklander mbedtls_asn1_buf pbe_alg_oid, pbe_params; 1120817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) 1121817466cbSJens Wiklander mbedtls_cipher_type_t cipher_alg; 1122817466cbSJens Wiklander mbedtls_md_type_t md_alg; 1123817466cbSJens Wiklander #endif 1124817466cbSJens Wiklander 11253d3b0591SJens Wiklander p = key; 1126817466cbSJens Wiklander end = p + keylen; 1127817466cbSJens Wiklander 1128*32b31808SJens Wiklander if (pwdlen == 0) { 1129*32b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; 1130*32b31808SJens Wiklander } 1131817466cbSJens Wiklander 1132817466cbSJens Wiklander /* 11333d3b0591SJens Wiklander * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) 1134817466cbSJens Wiklander * 1135817466cbSJens Wiklander * EncryptedPrivateKeyInfo ::= SEQUENCE { 1136817466cbSJens Wiklander * encryptionAlgorithm EncryptionAlgorithmIdentifier, 1137817466cbSJens Wiklander * encryptedData EncryptedData 1138817466cbSJens Wiklander * } 1139817466cbSJens Wiklander * 1140817466cbSJens Wiklander * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 1141817466cbSJens Wiklander * 1142817466cbSJens Wiklander * EncryptedData ::= OCTET STRING 1143817466cbSJens Wiklander * 1144817466cbSJens Wiklander * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo 11453d3b0591SJens Wiklander * 1146817466cbSJens Wiklander */ 1147817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1148*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 1149*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 1150817466cbSJens Wiklander } 1151817466cbSJens Wiklander 1152817466cbSJens Wiklander end = p + len; 1153817466cbSJens Wiklander 1154*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) { 1155*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 1156*32b31808SJens Wiklander } 1157817466cbSJens Wiklander 1158*32b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 1159*32b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 1160*32b31808SJens Wiklander } 1161817466cbSJens Wiklander 11623d3b0591SJens Wiklander buf = p; 1163817466cbSJens Wiklander 1164817466cbSJens Wiklander /* 11653d3b0591SJens Wiklander * Decrypt EncryptedData with appropriate PBE 1166817466cbSJens Wiklander */ 1167817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) 1168*32b31808SJens Wiklander if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { 1169817466cbSJens Wiklander if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, 1170817466cbSJens Wiklander cipher_alg, md_alg, 1171*32b31808SJens Wiklander pwd, pwdlen, p, len, buf)) != 0) { 1172*32b31808SJens Wiklander if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) { 1173*32b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; 1174*32b31808SJens Wiklander } 1175817466cbSJens Wiklander 1176*32b31808SJens Wiklander return ret; 1177817466cbSJens Wiklander } 1178817466cbSJens Wiklander 1179817466cbSJens Wiklander decrypted = 1; 1180*32b31808SJens Wiklander } else 1181817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C */ 1182817466cbSJens Wiklander #if defined(MBEDTLS_PKCS5_C) 1183*32b31808SJens Wiklander if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { 1184817466cbSJens Wiklander if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, 1185*32b31808SJens Wiklander p, len, buf)) != 0) { 1186*32b31808SJens Wiklander if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) { 1187*32b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; 1188*32b31808SJens Wiklander } 1189817466cbSJens Wiklander 1190*32b31808SJens Wiklander return ret; 1191817466cbSJens Wiklander } 1192817466cbSJens Wiklander 1193817466cbSJens Wiklander decrypted = 1; 1194*32b31808SJens Wiklander } else 1195817466cbSJens Wiklander #endif /* MBEDTLS_PKCS5_C */ 1196817466cbSJens Wiklander { 1197817466cbSJens Wiklander ((void) pwd); 1198817466cbSJens Wiklander } 1199817466cbSJens Wiklander 1200*32b31808SJens Wiklander if (decrypted == 0) { 1201*32b31808SJens Wiklander return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; 1202*32b31808SJens Wiklander } 1203817466cbSJens Wiklander 1204*32b31808SJens Wiklander return pk_parse_key_pkcs8_unencrypted_der(pk, buf, len, f_rng, p_rng); 1205817466cbSJens Wiklander } 1206817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 1207817466cbSJens Wiklander 1208817466cbSJens Wiklander /* 1209817466cbSJens Wiklander * Parse a private key 1210817466cbSJens Wiklander */ 1211817466cbSJens Wiklander int mbedtls_pk_parse_key(mbedtls_pk_context *pk, 1212817466cbSJens Wiklander const unsigned char *key, size_t keylen, 1213*32b31808SJens Wiklander const unsigned char *pwd, size_t pwdlen, 1214*32b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 1215817466cbSJens Wiklander { 121611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1217817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info; 1218817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 1219817466cbSJens Wiklander size_t len; 1220817466cbSJens Wiklander mbedtls_pem_context pem; 12213d3b0591SJens Wiklander #endif 1222817466cbSJens Wiklander 1223*32b31808SJens Wiklander if (keylen == 0) { 1224*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 1225*32b31808SJens Wiklander } 12263d3b0591SJens Wiklander 12273d3b0591SJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 1228817466cbSJens Wiklander mbedtls_pem_init(&pem); 1229817466cbSJens Wiklander 1230817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 1231817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1232*32b31808SJens Wiklander if (key[keylen - 1] != '\0') { 1233817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1234*32b31808SJens Wiklander } else { 1235817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem, 1236817466cbSJens Wiklander "-----BEGIN RSA PRIVATE KEY-----", 1237817466cbSJens Wiklander "-----END RSA PRIVATE KEY-----", 1238817466cbSJens Wiklander key, pwd, pwdlen, &len); 1239*32b31808SJens Wiklander } 1240817466cbSJens Wiklander 1241*32b31808SJens Wiklander if (ret == 0) { 12423d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); 1243817466cbSJens Wiklander if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || 1244817466cbSJens Wiklander (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), 1245*32b31808SJens Wiklander pem.buf, pem.buflen)) != 0) { 1246817466cbSJens Wiklander mbedtls_pk_free(pk); 1247817466cbSJens Wiklander } 1248817466cbSJens Wiklander 1249817466cbSJens Wiklander mbedtls_pem_free(&pem); 1250*32b31808SJens Wiklander return ret; 1251*32b31808SJens Wiklander } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { 1252*32b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; 1253*32b31808SJens Wiklander } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { 1254*32b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; 1255*32b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1256*32b31808SJens Wiklander return ret; 1257817466cbSJens Wiklander } 1258817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 1259817466cbSJens Wiklander 1260817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 1261817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1262*32b31808SJens Wiklander if (key[keylen - 1] != '\0') { 1263817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1264*32b31808SJens Wiklander } else { 1265817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem, 1266817466cbSJens Wiklander "-----BEGIN EC PRIVATE KEY-----", 1267817466cbSJens Wiklander "-----END EC PRIVATE KEY-----", 1268817466cbSJens Wiklander key, pwd, pwdlen, &len); 1269*32b31808SJens Wiklander } 1270*32b31808SJens Wiklander if (ret == 0) { 12713d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); 1272817466cbSJens Wiklander 1273817466cbSJens Wiklander if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || 1274817466cbSJens Wiklander (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), 1275*32b31808SJens Wiklander pem.buf, pem.buflen, 1276*32b31808SJens Wiklander f_rng, p_rng)) != 0) { 1277817466cbSJens Wiklander mbedtls_pk_free(pk); 1278817466cbSJens Wiklander } 1279817466cbSJens Wiklander 1280817466cbSJens Wiklander mbedtls_pem_free(&pem); 1281*32b31808SJens Wiklander return ret; 1282*32b31808SJens Wiklander } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { 1283*32b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; 1284*32b31808SJens Wiklander } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { 1285*32b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; 1286*32b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1287*32b31808SJens Wiklander return ret; 1288817466cbSJens Wiklander } 1289817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 1290817466cbSJens Wiklander 1291817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1292*32b31808SJens Wiklander if (key[keylen - 1] != '\0') { 1293817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1294*32b31808SJens Wiklander } else { 1295817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem, 1296817466cbSJens Wiklander "-----BEGIN PRIVATE KEY-----", 1297817466cbSJens Wiklander "-----END PRIVATE KEY-----", 1298817466cbSJens Wiklander key, NULL, 0, &len); 1299*32b31808SJens Wiklander } 1300*32b31808SJens Wiklander if (ret == 0) { 1301817466cbSJens Wiklander if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, 1302*32b31808SJens Wiklander pem.buf, pem.buflen, f_rng, p_rng)) != 0) { 1303817466cbSJens Wiklander mbedtls_pk_free(pk); 1304817466cbSJens Wiklander } 1305817466cbSJens Wiklander 1306817466cbSJens Wiklander mbedtls_pem_free(&pem); 1307*32b31808SJens Wiklander return ret; 1308*32b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1309*32b31808SJens Wiklander return ret; 1310817466cbSJens Wiklander } 1311817466cbSJens Wiklander 1312817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 1313817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1314*32b31808SJens Wiklander if (key[keylen - 1] != '\0') { 1315817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1316*32b31808SJens Wiklander } else { 1317817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem, 1318817466cbSJens Wiklander "-----BEGIN ENCRYPTED PRIVATE KEY-----", 1319817466cbSJens Wiklander "-----END ENCRYPTED PRIVATE KEY-----", 1320817466cbSJens Wiklander key, NULL, 0, &len); 1321*32b31808SJens Wiklander } 1322*32b31808SJens Wiklander if (ret == 0) { 1323*32b31808SJens Wiklander if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, 1324*32b31808SJens Wiklander pwd, pwdlen, f_rng, p_rng)) != 0) { 1325817466cbSJens Wiklander mbedtls_pk_free(pk); 1326817466cbSJens Wiklander } 1327817466cbSJens Wiklander 1328817466cbSJens Wiklander mbedtls_pem_free(&pem); 1329*32b31808SJens Wiklander return ret; 1330*32b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1331*32b31808SJens Wiklander return ret; 1332817466cbSJens Wiklander } 1333817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 1334817466cbSJens Wiklander #else 1335817466cbSJens Wiklander ((void) pwd); 1336817466cbSJens Wiklander ((void) pwdlen); 1337817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */ 1338817466cbSJens Wiklander 1339817466cbSJens Wiklander /* 1340817466cbSJens Wiklander * At this point we only know it's not a PEM formatted key. Could be any 1341817466cbSJens Wiklander * of the known DER encoded private key formats 1342817466cbSJens Wiklander * 1343817466cbSJens Wiklander * We try the different DER format parsers to see if one passes without 1344817466cbSJens Wiklander * error 1345817466cbSJens Wiklander */ 1346817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 1347*32b31808SJens Wiklander if (pwdlen != 0) { 13483d3b0591SJens Wiklander unsigned char *key_copy; 13493d3b0591SJens Wiklander 1350*32b31808SJens Wiklander if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) { 1351*32b31808SJens Wiklander return MBEDTLS_ERR_PK_ALLOC_FAILED; 1352*32b31808SJens Wiklander } 13533d3b0591SJens Wiklander 13543d3b0591SJens Wiklander memcpy(key_copy, key, keylen); 13553d3b0591SJens Wiklander 13563d3b0591SJens Wiklander ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, 1357*32b31808SJens Wiklander pwd, pwdlen, f_rng, p_rng); 13583d3b0591SJens Wiklander 13593d3b0591SJens Wiklander mbedtls_platform_zeroize(key_copy, keylen); 13603d3b0591SJens Wiklander mbedtls_free(key_copy); 1361817466cbSJens Wiklander } 1362817466cbSJens Wiklander 1363*32b31808SJens Wiklander if (ret == 0) { 1364*32b31808SJens Wiklander return 0; 1365*32b31808SJens Wiklander } 13663d3b0591SJens Wiklander 1367817466cbSJens Wiklander mbedtls_pk_free(pk); 13683d3b0591SJens Wiklander mbedtls_pk_init(pk); 1369817466cbSJens Wiklander 1370*32b31808SJens Wiklander if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { 1371*32b31808SJens Wiklander return ret; 1372817466cbSJens Wiklander } 1373817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 1374817466cbSJens Wiklander 1375*32b31808SJens Wiklander ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng); 1376*32b31808SJens Wiklander if (ret == 0) { 1377*32b31808SJens Wiklander return 0; 1378039e02dfSJerome Forissier } 1379817466cbSJens Wiklander 1380817466cbSJens Wiklander mbedtls_pk_free(pk); 13813d3b0591SJens Wiklander mbedtls_pk_init(pk); 1382817466cbSJens Wiklander 1383817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 1384817466cbSJens Wiklander 13853d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); 13863d3b0591SJens Wiklander if (mbedtls_pk_setup(pk, pk_info) == 0 && 1387*32b31808SJens Wiklander pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) { 1388*32b31808SJens Wiklander return 0; 1389817466cbSJens Wiklander } 1390817466cbSJens Wiklander 1391817466cbSJens Wiklander mbedtls_pk_free(pk); 13923d3b0591SJens Wiklander mbedtls_pk_init(pk); 1393817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 1394817466cbSJens Wiklander 1395817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 13963d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); 13973d3b0591SJens Wiklander if (mbedtls_pk_setup(pk, pk_info) == 0 && 13983d3b0591SJens Wiklander pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), 1399*32b31808SJens Wiklander key, keylen, f_rng, p_rng) == 0) { 1400*32b31808SJens Wiklander return 0; 1401817466cbSJens Wiklander } 1402817466cbSJens Wiklander mbedtls_pk_free(pk); 1403817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 1404817466cbSJens Wiklander 14053d3b0591SJens Wiklander /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, 14063d3b0591SJens Wiklander * it is ok to leave the PK context initialized but not 14073d3b0591SJens Wiklander * freed: It is the caller's responsibility to call pk_init() 14083d3b0591SJens Wiklander * before calling this function, and to call pk_free() 14093d3b0591SJens Wiklander * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C 14103d3b0591SJens Wiklander * isn't, this leads to mbedtls_pk_free() being called 14113d3b0591SJens Wiklander * twice, once here and once by the caller, but this is 14123d3b0591SJens Wiklander * also ok and in line with the mbedtls_pk_free() calls 14133d3b0591SJens Wiklander * on failed PEM parsing attempts. */ 14143d3b0591SJens Wiklander 1415*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 1416817466cbSJens Wiklander } 1417817466cbSJens Wiklander 1418817466cbSJens Wiklander /* 1419817466cbSJens Wiklander * Parse a public key 1420817466cbSJens Wiklander */ 1421817466cbSJens Wiklander int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, 1422817466cbSJens Wiklander const unsigned char *key, size_t keylen) 1423817466cbSJens Wiklander { 142411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1425817466cbSJens Wiklander unsigned char *p; 14263d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C) 14273d3b0591SJens Wiklander const mbedtls_pk_info_t *pk_info; 14283d3b0591SJens Wiklander #endif 1429817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 1430817466cbSJens Wiklander size_t len; 1431817466cbSJens Wiklander mbedtls_pem_context pem; 14323d3b0591SJens Wiklander #endif 1433817466cbSJens Wiklander 1434*32b31808SJens Wiklander if (keylen == 0) { 1435*32b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 1436*32b31808SJens Wiklander } 14373d3b0591SJens Wiklander 14383d3b0591SJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 1439817466cbSJens Wiklander mbedtls_pem_init(&pem); 14403d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C) 14413d3b0591SJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1442*32b31808SJens Wiklander if (key[keylen - 1] != '\0') { 14433d3b0591SJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1444*32b31808SJens Wiklander } else { 14453d3b0591SJens Wiklander ret = mbedtls_pem_read_buffer(&pem, 14463d3b0591SJens Wiklander "-----BEGIN RSA PUBLIC KEY-----", 14473d3b0591SJens Wiklander "-----END RSA PUBLIC KEY-----", 14483d3b0591SJens Wiklander key, NULL, 0, &len); 1449*32b31808SJens Wiklander } 14503d3b0591SJens Wiklander 1451*32b31808SJens Wiklander if (ret == 0) { 14523d3b0591SJens Wiklander p = pem.buf; 1453*32b31808SJens Wiklander if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { 1454039e02dfSJerome Forissier mbedtls_pem_free(&pem); 1455*32b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 1456039e02dfSJerome Forissier } 14573d3b0591SJens Wiklander 1458*32b31808SJens Wiklander if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { 1459039e02dfSJerome Forissier mbedtls_pem_free(&pem); 1460*32b31808SJens Wiklander return ret; 1461039e02dfSJerome Forissier } 14623d3b0591SJens Wiklander 1463*32b31808SJens Wiklander if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) { 14643d3b0591SJens Wiklander mbedtls_pk_free(ctx); 1465*32b31808SJens Wiklander } 14663d3b0591SJens Wiklander 14673d3b0591SJens Wiklander mbedtls_pem_free(&pem); 1468*32b31808SJens Wiklander return ret; 1469*32b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 14703d3b0591SJens Wiklander mbedtls_pem_free(&pem); 1471*32b31808SJens Wiklander return ret; 14723d3b0591SJens Wiklander } 14733d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_C */ 1474817466cbSJens Wiklander 1475817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 1476*32b31808SJens Wiklander if (key[keylen - 1] != '\0') { 1477817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1478*32b31808SJens Wiklander } else { 1479817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem, 1480817466cbSJens Wiklander "-----BEGIN PUBLIC KEY-----", 1481817466cbSJens Wiklander "-----END PUBLIC KEY-----", 1482817466cbSJens Wiklander key, NULL, 0, &len); 1483*32b31808SJens Wiklander } 1484817466cbSJens Wiklander 1485*32b31808SJens Wiklander if (ret == 0) { 1486817466cbSJens Wiklander /* 1487817466cbSJens Wiklander * Was PEM encoded 1488817466cbSJens Wiklander */ 14893d3b0591SJens Wiklander p = pem.buf; 14903d3b0591SJens Wiklander 14913d3b0591SJens Wiklander ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); 14923d3b0591SJens Wiklander mbedtls_pem_free(&pem); 1493*32b31808SJens Wiklander return ret; 1494*32b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { 1495817466cbSJens Wiklander mbedtls_pem_free(&pem); 1496*32b31808SJens Wiklander return ret; 1497817466cbSJens Wiklander } 14983d3b0591SJens Wiklander mbedtls_pem_free(&pem); 1499817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */ 15003d3b0591SJens Wiklander 15013d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C) 1502*32b31808SJens Wiklander if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { 1503*32b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 1504*32b31808SJens Wiklander } 15053d3b0591SJens Wiklander 1506*32b31808SJens Wiklander if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { 1507*32b31808SJens Wiklander return ret; 1508*32b31808SJens Wiklander } 15093d3b0591SJens Wiklander 15103d3b0591SJens Wiklander p = (unsigned char *) key; 15113d3b0591SJens Wiklander ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx)); 1512*32b31808SJens Wiklander if (ret == 0) { 1513*32b31808SJens Wiklander return ret; 15143d3b0591SJens Wiklander } 15153d3b0591SJens Wiklander mbedtls_pk_free(ctx); 15167901324dSJerome Forissier if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, 1517*32b31808SJens Wiklander MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) { 1518*32b31808SJens Wiklander return ret; 15193d3b0591SJens Wiklander } 15203d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_C */ 1521817466cbSJens Wiklander p = (unsigned char *) key; 1522817466cbSJens Wiklander 1523817466cbSJens Wiklander ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx); 1524817466cbSJens Wiklander 1525*32b31808SJens Wiklander return ret; 1526817466cbSJens Wiklander } 1527817466cbSJens Wiklander 1528817466cbSJens Wiklander #endif /* MBEDTLS_PK_PARSE_C */ 1529