RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

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