BBR 1 Ebene

Committer:
borlanic
Date:
Mon May 14 11:29:06 2018 +0000
Revision:
0:fbdae7e6d805
BBR

Who changed what in which revision?

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