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