mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

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