mbed TLS upgraded to 2.6.0

Fork of mbedtls by Mark Radbourne

Committer:
Jasper Wallace
Date:
Fri Sep 29 19:50:30 2017 +0100
Revision:
2:bbdeda018a3c
Parent:
0:cdf462088d13
Update to mbedtls 2.6.0, many changes.

Changes to mbedtls sources made:

in include/mbedtls/config.h comment out:

#define MBEDTLS_FS_IO
#define MBEDTLS_NET_C
#define MBEDTLS_TIMING_C

uncomment:

#define MBEDTLS_NO_PLATFORM_ENTROPY

remove the following directorys:

programs
yotta
visualc

Who changed what in which revision?

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