Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

Committer:
HannesTschofenig
Date:
Thu Sep 27 06:34:22 2018 +0000
Revision:
0:796d0f61a05b
Example AES-GCM test program

Who changed what in which revision?

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