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 #if defined(MBEDTLS_PLATFORM_C) 52817466cbSJens Wiklander #include "mbedtls/platform.h" 53817466cbSJens Wiklander #else 54817466cbSJens Wiklander #include <stdlib.h> 55817466cbSJens Wiklander #define mbedtls_calloc calloc 56817466cbSJens Wiklander #define mbedtls_free free 57817466cbSJens Wiklander #endif 58817466cbSJens Wiklander 593d3b0591SJens Wiklander /* Parameter validation macros based on platform_util.h */ 603d3b0591SJens Wiklander #define PK_VALIDATE_RET( cond ) \ 613d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) 623d3b0591SJens Wiklander #define PK_VALIDATE( cond ) \ 633d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE( cond ) 64817466cbSJens Wiklander 653d3b0591SJens Wiklander #if defined(MBEDTLS_FS_IO) 66817466cbSJens Wiklander /* 67817466cbSJens Wiklander * Load all data from a file into a given buffer. 68817466cbSJens Wiklander * 69817466cbSJens Wiklander * The file is expected to contain either PEM or DER encoded data. 70817466cbSJens Wiklander * A terminating null byte is always appended. It is included in the announced 71817466cbSJens Wiklander * length only if the data looks like it is PEM encoded. 72817466cbSJens Wiklander */ 73817466cbSJens Wiklander int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) 74817466cbSJens Wiklander { 75817466cbSJens Wiklander FILE *f; 76817466cbSJens Wiklander long size; 77817466cbSJens Wiklander 783d3b0591SJens Wiklander PK_VALIDATE_RET( path != NULL ); 793d3b0591SJens Wiklander PK_VALIDATE_RET( buf != NULL ); 803d3b0591SJens Wiklander PK_VALIDATE_RET( n != NULL ); 813d3b0591SJens Wiklander 82817466cbSJens Wiklander if( ( f = fopen( path, "rb" ) ) == NULL ) 83817466cbSJens Wiklander return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); 84817466cbSJens Wiklander 85817466cbSJens Wiklander fseek( f, 0, SEEK_END ); 86817466cbSJens Wiklander if( ( size = ftell( f ) ) == -1 ) 87817466cbSJens Wiklander { 88817466cbSJens Wiklander fclose( f ); 89817466cbSJens Wiklander return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); 90817466cbSJens Wiklander } 91817466cbSJens Wiklander fseek( f, 0, SEEK_SET ); 92817466cbSJens Wiklander 93817466cbSJens Wiklander *n = (size_t) size; 94817466cbSJens Wiklander 95817466cbSJens Wiklander if( *n + 1 == 0 || 96817466cbSJens Wiklander ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) 97817466cbSJens Wiklander { 98817466cbSJens Wiklander fclose( f ); 99817466cbSJens Wiklander return( MBEDTLS_ERR_PK_ALLOC_FAILED ); 100817466cbSJens Wiklander } 101817466cbSJens Wiklander 102817466cbSJens Wiklander if( fread( *buf, 1, *n, f ) != *n ) 103817466cbSJens Wiklander { 104817466cbSJens Wiklander fclose( f ); 1053d3b0591SJens Wiklander 1063d3b0591SJens Wiklander mbedtls_platform_zeroize( *buf, *n ); 107817466cbSJens Wiklander mbedtls_free( *buf ); 1083d3b0591SJens Wiklander 109817466cbSJens Wiklander return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); 110817466cbSJens Wiklander } 111817466cbSJens Wiklander 112817466cbSJens Wiklander fclose( f ); 113817466cbSJens Wiklander 114817466cbSJens Wiklander (*buf)[*n] = '\0'; 115817466cbSJens Wiklander 116817466cbSJens Wiklander if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) 117817466cbSJens Wiklander ++*n; 118817466cbSJens Wiklander 119817466cbSJens Wiklander return( 0 ); 120817466cbSJens Wiklander } 121817466cbSJens Wiklander 122817466cbSJens Wiklander /* 123817466cbSJens Wiklander * Load and parse a private key 124817466cbSJens Wiklander */ 125817466cbSJens Wiklander int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, 126817466cbSJens Wiklander const char *path, const char *pwd ) 127817466cbSJens Wiklander { 12811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 129817466cbSJens Wiklander size_t n; 130817466cbSJens Wiklander unsigned char *buf; 131817466cbSJens Wiklander 1323d3b0591SJens Wiklander PK_VALIDATE_RET( ctx != NULL ); 1333d3b0591SJens Wiklander PK_VALIDATE_RET( path != NULL ); 1343d3b0591SJens Wiklander 135817466cbSJens Wiklander if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) 136817466cbSJens Wiklander return( ret ); 137817466cbSJens Wiklander 138817466cbSJens Wiklander if( pwd == NULL ) 139817466cbSJens Wiklander ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); 140817466cbSJens Wiklander else 141817466cbSJens Wiklander ret = mbedtls_pk_parse_key( ctx, buf, n, 142817466cbSJens Wiklander (const unsigned char *) pwd, strlen( pwd ) ); 143817466cbSJens Wiklander 1443d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, n ); 145817466cbSJens Wiklander mbedtls_free( buf ); 146817466cbSJens Wiklander 147817466cbSJens Wiklander return( ret ); 148817466cbSJens Wiklander } 149817466cbSJens Wiklander 150817466cbSJens Wiklander /* 151817466cbSJens Wiklander * Load and parse a public key 152817466cbSJens Wiklander */ 153817466cbSJens Wiklander int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) 154817466cbSJens Wiklander { 15511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 156817466cbSJens Wiklander size_t n; 157817466cbSJens Wiklander unsigned char *buf; 158817466cbSJens Wiklander 1593d3b0591SJens Wiklander PK_VALIDATE_RET( ctx != NULL ); 1603d3b0591SJens Wiklander PK_VALIDATE_RET( path != NULL ); 1613d3b0591SJens Wiklander 162817466cbSJens Wiklander if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) 163817466cbSJens Wiklander return( ret ); 164817466cbSJens Wiklander 165817466cbSJens Wiklander ret = mbedtls_pk_parse_public_key( ctx, buf, n ); 166817466cbSJens Wiklander 1673d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, n ); 168817466cbSJens Wiklander mbedtls_free( buf ); 169817466cbSJens Wiklander 170817466cbSJens Wiklander return( ret ); 171817466cbSJens Wiklander } 172817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 173817466cbSJens Wiklander 174817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 175817466cbSJens Wiklander /* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf 176817466cbSJens Wiklander * 177817466cbSJens Wiklander * ECParameters ::= CHOICE { 178817466cbSJens Wiklander * namedCurve OBJECT IDENTIFIER 179817466cbSJens Wiklander * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } 180817466cbSJens Wiklander * -- implicitCurve NULL 181817466cbSJens Wiklander * } 182817466cbSJens Wiklander */ 183817466cbSJens Wiklander static int pk_get_ecparams( unsigned char **p, const unsigned char *end, 184817466cbSJens Wiklander mbedtls_asn1_buf *params ) 185817466cbSJens Wiklander { 18611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 187817466cbSJens Wiklander 1883d3b0591SJens Wiklander if ( end - *p < 1 ) 1897901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 1907901324dSJerome Forissier MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); 1913d3b0591SJens Wiklander 192817466cbSJens Wiklander /* Tag may be either OID or SEQUENCE */ 193817466cbSJens Wiklander params->tag = **p; 194817466cbSJens Wiklander if( params->tag != MBEDTLS_ASN1_OID 195817466cbSJens Wiklander #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) 196817466cbSJens Wiklander && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) 197817466cbSJens Wiklander #endif 198817466cbSJens Wiklander ) 199817466cbSJens Wiklander { 2007901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 2017901324dSJerome Forissier MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); 202817466cbSJens Wiklander } 203817466cbSJens Wiklander 204817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) 205817466cbSJens Wiklander { 2067901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 207817466cbSJens Wiklander } 208817466cbSJens Wiklander 209817466cbSJens Wiklander params->p = *p; 210817466cbSJens Wiklander *p += params->len; 211817466cbSJens Wiklander 212817466cbSJens Wiklander if( *p != end ) 2137901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 2147901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); 215817466cbSJens Wiklander 216817466cbSJens Wiklander return( 0 ); 217817466cbSJens Wiklander } 218817466cbSJens Wiklander 219817466cbSJens Wiklander #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) 220817466cbSJens Wiklander /* 221817466cbSJens Wiklander * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. 222817466cbSJens Wiklander * WARNING: the resulting group should only be used with 223817466cbSJens Wiklander * pk_group_id_from_specified(), since its base point may not be set correctly 224817466cbSJens Wiklander * if it was encoded compressed. 225817466cbSJens Wiklander * 226817466cbSJens Wiklander * SpecifiedECDomain ::= SEQUENCE { 227817466cbSJens Wiklander * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), 228817466cbSJens Wiklander * fieldID FieldID {{FieldTypes}}, 229817466cbSJens Wiklander * curve Curve, 230817466cbSJens Wiklander * base ECPoint, 231817466cbSJens Wiklander * order INTEGER, 232817466cbSJens Wiklander * cofactor INTEGER OPTIONAL, 233817466cbSJens Wiklander * hash HashAlgorithm OPTIONAL, 234817466cbSJens Wiklander * ... 235817466cbSJens Wiklander * } 236817466cbSJens Wiklander * 237817466cbSJens Wiklander * We only support prime-field as field type, and ignore hash and cofactor. 238817466cbSJens Wiklander */ 239817466cbSJens Wiklander static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) 240817466cbSJens Wiklander { 24111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 242817466cbSJens Wiklander unsigned char *p = params->p; 243817466cbSJens Wiklander const unsigned char * const end = params->p + params->len; 244817466cbSJens Wiklander const unsigned char *end_field, *end_curve; 245817466cbSJens Wiklander size_t len; 246817466cbSJens Wiklander int ver; 247817466cbSJens Wiklander 248817466cbSJens Wiklander /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ 249817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) 2507901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 251817466cbSJens Wiklander 252817466cbSJens Wiklander if( ver < 1 || ver > 3 ) 253817466cbSJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 254817466cbSJens Wiklander 255817466cbSJens Wiklander /* 256817466cbSJens Wiklander * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field 257817466cbSJens Wiklander * fieldType FIELD-ID.&id({IOSet}), 258817466cbSJens Wiklander * parameters FIELD-ID.&Type({IOSet}{@fieldType}) 259817466cbSJens Wiklander * } 260817466cbSJens Wiklander */ 261817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 262817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 263817466cbSJens Wiklander return( ret ); 264817466cbSJens Wiklander 265817466cbSJens Wiklander end_field = p + len; 266817466cbSJens Wiklander 267817466cbSJens Wiklander /* 268817466cbSJens Wiklander * FIELD-ID ::= TYPE-IDENTIFIER 269817466cbSJens Wiklander * FieldTypes FIELD-ID ::= { 270817466cbSJens Wiklander * { Prime-p IDENTIFIED BY prime-field } | 271817466cbSJens Wiklander * { Characteristic-two IDENTIFIED BY characteristic-two-field } 272817466cbSJens Wiklander * } 273817466cbSJens Wiklander * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } 274817466cbSJens Wiklander */ 275817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) 276817466cbSJens Wiklander return( ret ); 277817466cbSJens Wiklander 278817466cbSJens Wiklander if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || 279817466cbSJens Wiklander memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) 280817466cbSJens Wiklander { 281817466cbSJens Wiklander return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); 282817466cbSJens Wiklander } 283817466cbSJens Wiklander 284817466cbSJens Wiklander p += len; 285817466cbSJens Wiklander 286817466cbSJens Wiklander /* Prime-p ::= INTEGER -- Field of size p. */ 287817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) 2887901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 289817466cbSJens Wiklander 290817466cbSJens Wiklander grp->pbits = mbedtls_mpi_bitlen( &grp->P ); 291817466cbSJens Wiklander 292817466cbSJens Wiklander if( p != end_field ) 2937901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 2947901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); 295817466cbSJens Wiklander 296817466cbSJens Wiklander /* 297817466cbSJens Wiklander * Curve ::= SEQUENCE { 298817466cbSJens Wiklander * a FieldElement, 299817466cbSJens Wiklander * b FieldElement, 300817466cbSJens Wiklander * seed BIT STRING OPTIONAL 301817466cbSJens Wiklander * -- Shall be present if used in SpecifiedECDomain 302817466cbSJens Wiklander * -- with version equal to ecdpVer2 or ecdpVer3 303817466cbSJens Wiklander * } 304817466cbSJens Wiklander */ 305817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 306817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 307817466cbSJens Wiklander return( ret ); 308817466cbSJens Wiklander 309817466cbSJens Wiklander end_curve = p + len; 310817466cbSJens Wiklander 311817466cbSJens Wiklander /* 312817466cbSJens Wiklander * FieldElement ::= OCTET STRING 313817466cbSJens Wiklander * containing an integer in the case of a prime field 314817466cbSJens Wiklander */ 315817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || 316817466cbSJens Wiklander ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) 317817466cbSJens Wiklander { 3187901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 319817466cbSJens Wiklander } 320817466cbSJens Wiklander 321817466cbSJens Wiklander p += len; 322817466cbSJens Wiklander 323817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || 324817466cbSJens Wiklander ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) 325817466cbSJens Wiklander { 3267901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 327817466cbSJens Wiklander } 328817466cbSJens Wiklander 329817466cbSJens Wiklander p += len; 330817466cbSJens Wiklander 331817466cbSJens Wiklander /* Ignore seed BIT STRING OPTIONAL */ 332817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) 333817466cbSJens Wiklander p += len; 334817466cbSJens Wiklander 335817466cbSJens Wiklander if( p != end_curve ) 3367901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 3377901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); 338817466cbSJens Wiklander 339817466cbSJens Wiklander /* 340817466cbSJens Wiklander * ECPoint ::= OCTET STRING 341817466cbSJens Wiklander */ 342817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 3437901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 344817466cbSJens Wiklander 345817466cbSJens Wiklander if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, 346817466cbSJens Wiklander ( const unsigned char *) p, len ) ) != 0 ) 347817466cbSJens Wiklander { 348817466cbSJens Wiklander /* 349817466cbSJens Wiklander * If we can't read the point because it's compressed, cheat by 350817466cbSJens Wiklander * reading only the X coordinate and the parity bit of Y. 351817466cbSJens Wiklander */ 352817466cbSJens Wiklander if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || 353817466cbSJens Wiklander ( p[0] != 0x02 && p[0] != 0x03 ) || 354817466cbSJens Wiklander len != mbedtls_mpi_size( &grp->P ) + 1 || 355817466cbSJens Wiklander mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || 356817466cbSJens Wiklander mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || 357817466cbSJens Wiklander mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) 358817466cbSJens Wiklander { 359817466cbSJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 360817466cbSJens Wiklander } 361817466cbSJens Wiklander } 362817466cbSJens Wiklander 363817466cbSJens Wiklander p += len; 364817466cbSJens Wiklander 365817466cbSJens Wiklander /* 366817466cbSJens Wiklander * order INTEGER 367817466cbSJens Wiklander */ 368817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) 3697901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 370817466cbSJens Wiklander 371817466cbSJens Wiklander grp->nbits = mbedtls_mpi_bitlen( &grp->N ); 372817466cbSJens Wiklander 373817466cbSJens Wiklander /* 374817466cbSJens Wiklander * Allow optional elements by purposefully not enforcing p == end here. 375817466cbSJens Wiklander */ 376817466cbSJens Wiklander 377817466cbSJens Wiklander return( 0 ); 378817466cbSJens Wiklander } 379817466cbSJens Wiklander 380817466cbSJens Wiklander /* 381817466cbSJens Wiklander * Find the group id associated with an (almost filled) group as generated by 382817466cbSJens Wiklander * pk_group_from_specified(), or return an error if unknown. 383817466cbSJens Wiklander */ 384817466cbSJens Wiklander static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) 385817466cbSJens Wiklander { 386817466cbSJens Wiklander int ret = 0; 387817466cbSJens Wiklander mbedtls_ecp_group ref; 388817466cbSJens Wiklander const mbedtls_ecp_group_id *id; 389817466cbSJens Wiklander 390817466cbSJens Wiklander mbedtls_ecp_group_init( &ref ); 391817466cbSJens Wiklander 392817466cbSJens Wiklander for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) 393817466cbSJens Wiklander { 394817466cbSJens Wiklander /* Load the group associated to that id */ 395817466cbSJens Wiklander mbedtls_ecp_group_free( &ref ); 396817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); 397817466cbSJens Wiklander 398817466cbSJens Wiklander /* Compare to the group we were given, starting with easy tests */ 399817466cbSJens Wiklander if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && 400817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && 401817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && 402817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && 403817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && 404817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && 405817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && 406817466cbSJens Wiklander /* For Y we may only know the parity bit, so compare only that */ 407817466cbSJens Wiklander mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) 408817466cbSJens Wiklander { 409817466cbSJens Wiklander break; 410817466cbSJens Wiklander } 411817466cbSJens Wiklander 412817466cbSJens Wiklander } 413817466cbSJens Wiklander 414817466cbSJens Wiklander cleanup: 415817466cbSJens Wiklander mbedtls_ecp_group_free( &ref ); 416817466cbSJens Wiklander 417817466cbSJens Wiklander *grp_id = *id; 418817466cbSJens Wiklander 419817466cbSJens Wiklander if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) 420817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; 421817466cbSJens Wiklander 422817466cbSJens Wiklander return( ret ); 423817466cbSJens Wiklander } 424817466cbSJens Wiklander 425817466cbSJens Wiklander /* 426817466cbSJens Wiklander * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID 427817466cbSJens Wiklander */ 428817466cbSJens Wiklander static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, 429817466cbSJens Wiklander mbedtls_ecp_group_id *grp_id ) 430817466cbSJens Wiklander { 43111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 432817466cbSJens Wiklander mbedtls_ecp_group grp; 433817466cbSJens Wiklander 434817466cbSJens Wiklander mbedtls_ecp_group_init( &grp ); 435817466cbSJens Wiklander 436817466cbSJens Wiklander if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) 437817466cbSJens Wiklander goto cleanup; 438817466cbSJens Wiklander 439817466cbSJens Wiklander ret = pk_group_id_from_group( &grp, grp_id ); 440817466cbSJens Wiklander 441817466cbSJens Wiklander cleanup: 442817466cbSJens Wiklander mbedtls_ecp_group_free( &grp ); 443817466cbSJens Wiklander 444817466cbSJens Wiklander return( ret ); 445817466cbSJens Wiklander } 446817466cbSJens Wiklander #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ 447817466cbSJens Wiklander 448817466cbSJens Wiklander /* 449817466cbSJens Wiklander * Use EC parameters to initialise an EC group 450817466cbSJens Wiklander * 451817466cbSJens Wiklander * ECParameters ::= CHOICE { 452817466cbSJens Wiklander * namedCurve OBJECT IDENTIFIER 453817466cbSJens Wiklander * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } 454817466cbSJens Wiklander * -- implicitCurve NULL 455817466cbSJens Wiklander */ 456817466cbSJens Wiklander static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) 457817466cbSJens Wiklander { 45811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 459817466cbSJens Wiklander mbedtls_ecp_group_id grp_id; 460817466cbSJens Wiklander 461817466cbSJens Wiklander if( params->tag == MBEDTLS_ASN1_OID ) 462817466cbSJens Wiklander { 463817466cbSJens Wiklander if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) 464817466cbSJens Wiklander return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); 465817466cbSJens Wiklander } 466817466cbSJens Wiklander else 467817466cbSJens Wiklander { 468817466cbSJens Wiklander #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) 469817466cbSJens Wiklander if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) 470817466cbSJens Wiklander return( ret ); 471817466cbSJens Wiklander #else 472817466cbSJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 473817466cbSJens Wiklander #endif 474817466cbSJens Wiklander } 475817466cbSJens Wiklander 476817466cbSJens Wiklander /* 477*039e02dfSJerome Forissier * grp may already be initialized; if so, make sure IDs match 478817466cbSJens Wiklander */ 479817466cbSJens Wiklander if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) 480817466cbSJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 481817466cbSJens Wiklander 482817466cbSJens Wiklander if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) 483817466cbSJens Wiklander return( ret ); 484817466cbSJens Wiklander 485817466cbSJens Wiklander return( 0 ); 486817466cbSJens Wiklander } 487817466cbSJens Wiklander 488817466cbSJens Wiklander /* 489817466cbSJens Wiklander * EC public key is an EC point 490817466cbSJens Wiklander * 491817466cbSJens Wiklander * The caller is responsible for clearing the structure upon failure if 492817466cbSJens Wiklander * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE 493817466cbSJens Wiklander * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. 494817466cbSJens Wiklander */ 495817466cbSJens Wiklander static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, 496817466cbSJens Wiklander mbedtls_ecp_keypair *key ) 497817466cbSJens Wiklander { 49811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 499817466cbSJens Wiklander 500817466cbSJens Wiklander if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, 501817466cbSJens Wiklander (const unsigned char *) *p, end - *p ) ) == 0 ) 502817466cbSJens Wiklander { 503817466cbSJens Wiklander ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); 504817466cbSJens Wiklander } 505817466cbSJens Wiklander 506817466cbSJens Wiklander /* 507817466cbSJens Wiklander * We know mbedtls_ecp_point_read_binary consumed all bytes or failed 508817466cbSJens Wiklander */ 509817466cbSJens Wiklander *p = (unsigned char *) end; 510817466cbSJens Wiklander 511817466cbSJens Wiklander return( ret ); 512817466cbSJens Wiklander } 513817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 514817466cbSJens Wiklander 515817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 516817466cbSJens Wiklander /* 517817466cbSJens Wiklander * RSAPublicKey ::= SEQUENCE { 518817466cbSJens Wiklander * modulus INTEGER, -- n 519817466cbSJens Wiklander * publicExponent INTEGER -- e 520817466cbSJens Wiklander * } 521817466cbSJens Wiklander */ 522817466cbSJens Wiklander static int pk_get_rsapubkey( unsigned char **p, 523817466cbSJens Wiklander const unsigned char *end, 524817466cbSJens Wiklander mbedtls_rsa_context *rsa ) 525817466cbSJens Wiklander { 52611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 527817466cbSJens Wiklander size_t len; 528817466cbSJens Wiklander 529817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len, 530817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 5317901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); 532817466cbSJens Wiklander 533817466cbSJens Wiklander if( *p + len != end ) 5347901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, 5357901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); 536817466cbSJens Wiklander 5373d3b0591SJens Wiklander /* Import N */ 5383d3b0591SJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) 5397901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); 540817466cbSJens Wiklander 5413d3b0591SJens Wiklander if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, 5423d3b0591SJens Wiklander NULL, 0, NULL, 0 ) ) != 0 ) 5433d3b0591SJens Wiklander return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); 5443d3b0591SJens Wiklander 5453d3b0591SJens Wiklander *p += len; 5463d3b0591SJens Wiklander 5473d3b0591SJens Wiklander /* Import E */ 5483d3b0591SJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) 5497901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); 5503d3b0591SJens Wiklander 5513d3b0591SJens Wiklander if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, 5523d3b0591SJens Wiklander NULL, 0, *p, len ) ) != 0 ) 5533d3b0591SJens Wiklander return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); 5543d3b0591SJens Wiklander 5553d3b0591SJens Wiklander *p += len; 5563d3b0591SJens Wiklander 5573d3b0591SJens Wiklander if( mbedtls_rsa_complete( rsa ) != 0 || 5583d3b0591SJens Wiklander mbedtls_rsa_check_pubkey( rsa ) != 0 ) 5593d3b0591SJens Wiklander { 5603d3b0591SJens Wiklander return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); 5613d3b0591SJens Wiklander } 5623d3b0591SJens Wiklander 563817466cbSJens Wiklander if( *p != end ) 5647901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, 5657901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); 566817466cbSJens Wiklander 567817466cbSJens Wiklander return( 0 ); 568817466cbSJens Wiklander } 569817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 570817466cbSJens Wiklander 571817466cbSJens Wiklander /* Get a PK algorithm identifier 572817466cbSJens Wiklander * 573817466cbSJens Wiklander * AlgorithmIdentifier ::= SEQUENCE { 574817466cbSJens Wiklander * algorithm OBJECT IDENTIFIER, 575817466cbSJens Wiklander * parameters ANY DEFINED BY algorithm OPTIONAL } 576817466cbSJens Wiklander */ 577817466cbSJens Wiklander static int pk_get_pk_alg( unsigned char **p, 578817466cbSJens Wiklander const unsigned char *end, 579817466cbSJens Wiklander mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) 580817466cbSJens Wiklander { 58111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 582817466cbSJens Wiklander mbedtls_asn1_buf alg_oid; 583817466cbSJens Wiklander 584817466cbSJens Wiklander memset( params, 0, sizeof(mbedtls_asn1_buf) ); 585817466cbSJens Wiklander 586817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) 5877901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) ); 588817466cbSJens Wiklander 589817466cbSJens Wiklander if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) 590817466cbSJens Wiklander return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); 591817466cbSJens Wiklander 592817466cbSJens Wiklander /* 593817466cbSJens Wiklander * No parameters with RSA (only for EC) 594817466cbSJens Wiklander */ 595817466cbSJens Wiklander if( *pk_alg == MBEDTLS_PK_RSA && 596817466cbSJens Wiklander ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || 597817466cbSJens Wiklander params->len != 0 ) ) 598817466cbSJens Wiklander { 599817466cbSJens Wiklander return( MBEDTLS_ERR_PK_INVALID_ALG ); 600817466cbSJens Wiklander } 601817466cbSJens Wiklander 602817466cbSJens Wiklander return( 0 ); 603817466cbSJens Wiklander } 604817466cbSJens Wiklander 605817466cbSJens Wiklander /* 606817466cbSJens Wiklander * SubjectPublicKeyInfo ::= SEQUENCE { 607817466cbSJens Wiklander * algorithm AlgorithmIdentifier, 608817466cbSJens Wiklander * subjectPublicKey BIT STRING } 609817466cbSJens Wiklander */ 610817466cbSJens Wiklander int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, 611817466cbSJens Wiklander mbedtls_pk_context *pk ) 612817466cbSJens Wiklander { 61311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 614817466cbSJens Wiklander size_t len; 615817466cbSJens Wiklander mbedtls_asn1_buf alg_params; 616817466cbSJens Wiklander mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; 617817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info; 618817466cbSJens Wiklander 6193d3b0591SJens Wiklander PK_VALIDATE_RET( p != NULL ); 6203d3b0591SJens Wiklander PK_VALIDATE_RET( *p != NULL ); 6213d3b0591SJens Wiklander PK_VALIDATE_RET( end != NULL ); 6223d3b0591SJens Wiklander PK_VALIDATE_RET( pk != NULL ); 6233d3b0591SJens Wiklander 624817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( p, end, &len, 625817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 626817466cbSJens Wiklander { 6277901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 628817466cbSJens Wiklander } 629817466cbSJens Wiklander 630817466cbSJens Wiklander end = *p + len; 631817466cbSJens Wiklander 632817466cbSJens Wiklander if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) 633817466cbSJens Wiklander return( ret ); 634817466cbSJens Wiklander 635817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) 6367901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); 637817466cbSJens Wiklander 638817466cbSJens Wiklander if( *p + len != end ) 6397901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, 6407901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); 641817466cbSJens Wiklander 642817466cbSJens Wiklander if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) 643817466cbSJens Wiklander return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); 644817466cbSJens Wiklander 645817466cbSJens Wiklander if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) 646817466cbSJens Wiklander return( ret ); 647817466cbSJens Wiklander 648817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 649817466cbSJens Wiklander if( pk_alg == MBEDTLS_PK_RSA ) 650817466cbSJens Wiklander { 651817466cbSJens Wiklander ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); 652817466cbSJens Wiklander } else 653817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 654817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 655817466cbSJens Wiklander if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) 656817466cbSJens Wiklander { 657817466cbSJens Wiklander ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); 658817466cbSJens Wiklander if( ret == 0 ) 659817466cbSJens Wiklander ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); 660817466cbSJens Wiklander } else 661817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 662817466cbSJens Wiklander ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; 663817466cbSJens Wiklander 664817466cbSJens Wiklander if( ret == 0 && *p != end ) 6657901324dSJerome Forissier ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, 6667901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 667817466cbSJens Wiklander 668817466cbSJens Wiklander if( ret != 0 ) 669817466cbSJens Wiklander mbedtls_pk_free( pk ); 670817466cbSJens Wiklander 671817466cbSJens Wiklander return( ret ); 672817466cbSJens Wiklander } 673817466cbSJens Wiklander 674817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 675817466cbSJens Wiklander /* 6765b25c76aSJerome Forissier * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. 6775b25c76aSJerome Forissier * 6785b25c76aSJerome Forissier * The value zero is: 6795b25c76aSJerome Forissier * - never a valid value for an RSA parameter 6805b25c76aSJerome Forissier * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). 6815b25c76aSJerome Forissier * 6825b25c76aSJerome Forissier * Since values can't be omitted in PKCS#1, passing a zero value to 6835b25c76aSJerome Forissier * rsa_complete() would be incorrect, so reject zero values early. 6845b25c76aSJerome Forissier */ 6855b25c76aSJerome Forissier static int asn1_get_nonzero_mpi( unsigned char **p, 6865b25c76aSJerome Forissier const unsigned char *end, 6875b25c76aSJerome Forissier mbedtls_mpi *X ) 6885b25c76aSJerome Forissier { 6895b25c76aSJerome Forissier int ret; 6905b25c76aSJerome Forissier 6915b25c76aSJerome Forissier ret = mbedtls_asn1_get_mpi( p, end, X ); 6925b25c76aSJerome Forissier if( ret != 0 ) 6935b25c76aSJerome Forissier return( ret ); 6945b25c76aSJerome Forissier 6955b25c76aSJerome Forissier if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) 6965b25c76aSJerome Forissier return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 6975b25c76aSJerome Forissier 6985b25c76aSJerome Forissier return( 0 ); 6995b25c76aSJerome Forissier } 7005b25c76aSJerome Forissier 7015b25c76aSJerome Forissier /* 702817466cbSJens Wiklander * Parse a PKCS#1 encoded private RSA key 703817466cbSJens Wiklander */ 704817466cbSJens Wiklander static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, 705817466cbSJens Wiklander const unsigned char *key, 706817466cbSJens Wiklander size_t keylen ) 707817466cbSJens Wiklander { 7083d3b0591SJens Wiklander int ret, version; 709817466cbSJens Wiklander size_t len; 710817466cbSJens Wiklander unsigned char *p, *end; 711817466cbSJens Wiklander 7123d3b0591SJens Wiklander mbedtls_mpi T; 7133d3b0591SJens Wiklander mbedtls_mpi_init( &T ); 7143d3b0591SJens Wiklander 715817466cbSJens Wiklander p = (unsigned char *) key; 716817466cbSJens Wiklander end = p + keylen; 717817466cbSJens Wiklander 718817466cbSJens Wiklander /* 719817466cbSJens Wiklander * This function parses the RSAPrivateKey (PKCS#1) 720817466cbSJens Wiklander * 721817466cbSJens Wiklander * RSAPrivateKey ::= SEQUENCE { 722817466cbSJens Wiklander * version Version, 723817466cbSJens Wiklander * modulus INTEGER, -- n 724817466cbSJens Wiklander * publicExponent INTEGER, -- e 725817466cbSJens Wiklander * privateExponent INTEGER, -- d 726817466cbSJens Wiklander * prime1 INTEGER, -- p 727817466cbSJens Wiklander * prime2 INTEGER, -- q 728817466cbSJens Wiklander * exponent1 INTEGER, -- d mod (p-1) 729817466cbSJens Wiklander * exponent2 INTEGER, -- d mod (q-1) 730817466cbSJens Wiklander * coefficient INTEGER, -- (inverse of q) mod p 731817466cbSJens Wiklander * otherPrimeInfos OtherPrimeInfos OPTIONAL 732817466cbSJens Wiklander * } 733817466cbSJens Wiklander */ 734817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 735817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 736817466cbSJens Wiklander { 7377901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 738817466cbSJens Wiklander } 739817466cbSJens Wiklander 740817466cbSJens Wiklander end = p + len; 741817466cbSJens Wiklander 7423d3b0591SJens Wiklander if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) 743817466cbSJens Wiklander { 7447901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 745817466cbSJens Wiklander } 746817466cbSJens Wiklander 7473d3b0591SJens Wiklander if( version != 0 ) 748817466cbSJens Wiklander { 749817466cbSJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); 750817466cbSJens Wiklander } 751817466cbSJens Wiklander 7523d3b0591SJens Wiklander /* Import N */ 7535b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 7545b25c76aSJerome Forissier ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, 7555b25c76aSJerome Forissier NULL, NULL ) ) != 0 ) 7563d3b0591SJens Wiklander goto cleanup; 757817466cbSJens Wiklander 7583d3b0591SJens Wiklander /* Import E */ 7595b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 7605b25c76aSJerome Forissier ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, 7615b25c76aSJerome Forissier NULL, &T ) ) != 0 ) 7623d3b0591SJens Wiklander goto cleanup; 7633d3b0591SJens Wiklander 7643d3b0591SJens Wiklander /* Import D */ 7655b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 7665b25c76aSJerome Forissier ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, 7675b25c76aSJerome Forissier &T, NULL ) ) != 0 ) 7683d3b0591SJens Wiklander goto cleanup; 7693d3b0591SJens Wiklander 7703d3b0591SJens Wiklander /* Import P */ 7715b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 7725b25c76aSJerome Forissier ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, 7735b25c76aSJerome Forissier NULL, NULL ) ) != 0 ) 7743d3b0591SJens Wiklander goto cleanup; 7753d3b0591SJens Wiklander 7763d3b0591SJens Wiklander /* Import Q */ 7775b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 7785b25c76aSJerome Forissier ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, 7795b25c76aSJerome Forissier NULL, NULL ) ) != 0 ) 7803d3b0591SJens Wiklander goto cleanup; 7813d3b0591SJens Wiklander 7825b25c76aSJerome Forissier #if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) 7835b25c76aSJerome Forissier /* 7845b25c76aSJerome Forissier * The RSA CRT parameters DP, DQ and QP are nominally redundant, in 7855b25c76aSJerome Forissier * that they can be easily recomputed from D, P and Q. However by 7865b25c76aSJerome Forissier * parsing them from the PKCS1 structure it is possible to avoid 7875b25c76aSJerome Forissier * recalculating them which both reduces the overhead of loading 7885b25c76aSJerome Forissier * RSA private keys into memory and also avoids side channels which 7895b25c76aSJerome Forissier * can arise when computing those values, since all of D, P, and Q 7905b25c76aSJerome Forissier * are secret. See https://eprint.iacr.org/2020/055 for a 7915b25c76aSJerome Forissier * description of one such attack. 7925b25c76aSJerome Forissier */ 7935b25c76aSJerome Forissier 7945b25c76aSJerome Forissier /* Import DP */ 7955b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 7965b25c76aSJerome Forissier ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) 7973d3b0591SJens Wiklander goto cleanup; 798817466cbSJens Wiklander 7995b25c76aSJerome Forissier /* Import DQ */ 8005b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 8015b25c76aSJerome Forissier ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) 8025b25c76aSJerome Forissier goto cleanup; 8035b25c76aSJerome Forissier 8045b25c76aSJerome Forissier /* Import QP */ 8055b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 8065b25c76aSJerome Forissier ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) 8075b25c76aSJerome Forissier goto cleanup; 8085b25c76aSJerome Forissier 8095b25c76aSJerome Forissier #else 810*039e02dfSJerome Forissier /* Verify existence of the CRT params */ 8115b25c76aSJerome Forissier if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 8125b25c76aSJerome Forissier ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || 8135b25c76aSJerome Forissier ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) 8145b25c76aSJerome Forissier goto cleanup; 8155b25c76aSJerome Forissier #endif 8165b25c76aSJerome Forissier 8175b25c76aSJerome Forissier /* rsa_complete() doesn't complete anything with the default 8185b25c76aSJerome Forissier * implementation but is still called: 8195b25c76aSJerome Forissier * - for the benefit of alternative implementation that may want to 8205b25c76aSJerome Forissier * pre-compute stuff beyond what's provided (eg Montgomery factors) 8215b25c76aSJerome Forissier * - as is also sanity-checks the key 8225b25c76aSJerome Forissier * 8235b25c76aSJerome Forissier * Furthermore, we also check the public part for consistency with 8245b25c76aSJerome Forissier * mbedtls_pk_parse_pubkey(), as it includes size minima for example. 8255b25c76aSJerome Forissier */ 8265b25c76aSJerome Forissier if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || 8275b25c76aSJerome Forissier ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) 8285b25c76aSJerome Forissier { 8295b25c76aSJerome Forissier goto cleanup; 8305b25c76aSJerome Forissier } 8315b25c76aSJerome Forissier 832817466cbSJens Wiklander if( p != end ) 833817466cbSJens Wiklander { 8347901324dSJerome Forissier ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 8357901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 836817466cbSJens Wiklander } 837817466cbSJens Wiklander 8383d3b0591SJens Wiklander cleanup: 8393d3b0591SJens Wiklander 8403d3b0591SJens Wiklander mbedtls_mpi_free( &T ); 8413d3b0591SJens Wiklander 8423d3b0591SJens Wiklander if( ret != 0 ) 843817466cbSJens Wiklander { 8443d3b0591SJens Wiklander /* Wrap error code if it's coming from a lower level */ 8453d3b0591SJens Wiklander if( ( ret & 0xff80 ) == 0 ) 8467901324dSJerome Forissier ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ); 8473d3b0591SJens Wiklander else 8483d3b0591SJens Wiklander ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 8493d3b0591SJens Wiklander 850817466cbSJens Wiklander mbedtls_rsa_free( rsa ); 851817466cbSJens Wiklander } 852817466cbSJens Wiklander 8533d3b0591SJens Wiklander return( ret ); 854817466cbSJens Wiklander } 855817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 856817466cbSJens Wiklander 857817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 858817466cbSJens Wiklander /* 859817466cbSJens Wiklander * Parse a SEC1 encoded private EC key 860817466cbSJens Wiklander */ 861817466cbSJens Wiklander static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, 862817466cbSJens Wiklander const unsigned char *key, 863817466cbSJens Wiklander size_t keylen ) 864817466cbSJens Wiklander { 86511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 866817466cbSJens Wiklander int version, pubkey_done; 867817466cbSJens Wiklander size_t len; 868817466cbSJens Wiklander mbedtls_asn1_buf params; 869817466cbSJens Wiklander unsigned char *p = (unsigned char *) key; 870817466cbSJens Wiklander unsigned char *end = p + keylen; 871817466cbSJens Wiklander unsigned char *end2; 872817466cbSJens Wiklander 873817466cbSJens Wiklander /* 874817466cbSJens Wiklander * RFC 5915, or SEC1 Appendix C.4 875817466cbSJens Wiklander * 876817466cbSJens Wiklander * ECPrivateKey ::= SEQUENCE { 877817466cbSJens Wiklander * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), 878817466cbSJens Wiklander * privateKey OCTET STRING, 879817466cbSJens Wiklander * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, 880817466cbSJens Wiklander * publicKey [1] BIT STRING OPTIONAL 881817466cbSJens Wiklander * } 882817466cbSJens Wiklander */ 883817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 884817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 885817466cbSJens Wiklander { 8867901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 887817466cbSJens Wiklander } 888817466cbSJens Wiklander 889817466cbSJens Wiklander end = p + len; 890817466cbSJens Wiklander 891817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) 8927901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 893817466cbSJens Wiklander 894817466cbSJens Wiklander if( version != 1 ) 895817466cbSJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); 896817466cbSJens Wiklander 897817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 8987901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 899817466cbSJens Wiklander 900817466cbSJens Wiklander if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) 901817466cbSJens Wiklander { 902817466cbSJens Wiklander mbedtls_ecp_keypair_free( eck ); 9037901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 904817466cbSJens Wiklander } 905817466cbSJens Wiklander 906817466cbSJens Wiklander p += len; 907817466cbSJens Wiklander 908817466cbSJens Wiklander pubkey_done = 0; 909817466cbSJens Wiklander if( p != end ) 910817466cbSJens Wiklander { 911817466cbSJens Wiklander /* 912817466cbSJens Wiklander * Is 'parameters' present? 913817466cbSJens Wiklander */ 914817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 915817466cbSJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) 916817466cbSJens Wiklander { 917817466cbSJens Wiklander if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || 918817466cbSJens Wiklander ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) 919817466cbSJens Wiklander { 920817466cbSJens Wiklander mbedtls_ecp_keypair_free( eck ); 921817466cbSJens Wiklander return( ret ); 922817466cbSJens Wiklander } 923817466cbSJens Wiklander } 924817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 925817466cbSJens Wiklander { 926817466cbSJens Wiklander mbedtls_ecp_keypair_free( eck ); 9277901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 928817466cbSJens Wiklander } 9293d3b0591SJens Wiklander } 930817466cbSJens Wiklander 9313d3b0591SJens Wiklander if( p != end ) 9323d3b0591SJens Wiklander { 933817466cbSJens Wiklander /* 934817466cbSJens Wiklander * Is 'publickey' present? If not, or if we can't read it (eg because it 935817466cbSJens Wiklander * is compressed), create it from the private key. 936817466cbSJens Wiklander */ 937817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 938817466cbSJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) 939817466cbSJens Wiklander { 940817466cbSJens Wiklander end2 = p + len; 941817466cbSJens Wiklander 942817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) 9437901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 944817466cbSJens Wiklander 945817466cbSJens Wiklander if( p + len != end2 ) 9467901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 9477901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); 948817466cbSJens Wiklander 949817466cbSJens Wiklander if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) 950817466cbSJens Wiklander pubkey_done = 1; 951817466cbSJens Wiklander else 952817466cbSJens Wiklander { 953817466cbSJens Wiklander /* 954817466cbSJens Wiklander * The only acceptable failure mode of pk_get_ecpubkey() above 955817466cbSJens Wiklander * is if the point format is not recognized. 956817466cbSJens Wiklander */ 957817466cbSJens Wiklander if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) 958817466cbSJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 959817466cbSJens Wiklander } 960817466cbSJens Wiklander } 961817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 962817466cbSJens Wiklander { 963817466cbSJens Wiklander mbedtls_ecp_keypair_free( eck ); 9647901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 965817466cbSJens Wiklander } 966817466cbSJens Wiklander } 967817466cbSJens Wiklander 968817466cbSJens Wiklander if( ! pubkey_done && 969817466cbSJens Wiklander ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, 970817466cbSJens Wiklander NULL, NULL ) ) != 0 ) 971817466cbSJens Wiklander { 972817466cbSJens Wiklander mbedtls_ecp_keypair_free( eck ); 9737901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 974817466cbSJens Wiklander } 975817466cbSJens Wiklander 976817466cbSJens Wiklander if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) 977817466cbSJens Wiklander { 978817466cbSJens Wiklander mbedtls_ecp_keypair_free( eck ); 979817466cbSJens Wiklander return( ret ); 980817466cbSJens Wiklander } 981817466cbSJens Wiklander 982817466cbSJens Wiklander return( 0 ); 983817466cbSJens Wiklander } 984817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 985817466cbSJens Wiklander 986817466cbSJens Wiklander /* 987817466cbSJens Wiklander * Parse an unencrypted PKCS#8 encoded private key 9883d3b0591SJens Wiklander * 9893d3b0591SJens Wiklander * Notes: 9903d3b0591SJens Wiklander * 9913d3b0591SJens Wiklander * - This function does not own the key buffer. It is the 9923d3b0591SJens Wiklander * responsibility of the caller to take care of zeroizing 9933d3b0591SJens Wiklander * and freeing it after use. 9943d3b0591SJens Wiklander * 9953d3b0591SJens Wiklander * - The function is responsible for freeing the provided 9963d3b0591SJens Wiklander * PK context on failure. 9973d3b0591SJens Wiklander * 998817466cbSJens Wiklander */ 999817466cbSJens Wiklander static int pk_parse_key_pkcs8_unencrypted_der( 1000817466cbSJens Wiklander mbedtls_pk_context *pk, 1001817466cbSJens Wiklander const unsigned char* key, 1002817466cbSJens Wiklander size_t keylen ) 1003817466cbSJens Wiklander { 1004817466cbSJens Wiklander int ret, version; 1005817466cbSJens Wiklander size_t len; 1006817466cbSJens Wiklander mbedtls_asn1_buf params; 1007817466cbSJens Wiklander unsigned char *p = (unsigned char *) key; 1008817466cbSJens Wiklander unsigned char *end = p + keylen; 1009817466cbSJens Wiklander mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; 1010817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info; 1011817466cbSJens Wiklander 1012817466cbSJens Wiklander /* 10133d3b0591SJens Wiklander * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) 1014817466cbSJens Wiklander * 1015817466cbSJens Wiklander * PrivateKeyInfo ::= SEQUENCE { 1016817466cbSJens Wiklander * version Version, 1017817466cbSJens Wiklander * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, 1018817466cbSJens Wiklander * privateKey PrivateKey, 1019817466cbSJens Wiklander * attributes [0] IMPLICIT Attributes OPTIONAL } 1020817466cbSJens Wiklander * 1021817466cbSJens Wiklander * Version ::= INTEGER 1022817466cbSJens Wiklander * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier 1023817466cbSJens Wiklander * PrivateKey ::= OCTET STRING 1024817466cbSJens Wiklander * 1025817466cbSJens Wiklander * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey 1026817466cbSJens Wiklander */ 1027817466cbSJens Wiklander 1028817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 1029817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 1030817466cbSJens Wiklander { 10317901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 1032817466cbSJens Wiklander } 1033817466cbSJens Wiklander 1034817466cbSJens Wiklander end = p + len; 1035817466cbSJens Wiklander 1036817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) 10377901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 1038817466cbSJens Wiklander 1039817466cbSJens Wiklander if( version != 0 ) 10407901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret ) ); 1041817466cbSJens Wiklander 1042817466cbSJens Wiklander if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) 10437901324dSJerome Forissier { 10447901324dSJerome Forissier return( ret ); 10457901324dSJerome Forissier } 1046817466cbSJens Wiklander 1047817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 10487901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 1049817466cbSJens Wiklander 1050817466cbSJens Wiklander if( len < 1 ) 10517901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, 10527901324dSJerome Forissier MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); 1053817466cbSJens Wiklander 1054817466cbSJens Wiklander if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) 1055817466cbSJens Wiklander return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); 1056817466cbSJens Wiklander 1057817466cbSJens Wiklander if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) 1058817466cbSJens Wiklander return( ret ); 1059817466cbSJens Wiklander 1060817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 1061817466cbSJens Wiklander if( pk_alg == MBEDTLS_PK_RSA ) 1062817466cbSJens Wiklander { 1063817466cbSJens Wiklander if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) 1064817466cbSJens Wiklander { 1065817466cbSJens Wiklander mbedtls_pk_free( pk ); 1066817466cbSJens Wiklander return( ret ); 1067817466cbSJens Wiklander } 1068817466cbSJens Wiklander } else 1069817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 1070817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 1071817466cbSJens Wiklander if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) 1072817466cbSJens Wiklander { 1073817466cbSJens Wiklander if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || 1074817466cbSJens Wiklander ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) 1075817466cbSJens Wiklander { 1076817466cbSJens Wiklander mbedtls_pk_free( pk ); 1077817466cbSJens Wiklander return( ret ); 1078817466cbSJens Wiklander } 1079817466cbSJens Wiklander } else 1080817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 1081817466cbSJens Wiklander return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); 1082817466cbSJens Wiklander 1083817466cbSJens Wiklander return( 0 ); 1084817466cbSJens Wiklander } 1085817466cbSJens Wiklander 1086817466cbSJens Wiklander /* 1087817466cbSJens Wiklander * Parse an encrypted PKCS#8 encoded private key 10883d3b0591SJens Wiklander * 10893d3b0591SJens Wiklander * To save space, the decryption happens in-place on the given key buffer. 10903d3b0591SJens Wiklander * Also, while this function may modify the keybuffer, it doesn't own it, 10913d3b0591SJens Wiklander * and instead it is the responsibility of the caller to zeroize and properly 10923d3b0591SJens Wiklander * free it after use. 10933d3b0591SJens Wiklander * 1094817466cbSJens Wiklander */ 1095817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 1096817466cbSJens Wiklander static int pk_parse_key_pkcs8_encrypted_der( 1097817466cbSJens Wiklander mbedtls_pk_context *pk, 10983d3b0591SJens Wiklander unsigned char *key, size_t keylen, 1099817466cbSJens Wiklander const unsigned char *pwd, size_t pwdlen ) 1100817466cbSJens Wiklander { 1101817466cbSJens Wiklander int ret, decrypted = 0; 1102817466cbSJens Wiklander size_t len; 11033d3b0591SJens Wiklander unsigned char *buf; 1104817466cbSJens Wiklander unsigned char *p, *end; 1105817466cbSJens Wiklander mbedtls_asn1_buf pbe_alg_oid, pbe_params; 1106817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) 1107817466cbSJens Wiklander mbedtls_cipher_type_t cipher_alg; 1108817466cbSJens Wiklander mbedtls_md_type_t md_alg; 1109817466cbSJens Wiklander #endif 1110817466cbSJens Wiklander 11113d3b0591SJens Wiklander p = key; 1112817466cbSJens Wiklander end = p + keylen; 1113817466cbSJens Wiklander 1114817466cbSJens Wiklander if( pwdlen == 0 ) 1115817466cbSJens Wiklander return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); 1116817466cbSJens Wiklander 1117817466cbSJens Wiklander /* 11183d3b0591SJens Wiklander * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) 1119817466cbSJens Wiklander * 1120817466cbSJens Wiklander * EncryptedPrivateKeyInfo ::= SEQUENCE { 1121817466cbSJens Wiklander * encryptionAlgorithm EncryptionAlgorithmIdentifier, 1122817466cbSJens Wiklander * encryptedData EncryptedData 1123817466cbSJens Wiklander * } 1124817466cbSJens Wiklander * 1125817466cbSJens Wiklander * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 1126817466cbSJens Wiklander * 1127817466cbSJens Wiklander * EncryptedData ::= OCTET STRING 1128817466cbSJens Wiklander * 1129817466cbSJens Wiklander * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo 11303d3b0591SJens Wiklander * 1131817466cbSJens Wiklander */ 1132817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 1133817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 1134817466cbSJens Wiklander { 11357901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 1136817466cbSJens Wiklander } 1137817466cbSJens Wiklander 1138817466cbSJens Wiklander end = p + len; 1139817466cbSJens Wiklander 1140817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) 11417901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 1142817466cbSJens Wiklander 1143817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 11447901324dSJerome Forissier return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); 1145817466cbSJens Wiklander 11463d3b0591SJens Wiklander buf = p; 1147817466cbSJens Wiklander 1148817466cbSJens Wiklander /* 11493d3b0591SJens Wiklander * Decrypt EncryptedData with appropriate PBE 1150817466cbSJens Wiklander */ 1151817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) 1152817466cbSJens Wiklander if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) 1153817466cbSJens Wiklander { 1154817466cbSJens Wiklander if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, 1155817466cbSJens Wiklander cipher_alg, md_alg, 1156817466cbSJens Wiklander pwd, pwdlen, p, len, buf ) ) != 0 ) 1157817466cbSJens Wiklander { 1158817466cbSJens Wiklander if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) 1159817466cbSJens Wiklander return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); 1160817466cbSJens Wiklander 1161817466cbSJens Wiklander return( ret ); 1162817466cbSJens Wiklander } 1163817466cbSJens Wiklander 1164817466cbSJens Wiklander decrypted = 1; 1165817466cbSJens Wiklander } 1166817466cbSJens Wiklander else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) 1167817466cbSJens Wiklander { 1168817466cbSJens Wiklander if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, 1169817466cbSJens Wiklander MBEDTLS_PKCS12_PBE_DECRYPT, 1170817466cbSJens Wiklander pwd, pwdlen, 1171817466cbSJens Wiklander p, len, buf ) ) != 0 ) 1172817466cbSJens Wiklander { 1173817466cbSJens Wiklander return( ret ); 1174817466cbSJens Wiklander } 1175817466cbSJens Wiklander 1176817466cbSJens Wiklander // Best guess for password mismatch when using RC4. If first tag is 1177817466cbSJens Wiklander // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE 1178817466cbSJens Wiklander // 1179817466cbSJens Wiklander if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 1180817466cbSJens Wiklander return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); 1181817466cbSJens Wiklander 1182817466cbSJens Wiklander decrypted = 1; 1183817466cbSJens Wiklander } 1184817466cbSJens Wiklander else 1185817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C */ 1186817466cbSJens Wiklander #if defined(MBEDTLS_PKCS5_C) 1187817466cbSJens Wiklander if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) 1188817466cbSJens Wiklander { 1189817466cbSJens Wiklander if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, 1190817466cbSJens Wiklander p, len, buf ) ) != 0 ) 1191817466cbSJens Wiklander { 1192817466cbSJens Wiklander if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) 1193817466cbSJens Wiklander return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); 1194817466cbSJens Wiklander 1195817466cbSJens Wiklander return( ret ); 1196817466cbSJens Wiklander } 1197817466cbSJens Wiklander 1198817466cbSJens Wiklander decrypted = 1; 1199817466cbSJens Wiklander } 1200817466cbSJens Wiklander else 1201817466cbSJens Wiklander #endif /* MBEDTLS_PKCS5_C */ 1202817466cbSJens Wiklander { 1203817466cbSJens Wiklander ((void) pwd); 1204817466cbSJens Wiklander } 1205817466cbSJens Wiklander 1206817466cbSJens Wiklander if( decrypted == 0 ) 1207817466cbSJens Wiklander return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); 1208817466cbSJens Wiklander 1209817466cbSJens Wiklander return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); 1210817466cbSJens Wiklander } 1211817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 1212817466cbSJens Wiklander 1213817466cbSJens Wiklander /* 1214817466cbSJens Wiklander * Parse a private key 1215817466cbSJens Wiklander */ 1216817466cbSJens Wiklander int mbedtls_pk_parse_key( mbedtls_pk_context *pk, 1217817466cbSJens Wiklander const unsigned char *key, size_t keylen, 1218817466cbSJens Wiklander const unsigned char *pwd, size_t pwdlen ) 1219817466cbSJens Wiklander { 122011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1221817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info; 1222817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 1223817466cbSJens Wiklander size_t len; 1224817466cbSJens Wiklander mbedtls_pem_context pem; 12253d3b0591SJens Wiklander #endif 1226817466cbSJens Wiklander 12273d3b0591SJens Wiklander PK_VALIDATE_RET( pk != NULL ); 12283d3b0591SJens Wiklander if( keylen == 0 ) 12293d3b0591SJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 12303d3b0591SJens Wiklander PK_VALIDATE_RET( key != NULL ); 12313d3b0591SJens Wiklander 12323d3b0591SJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 1233817466cbSJens Wiklander mbedtls_pem_init( &pem ); 1234817466cbSJens Wiklander 1235817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 1236817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 12373d3b0591SJens Wiklander if( key[keylen - 1] != '\0' ) 1238817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1239817466cbSJens Wiklander else 1240817466cbSJens Wiklander ret = mbedtls_pem_read_buffer( &pem, 1241817466cbSJens Wiklander "-----BEGIN RSA PRIVATE KEY-----", 1242817466cbSJens Wiklander "-----END RSA PRIVATE KEY-----", 1243817466cbSJens Wiklander key, pwd, pwdlen, &len ); 1244817466cbSJens Wiklander 1245817466cbSJens Wiklander if( ret == 0 ) 1246817466cbSJens Wiklander { 12473d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); 1248817466cbSJens Wiklander if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || 1249817466cbSJens Wiklander ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), 1250817466cbSJens Wiklander pem.buf, pem.buflen ) ) != 0 ) 1251817466cbSJens Wiklander { 1252817466cbSJens Wiklander mbedtls_pk_free( pk ); 1253817466cbSJens Wiklander } 1254817466cbSJens Wiklander 1255817466cbSJens Wiklander mbedtls_pem_free( &pem ); 1256817466cbSJens Wiklander return( ret ); 1257817466cbSJens Wiklander } 1258817466cbSJens Wiklander else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) 1259817466cbSJens Wiklander return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); 1260817466cbSJens Wiklander else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) 1261817466cbSJens Wiklander return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); 1262817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 1263817466cbSJens Wiklander return( ret ); 1264817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 1265817466cbSJens Wiklander 1266817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 1267817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 12683d3b0591SJens Wiklander if( key[keylen - 1] != '\0' ) 1269817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1270817466cbSJens Wiklander else 1271817466cbSJens Wiklander ret = mbedtls_pem_read_buffer( &pem, 1272817466cbSJens Wiklander "-----BEGIN EC PRIVATE KEY-----", 1273817466cbSJens Wiklander "-----END EC PRIVATE KEY-----", 1274817466cbSJens Wiklander key, pwd, pwdlen, &len ); 1275817466cbSJens Wiklander if( ret == 0 ) 1276817466cbSJens Wiklander { 12773d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); 1278817466cbSJens Wiklander 1279817466cbSJens Wiklander if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || 1280817466cbSJens Wiklander ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), 1281817466cbSJens Wiklander pem.buf, pem.buflen ) ) != 0 ) 1282817466cbSJens Wiklander { 1283817466cbSJens Wiklander mbedtls_pk_free( pk ); 1284817466cbSJens Wiklander } 1285817466cbSJens Wiklander 1286817466cbSJens Wiklander mbedtls_pem_free( &pem ); 1287817466cbSJens Wiklander return( ret ); 1288817466cbSJens Wiklander } 1289817466cbSJens Wiklander else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) 1290817466cbSJens Wiklander return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); 1291817466cbSJens Wiklander else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) 1292817466cbSJens Wiklander return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); 1293817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 1294817466cbSJens Wiklander return( ret ); 1295817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 1296817466cbSJens Wiklander 1297817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 12983d3b0591SJens Wiklander if( key[keylen - 1] != '\0' ) 1299817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1300817466cbSJens Wiklander else 1301817466cbSJens Wiklander ret = mbedtls_pem_read_buffer( &pem, 1302817466cbSJens Wiklander "-----BEGIN PRIVATE KEY-----", 1303817466cbSJens Wiklander "-----END PRIVATE KEY-----", 1304817466cbSJens Wiklander key, NULL, 0, &len ); 1305817466cbSJens Wiklander if( ret == 0 ) 1306817466cbSJens Wiklander { 1307817466cbSJens Wiklander if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, 1308817466cbSJens Wiklander pem.buf, pem.buflen ) ) != 0 ) 1309817466cbSJens Wiklander { 1310817466cbSJens Wiklander mbedtls_pk_free( pk ); 1311817466cbSJens Wiklander } 1312817466cbSJens Wiklander 1313817466cbSJens Wiklander mbedtls_pem_free( &pem ); 1314817466cbSJens Wiklander return( ret ); 1315817466cbSJens Wiklander } 1316817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 1317817466cbSJens Wiklander return( ret ); 1318817466cbSJens Wiklander 1319817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 1320817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 13213d3b0591SJens Wiklander if( key[keylen - 1] != '\0' ) 1322817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1323817466cbSJens Wiklander else 1324817466cbSJens Wiklander ret = mbedtls_pem_read_buffer( &pem, 1325817466cbSJens Wiklander "-----BEGIN ENCRYPTED PRIVATE KEY-----", 1326817466cbSJens Wiklander "-----END ENCRYPTED PRIVATE KEY-----", 1327817466cbSJens Wiklander key, NULL, 0, &len ); 1328817466cbSJens Wiklander if( ret == 0 ) 1329817466cbSJens Wiklander { 1330817466cbSJens Wiklander if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, 1331817466cbSJens Wiklander pem.buf, pem.buflen, 1332817466cbSJens Wiklander pwd, pwdlen ) ) != 0 ) 1333817466cbSJens Wiklander { 1334817466cbSJens Wiklander mbedtls_pk_free( pk ); 1335817466cbSJens Wiklander } 1336817466cbSJens Wiklander 1337817466cbSJens Wiklander mbedtls_pem_free( &pem ); 1338817466cbSJens Wiklander return( ret ); 1339817466cbSJens Wiklander } 1340817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 1341817466cbSJens Wiklander return( ret ); 1342817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 1343817466cbSJens Wiklander #else 1344817466cbSJens Wiklander ((void) pwd); 1345817466cbSJens Wiklander ((void) pwdlen); 1346817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */ 1347817466cbSJens Wiklander 1348817466cbSJens Wiklander /* 1349817466cbSJens Wiklander * At this point we only know it's not a PEM formatted key. Could be any 1350817466cbSJens Wiklander * of the known DER encoded private key formats 1351817466cbSJens Wiklander * 1352817466cbSJens Wiklander * We try the different DER format parsers to see if one passes without 1353817466cbSJens Wiklander * error 1354817466cbSJens Wiklander */ 1355817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 1356817466cbSJens Wiklander { 13573d3b0591SJens Wiklander unsigned char *key_copy; 13583d3b0591SJens Wiklander 13593d3b0591SJens Wiklander if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) 13603d3b0591SJens Wiklander return( MBEDTLS_ERR_PK_ALLOC_FAILED ); 13613d3b0591SJens Wiklander 13623d3b0591SJens Wiklander memcpy( key_copy, key, keylen ); 13633d3b0591SJens Wiklander 13643d3b0591SJens Wiklander ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, 13653d3b0591SJens Wiklander pwd, pwdlen ); 13663d3b0591SJens Wiklander 13673d3b0591SJens Wiklander mbedtls_platform_zeroize( key_copy, keylen ); 13683d3b0591SJens Wiklander mbedtls_free( key_copy ); 1369817466cbSJens Wiklander } 1370817466cbSJens Wiklander 13713d3b0591SJens Wiklander if( ret == 0 ) 13723d3b0591SJens Wiklander return( 0 ); 13733d3b0591SJens Wiklander 1374817466cbSJens Wiklander mbedtls_pk_free( pk ); 13753d3b0591SJens Wiklander mbedtls_pk_init( pk ); 1376817466cbSJens Wiklander 1377817466cbSJens Wiklander if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) 1378817466cbSJens Wiklander { 1379817466cbSJens Wiklander return( ret ); 1380817466cbSJens Wiklander } 1381817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ 1382817466cbSJens Wiklander 1383*039e02dfSJerome Forissier ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ); 1384*039e02dfSJerome Forissier if( ret == 0 ) 1385*039e02dfSJerome Forissier { 1386817466cbSJens Wiklander return( 0 ); 1387*039e02dfSJerome Forissier } 1388817466cbSJens Wiklander 1389817466cbSJens Wiklander mbedtls_pk_free( pk ); 13903d3b0591SJens Wiklander mbedtls_pk_init( pk ); 1391817466cbSJens Wiklander 1392817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 1393817466cbSJens Wiklander 13943d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); 13953d3b0591SJens Wiklander if( mbedtls_pk_setup( pk, pk_info ) == 0 && 13963d3b0591SJens Wiklander pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) 1397817466cbSJens Wiklander { 1398817466cbSJens Wiklander return( 0 ); 1399817466cbSJens Wiklander } 1400817466cbSJens Wiklander 1401817466cbSJens Wiklander mbedtls_pk_free( pk ); 14023d3b0591SJens Wiklander mbedtls_pk_init( pk ); 1403817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 1404817466cbSJens Wiklander 1405817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C) 14063d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); 14073d3b0591SJens Wiklander if( mbedtls_pk_setup( pk, pk_info ) == 0 && 14083d3b0591SJens Wiklander pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), 14093d3b0591SJens Wiklander key, keylen ) == 0 ) 1410817466cbSJens Wiklander { 1411817466cbSJens Wiklander return( 0 ); 1412817466cbSJens Wiklander } 1413817466cbSJens Wiklander mbedtls_pk_free( pk ); 1414817466cbSJens Wiklander #endif /* MBEDTLS_ECP_C */ 1415817466cbSJens Wiklander 14163d3b0591SJens Wiklander /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, 14173d3b0591SJens Wiklander * it is ok to leave the PK context initialized but not 14183d3b0591SJens Wiklander * freed: It is the caller's responsibility to call pk_init() 14193d3b0591SJens Wiklander * before calling this function, and to call pk_free() 14203d3b0591SJens Wiklander * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C 14213d3b0591SJens Wiklander * isn't, this leads to mbedtls_pk_free() being called 14223d3b0591SJens Wiklander * twice, once here and once by the caller, but this is 14233d3b0591SJens Wiklander * also ok and in line with the mbedtls_pk_free() calls 14243d3b0591SJens Wiklander * on failed PEM parsing attempts. */ 14253d3b0591SJens Wiklander 1426817466cbSJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 1427817466cbSJens Wiklander } 1428817466cbSJens Wiklander 1429817466cbSJens Wiklander /* 1430817466cbSJens Wiklander * Parse a public key 1431817466cbSJens Wiklander */ 1432817466cbSJens Wiklander int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, 1433817466cbSJens Wiklander const unsigned char *key, size_t keylen ) 1434817466cbSJens Wiklander { 143511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1436817466cbSJens Wiklander unsigned char *p; 14373d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C) 14383d3b0591SJens Wiklander const mbedtls_pk_info_t *pk_info; 14393d3b0591SJens Wiklander #endif 1440817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 1441817466cbSJens Wiklander size_t len; 1442817466cbSJens Wiklander mbedtls_pem_context pem; 14433d3b0591SJens Wiklander #endif 1444817466cbSJens Wiklander 14453d3b0591SJens Wiklander PK_VALIDATE_RET( ctx != NULL ); 14463d3b0591SJens Wiklander if( keylen == 0 ) 14473d3b0591SJens Wiklander return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); 14483d3b0591SJens Wiklander PK_VALIDATE_RET( key != NULL || keylen == 0 ); 14493d3b0591SJens Wiklander 14503d3b0591SJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C) 1451817466cbSJens Wiklander mbedtls_pem_init( &pem ); 14523d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C) 14533d3b0591SJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 14543d3b0591SJens Wiklander if( key[keylen - 1] != '\0' ) 14553d3b0591SJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 14563d3b0591SJens Wiklander else 14573d3b0591SJens Wiklander ret = mbedtls_pem_read_buffer( &pem, 14583d3b0591SJens Wiklander "-----BEGIN RSA PUBLIC KEY-----", 14593d3b0591SJens Wiklander "-----END RSA PUBLIC KEY-----", 14603d3b0591SJens Wiklander key, NULL, 0, &len ); 14613d3b0591SJens Wiklander 14623d3b0591SJens Wiklander if( ret == 0 ) 14633d3b0591SJens Wiklander { 14643d3b0591SJens Wiklander p = pem.buf; 14653d3b0591SJens Wiklander if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) 1466*039e02dfSJerome Forissier { 1467*039e02dfSJerome Forissier mbedtls_pem_free( &pem ); 14683d3b0591SJens Wiklander return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); 1469*039e02dfSJerome Forissier } 14703d3b0591SJens Wiklander 14713d3b0591SJens Wiklander if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) 1472*039e02dfSJerome Forissier { 1473*039e02dfSJerome Forissier mbedtls_pem_free( &pem ); 14743d3b0591SJens Wiklander return( ret ); 1475*039e02dfSJerome Forissier } 14763d3b0591SJens Wiklander 14773d3b0591SJens Wiklander if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) 14783d3b0591SJens Wiklander mbedtls_pk_free( ctx ); 14793d3b0591SJens Wiklander 14803d3b0591SJens Wiklander mbedtls_pem_free( &pem ); 14813d3b0591SJens Wiklander return( ret ); 14823d3b0591SJens Wiklander } 14833d3b0591SJens Wiklander else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 14843d3b0591SJens Wiklander { 14853d3b0591SJens Wiklander mbedtls_pem_free( &pem ); 14863d3b0591SJens Wiklander return( ret ); 14873d3b0591SJens Wiklander } 14883d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_C */ 1489817466cbSJens Wiklander 1490817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 14913d3b0591SJens Wiklander if( key[keylen - 1] != '\0' ) 1492817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 1493817466cbSJens Wiklander else 1494817466cbSJens Wiklander ret = mbedtls_pem_read_buffer( &pem, 1495817466cbSJens Wiklander "-----BEGIN PUBLIC KEY-----", 1496817466cbSJens Wiklander "-----END PUBLIC KEY-----", 1497817466cbSJens Wiklander key, NULL, 0, &len ); 1498817466cbSJens Wiklander 1499817466cbSJens Wiklander if( ret == 0 ) 1500817466cbSJens Wiklander { 1501817466cbSJens Wiklander /* 1502817466cbSJens Wiklander * Was PEM encoded 1503817466cbSJens Wiklander */ 15043d3b0591SJens Wiklander p = pem.buf; 15053d3b0591SJens Wiklander 15063d3b0591SJens Wiklander ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); 15073d3b0591SJens Wiklander mbedtls_pem_free( &pem ); 15083d3b0591SJens Wiklander return( ret ); 1509817466cbSJens Wiklander } 1510817466cbSJens Wiklander else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 1511817466cbSJens Wiklander { 1512817466cbSJens Wiklander mbedtls_pem_free( &pem ); 1513817466cbSJens Wiklander return( ret ); 1514817466cbSJens Wiklander } 15153d3b0591SJens Wiklander mbedtls_pem_free( &pem ); 1516817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */ 15173d3b0591SJens Wiklander 15183d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C) 15193d3b0591SJens Wiklander if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) 15203d3b0591SJens Wiklander return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); 15213d3b0591SJens Wiklander 15223d3b0591SJens Wiklander if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) 15233d3b0591SJens Wiklander return( ret ); 15243d3b0591SJens Wiklander 15253d3b0591SJens Wiklander p = (unsigned char *)key; 15263d3b0591SJens Wiklander ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); 15273d3b0591SJens Wiklander if( ret == 0 ) 15283d3b0591SJens Wiklander { 15293d3b0591SJens Wiklander return( ret ); 15303d3b0591SJens Wiklander } 15313d3b0591SJens Wiklander mbedtls_pk_free( ctx ); 15327901324dSJerome Forissier if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, 15337901324dSJerome Forissier MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) ) 15343d3b0591SJens Wiklander { 15353d3b0591SJens Wiklander return( ret ); 15363d3b0591SJens Wiklander } 15373d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_C */ 1538817466cbSJens Wiklander p = (unsigned char *) key; 1539817466cbSJens Wiklander 1540817466cbSJens Wiklander ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); 1541817466cbSJens Wiklander 1542817466cbSJens Wiklander return( ret ); 1543817466cbSJens Wiklander } 1544817466cbSJens Wiklander 1545817466cbSJens Wiklander #endif /* MBEDTLS_PK_PARSE_C */ 1546