blob: 7c14e34ec78d877aaf427e88cbf715c022fdab68 [file] [log] [blame]
Paul Bakker1a7550a2013-09-15 13:01:22 +02001/*
2 * Public Key layer for parsing key files and structures
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker1a7550a2013-09-15 13:01:22 +020018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker1a7550a2013-09-15 13:01:22 +020020 */
21
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020022#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000023#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020024#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020025#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020026#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +020027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if defined(MBEDTLS_PK_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +020029
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/pk.h"
31#include "mbedtls/asn1.h"
32#include "mbedtls/oid.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050033#include "mbedtls/platform_util.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020034
Rich Evans00ab4702015-02-06 13:43:58 +000035#include <string.h>
36
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020037#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/rsa.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020039#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000041#include "mbedtls/ecp.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020042#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#if defined(MBEDTLS_ECDSA_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000044#include "mbedtls/ecdsa.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020045#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020046#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/pem.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020048#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/pkcs5.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020051#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PKCS12_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/pkcs12.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020054#endif
55
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000057#include "mbedtls/platform.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020058#else
59#include <stdlib.h>
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020060#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020061#define mbedtls_free free
Paul Bakker1a7550a2013-09-15 13:01:22 +020062#endif
63
Gilles Peskinee97dc602018-12-19 00:51:38 +010064/* Parameter validation macros based on platform_util.h */
65#define PK_VALIDATE_RET( cond ) \
66 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
67#define PK_VALIDATE( cond ) \
68 MBEDTLS_INTERNAL_VALIDATE( cond )
69
Gilles Peskine832f3492017-11-30 11:42:12 +010070#if defined(MBEDTLS_FS_IO)
Paul Bakker1a7550a2013-09-15 13:01:22 +020071/*
72 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +020073 *
74 * The file is expected to contain either PEM or DER encoded data.
75 * A terminating null byte is always appended. It is included in the announced
76 * length only if the data looks like it is PEM encoded.
Paul Bakker1a7550a2013-09-15 13:01:22 +020077 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n )
Paul Bakker1a7550a2013-09-15 13:01:22 +020079{
80 FILE *f;
81 long size;
82
Gilles Peskinee97dc602018-12-19 00:51:38 +010083 PK_VALIDATE_RET( path != NULL );
84 PK_VALIDATE_RET( buf != NULL );
85 PK_VALIDATE_RET( n != NULL );
86
Paul Bakker1a7550a2013-09-15 13:01:22 +020087 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088 return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
Paul Bakker1a7550a2013-09-15 13:01:22 +020089
90 fseek( f, 0, SEEK_END );
91 if( ( size = ftell( f ) ) == -1 )
92 {
93 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094 return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
Paul Bakker1a7550a2013-09-15 13:01:22 +020095 }
96 fseek( f, 0, SEEK_SET );
97
98 *n = (size_t) size;
99
100 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200101 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200102 {
103 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200104 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200105 }
106
107 if( fread( *buf, 1, *n, f ) != *n )
108 {
109 fclose( f );
Andres Amaya Garcia1f2666f2017-06-26 10:36:20 +0100110
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500111 mbedtls_platform_zeroize( *buf, *n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112 mbedtls_free( *buf );
Andres Amaya Garcia1f2666f2017-06-26 10:36:20 +0100113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114 return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200115 }
116
117 fclose( f );
118
119 (*buf)[*n] = '\0';
120
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200121 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
122 ++*n;
123
Paul Bakker1a7550a2013-09-15 13:01:22 +0200124 return( 0 );
125}
126
127/*
128 * Load and parse a private key
129 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
Paul Bakker1a7550a2013-09-15 13:01:22 +0200131 const char *path, const char *pwd )
132{
133 int ret;
134 size_t n;
135 unsigned char *buf;
136
Gilles Peskinee97dc602018-12-19 00:51:38 +0100137 PK_VALIDATE_RET( ctx != NULL );
138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200140 return( ret );
141
142 if( pwd == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200143 ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200144 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 ret = mbedtls_pk_parse_key( ctx, buf, n,
Paul Bakker1a7550a2013-09-15 13:01:22 +0200146 (const unsigned char *) pwd, strlen( pwd ) );
147
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500148 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 mbedtls_free( buf );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200150
151 return( ret );
152}
153
154/*
155 * Load and parse a public key
156 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200158{
159 int ret;
160 size_t n;
161 unsigned char *buf;
162
Gilles Peskinee97dc602018-12-19 00:51:38 +0100163 PK_VALIDATE_RET( ctx != NULL );
164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200166 return( ret );
167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 ret = mbedtls_pk_parse_public_key( ctx, buf, n );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200169
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500170 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 mbedtls_free( buf );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200172
173 return( ret );
174}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175#endif /* MBEDTLS_FS_IO */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177#if defined(MBEDTLS_ECP_C)
178/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
Paul Bakker1a7550a2013-09-15 13:01:22 +0200179 *
180 * ECParameters ::= CHOICE {
181 * namedCurve OBJECT IDENTIFIER
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100182 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200183 * -- implicitCurve NULL
Paul Bakker1a7550a2013-09-15 13:01:22 +0200184 * }
185 */
186static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 mbedtls_asn1_buf *params )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200188{
189 int ret;
190
Sanne Woudab2b29d52017-08-21 15:58:12 +0100191 if ( end - *p < 1 )
Sanne Wouda7b2e85d2017-08-30 21:10:42 +0100192 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
193 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Sanne Woudab2b29d52017-08-21 15:58:12 +0100194
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100195 /* Tag may be either OID or SEQUENCE */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200196 params->tag = **p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 if( params->tag != MBEDTLS_ASN1_OID
198#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
199 && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE )
Manuel Pégourié-Gonnard6fac3512014-03-19 16:39:52 +0100200#endif
201 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
204 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100205 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 if( ( ret = mbedtls_asn1_get_tag( p, end, &params->len, params->tag ) ) != 0 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100208 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100210 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200211
212 params->p = *p;
213 *p += params->len;
214
215 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
217 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200218
219 return( 0 );
220}
221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200223/*
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100224 * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
225 * WARNING: the resulting group should only be used with
226 * pk_group_id_from_specified(), since its base point may not be set correctly
227 * if it was encoded compressed.
228 *
229 * SpecifiedECDomain ::= SEQUENCE {
230 * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
231 * fieldID FieldID {{FieldTypes}},
232 * curve Curve,
233 * base ECPoint,
234 * order INTEGER,
235 * cofactor INTEGER OPTIONAL,
236 * hash HashAlgorithm OPTIONAL,
237 * ...
238 * }
239 *
240 * We only support prime-field as field type, and ignore hash and cofactor.
241 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100243{
244 int ret;
245 unsigned char *p = params->p;
246 const unsigned char * const end = params->p + params->len;
247 const unsigned char *end_field, *end_curve;
248 size_t len;
249 int ver;
250
251 /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 )
253 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100254
255 if( ver < 1 || ver > 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100257
258 /*
259 * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
260 * fieldType FIELD-ID.&id({IOSet}),
261 * parameters FIELD-ID.&Type({IOSet}{@fieldType})
262 * }
263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
265 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100266 return( ret );
267
268 end_field = p + len;
269
270 /*
271 * FIELD-ID ::= TYPE-IDENTIFIER
272 * FieldTypes FIELD-ID ::= {
273 * { Prime-p IDENTIFIED BY prime-field } |
274 * { Characteristic-two IDENTIFIED BY characteristic-two-field }
275 * }
276 * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100279 return( ret );
280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) ||
282 memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100283 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100285 }
286
287 p += len;
288
289 /* Prime-p ::= INTEGER -- Field of size p. */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 )
291 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100292
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200293 grp->pbits = mbedtls_mpi_bitlen( &grp->P );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100294
295 if( p != end_field )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
297 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100298
299 /*
300 * Curve ::= SEQUENCE {
301 * a FieldElement,
302 * b FieldElement,
303 * seed BIT STRING OPTIONAL
304 * -- Shall be present if used in SpecifiedECDomain
305 * -- with version equal to ecdpVer2 or ecdpVer3
306 * }
307 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
309 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100310 return( ret );
311
312 end_curve = p + len;
313
314 /*
315 * FieldElement ::= OCTET STRING
316 * containing an integer in the case of a prime field
317 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318 if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
319 ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100320 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100322 }
323
324 p += len;
325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
327 ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100328 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100330 }
331
332 p += len;
333
334 /* Ignore seed BIT STRING OPTIONAL */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100336 p += len;
337
338 if( p != end_curve )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
340 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100341
342 /*
343 * ECPoint ::= OCTET STRING
344 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
346 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100349 ( const unsigned char *) p, len ) ) != 0 )
350 {
351 /*
352 * If we can't read the point because it's compressed, cheat by
353 * reading only the X coordinate and the parity bit of Y.
354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100356 ( p[0] != 0x02 && p[0] != 0x03 ) ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 len != mbedtls_mpi_size( &grp->P ) + 1 ||
358 mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 ||
359 mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 ||
360 mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100361 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100363 }
364 }
365
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100366 p += len;
367
368 /*
369 * order INTEGER
370 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 )
372 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100373
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200374 grp->nbits = mbedtls_mpi_bitlen( &grp->N );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100375
376 /*
377 * Allow optional elements by purposefully not enforcing p == end here.
378 */
379
380 return( 0 );
381}
382
383/*
384 * Find the group id associated with an (almost filled) group as generated by
385 * pk_group_from_specified(), or return an error if unknown.
386 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100388{
Manuel Pégourié-Gonnard5b8c4092014-03-27 14:59:42 +0100389 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 mbedtls_ecp_group ref;
391 const mbedtls_ecp_group_id *id;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 mbedtls_ecp_group_init( &ref );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100396 {
397 /* Load the group associated to that id */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 mbedtls_ecp_group_free( &ref );
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200399 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100400
401 /* Compare to the group we were given, starting with easy tests */
402 if( grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 &&
404 mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 &&
405 mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 &&
406 mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 &&
407 mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 &&
408 mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 &&
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100409 /* For Y we may only know the parity bit, so compare only that */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410 mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100411 {
412 break;
413 }
414
415 }
416
417cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 mbedtls_ecp_group_free( &ref );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100419
420 *grp_id = *id;
421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE )
423 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100424
425 return( ret );
426}
427
428/*
429 * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
430 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431static int pk_group_id_from_specified( const mbedtls_asn1_buf *params,
432 mbedtls_ecp_group_id *grp_id )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100433{
434 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100438
439 if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 )
440 goto cleanup;
441
442 ret = pk_group_id_from_group( &grp, grp_id );
443
444cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100446
447 return( ret );
448}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100450
451/*
Paul Bakker1a7550a2013-09-15 13:01:22 +0200452 * Use EC parameters to initialise an EC group
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100453 *
454 * ECParameters ::= CHOICE {
455 * namedCurve OBJECT IDENTIFIER
456 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
457 * -- implicitCurve NULL
Paul Bakker1a7550a2013-09-15 13:01:22 +0200458 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200460{
461 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_ecp_group_id grp_id;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 if( params->tag == MBEDTLS_ASN1_OID )
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100465 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 )
467 return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100468 }
469 else
470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100472 if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 )
473 return( ret );
Manuel Pégourié-Gonnard6fac3512014-03-19 16:39:52 +0100474#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
Manuel Pégourié-Gonnard6fac3512014-03-19 16:39:52 +0100476#endif
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100477 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200478
479 /*
480 * grp may already be initilialized; if so, make sure IDs match
481 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id )
483 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200484
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200485 if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200486 return( ret );
487
488 return( 0 );
489}
490
491/*
492 * EC public key is an EC point
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100493 *
494 * The caller is responsible for clearing the structure upon failure if
495 * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
Paul Bakker1a7550a2013-09-15 13:01:22 +0200497 */
498static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_ecp_keypair *key )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200500{
501 int ret;
502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100504 (const unsigned char *) *p, end - *p ) ) == 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200505 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200507 }
508
509 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 * We know mbedtls_ecp_point_read_binary consumed all bytes or failed
Paul Bakker1a7550a2013-09-15 13:01:22 +0200511 */
512 *p = (unsigned char *) end;
513
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100514 return( ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200515}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200519/*
520 * RSAPublicKey ::= SEQUENCE {
521 * modulus INTEGER, -- n
522 * publicExponent INTEGER -- e
523 * }
524 */
525static int pk_get_rsapubkey( unsigned char **p,
526 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 mbedtls_rsa_context *rsa )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200528{
529 int ret;
530 size_t len;
531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
533 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
534 return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200535
536 if( *p + len != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
538 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200539
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100540 /* Import N */
541 if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200543
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100544 if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0,
545 NULL, 0, NULL, 0 ) ) != 0 )
546 return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
547
548 *p += len;
549
550 /* Import E */
551 if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
552 return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
553
554 if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
555 NULL, 0, *p, len ) ) != 0 )
556 return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
557
558 *p += len;
559
Hanno Becker895c5ab2018-01-05 08:08:09 +0000560 if( mbedtls_rsa_complete( rsa ) != 0 ||
561 mbedtls_rsa_check_pubkey( rsa ) != 0 )
562 {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100563 return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
Hanno Becker895c5ab2018-01-05 08:08:09 +0000564 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100565
Paul Bakker1a7550a2013-09-15 13:01:22 +0200566 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
568 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200569
Paul Bakker1a7550a2013-09-15 13:01:22 +0200570 return( 0 );
571}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200573
574/* Get a PK algorithm identifier
575 *
576 * AlgorithmIdentifier ::= SEQUENCE {
577 * algorithm OBJECT IDENTIFIER,
578 * parameters ANY DEFINED BY algorithm OPTIONAL }
579 */
580static int pk_get_pk_alg( unsigned char **p,
581 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200583{
584 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 mbedtls_asn1_buf alg_oid;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200586
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 memset( params, 0, sizeof(mbedtls_asn1_buf) );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
590 return( MBEDTLS_ERR_PK_INVALID_ALG + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
593 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200594
595 /*
596 * No parameters with RSA (only for EC)
597 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598 if( *pk_alg == MBEDTLS_PK_RSA &&
599 ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) ||
Paul Bakker1a7550a2013-09-15 13:01:22 +0200600 params->len != 0 ) )
601 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 return( MBEDTLS_ERR_PK_INVALID_ALG );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200603 }
604
605 return( 0 );
606}
607
608/*
609 * SubjectPublicKeyInfo ::= SEQUENCE {
610 * algorithm AlgorithmIdentifier,
611 * subjectPublicKey BIT STRING }
612 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
614 mbedtls_pk_context *pk )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200615{
616 int ret;
617 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 mbedtls_asn1_buf alg_params;
619 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
620 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200621
Gilles Peskinee97dc602018-12-19 00:51:38 +0100622 PK_VALIDATE_RET( p != NULL );
623 PK_VALIDATE_RET( *p != NULL );
624 PK_VALIDATE_RET( end != NULL );
625 PK_VALIDATE_RET( pk != NULL );
626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
628 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200629 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200631 }
632
633 end = *p + len;
634
635 if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
636 return( ret );
637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
639 return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200640
641 if( *p + len != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
643 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
646 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200647
Manuel Pégourié-Gonnardd9e6a3a2015-05-14 19:41:36 +0200648 if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200649 return( ret );
650
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651#if defined(MBEDTLS_RSA_C)
652 if( pk_alg == MBEDTLS_PK_RSA )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200653 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200655 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656#endif /* MBEDTLS_RSA_C */
657#if defined(MBEDTLS_ECP_C)
658 if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200659 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660 ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200661 if( ret == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200663 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664#endif /* MBEDTLS_ECP_C */
665 ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200666
667 if( ret == 0 && *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 ret = MBEDTLS_ERR_PK_INVALID_PUBKEY
669 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200670
671 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 mbedtls_pk_free( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200673
674 return( ret );
675}
676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200678/*
679 * Parse a PKCS#1 encoded private RSA key
680 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
Paul Bakker1a7550a2013-09-15 13:01:22 +0200682 const unsigned char *key,
683 size_t keylen )
684{
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100685 int ret, version;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200686 size_t len;
687 unsigned char *p, *end;
688
Hanno Beckerefa14e82017-10-11 19:45:19 +0100689 mbedtls_mpi T;
690 mbedtls_mpi_init( &T );
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100691
Paul Bakker1a7550a2013-09-15 13:01:22 +0200692 p = (unsigned char *) key;
693 end = p + keylen;
694
695 /*
696 * This function parses the RSAPrivateKey (PKCS#1)
697 *
698 * RSAPrivateKey ::= SEQUENCE {
699 * version Version,
700 * modulus INTEGER, -- n
701 * publicExponent INTEGER, -- e
702 * privateExponent INTEGER, -- d
703 * prime1 INTEGER, -- p
704 * prime2 INTEGER, -- q
705 * exponent1 INTEGER, -- d mod (p-1)
706 * exponent2 INTEGER, -- d mod (q-1)
707 * coefficient INTEGER, -- (inverse of q) mod p
708 * otherPrimeInfos OtherPrimeInfos OPTIONAL
709 * }
710 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
712 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200713 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200715 }
716
717 end = p + len;
718
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100719 if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200720 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200722 }
723
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100724 if( version != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200725 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200727 }
728
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100729 /* Import N */
730 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
731 MBEDTLS_ASN1_INTEGER ) ) != 0 ||
732 ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0,
733 NULL, 0, NULL, 0 ) ) != 0 )
734 goto cleanup;
735 p += len;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200736
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100737 /* Import E */
738 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
739 MBEDTLS_ASN1_INTEGER ) ) != 0 ||
740 ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
741 NULL, 0, p, len ) ) != 0 )
742 goto cleanup;
743 p += len;
744
745 /* Import D */
746 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
747 MBEDTLS_ASN1_INTEGER ) ) != 0 ||
748 ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
749 p, len, NULL, 0 ) ) != 0 )
750 goto cleanup;
751 p += len;
752
753 /* Import P */
754 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
755 MBEDTLS_ASN1_INTEGER ) ) != 0 ||
756 ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0,
757 NULL, 0, NULL, 0 ) ) != 0 )
758 goto cleanup;
759 p += len;
760
761 /* Import Q */
762 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
763 MBEDTLS_ASN1_INTEGER ) ) != 0 ||
764 ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len,
765 NULL, 0, NULL, 0 ) ) != 0 )
766 goto cleanup;
767 p += len;
768
769 /* Complete the RSA private key */
Hanno Becker7f25f852017-10-10 16:56:22 +0100770 if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100771 goto cleanup;
772
773 /* Check optional parameters */
Hanno Beckerefa14e82017-10-11 19:45:19 +0100774 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
775 ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
776 ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100777 goto cleanup;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200778
779 if( p != end )
780 {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100781 ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
782 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200783 }
784
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100785cleanup:
786
Hanno Beckerefa14e82017-10-11 19:45:19 +0100787 mbedtls_mpi_free( &T );
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100788
789 if( ret != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200790 {
Hanno Beckerefa14e82017-10-11 19:45:19 +0100791 /* Wrap error code if it's coming from a lower level */
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100792 if( ( ret & 0xff80 ) == 0 )
793 ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret;
794 else
795 ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797 mbedtls_rsa_free( rsa );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200798 }
799
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100800 return( ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200801}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804#if defined(MBEDTLS_ECP_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200805/*
806 * Parse a SEC1 encoded private EC key
807 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck,
Paul Bakker1a7550a2013-09-15 13:01:22 +0200809 const unsigned char *key,
810 size_t keylen )
811{
812 int ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100813 int version, pubkey_done;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200814 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200815 mbedtls_asn1_buf params;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200816 unsigned char *p = (unsigned char *) key;
817 unsigned char *end = p + keylen;
818 unsigned char *end2;
819
820 /*
821 * RFC 5915, or SEC1 Appendix C.4
822 *
823 * ECPrivateKey ::= SEQUENCE {
824 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
825 * privateKey OCTET STRING,
826 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
827 * publicKey [1] BIT STRING OPTIONAL
828 * }
829 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200830 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
831 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200832 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200834 }
835
836 end = p + len;
837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
839 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200840
841 if( version != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200844 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
845 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847 if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200848 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 mbedtls_ecp_keypair_free( eck );
850 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200851 }
852
853 p += len;
854
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200855 pubkey_done = 0;
856 if( p != end )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200857 {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200858 /*
859 * Is 'parameters' present?
860 */
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200861 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
862 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200863 {
864 if( ( ret = pk_get_ecparams( &p, p + len, &params) ) != 0 ||
865 ( ret = pk_use_ecparams( &params, &eck->grp ) ) != 0 )
866 {
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200867 mbedtls_ecp_keypair_free( eck );
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200868 return( ret );
869 }
870 }
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200871 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200872 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200873 mbedtls_ecp_keypair_free( eck );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100875 }
Jethro Beekmand2df9362018-02-16 13:11:04 -0800876 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200877
Jethro Beekmand2df9362018-02-16 13:11:04 -0800878 if( p != end )
879 {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200880 /*
881 * Is 'publickey' present? If not, or if we can't read it (eg because it
882 * is compressed), create it from the private key.
883 */
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200884 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
885 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200886 {
887 end2 = p + len;
888
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200889 if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
890 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200891
892 if( p + len != end2 )
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200893 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
894 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200895
896 if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 )
897 pubkey_done = 1;
898 else
899 {
900 /*
901 * The only acceptable failure mode of pk_get_ecpubkey() above
902 * is if the point format is not recognized.
903 */
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200904 if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE )
905 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200906 }
907 }
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200908 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200909 {
Manuel Pégourié-Gonnarde1e58712015-04-15 10:50:34 +0200910 mbedtls_ecp_keypair_free( eck );
911 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200912 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200913 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100914
915 if( ! pubkey_done &&
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916 ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G,
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100917 NULL, NULL ) ) != 0 )
Manuel Pégourié-Gonnardff29f9c2013-09-18 16:13:02 +0200918 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_ecp_keypair_free( eck );
920 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Manuel Pégourié-Gonnardff29f9c2013-09-18 16:13:02 +0200921 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200924 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 mbedtls_ecp_keypair_free( eck );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200926 return( ret );
927 }
928
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200929 return( 0 );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200930}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200932
933/*
934 * Parse an unencrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +0100935 *
936 * Notes:
937 *
938 * - This function does not own the key buffer. It is the
939 * responsibility of the caller to take care of zeroizing
940 * and freeing it after use.
941 *
942 * - The function is responsible for freeing the provided
943 * PK context on failure.
944 *
Paul Bakker1a7550a2013-09-15 13:01:22 +0200945 */
946static int pk_parse_key_pkcs8_unencrypted_der(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 mbedtls_pk_context *pk,
Paul Bakker1a7550a2013-09-15 13:01:22 +0200948 const unsigned char* key,
949 size_t keylen )
950{
951 int ret, version;
952 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953 mbedtls_asn1_buf params;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200954 unsigned char *p = (unsigned char *) key;
955 unsigned char *end = p + keylen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
957 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200958
959 /*
Hanno Becker9c6cb382017-09-05 10:08:01 +0100960 * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200961 *
962 * PrivateKeyInfo ::= SEQUENCE {
963 * version Version,
964 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
965 * privateKey PrivateKey,
966 * attributes [0] IMPLICIT Attributes OPTIONAL }
967 *
968 * Version ::= INTEGER
969 * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
970 * PrivateKey ::= OCTET STRING
971 *
972 * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
973 */
974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
976 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +0200977 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200978 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200979 }
980
981 end = p + len;
982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
984 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200985
986 if( version != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200988
989 if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
993 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200994
995 if( len < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200996 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
997 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Paul Bakker1a7550a2013-09-15 13:01:22 +0200998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200999 if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
1000 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001001
Manuel Pégourié-Gonnardd9e6a3a2015-05-14 19:41:36 +02001002 if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001003 return( ret );
1004
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001005#if defined(MBEDTLS_RSA_C)
1006 if( pk_alg == MBEDTLS_PK_RSA )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001007 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001008 if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001009 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001010 mbedtls_pk_free( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001011 return( ret );
1012 }
1013 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014#endif /* MBEDTLS_RSA_C */
1015#if defined(MBEDTLS_ECP_C)
1016 if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001017 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018 if( ( ret = pk_use_ecparams( &params, &mbedtls_pk_ec( *pk )->grp ) ) != 0 ||
1019 ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001020 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 mbedtls_pk_free( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001022 return( ret );
1023 }
1024 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025#endif /* MBEDTLS_ECP_C */
1026 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001027
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001028 return( 0 );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001029}
1030
1031/*
1032 * Parse an encrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +01001033 *
1034 * To save space, the decryption happens in-place on the given key buffer.
1035 * Also, while this function may modify the keybuffer, it doesn't own it,
1036 * and instead it is the responsibility of the caller to zeroize and properly
1037 * free it after use.
1038 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001039 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001041static int pk_parse_key_pkcs8_encrypted_der(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 mbedtls_pk_context *pk,
Hanno Beckerfab35692017-08-25 13:38:26 +01001043 unsigned char *key, size_t keylen,
Paul Bakker1a7550a2013-09-15 13:01:22 +02001044 const unsigned char *pwd, size_t pwdlen )
1045{
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001046 int ret, decrypted = 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001047 size_t len;
Hanno Beckerfab35692017-08-25 13:38:26 +01001048 unsigned char *buf;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001049 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 mbedtls_asn1_buf pbe_alg_oid, pbe_params;
1051#if defined(MBEDTLS_PKCS12_C)
1052 mbedtls_cipher_type_t cipher_alg;
1053 mbedtls_md_type_t md_alg;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001054#endif
1055
Hanno Becker2aa80a72017-09-07 15:28:45 +01001056 p = key;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001057 end = p + keylen;
1058
1059 if( pwdlen == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001061
1062 /*
Hanno Beckerf04111f2017-09-29 19:18:42 +01001063 * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001064 *
1065 * EncryptedPrivateKeyInfo ::= SEQUENCE {
1066 * encryptionAlgorithm EncryptionAlgorithmIdentifier,
1067 * encryptedData EncryptedData
1068 * }
1069 *
1070 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
1071 *
1072 * EncryptedData ::= OCTET STRING
1073 *
1074 * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
Hanno Beckerb8d16572017-09-07 15:29:01 +01001075 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001076 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001077 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1078 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001081 }
1082
1083 end = p + len;
1084
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085 if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 )
1086 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001087
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
1089 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001090
Hanno Beckerfab35692017-08-25 13:38:26 +01001091 buf = p;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001092
1093 /*
Hanno Beckerb8d16572017-09-07 15:29:01 +01001094 * Decrypt EncryptedData with appropriate PBE
Paul Bakker1a7550a2013-09-15 13:01:22 +02001095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096#if defined(MBEDTLS_PKCS12_C)
1097 if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001098 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099 if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
Paul Bakker1a7550a2013-09-15 13:01:22 +02001100 cipher_alg, md_alg,
1101 pwd, pwdlen, p, len, buf ) ) != 0 )
1102 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH )
1104 return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001105
1106 return( ret );
1107 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001108
1109 decrypted = 1;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001110 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111 else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001112 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113 if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params,
1114 MBEDTLS_PKCS12_PBE_DECRYPT,
Paul Bakker1a7550a2013-09-15 13:01:22 +02001115 pwd, pwdlen,
1116 p, len, buf ) ) != 0 )
1117 {
1118 return( ret );
1119 }
1120
1121 // Best guess for password mismatch when using RC4. If first tag is
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122 // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
Paul Bakker1a7550a2013-09-15 13:01:22 +02001123 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124 if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
1125 return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001126
1127 decrypted = 1;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001128 }
1129 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130#endif /* MBEDTLS_PKCS12_C */
1131#if defined(MBEDTLS_PKCS5_C)
1132 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001133 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134 if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
Paul Bakker1a7550a2013-09-15 13:01:22 +02001135 p, len, buf ) ) != 0 )
1136 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001137 if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH )
1138 return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001139
1140 return( ret );
1141 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001142
1143 decrypted = 1;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001144 }
1145 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146#endif /* MBEDTLS_PKCS5_C */
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +02001147 {
1148 ((void) pwd);
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +02001149 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001150
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001151 if( decrypted == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001153
Paul Bakker1a7550a2013-09-15 13:01:22 +02001154 return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
1155}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001156#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001157
1158/*
1159 * Parse a private key
1160 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001161int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
Paul Bakker1a7550a2013-09-15 13:01:22 +02001162 const unsigned char *key, size_t keylen,
1163 const unsigned char *pwd, size_t pwdlen )
1164{
1165 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166 const mbedtls_pk_info_t *pk_info;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001168 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 mbedtls_pem_context pem;
Gilles Peskinee97dc602018-12-19 00:51:38 +01001170#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001171
Gilles Peskinee97dc602018-12-19 00:51:38 +01001172 PK_VALIDATE_RET( pk != NULL );
1173 PK_VALIDATE_RET( key != NULL || keylen == 0 );
1174 PK_VALIDATE_RET( pwd != NULL || pwdlen == 0 );
1175
1176#if defined(MBEDTLS_PEM_PARSE_C)
1177 mbedtls_pem_init( &pem );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001180 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001181 if( keylen == 0 || key[keylen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001182 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1183 else
1184 ret = mbedtls_pem_read_buffer( &pem,
1185 "-----BEGIN RSA PRIVATE KEY-----",
1186 "-----END RSA PRIVATE KEY-----",
1187 key, pwd, pwdlen, &len );
1188
Paul Bakker1a7550a2013-09-15 13:01:22 +02001189 if( ret == 0 )
1190 {
Hanno Becker66a0f832017-09-08 12:39:21 +01001191 pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
Hanno Beckerfab35692017-08-25 13:38:26 +01001192 if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001193 ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
Paul Bakker1a7550a2013-09-15 13:01:22 +02001194 pem.buf, pem.buflen ) ) != 0 )
1195 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 mbedtls_pk_free( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001197 }
1198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 mbedtls_pem_free( &pem );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001200 return( ret );
1201 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH )
1203 return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
1204 else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED )
1205 return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
1206 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001207 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001211 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001212 if( keylen == 0 || key[keylen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001213 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1214 else
1215 ret = mbedtls_pem_read_buffer( &pem,
1216 "-----BEGIN EC PRIVATE KEY-----",
1217 "-----END EC PRIVATE KEY-----",
1218 key, pwd, pwdlen, &len );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001219 if( ret == 0 )
1220 {
Hanno Becker66a0f832017-09-08 12:39:21 +01001221 pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001222
Hanno Beckerfab35692017-08-25 13:38:26 +01001223 if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
Paul Bakker1a7550a2013-09-15 13:01:22 +02001225 pem.buf, pem.buflen ) ) != 0 )
1226 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 mbedtls_pk_free( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001228 }
1229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 mbedtls_pem_free( &pem );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001231 return( ret );
1232 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH )
1234 return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
1235 else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED )
1236 return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
1237 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001238 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001240
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001241 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001242 if( keylen == 0 || key[keylen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001243 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1244 else
1245 ret = mbedtls_pem_read_buffer( &pem,
1246 "-----BEGIN PRIVATE KEY-----",
1247 "-----END PRIVATE KEY-----",
1248 key, NULL, 0, &len );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001249 if( ret == 0 )
1250 {
1251 if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk,
1252 pem.buf, pem.buflen ) ) != 0 )
1253 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 mbedtls_pk_free( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001255 }
1256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001257 mbedtls_pem_free( &pem );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001258 return( ret );
1259 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001261 return( ret );
1262
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001263#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001264 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001265 if( keylen == 0 || key[keylen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001266 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1267 else
1268 ret = mbedtls_pem_read_buffer( &pem,
1269 "-----BEGIN ENCRYPTED PRIVATE KEY-----",
1270 "-----END ENCRYPTED PRIVATE KEY-----",
1271 key, NULL, 0, &len );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001272 if( ret == 0 )
1273 {
1274 if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk,
1275 pem.buf, pem.buflen,
1276 pwd, pwdlen ) ) != 0 )
1277 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 mbedtls_pk_free( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001279 }
1280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001281 mbedtls_pem_free( &pem );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001282 return( ret );
1283 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001285 return( ret );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001286#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001287#else
1288 ((void) pwd);
1289 ((void) pwdlen);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001291
1292 /*
Brian J Murray2adecba2016-11-06 04:45:15 -08001293 * At this point we only know it's not a PEM formatted key. Could be any
1294 * of the known DER encoded private key formats
1295 *
1296 * We try the different DER format parsers to see if one passes without
1297 * error
1298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001300 {
Hanno Beckerfab35692017-08-25 13:38:26 +01001301 unsigned char *key_copy;
1302
Andres Amaya Garciae9124b92018-01-23 20:03:52 +00001303 if( keylen == 0 )
1304 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
1305
Hanno Beckerfab35692017-08-25 13:38:26 +01001306 if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL )
1307 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
1308
1309 memcpy( key_copy, key, keylen );
1310
1311 ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen,
1312 pwd, pwdlen );
1313
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001314 mbedtls_platform_zeroize( key_copy, keylen );
Hanno Beckerfab35692017-08-25 13:38:26 +01001315 mbedtls_free( key_copy );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001316 }
1317
Hanno Beckerfab35692017-08-25 13:38:26 +01001318 if( ret == 0 )
1319 return( 0 );
1320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 mbedtls_pk_free( pk );
Hanno Becker780f0a42018-10-10 11:23:33 +01001322 mbedtls_pk_init( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001325 {
1326 return( ret );
1327 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001329
1330 if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
1331 return( 0 );
1332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001333 mbedtls_pk_free( pk );
Hanno Becker780f0a42018-10-10 11:23:33 +01001334 mbedtls_pk_init( pk );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001337
Hanno Becker9be19262017-09-08 12:39:44 +01001338 pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
Hanno Becker780f0a42018-10-10 11:23:33 +01001339 if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
1340 pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001341 {
1342 return( 0 );
1343 }
1344
Hanno Becker780f0a42018-10-10 11:23:33 +01001345 mbedtls_pk_free( pk );
1346 mbedtls_pk_init( pk );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349#if defined(MBEDTLS_ECP_C)
Hanno Becker9be19262017-09-08 12:39:44 +01001350 pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
Hanno Becker780f0a42018-10-10 11:23:33 +01001351 if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
1352 pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
1353 key, keylen ) == 0 )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001354 {
1355 return( 0 );
1356 }
Hanno Becker780f0a42018-10-10 11:23:33 +01001357 mbedtls_pk_free( pk );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001359
Hanno Becker780f0a42018-10-10 11:23:33 +01001360 /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
1361 * it is ok to leave the PK context initialized but not
1362 * freed: It is the caller's responsibility to call pk_init()
1363 * before calling this function, and to call pk_free()
1364 * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
1365 * isn't, this leads to mbedtls_pk_free() being called
1366 * twice, once here and once by the caller, but this is
1367 * also ok and in line with the mbedtls_pk_free() calls
1368 * on failed PEM parsing attempts. */
1369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001371}
1372
1373/*
1374 * Parse a public key
1375 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
Paul Bakker1a7550a2013-09-15 13:01:22 +02001377 const unsigned char *key, size_t keylen )
1378{
1379 int ret;
1380 unsigned char *p;
Ron Eldor5472d432017-10-17 09:49:00 +03001381#if defined(MBEDTLS_RSA_C)
1382 const mbedtls_pk_info_t *pk_info;
1383#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001385 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001386 mbedtls_pem_context pem;
Gilles Peskinee97dc602018-12-19 00:51:38 +01001387#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001388
Gilles Peskinee97dc602018-12-19 00:51:38 +01001389 PK_VALIDATE_RET( ctx != NULL );
1390 PK_VALIDATE_RET( key != NULL || keylen == 0 );
1391
1392#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 mbedtls_pem_init( &pem );
Ron Eldord0c56de2017-10-10 17:03:08 +03001394#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001395 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001396 if( keylen == 0 || key[keylen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001397 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1398 else
1399 ret = mbedtls_pem_read_buffer( &pem,
Ron Eldord0c56de2017-10-10 17:03:08 +03001400 "-----BEGIN RSA PUBLIC KEY-----",
1401 "-----END RSA PUBLIC KEY-----",
1402 key, NULL, 0, &len );
1403
1404 if( ret == 0 )
1405 {
Ron Eldor84df1ae2017-10-16 17:11:52 +03001406 p = pem.buf;
1407 if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
1408 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
Ron Eldord0c56de2017-10-10 17:03:08 +03001409
Ron Eldor84df1ae2017-10-16 17:11:52 +03001410 if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
1411 return( ret );
Ron Eldord0c56de2017-10-10 17:03:08 +03001412
Ron Eldor84df1ae2017-10-16 17:11:52 +03001413 if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 )
1414 mbedtls_pk_free( ctx );
Ron Eldor3f2da842017-10-17 15:50:30 +03001415
Ron Eldord0c56de2017-10-10 17:03:08 +03001416 mbedtls_pem_free( &pem );
1417 return( ret );
1418 }
1419 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
1420 {
1421 mbedtls_pem_free( &pem );
1422 return( ret );
1423 }
1424#endif /* MBEDTLS_RSA_C */
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001425
1426 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1427 if( keylen == 0 || key[keylen - 1] != '\0' )
1428 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1429 else
1430 ret = mbedtls_pem_read_buffer( &pem,
1431 "-----BEGIN PUBLIC KEY-----",
1432 "-----END PUBLIC KEY-----",
1433 key, NULL, 0, &len );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001434
1435 if( ret == 0 )
1436 {
1437 /*
1438 * Was PEM encoded
1439 */
Ron Eldor40b14a82017-10-16 19:30:00 +03001440 p = pem.buf;
1441
1442 ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx );
1443 mbedtls_pem_free( &pem );
1444 return( ret );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001445 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker1a7550a2013-09-15 13:01:22 +02001447 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448 mbedtls_pem_free( &pem );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001449 return( ret );
1450 }
Ron Eldor5472d432017-10-17 09:49:00 +03001451 mbedtls_pem_free( &pem );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452#endif /* MBEDTLS_PEM_PARSE_C */
Ron Eldor40b14a82017-10-16 19:30:00 +03001453
1454#if defined(MBEDTLS_RSA_C)
1455 if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
1456 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
1457
1458 if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
1459 return( ret );
1460
Ron Eldor9566ff72018-02-07 18:59:41 +02001461 p = (unsigned char *)key;
Ron Eldor40b14a82017-10-16 19:30:00 +03001462 ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) );
Ron Eldor9566ff72018-02-07 18:59:41 +02001463 if( ret == 0 )
Ron Eldor40b14a82017-10-16 19:30:00 +03001464 {
Ron Eldor40b14a82017-10-16 19:30:00 +03001465 return( ret );
1466 }
1467 mbedtls_pk_free( ctx );
Ron Eldor9566ff72018-02-07 18:59:41 +02001468 if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
Ron Eldor40b14a82017-10-16 19:30:00 +03001469 {
Ron Eldor9566ff72018-02-07 18:59:41 +02001470 return( ret );
Ron Eldor40b14a82017-10-16 19:30:00 +03001471 }
1472#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001473 p = (unsigned char *) key;
1474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx );
Paul Bakker1a7550a2013-09-15 13:01:22 +02001476
Paul Bakker1a7550a2013-09-15 13:01:22 +02001477 return( ret );
1478}
1479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480#endif /* MBEDTLS_PK_PARSE_C */