1c2c66affSColin Finck /*
2c2c66affSColin Finck * Public Key layer for parsing key files and structures
3c2c66affSColin Finck *
4218e2596SThomas Faber * Copyright The Mbed TLS Contributors
5e57126f5SThomas Faber * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6e57126f5SThomas Faber *
7e57126f5SThomas Faber * This file is provided under the Apache License 2.0, or the
8e57126f5SThomas Faber * GNU General Public License v2.0 or later.
9e57126f5SThomas Faber *
10e57126f5SThomas Faber * **********
11e57126f5SThomas Faber * Apache License 2.0:
12e57126f5SThomas Faber *
13e57126f5SThomas Faber * Licensed under the Apache License, Version 2.0 (the "License"); you may
14e57126f5SThomas Faber * not use this file except in compliance with the License.
15e57126f5SThomas Faber * You may obtain a copy of the License at
16e57126f5SThomas Faber *
17e57126f5SThomas Faber * http://www.apache.org/licenses/LICENSE-2.0
18e57126f5SThomas Faber *
19e57126f5SThomas Faber * Unless required by applicable law or agreed to in writing, software
20e57126f5SThomas Faber * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21e57126f5SThomas Faber * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22e57126f5SThomas Faber * See the License for the specific language governing permissions and
23e57126f5SThomas Faber * limitations under the License.
24e57126f5SThomas Faber *
25e57126f5SThomas Faber * **********
26e57126f5SThomas Faber *
27e57126f5SThomas Faber * **********
28e57126f5SThomas Faber * GNU General Public License v2.0 or later:
29c2c66affSColin Finck *
30c2c66affSColin Finck * This program is free software; you can redistribute it and/or modify
31c2c66affSColin Finck * it under the terms of the GNU General Public License as published by
32c2c66affSColin Finck * the Free Software Foundation; either version 2 of the License, or
33c2c66affSColin Finck * (at your option) any later version.
34c2c66affSColin Finck *
35c2c66affSColin Finck * This program is distributed in the hope that it will be useful,
36c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
37c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38c2c66affSColin Finck * GNU General Public License for more details.
39c2c66affSColin Finck *
40c2c66affSColin Finck * You should have received a copy of the GNU General Public License along
41c2c66affSColin Finck * with this program; if not, write to the Free Software Foundation, Inc.,
42c2c66affSColin Finck * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43c2c66affSColin Finck *
44e57126f5SThomas Faber * **********
45c2c66affSColin Finck */
46c2c66affSColin Finck
47c2c66affSColin Finck #if !defined(MBEDTLS_CONFIG_FILE)
48c2c66affSColin Finck #include "mbedtls/config.h"
49c2c66affSColin Finck #else
50c2c66affSColin Finck #include MBEDTLS_CONFIG_FILE
51c2c66affSColin Finck #endif
52c2c66affSColin Finck
53c2c66affSColin Finck #if defined(MBEDTLS_PK_PARSE_C)
54c2c66affSColin Finck
55c2c66affSColin Finck #include "mbedtls/pk.h"
56c2c66affSColin Finck #include "mbedtls/asn1.h"
57c2c66affSColin Finck #include "mbedtls/oid.h"
58cbda039fSThomas Faber #include "mbedtls/platform_util.h"
59c2c66affSColin Finck
60c2c66affSColin Finck #include <string.h>
61c2c66affSColin Finck
62c2c66affSColin Finck #if defined(MBEDTLS_RSA_C)
63c2c66affSColin Finck #include "mbedtls/rsa.h"
64c2c66affSColin Finck #endif
65c2c66affSColin Finck #if defined(MBEDTLS_ECP_C)
66c2c66affSColin Finck #include "mbedtls/ecp.h"
67c2c66affSColin Finck #endif
68c2c66affSColin Finck #if defined(MBEDTLS_ECDSA_C)
69c2c66affSColin Finck #include "mbedtls/ecdsa.h"
70c2c66affSColin Finck #endif
71c2c66affSColin Finck #if defined(MBEDTLS_PEM_PARSE_C)
72c2c66affSColin Finck #include "mbedtls/pem.h"
73c2c66affSColin Finck #endif
74c2c66affSColin Finck #if defined(MBEDTLS_PKCS5_C)
75c2c66affSColin Finck #include "mbedtls/pkcs5.h"
76c2c66affSColin Finck #endif
77c2c66affSColin Finck #if defined(MBEDTLS_PKCS12_C)
78c2c66affSColin Finck #include "mbedtls/pkcs12.h"
79c2c66affSColin Finck #endif
80c2c66affSColin Finck
81c2c66affSColin Finck #if defined(MBEDTLS_PLATFORM_C)
82c2c66affSColin Finck #include "mbedtls/platform.h"
83c2c66affSColin Finck #else
84c2c66affSColin Finck #include <stdlib.h>
85c2c66affSColin Finck #define mbedtls_calloc calloc
86c2c66affSColin Finck #define mbedtls_free free
87c2c66affSColin Finck #endif
88c2c66affSColin Finck
89cbda039fSThomas Faber /* Parameter validation macros based on platform_util.h */
90cbda039fSThomas Faber #define PK_VALIDATE_RET( cond ) \
91cbda039fSThomas Faber MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
92cbda039fSThomas Faber #define PK_VALIDATE( cond ) \
93cbda039fSThomas Faber MBEDTLS_INTERNAL_VALIDATE( cond )
94c2c66affSColin Finck
95d9e6c9b5SThomas Faber #if defined(MBEDTLS_FS_IO)
96c2c66affSColin Finck /*
97c2c66affSColin Finck * Load all data from a file into a given buffer.
98c2c66affSColin Finck *
99c2c66affSColin Finck * The file is expected to contain either PEM or DER encoded data.
100c2c66affSColin Finck * A terminating null byte is always appended. It is included in the announced
101c2c66affSColin Finck * length only if the data looks like it is PEM encoded.
102c2c66affSColin Finck */
mbedtls_pk_load_file(const char * path,unsigned char ** buf,size_t * n)103c2c66affSColin Finck int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n )
104c2c66affSColin Finck {
105c2c66affSColin Finck FILE *f;
106c2c66affSColin Finck long size;
107c2c66affSColin Finck
108cbda039fSThomas Faber PK_VALIDATE_RET( path != NULL );
109cbda039fSThomas Faber PK_VALIDATE_RET( buf != NULL );
110cbda039fSThomas Faber PK_VALIDATE_RET( n != NULL );
111cbda039fSThomas Faber
112c2c66affSColin Finck if( ( f = fopen( path, "rb" ) ) == NULL )
113c2c66affSColin Finck return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
114c2c66affSColin Finck
115c2c66affSColin Finck fseek( f, 0, SEEK_END );
116c2c66affSColin Finck if( ( size = ftell( f ) ) == -1 )
117c2c66affSColin Finck {
118c2c66affSColin Finck fclose( f );
119c2c66affSColin Finck return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
120c2c66affSColin Finck }
121c2c66affSColin Finck fseek( f, 0, SEEK_SET );
122c2c66affSColin Finck
123c2c66affSColin Finck *n = (size_t) size;
124c2c66affSColin Finck
125c2c66affSColin Finck if( *n + 1 == 0 ||
126c2c66affSColin Finck ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
127c2c66affSColin Finck {
128c2c66affSColin Finck fclose( f );
129c2c66affSColin Finck return( MBEDTLS_ERR_PK_ALLOC_FAILED );
130c2c66affSColin Finck }
131c2c66affSColin Finck
132c2c66affSColin Finck if( fread( *buf, 1, *n, f ) != *n )
133c2c66affSColin Finck {
134c2c66affSColin Finck fclose( f );
135d9e6c9b5SThomas Faber
136cbda039fSThomas Faber mbedtls_platform_zeroize( *buf, *n );
137c2c66affSColin Finck mbedtls_free( *buf );
138d9e6c9b5SThomas Faber
139c2c66affSColin Finck return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
140c2c66affSColin Finck }
141c2c66affSColin Finck
142c2c66affSColin Finck fclose( f );
143c2c66affSColin Finck
144c2c66affSColin Finck (*buf)[*n] = '\0';
145c2c66affSColin Finck
146c2c66affSColin Finck if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
147c2c66affSColin Finck ++*n;
148c2c66affSColin Finck
149c2c66affSColin Finck return( 0 );
150c2c66affSColin Finck }
151c2c66affSColin Finck
152c2c66affSColin Finck /*
153c2c66affSColin Finck * Load and parse a private key
154c2c66affSColin Finck */
mbedtls_pk_parse_keyfile(mbedtls_pk_context * ctx,const char * path,const char * pwd)155c2c66affSColin Finck int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
156c2c66affSColin Finck const char *path, const char *pwd )
157c2c66affSColin Finck {
158c2c66affSColin Finck int ret;
159c2c66affSColin Finck size_t n;
160c2c66affSColin Finck unsigned char *buf;
161c2c66affSColin Finck
162cbda039fSThomas Faber PK_VALIDATE_RET( ctx != NULL );
163cbda039fSThomas Faber PK_VALIDATE_RET( path != NULL );
164cbda039fSThomas Faber
165c2c66affSColin Finck if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
166c2c66affSColin Finck return( ret );
167c2c66affSColin Finck
168c2c66affSColin Finck if( pwd == NULL )
169c2c66affSColin Finck ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 );
170c2c66affSColin Finck else
171c2c66affSColin Finck ret = mbedtls_pk_parse_key( ctx, buf, n,
172c2c66affSColin Finck (const unsigned char *) pwd, strlen( pwd ) );
173c2c66affSColin Finck
174cbda039fSThomas Faber mbedtls_platform_zeroize( buf, n );
175c2c66affSColin Finck mbedtls_free( buf );
176c2c66affSColin Finck
177c2c66affSColin Finck return( ret );
178c2c66affSColin Finck }
179c2c66affSColin Finck
180c2c66affSColin Finck /*
181c2c66affSColin Finck * Load and parse a public key
182c2c66affSColin Finck */
mbedtls_pk_parse_public_keyfile(mbedtls_pk_context * ctx,const char * path)183c2c66affSColin Finck int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path )
184c2c66affSColin Finck {
185c2c66affSColin Finck int ret;
186c2c66affSColin Finck size_t n;
187c2c66affSColin Finck unsigned char *buf;
188c2c66affSColin Finck
189cbda039fSThomas Faber PK_VALIDATE_RET( ctx != NULL );
190cbda039fSThomas Faber PK_VALIDATE_RET( path != NULL );
191cbda039fSThomas Faber
192c2c66affSColin Finck if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
193c2c66affSColin Finck return( ret );
194c2c66affSColin Finck
195c2c66affSColin Finck ret = mbedtls_pk_parse_public_key( ctx, buf, n );
196c2c66affSColin Finck
197cbda039fSThomas Faber mbedtls_platform_zeroize( buf, n );
198c2c66affSColin Finck mbedtls_free( buf );
199c2c66affSColin Finck
200c2c66affSColin Finck return( ret );
201c2c66affSColin Finck }
202c2c66affSColin Finck #endif /* MBEDTLS_FS_IO */
203c2c66affSColin Finck
204c2c66affSColin Finck #if defined(MBEDTLS_ECP_C)
205c2c66affSColin Finck /* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
206c2c66affSColin Finck *
207c2c66affSColin Finck * ECParameters ::= CHOICE {
208c2c66affSColin Finck * namedCurve OBJECT IDENTIFIER
209c2c66affSColin Finck * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
210c2c66affSColin Finck * -- implicitCurve NULL
211c2c66affSColin Finck * }
212c2c66affSColin Finck */
pk_get_ecparams(unsigned char ** p,const unsigned char * end,mbedtls_asn1_buf * params)213c2c66affSColin Finck static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
214c2c66affSColin Finck mbedtls_asn1_buf *params )
215c2c66affSColin Finck {
216c2c66affSColin Finck int ret;
217c2c66affSColin Finck
218d9e6c9b5SThomas Faber if ( end - *p < 1 )
219d9e6c9b5SThomas Faber return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
220d9e6c9b5SThomas Faber MBEDTLS_ERR_ASN1_OUT_OF_DATA );
221d9e6c9b5SThomas Faber
222c2c66affSColin Finck /* Tag may be either OID or SEQUENCE */
223c2c66affSColin Finck params->tag = **p;
224c2c66affSColin Finck if( params->tag != MBEDTLS_ASN1_OID
225c2c66affSColin Finck #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
226c2c66affSColin Finck && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE )
227c2c66affSColin Finck #endif
228c2c66affSColin Finck )
229c2c66affSColin Finck {
230c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
231c2c66affSColin Finck MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
232c2c66affSColin Finck }
233c2c66affSColin Finck
234c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 )
235c2c66affSColin Finck {
236c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
237c2c66affSColin Finck }
238c2c66affSColin Finck
239c2c66affSColin Finck params->p = *p;
240c2c66affSColin Finck *p += params->len;
241c2c66affSColin Finck
242c2c66affSColin Finck if( *p != end )
243c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
244c2c66affSColin Finck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
245c2c66affSColin Finck
246c2c66affSColin Finck return( 0 );
247c2c66affSColin Finck }
248c2c66affSColin Finck
249c2c66affSColin Finck #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
250c2c66affSColin Finck /*
251c2c66affSColin Finck * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
252c2c66affSColin Finck * WARNING: the resulting group should only be used with
253c2c66affSColin Finck * pk_group_id_from_specified(), since its base point may not be set correctly
254c2c66affSColin Finck * if it was encoded compressed.
255c2c66affSColin Finck *
256c2c66affSColin Finck * SpecifiedECDomain ::= SEQUENCE {
257c2c66affSColin Finck * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
258c2c66affSColin Finck * fieldID FieldID {{FieldTypes}},
259c2c66affSColin Finck * curve Curve,
260c2c66affSColin Finck * base ECPoint,
261c2c66affSColin Finck * order INTEGER,
262c2c66affSColin Finck * cofactor INTEGER OPTIONAL,
263c2c66affSColin Finck * hash HashAlgorithm OPTIONAL,
264c2c66affSColin Finck * ...
265c2c66affSColin Finck * }
266c2c66affSColin Finck *
267c2c66affSColin Finck * We only support prime-field as field type, and ignore hash and cofactor.
268c2c66affSColin Finck */
pk_group_from_specified(const mbedtls_asn1_buf * params,mbedtls_ecp_group * grp)269c2c66affSColin Finck static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
270c2c66affSColin Finck {
271c2c66affSColin Finck int ret;
272c2c66affSColin Finck unsigned char *p = params->p;
273c2c66affSColin Finck const unsigned char * const end = params->p + params->len;
274c2c66affSColin Finck const unsigned char *end_field, *end_curve;
275c2c66affSColin Finck size_t len;
276c2c66affSColin Finck int ver;
277c2c66affSColin Finck
278c2c66affSColin Finck /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
279c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 )
280c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
281c2c66affSColin Finck
282c2c66affSColin Finck if( ver < 1 || ver > 3 )
283c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
284c2c66affSColin Finck
285c2c66affSColin Finck /*
286c2c66affSColin Finck * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
287c2c66affSColin Finck * fieldType FIELD-ID.&id({IOSet}),
288c2c66affSColin Finck * parameters FIELD-ID.&Type({IOSet}{@fieldType})
289c2c66affSColin Finck * }
290c2c66affSColin Finck */
291c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
292c2c66affSColin Finck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
293c2c66affSColin Finck return( ret );
294c2c66affSColin Finck
295c2c66affSColin Finck end_field = p + len;
296c2c66affSColin Finck
297c2c66affSColin Finck /*
298c2c66affSColin Finck * FIELD-ID ::= TYPE-IDENTIFIER
299c2c66affSColin Finck * FieldTypes FIELD-ID ::= {
300c2c66affSColin Finck * { Prime-p IDENTIFIED BY prime-field } |
301c2c66affSColin Finck * { Characteristic-two IDENTIFIED BY characteristic-two-field }
302c2c66affSColin Finck * }
303c2c66affSColin Finck * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
304c2c66affSColin Finck */
305c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 )
306c2c66affSColin Finck return( ret );
307c2c66affSColin Finck
308c2c66affSColin Finck if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) ||
309c2c66affSColin Finck memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 )
310c2c66affSColin Finck {
311c2c66affSColin Finck return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
312c2c66affSColin Finck }
313c2c66affSColin Finck
314c2c66affSColin Finck p += len;
315c2c66affSColin Finck
316c2c66affSColin Finck /* Prime-p ::= INTEGER -- Field of size p. */
317c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 )
318c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
319c2c66affSColin Finck
320c2c66affSColin Finck grp->pbits = mbedtls_mpi_bitlen( &grp->P );
321c2c66affSColin Finck
322c2c66affSColin Finck if( p != end_field )
323c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
324c2c66affSColin Finck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
325c2c66affSColin Finck
326c2c66affSColin Finck /*
327c2c66affSColin Finck * Curve ::= SEQUENCE {
328c2c66affSColin Finck * a FieldElement,
329c2c66affSColin Finck * b FieldElement,
330c2c66affSColin Finck * seed BIT STRING OPTIONAL
331c2c66affSColin Finck * -- Shall be present if used in SpecifiedECDomain
332c2c66affSColin Finck * -- with version equal to ecdpVer2 or ecdpVer3
333c2c66affSColin Finck * }
334c2c66affSColin Finck */
335c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
336c2c66affSColin Finck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
337c2c66affSColin Finck return( ret );
338c2c66affSColin Finck
339c2c66affSColin Finck end_curve = p + len;
340c2c66affSColin Finck
341c2c66affSColin Finck /*
342c2c66affSColin Finck * FieldElement ::= OCTET STRING
343c2c66affSColin Finck * containing an integer in the case of a prime field
344c2c66affSColin Finck */
345c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
346c2c66affSColin Finck ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 )
347c2c66affSColin Finck {
348c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
349c2c66affSColin Finck }
350c2c66affSColin Finck
351c2c66affSColin Finck p += len;
352c2c66affSColin Finck
353c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
354c2c66affSColin Finck ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 )
355c2c66affSColin Finck {
356c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
357c2c66affSColin Finck }
358c2c66affSColin Finck
359c2c66affSColin Finck p += len;
360c2c66affSColin Finck
361c2c66affSColin Finck /* Ignore seed BIT STRING OPTIONAL */
362c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 )
363c2c66affSColin Finck p += len;
364c2c66affSColin Finck
365c2c66affSColin Finck if( p != end_curve )
366c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
367c2c66affSColin Finck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
368c2c66affSColin Finck
369c2c66affSColin Finck /*
370c2c66affSColin Finck * ECPoint ::= OCTET STRING
371c2c66affSColin Finck */
372c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
373c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
374c2c66affSColin Finck
375c2c66affSColin Finck if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G,
376c2c66affSColin Finck ( const unsigned char *) p, len ) ) != 0 )
377c2c66affSColin Finck {
378c2c66affSColin Finck /*
379c2c66affSColin Finck * If we can't read the point because it's compressed, cheat by
380c2c66affSColin Finck * reading only the X coordinate and the parity bit of Y.
381c2c66affSColin Finck */
382c2c66affSColin Finck if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
383c2c66affSColin Finck ( p[0] != 0x02 && p[0] != 0x03 ) ||
384c2c66affSColin Finck len != mbedtls_mpi_size( &grp->P ) + 1 ||
385c2c66affSColin Finck mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 ||
386c2c66affSColin Finck mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 ||
387c2c66affSColin Finck mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 )
388c2c66affSColin Finck {
389c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
390c2c66affSColin Finck }
391c2c66affSColin Finck }
392c2c66affSColin Finck
393c2c66affSColin Finck p += len;
394c2c66affSColin Finck
395c2c66affSColin Finck /*
396c2c66affSColin Finck * order INTEGER
397c2c66affSColin Finck */
398c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 )
399c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
400c2c66affSColin Finck
401c2c66affSColin Finck grp->nbits = mbedtls_mpi_bitlen( &grp->N );
402c2c66affSColin Finck
403c2c66affSColin Finck /*
404c2c66affSColin Finck * Allow optional elements by purposefully not enforcing p == end here.
405c2c66affSColin Finck */
406c2c66affSColin Finck
407c2c66affSColin Finck return( 0 );
408c2c66affSColin Finck }
409c2c66affSColin Finck
410c2c66affSColin Finck /*
411c2c66affSColin Finck * Find the group id associated with an (almost filled) group as generated by
412c2c66affSColin Finck * pk_group_from_specified(), or return an error if unknown.
413c2c66affSColin Finck */
pk_group_id_from_group(const mbedtls_ecp_group * grp,mbedtls_ecp_group_id * grp_id)414c2c66affSColin Finck static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id )
415c2c66affSColin Finck {
416c2c66affSColin Finck int ret = 0;
417c2c66affSColin Finck mbedtls_ecp_group ref;
418c2c66affSColin Finck const mbedtls_ecp_group_id *id;
419c2c66affSColin Finck
420c2c66affSColin Finck mbedtls_ecp_group_init( &ref );
421c2c66affSColin Finck
422c2c66affSColin Finck for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ )
423c2c66affSColin Finck {
424c2c66affSColin Finck /* Load the group associated to that id */
425c2c66affSColin Finck mbedtls_ecp_group_free( &ref );
426c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) );
427c2c66affSColin Finck
428c2c66affSColin Finck /* Compare to the group we were given, starting with easy tests */
429c2c66affSColin Finck if( grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
430c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 &&
431c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 &&
432c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 &&
433c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 &&
434c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 &&
435c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 &&
436c2c66affSColin Finck /* For Y we may only know the parity bit, so compare only that */
437c2c66affSColin Finck mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) )
438c2c66affSColin Finck {
439c2c66affSColin Finck break;
440c2c66affSColin Finck }
441c2c66affSColin Finck
442c2c66affSColin Finck }
443c2c66affSColin Finck
444c2c66affSColin Finck cleanup:
445c2c66affSColin Finck mbedtls_ecp_group_free( &ref );
446c2c66affSColin Finck
447c2c66affSColin Finck *grp_id = *id;
448c2c66affSColin Finck
449c2c66affSColin Finck if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE )
450c2c66affSColin Finck ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
451c2c66affSColin Finck
452c2c66affSColin Finck return( ret );
453c2c66affSColin Finck }
454c2c66affSColin Finck
455c2c66affSColin Finck /*
456c2c66affSColin Finck * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
457c2c66affSColin Finck */
pk_group_id_from_specified(const mbedtls_asn1_buf * params,mbedtls_ecp_group_id * grp_id)458c2c66affSColin Finck static int pk_group_id_from_specified( const mbedtls_asn1_buf *params,
459c2c66affSColin Finck mbedtls_ecp_group_id *grp_id )
460c2c66affSColin Finck {
461c2c66affSColin Finck int ret;
462c2c66affSColin Finck mbedtls_ecp_group grp;
463c2c66affSColin Finck
464c2c66affSColin Finck mbedtls_ecp_group_init( &grp );
465c2c66affSColin Finck
466c2c66affSColin Finck if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 )
467c2c66affSColin Finck goto cleanup;
468c2c66affSColin Finck
469c2c66affSColin Finck ret = pk_group_id_from_group( &grp, grp_id );
470c2c66affSColin Finck
471c2c66affSColin Finck cleanup:
472c2c66affSColin Finck mbedtls_ecp_group_free( &grp );
473c2c66affSColin Finck
474c2c66affSColin Finck return( ret );
475c2c66affSColin Finck }
476c2c66affSColin Finck #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
477c2c66affSColin Finck
478c2c66affSColin Finck /*
479c2c66affSColin Finck * Use EC parameters to initialise an EC group
480c2c66affSColin Finck *
481c2c66affSColin Finck * ECParameters ::= CHOICE {
482c2c66affSColin Finck * namedCurve OBJECT IDENTIFIER
483c2c66affSColin Finck * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
484c2c66affSColin Finck * -- implicitCurve NULL
485c2c66affSColin Finck */
pk_use_ecparams(const mbedtls_asn1_buf * params,mbedtls_ecp_group * grp)486c2c66affSColin Finck static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
487c2c66affSColin Finck {
488c2c66affSColin Finck int ret;
489c2c66affSColin Finck mbedtls_ecp_group_id grp_id;
490c2c66affSColin Finck
491c2c66affSColin Finck if( params->tag == MBEDTLS_ASN1_OID )
492c2c66affSColin Finck {
493c2c66affSColin Finck if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 )
494c2c66affSColin Finck return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
495c2c66affSColin Finck }
496c2c66affSColin Finck else
497c2c66affSColin Finck {
498c2c66affSColin Finck #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
499c2c66affSColin Finck if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 )
500c2c66affSColin Finck return( ret );
501c2c66affSColin Finck #else
502c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
503c2c66affSColin Finck #endif
504c2c66affSColin Finck }
505c2c66affSColin Finck
506c2c66affSColin Finck /*
507c2c66affSColin Finck * grp may already be initilialized; if so, make sure IDs match
508c2c66affSColin Finck */
509c2c66affSColin Finck if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id )
510c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
511c2c66affSColin Finck
512c2c66affSColin Finck if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 )
513c2c66affSColin Finck return( ret );
514c2c66affSColin Finck
515c2c66affSColin Finck return( 0 );
516c2c66affSColin Finck }
517c2c66affSColin Finck
518c2c66affSColin Finck /*
519c2c66affSColin Finck * EC public key is an EC point
520c2c66affSColin Finck *
521c2c66affSColin Finck * The caller is responsible for clearing the structure upon failure if
522c2c66affSColin Finck * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
523c2c66affSColin Finck * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
524c2c66affSColin Finck */
pk_get_ecpubkey(unsigned char ** p,const unsigned char * end,mbedtls_ecp_keypair * key)525c2c66affSColin Finck static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
526c2c66affSColin Finck mbedtls_ecp_keypair *key )
527c2c66affSColin Finck {
528c2c66affSColin Finck int ret;
529c2c66affSColin Finck
530c2c66affSColin Finck if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q,
531c2c66affSColin Finck (const unsigned char *) *p, end - *p ) ) == 0 )
532c2c66affSColin Finck {
533c2c66affSColin Finck ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q );
534c2c66affSColin Finck }
535c2c66affSColin Finck
536c2c66affSColin Finck /*
537c2c66affSColin Finck * We know mbedtls_ecp_point_read_binary consumed all bytes or failed
538c2c66affSColin Finck */
539c2c66affSColin Finck *p = (unsigned char *) end;
540c2c66affSColin Finck
541c2c66affSColin Finck return( ret );
542c2c66affSColin Finck }
543c2c66affSColin Finck #endif /* MBEDTLS_ECP_C */
544c2c66affSColin Finck
545c2c66affSColin Finck #if defined(MBEDTLS_RSA_C)
546c2c66affSColin Finck /*
547c2c66affSColin Finck * RSAPublicKey ::= SEQUENCE {
548c2c66affSColin Finck * modulus INTEGER, -- n
549c2c66affSColin Finck * publicExponent INTEGER -- e
550c2c66affSColin Finck * }
551c2c66affSColin Finck */
pk_get_rsapubkey(unsigned char ** p,const unsigned char * end,mbedtls_rsa_context * rsa)552c2c66affSColin Finck static int pk_get_rsapubkey( unsigned char **p,
553c2c66affSColin Finck const unsigned char *end,
554c2c66affSColin Finck mbedtls_rsa_context *rsa )
555c2c66affSColin Finck {
556c2c66affSColin Finck int ret;
557c2c66affSColin Finck size_t len;
558c2c66affSColin Finck
559c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
560c2c66affSColin Finck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
561c2c66affSColin Finck return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
562c2c66affSColin Finck
563c2c66affSColin Finck if( *p + len != end )
564c2c66affSColin Finck return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
565c2c66affSColin Finck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
566c2c66affSColin Finck
567d9e6c9b5SThomas Faber /* Import N */
568d9e6c9b5SThomas Faber if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
569c2c66affSColin Finck return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
570c2c66affSColin Finck
571d9e6c9b5SThomas Faber if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0,
572d9e6c9b5SThomas Faber NULL, 0, NULL, 0 ) ) != 0 )
573d9e6c9b5SThomas Faber return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
574d9e6c9b5SThomas Faber
575d9e6c9b5SThomas Faber *p += len;
576d9e6c9b5SThomas Faber
577d9e6c9b5SThomas Faber /* Import E */
578d9e6c9b5SThomas Faber if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
579d9e6c9b5SThomas Faber return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
580d9e6c9b5SThomas Faber
581d9e6c9b5SThomas Faber if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
582d9e6c9b5SThomas Faber NULL, 0, *p, len ) ) != 0 )
583d9e6c9b5SThomas Faber return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
584d9e6c9b5SThomas Faber
585d9e6c9b5SThomas Faber *p += len;
586d9e6c9b5SThomas Faber
587d9e6c9b5SThomas Faber if( mbedtls_rsa_complete( rsa ) != 0 ||
588d9e6c9b5SThomas Faber mbedtls_rsa_check_pubkey( rsa ) != 0 )
589d9e6c9b5SThomas Faber {
590d9e6c9b5SThomas Faber return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
591d9e6c9b5SThomas Faber }
592d9e6c9b5SThomas Faber
593c2c66affSColin Finck if( *p != end )
594c2c66affSColin Finck return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
595c2c66affSColin Finck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
596c2c66affSColin Finck
597c2c66affSColin Finck return( 0 );
598c2c66affSColin Finck }
599c2c66affSColin Finck #endif /* MBEDTLS_RSA_C */
600c2c66affSColin Finck
601c2c66affSColin Finck /* Get a PK algorithm identifier
602c2c66affSColin Finck *
603c2c66affSColin Finck * AlgorithmIdentifier ::= SEQUENCE {
604c2c66affSColin Finck * algorithm OBJECT IDENTIFIER,
605c2c66affSColin Finck * parameters ANY DEFINED BY algorithm OPTIONAL }
606c2c66affSColin Finck */
pk_get_pk_alg(unsigned char ** p,const unsigned char * end,mbedtls_pk_type_t * pk_alg,mbedtls_asn1_buf * params)607c2c66affSColin Finck static int pk_get_pk_alg( unsigned char **p,
608c2c66affSColin Finck const unsigned char *end,
609c2c66affSColin Finck mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params )
610c2c66affSColin Finck {
611c2c66affSColin Finck int ret;
612c2c66affSColin Finck mbedtls_asn1_buf alg_oid;
613c2c66affSColin Finck
614c2c66affSColin Finck memset( params, 0, sizeof(mbedtls_asn1_buf) );
615c2c66affSColin Finck
616c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
617c2c66affSColin Finck return( MBEDTLS_ERR_PK_INVALID_ALG + ret );
618c2c66affSColin Finck
619c2c66affSColin Finck if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
620c2c66affSColin Finck return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
621c2c66affSColin Finck
622c2c66affSColin Finck /*
623c2c66affSColin Finck * No parameters with RSA (only for EC)
624c2c66affSColin Finck */
625c2c66affSColin Finck if( *pk_alg == MBEDTLS_PK_RSA &&
626c2c66affSColin Finck ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) ||
627c2c66affSColin Finck params->len != 0 ) )
628c2c66affSColin Finck {
629c2c66affSColin Finck return( MBEDTLS_ERR_PK_INVALID_ALG );
630c2c66affSColin Finck }
631c2c66affSColin Finck
632c2c66affSColin Finck return( 0 );
633c2c66affSColin Finck }
634c2c66affSColin Finck
635c2c66affSColin Finck /*
636c2c66affSColin Finck * SubjectPublicKeyInfo ::= SEQUENCE {
637c2c66affSColin Finck * algorithm AlgorithmIdentifier,
638c2c66affSColin Finck * subjectPublicKey BIT STRING }
639c2c66affSColin Finck */
mbedtls_pk_parse_subpubkey(unsigned char ** p,const unsigned char * end,mbedtls_pk_context * pk)640c2c66affSColin Finck int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
641c2c66affSColin Finck mbedtls_pk_context *pk )
642c2c66affSColin Finck {
643c2c66affSColin Finck int ret;
644c2c66affSColin Finck size_t len;
645c2c66affSColin Finck mbedtls_asn1_buf alg_params;
646c2c66affSColin Finck mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
647c2c66affSColin Finck const mbedtls_pk_info_t *pk_info;
648c2c66affSColin Finck
649cbda039fSThomas Faber PK_VALIDATE_RET( p != NULL );
650cbda039fSThomas Faber PK_VALIDATE_RET( *p != NULL );
651cbda039fSThomas Faber PK_VALIDATE_RET( end != NULL );
652cbda039fSThomas Faber PK_VALIDATE_RET( pk != NULL );
653cbda039fSThomas Faber
654c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
655c2c66affSColin Finck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
656c2c66affSColin Finck {
657c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
658c2c66affSColin Finck }
659c2c66affSColin Finck
660c2c66affSColin Finck end = *p + len;
661c2c66affSColin Finck
662c2c66affSColin Finck if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
663c2c66affSColin Finck return( ret );
664c2c66affSColin Finck
665c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
666c2c66affSColin Finck return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
667c2c66affSColin Finck
668c2c66affSColin Finck if( *p + len != end )
669c2c66affSColin Finck return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
670c2c66affSColin Finck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
671c2c66affSColin Finck
672c2c66affSColin Finck if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
673c2c66affSColin Finck return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
674c2c66affSColin Finck
675c2c66affSColin Finck if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 )
676c2c66affSColin Finck return( ret );
677c2c66affSColin Finck
678c2c66affSColin Finck #if defined(MBEDTLS_RSA_C)
679c2c66affSColin Finck if( pk_alg == MBEDTLS_PK_RSA )
680c2c66affSColin Finck {
681c2c66affSColin Finck ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) );
682c2c66affSColin Finck } else
683c2c66affSColin Finck #endif /* MBEDTLS_RSA_C */
684c2c66affSColin Finck #if defined(MBEDTLS_ECP_C)
685c2c66affSColin Finck if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY )
686c2c66affSColin Finck {
687c2c66affSColin Finck ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp );
688c2c66affSColin Finck if( ret == 0 )
689c2c66affSColin Finck ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) );
690c2c66affSColin Finck } else
691c2c66affSColin Finck #endif /* MBEDTLS_ECP_C */
692c2c66affSColin Finck ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
693c2c66affSColin Finck
694c2c66affSColin Finck if( ret == 0 && *p != end )
6952e53fc8eSThomas Faber ret = MBEDTLS_ERR_PK_INVALID_PUBKEY +
696c2c66affSColin Finck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
697c2c66affSColin Finck
698c2c66affSColin Finck if( ret != 0 )
699c2c66affSColin Finck mbedtls_pk_free( pk );
700c2c66affSColin Finck
701c2c66affSColin Finck return( ret );
702c2c66affSColin Finck }
703c2c66affSColin Finck
704c2c66affSColin Finck #if defined(MBEDTLS_RSA_C)
705c2c66affSColin Finck /*
7061b00a1f5SThomas Faber * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
7071b00a1f5SThomas Faber *
7081b00a1f5SThomas Faber * The value zero is:
7091b00a1f5SThomas Faber * - never a valid value for an RSA parameter
7101b00a1f5SThomas Faber * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
7111b00a1f5SThomas Faber *
7121b00a1f5SThomas Faber * Since values can't be omitted in PKCS#1, passing a zero value to
7131b00a1f5SThomas Faber * rsa_complete() would be incorrect, so reject zero values early.
7141b00a1f5SThomas Faber */
asn1_get_nonzero_mpi(unsigned char ** p,const unsigned char * end,mbedtls_mpi * X)7151b00a1f5SThomas Faber static int asn1_get_nonzero_mpi( unsigned char **p,
7161b00a1f5SThomas Faber const unsigned char *end,
7171b00a1f5SThomas Faber mbedtls_mpi *X )
7181b00a1f5SThomas Faber {
7191b00a1f5SThomas Faber int ret;
7201b00a1f5SThomas Faber
7211b00a1f5SThomas Faber ret = mbedtls_asn1_get_mpi( p, end, X );
7221b00a1f5SThomas Faber if( ret != 0 )
7231b00a1f5SThomas Faber return( ret );
7241b00a1f5SThomas Faber
7251b00a1f5SThomas Faber if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
7261b00a1f5SThomas Faber return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
7271b00a1f5SThomas Faber
7281b00a1f5SThomas Faber return( 0 );
7291b00a1f5SThomas Faber }
7301b00a1f5SThomas Faber
7311b00a1f5SThomas Faber /*
732c2c66affSColin Finck * Parse a PKCS#1 encoded private RSA key
733c2c66affSColin Finck */
pk_parse_key_pkcs1_der(mbedtls_rsa_context * rsa,const unsigned char * key,size_t keylen)734c2c66affSColin Finck static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
735c2c66affSColin Finck const unsigned char *key,
736c2c66affSColin Finck size_t keylen )
737c2c66affSColin Finck {
738d9e6c9b5SThomas Faber int ret, version;
739c2c66affSColin Finck size_t len;
740c2c66affSColin Finck unsigned char *p, *end;
741c2c66affSColin Finck
742d9e6c9b5SThomas Faber mbedtls_mpi T;
743d9e6c9b5SThomas Faber mbedtls_mpi_init( &T );
744d9e6c9b5SThomas Faber
745c2c66affSColin Finck p = (unsigned char *) key;
746c2c66affSColin Finck end = p + keylen;
747c2c66affSColin Finck
748c2c66affSColin Finck /*
749c2c66affSColin Finck * This function parses the RSAPrivateKey (PKCS#1)
750c2c66affSColin Finck *
751c2c66affSColin Finck * RSAPrivateKey ::= SEQUENCE {
752c2c66affSColin Finck * version Version,
753c2c66affSColin Finck * modulus INTEGER, -- n
754c2c66affSColin Finck * publicExponent INTEGER, -- e
755c2c66affSColin Finck * privateExponent INTEGER, -- d
756c2c66affSColin Finck * prime1 INTEGER, -- p
757c2c66affSColin Finck * prime2 INTEGER, -- q
758c2c66affSColin Finck * exponent1 INTEGER, -- d mod (p-1)
759c2c66affSColin Finck * exponent2 INTEGER, -- d mod (q-1)
760c2c66affSColin Finck * coefficient INTEGER, -- (inverse of q) mod p
761c2c66affSColin Finck * otherPrimeInfos OtherPrimeInfos OPTIONAL
762c2c66affSColin Finck * }
763c2c66affSColin Finck */
764c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
765c2c66affSColin Finck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
766c2c66affSColin Finck {
767c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
768c2c66affSColin Finck }
769c2c66affSColin Finck
770c2c66affSColin Finck end = p + len;
771c2c66affSColin Finck
772d9e6c9b5SThomas Faber if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
773c2c66affSColin Finck {
774c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
775c2c66affSColin Finck }
776c2c66affSColin Finck
777d9e6c9b5SThomas Faber if( version != 0 )
778c2c66affSColin Finck {
779c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
780c2c66affSColin Finck }
781c2c66affSColin Finck
782d9e6c9b5SThomas Faber /* Import N */
7831b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
7841b00a1f5SThomas Faber ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL,
7851b00a1f5SThomas Faber NULL, NULL ) ) != 0 )
786d9e6c9b5SThomas Faber goto cleanup;
787c2c66affSColin Finck
788d9e6c9b5SThomas Faber /* Import E */
7891b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
7901b00a1f5SThomas Faber ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL,
7911b00a1f5SThomas Faber NULL, &T ) ) != 0 )
792d9e6c9b5SThomas Faber goto cleanup;
793d9e6c9b5SThomas Faber
794d9e6c9b5SThomas Faber /* Import D */
7951b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
7961b00a1f5SThomas Faber ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL,
7971b00a1f5SThomas Faber &T, NULL ) ) != 0 )
798d9e6c9b5SThomas Faber goto cleanup;
799d9e6c9b5SThomas Faber
800d9e6c9b5SThomas Faber /* Import P */
8011b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
8021b00a1f5SThomas Faber ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL,
8031b00a1f5SThomas Faber NULL, NULL ) ) != 0 )
804d9e6c9b5SThomas Faber goto cleanup;
805d9e6c9b5SThomas Faber
806d9e6c9b5SThomas Faber /* Import Q */
8071b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
8081b00a1f5SThomas Faber ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T,
8091b00a1f5SThomas Faber NULL, NULL ) ) != 0 )
810d9e6c9b5SThomas Faber goto cleanup;
811d9e6c9b5SThomas Faber
8121b00a1f5SThomas Faber #if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
8131b00a1f5SThomas Faber /*
8141b00a1f5SThomas Faber * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
8151b00a1f5SThomas Faber * that they can be easily recomputed from D, P and Q. However by
8161b00a1f5SThomas Faber * parsing them from the PKCS1 structure it is possible to avoid
8171b00a1f5SThomas Faber * recalculating them which both reduces the overhead of loading
8181b00a1f5SThomas Faber * RSA private keys into memory and also avoids side channels which
8191b00a1f5SThomas Faber * can arise when computing those values, since all of D, P, and Q
8201b00a1f5SThomas Faber * are secret. See https://eprint.iacr.org/2020/055 for a
8211b00a1f5SThomas Faber * description of one such attack.
8221b00a1f5SThomas Faber */
8231b00a1f5SThomas Faber
8241b00a1f5SThomas Faber /* Import DP */
8251b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
8261b00a1f5SThomas Faber ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 )
827d9e6c9b5SThomas Faber goto cleanup;
828c2c66affSColin Finck
8291b00a1f5SThomas Faber /* Import DQ */
8301b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
8311b00a1f5SThomas Faber ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 )
8321b00a1f5SThomas Faber goto cleanup;
8331b00a1f5SThomas Faber
8341b00a1f5SThomas Faber /* Import QP */
8351b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
8361b00a1f5SThomas Faber ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 )
8371b00a1f5SThomas Faber goto cleanup;
8381b00a1f5SThomas Faber
8391b00a1f5SThomas Faber #else
8401b00a1f5SThomas Faber /* Verify existance of the CRT params */
8411b00a1f5SThomas Faber if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
8421b00a1f5SThomas Faber ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
8431b00a1f5SThomas Faber ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 )
8441b00a1f5SThomas Faber goto cleanup;
8451b00a1f5SThomas Faber #endif
8461b00a1f5SThomas Faber
8471b00a1f5SThomas Faber /* rsa_complete() doesn't complete anything with the default
8481b00a1f5SThomas Faber * implementation but is still called:
8491b00a1f5SThomas Faber * - for the benefit of alternative implementation that may want to
8501b00a1f5SThomas Faber * pre-compute stuff beyond what's provided (eg Montgomery factors)
8511b00a1f5SThomas Faber * - as is also sanity-checks the key
8521b00a1f5SThomas Faber *
8531b00a1f5SThomas Faber * Furthermore, we also check the public part for consistency with
8541b00a1f5SThomas Faber * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
8551b00a1f5SThomas Faber */
8561b00a1f5SThomas Faber if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ||
8571b00a1f5SThomas Faber ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 )
8581b00a1f5SThomas Faber {
8591b00a1f5SThomas Faber goto cleanup;
8601b00a1f5SThomas Faber }
8611b00a1f5SThomas Faber
862c2c66affSColin Finck if( p != end )
863c2c66affSColin Finck {
864d9e6c9b5SThomas Faber ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
865d9e6c9b5SThomas Faber MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ;
866c2c66affSColin Finck }
867c2c66affSColin Finck
868d9e6c9b5SThomas Faber cleanup:
869d9e6c9b5SThomas Faber
870d9e6c9b5SThomas Faber mbedtls_mpi_free( &T );
871d9e6c9b5SThomas Faber
872d9e6c9b5SThomas Faber if( ret != 0 )
873c2c66affSColin Finck {
874d9e6c9b5SThomas Faber /* Wrap error code if it's coming from a lower level */
875d9e6c9b5SThomas Faber if( ( ret & 0xff80 ) == 0 )
876d9e6c9b5SThomas Faber ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret;
877d9e6c9b5SThomas Faber else
878d9e6c9b5SThomas Faber ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
879d9e6c9b5SThomas Faber
880c2c66affSColin Finck mbedtls_rsa_free( rsa );
881c2c66affSColin Finck }
882c2c66affSColin Finck
883d9e6c9b5SThomas Faber return( ret );
884c2c66affSColin Finck }
885c2c66affSColin Finck #endif /* MBEDTLS_RSA_C */
886c2c66affSColin Finck
887c2c66affSColin Finck #if defined(MBEDTLS_ECP_C)
888c2c66affSColin Finck /*
889c2c66affSColin Finck * Parse a SEC1 encoded private EC key
890c2c66affSColin Finck */
pk_parse_key_sec1_der(mbedtls_ecp_keypair * eck,const unsigned char * key,size_t keylen)891c2c66affSColin Finck static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck,
892c2c66affSColin Finck const unsigned char *key,
893c2c66affSColin Finck size_t keylen )
894c2c66affSColin Finck {
895c2c66affSColin Finck int ret;
896c2c66affSColin Finck int version, pubkey_done;
897c2c66affSColin Finck size_t len;
898c2c66affSColin Finck mbedtls_asn1_buf params;
899c2c66affSColin Finck unsigned char *p = (unsigned char *) key;
900c2c66affSColin Finck unsigned char *end = p + keylen;
901c2c66affSColin Finck unsigned char *end2;
902c2c66affSColin Finck
903c2c66affSColin Finck /*
904c2c66affSColin Finck * RFC 5915, or SEC1 Appendix C.4
905c2c66affSColin Finck *
906c2c66affSColin Finck * ECPrivateKey ::= SEQUENCE {
907c2c66affSColin Finck * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
908c2c66affSColin Finck * privateKey OCTET STRING,
909c2c66affSColin Finck * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
910c2c66affSColin Finck * publicKey [1] BIT STRING OPTIONAL
911c2c66affSColin Finck * }
912c2c66affSColin Finck */
913c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
914c2c66affSColin Finck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
915c2c66affSColin Finck {
916c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
917c2c66affSColin Finck }
918c2c66affSColin Finck
919c2c66affSColin Finck end = p + len;
920c2c66affSColin Finck
921c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
922c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
923c2c66affSColin Finck
924c2c66affSColin Finck if( version != 1 )
925c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
926c2c66affSColin Finck
927c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
928c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
929c2c66affSColin Finck
930c2c66affSColin Finck if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 )
931c2c66affSColin Finck {
932c2c66affSColin Finck mbedtls_ecp_keypair_free( eck );
933c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
934c2c66affSColin Finck }
935c2c66affSColin Finck
936c2c66affSColin Finck p += len;
937c2c66affSColin Finck
938c2c66affSColin Finck pubkey_done = 0;
939c2c66affSColin Finck if( p != end )
940c2c66affSColin Finck {
941c2c66affSColin Finck /*
942c2c66affSColin Finck * Is 'parameters' present?
943c2c66affSColin Finck */
944c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
945c2c66affSColin Finck MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
946c2c66affSColin Finck {
947c2c66affSColin Finck if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 ||
948c2c66affSColin Finck ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 )
949c2c66affSColin Finck {
950c2c66affSColin Finck mbedtls_ecp_keypair_free( eck );
951c2c66affSColin Finck return( ret );
952c2c66affSColin Finck }
953c2c66affSColin Finck }
954c2c66affSColin Finck else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
955c2c66affSColin Finck {
956c2c66affSColin Finck mbedtls_ecp_keypair_free( eck );
957c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
958c2c66affSColin Finck }
959d9e6c9b5SThomas Faber }
960c2c66affSColin Finck
961d9e6c9b5SThomas Faber if( p != end )
962d9e6c9b5SThomas Faber {
963c2c66affSColin Finck /*
964c2c66affSColin Finck * Is 'publickey' present? If not, or if we can't read it (eg because it
965c2c66affSColin Finck * is compressed), create it from the private key.
966c2c66affSColin Finck */
967c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
968c2c66affSColin Finck MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
969c2c66affSColin Finck {
970c2c66affSColin Finck end2 = p + len;
971c2c66affSColin Finck
972c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
973c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
974c2c66affSColin Finck
975c2c66affSColin Finck if( p + len != end2 )
976c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
977c2c66affSColin Finck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
978c2c66affSColin Finck
979c2c66affSColin Finck if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 )
980c2c66affSColin Finck pubkey_done = 1;
981c2c66affSColin Finck else
982c2c66affSColin Finck {
983c2c66affSColin Finck /*
984c2c66affSColin Finck * The only acceptable failure mode of pk_get_ecpubkey() above
985c2c66affSColin Finck * is if the point format is not recognized.
986c2c66affSColin Finck */
987c2c66affSColin Finck if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE )
988c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
989c2c66affSColin Finck }
990c2c66affSColin Finck }
991c2c66affSColin Finck else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
992c2c66affSColin Finck {
993c2c66affSColin Finck mbedtls_ecp_keypair_free( eck );
994c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
995c2c66affSColin Finck }
996c2c66affSColin Finck }
997c2c66affSColin Finck
998c2c66affSColin Finck if( ! pubkey_done &&
999c2c66affSColin Finck ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G,
1000c2c66affSColin Finck NULL, NULL ) ) != 0 )
1001c2c66affSColin Finck {
1002c2c66affSColin Finck mbedtls_ecp_keypair_free( eck );
1003c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
1004c2c66affSColin Finck }
1005c2c66affSColin Finck
1006c2c66affSColin Finck if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
1007c2c66affSColin Finck {
1008c2c66affSColin Finck mbedtls_ecp_keypair_free( eck );
1009c2c66affSColin Finck return( ret );
1010c2c66affSColin Finck }
1011c2c66affSColin Finck
1012c2c66affSColin Finck return( 0 );
1013c2c66affSColin Finck }
1014c2c66affSColin Finck #endif /* MBEDTLS_ECP_C */
1015c2c66affSColin Finck
1016c2c66affSColin Finck /*
1017c2c66affSColin Finck * Parse an unencrypted PKCS#8 encoded private key
1018d9e6c9b5SThomas Faber *
1019d9e6c9b5SThomas Faber * Notes:
1020d9e6c9b5SThomas Faber *
1021d9e6c9b5SThomas Faber * - This function does not own the key buffer. It is the
1022d9e6c9b5SThomas Faber * responsibility of the caller to take care of zeroizing
1023d9e6c9b5SThomas Faber * and freeing it after use.
1024d9e6c9b5SThomas Faber *
1025d9e6c9b5SThomas Faber * - The function is responsible for freeing the provided
1026d9e6c9b5SThomas Faber * PK context on failure.
1027d9e6c9b5SThomas Faber *
1028c2c66affSColin Finck */
pk_parse_key_pkcs8_unencrypted_der(mbedtls_pk_context * pk,const unsigned char * key,size_t keylen)1029c2c66affSColin Finck static int pk_parse_key_pkcs8_unencrypted_der(
1030c2c66affSColin Finck mbedtls_pk_context *pk,
1031c2c66affSColin Finck const unsigned char* key,
1032c2c66affSColin Finck size_t keylen )
1033c2c66affSColin Finck {
1034c2c66affSColin Finck int ret, version;
1035c2c66affSColin Finck size_t len;
1036c2c66affSColin Finck mbedtls_asn1_buf params;
1037c2c66affSColin Finck unsigned char *p = (unsigned char *) key;
1038c2c66affSColin Finck unsigned char *end = p + keylen;
1039c2c66affSColin Finck mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
1040c2c66affSColin Finck const mbedtls_pk_info_t *pk_info;
1041c2c66affSColin Finck
1042c2c66affSColin Finck /*
1043d9e6c9b5SThomas Faber * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
1044c2c66affSColin Finck *
1045c2c66affSColin Finck * PrivateKeyInfo ::= SEQUENCE {
1046c2c66affSColin Finck * version Version,
1047c2c66affSColin Finck * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
1048c2c66affSColin Finck * privateKey PrivateKey,
1049c2c66affSColin Finck * attributes [0] IMPLICIT Attributes OPTIONAL }
1050c2c66affSColin Finck *
1051c2c66affSColin Finck * Version ::= INTEGER
1052c2c66affSColin Finck * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
1053c2c66affSColin Finck * PrivateKey ::= OCTET STRING
1054c2c66affSColin Finck *
1055c2c66affSColin Finck * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
1056c2c66affSColin Finck */
1057c2c66affSColin Finck
1058c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1059c2c66affSColin Finck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1060c2c66affSColin Finck {
1061c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
1062c2c66affSColin Finck }
1063c2c66affSColin Finck
1064c2c66affSColin Finck end = p + len;
1065c2c66affSColin Finck
1066c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
1067c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
1068c2c66affSColin Finck
1069c2c66affSColin Finck if( version != 0 )
1070c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret );
1071c2c66affSColin Finck
1072c2c66affSColin Finck if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 )
1073*103a79ceSThomas Faber return( ret );
1074c2c66affSColin Finck
1075c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
1076c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
1077c2c66affSColin Finck
1078c2c66affSColin Finck if( len < 1 )
1079c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
1080c2c66affSColin Finck MBEDTLS_ERR_ASN1_OUT_OF_DATA );
1081c2c66affSColin Finck
1082c2c66affSColin Finck if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
1083c2c66affSColin Finck return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
1084c2c66affSColin Finck
1085c2c66affSColin Finck if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 )
1086c2c66affSColin Finck return( ret );
1087c2c66affSColin Finck
1088c2c66affSColin Finck #if defined(MBEDTLS_RSA_C)
1089c2c66affSColin Finck if( pk_alg == MBEDTLS_PK_RSA )
1090c2c66affSColin Finck {
1091c2c66affSColin Finck if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 )
1092c2c66affSColin Finck {
1093c2c66affSColin Finck mbedtls_pk_free( pk );
1094c2c66affSColin Finck return( ret );
1095c2c66affSColin Finck }
1096c2c66affSColin Finck } else
1097c2c66affSColin Finck #endif /* MBEDTLS_RSA_C */
1098c2c66affSColin Finck #if defined(MBEDTLS_ECP_C)
1099c2c66affSColin Finck if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH )
1100c2c66affSColin Finck {
1101c2c66affSColin Finck if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 ||
1102c2c66affSColin Finck ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 )
1103c2c66affSColin Finck {
1104c2c66affSColin Finck mbedtls_pk_free( pk );
1105c2c66affSColin Finck return( ret );
1106c2c66affSColin Finck }
1107c2c66affSColin Finck } else
1108c2c66affSColin Finck #endif /* MBEDTLS_ECP_C */
1109c2c66affSColin Finck return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
1110c2c66affSColin Finck
1111c2c66affSColin Finck return( 0 );
1112c2c66affSColin Finck }
1113c2c66affSColin Finck
1114c2c66affSColin Finck /*
1115c2c66affSColin Finck * Parse an encrypted PKCS#8 encoded private key
1116d9e6c9b5SThomas Faber *
1117d9e6c9b5SThomas Faber * To save space, the decryption happens in-place on the given key buffer.
1118d9e6c9b5SThomas Faber * Also, while this function may modify the keybuffer, it doesn't own it,
1119d9e6c9b5SThomas Faber * and instead it is the responsibility of the caller to zeroize and properly
1120d9e6c9b5SThomas Faber * free it after use.
1121d9e6c9b5SThomas Faber *
1122c2c66affSColin Finck */
1123c2c66affSColin Finck #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
pk_parse_key_pkcs8_encrypted_der(mbedtls_pk_context * pk,unsigned char * key,size_t keylen,const unsigned char * pwd,size_t pwdlen)1124c2c66affSColin Finck static int pk_parse_key_pkcs8_encrypted_der(
1125c2c66affSColin Finck mbedtls_pk_context *pk,
1126d9e6c9b5SThomas Faber unsigned char *key, size_t keylen,
1127c2c66affSColin Finck const unsigned char *pwd, size_t pwdlen )
1128c2c66affSColin Finck {
1129c2c66affSColin Finck int ret, decrypted = 0;
1130c2c66affSColin Finck size_t len;
1131d9e6c9b5SThomas Faber unsigned char *buf;
1132c2c66affSColin Finck unsigned char *p, *end;
1133c2c66affSColin Finck mbedtls_asn1_buf pbe_alg_oid, pbe_params;
1134c2c66affSColin Finck #if defined(MBEDTLS_PKCS12_C)
1135c2c66affSColin Finck mbedtls_cipher_type_t cipher_alg;
1136c2c66affSColin Finck mbedtls_md_type_t md_alg;
1137c2c66affSColin Finck #endif
1138c2c66affSColin Finck
1139d9e6c9b5SThomas Faber p = key;
1140c2c66affSColin Finck end = p + keylen;
1141c2c66affSColin Finck
1142c2c66affSColin Finck if( pwdlen == 0 )
1143c2c66affSColin Finck return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
1144c2c66affSColin Finck
1145c2c66affSColin Finck /*
1146d9e6c9b5SThomas Faber * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
1147c2c66affSColin Finck *
1148c2c66affSColin Finck * EncryptedPrivateKeyInfo ::= SEQUENCE {
1149c2c66affSColin Finck * encryptionAlgorithm EncryptionAlgorithmIdentifier,
1150c2c66affSColin Finck * encryptedData EncryptedData
1151c2c66affSColin Finck * }
1152c2c66affSColin Finck *
1153c2c66affSColin Finck * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
1154c2c66affSColin Finck *
1155c2c66affSColin Finck * EncryptedData ::= OCTET STRING
1156c2c66affSColin Finck *
1157c2c66affSColin Finck * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
1158d9e6c9b5SThomas Faber *
1159c2c66affSColin Finck */
1160c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1161c2c66affSColin Finck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1162c2c66affSColin Finck {
1163c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
1164c2c66affSColin Finck }
1165c2c66affSColin Finck
1166c2c66affSColin Finck end = p + len;
1167c2c66affSColin Finck
1168c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 )
1169c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
1170c2c66affSColin Finck
1171c2c66affSColin Finck if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
1172c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
1173c2c66affSColin Finck
1174d9e6c9b5SThomas Faber buf = p;
1175c2c66affSColin Finck
1176c2c66affSColin Finck /*
1177d9e6c9b5SThomas Faber * Decrypt EncryptedData with appropriate PBE
1178c2c66affSColin Finck */
1179c2c66affSColin Finck #if defined(MBEDTLS_PKCS12_C)
1180c2c66affSColin Finck if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
1181c2c66affSColin Finck {
1182c2c66affSColin Finck if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
1183c2c66affSColin Finck cipher_alg, md_alg,
1184c2c66affSColin Finck pwd, pwdlen, p, len, buf ) ) != 0 )
1185c2c66affSColin Finck {
1186c2c66affSColin Finck if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH )
1187c2c66affSColin Finck return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
1188c2c66affSColin Finck
1189c2c66affSColin Finck return( ret );
1190c2c66affSColin Finck }
1191c2c66affSColin Finck
1192c2c66affSColin Finck decrypted = 1;
1193c2c66affSColin Finck }
1194c2c66affSColin Finck else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 )
1195c2c66affSColin Finck {
1196c2c66affSColin Finck if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params,
1197c2c66affSColin Finck MBEDTLS_PKCS12_PBE_DECRYPT,
1198c2c66affSColin Finck pwd, pwdlen,
1199c2c66affSColin Finck p, len, buf ) ) != 0 )
1200c2c66affSColin Finck {
1201c2c66affSColin Finck return( ret );
1202c2c66affSColin Finck }
1203c2c66affSColin Finck
1204c2c66affSColin Finck // Best guess for password mismatch when using RC4. If first tag is
1205c2c66affSColin Finck // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
1206c2c66affSColin Finck //
1207c2c66affSColin Finck if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
1208c2c66affSColin Finck return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
1209c2c66affSColin Finck
1210c2c66affSColin Finck decrypted = 1;
1211c2c66affSColin Finck }
1212c2c66affSColin Finck else
1213c2c66affSColin Finck #endif /* MBEDTLS_PKCS12_C */
1214c2c66affSColin Finck #if defined(MBEDTLS_PKCS5_C)
1215c2c66affSColin Finck if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 )
1216c2c66affSColin Finck {
1217c2c66affSColin Finck if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
1218c2c66affSColin Finck p, len, buf ) ) != 0 )
1219c2c66affSColin Finck {
1220c2c66affSColin Finck if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH )
1221c2c66affSColin Finck return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
1222c2c66affSColin Finck
1223c2c66affSColin Finck return( ret );
1224c2c66affSColin Finck }
1225c2c66affSColin Finck
1226c2c66affSColin Finck decrypted = 1;
1227c2c66affSColin Finck }
1228c2c66affSColin Finck else
1229c2c66affSColin Finck #endif /* MBEDTLS_PKCS5_C */
1230c2c66affSColin Finck {
1231c2c66affSColin Finck ((void) pwd);
1232c2c66affSColin Finck }
1233c2c66affSColin Finck
1234c2c66affSColin Finck if( decrypted == 0 )
1235c2c66affSColin Finck return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
1236c2c66affSColin Finck
1237c2c66affSColin Finck return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
1238c2c66affSColin Finck }
1239c2c66affSColin Finck #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
1240c2c66affSColin Finck
1241c2c66affSColin Finck /*
1242c2c66affSColin Finck * Parse a private key
1243c2c66affSColin Finck */
mbedtls_pk_parse_key(mbedtls_pk_context * pk,const unsigned char * key,size_t keylen,const unsigned char * pwd,size_t pwdlen)1244c2c66affSColin Finck int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
1245c2c66affSColin Finck const unsigned char *key, size_t keylen,
1246c2c66affSColin Finck const unsigned char *pwd, size_t pwdlen )
1247c2c66affSColin Finck {
1248c2c66affSColin Finck int ret;
1249c2c66affSColin Finck const mbedtls_pk_info_t *pk_info;
1250c2c66affSColin Finck #if defined(MBEDTLS_PEM_PARSE_C)
1251c2c66affSColin Finck size_t len;
1252c2c66affSColin Finck mbedtls_pem_context pem;
1253cbda039fSThomas Faber #endif
1254c2c66affSColin Finck
1255cbda039fSThomas Faber PK_VALIDATE_RET( pk != NULL );
1256cbda039fSThomas Faber if( keylen == 0 )
1257cbda039fSThomas Faber return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
1258cbda039fSThomas Faber PK_VALIDATE_RET( key != NULL );
1259cbda039fSThomas Faber
1260cbda039fSThomas Faber #if defined(MBEDTLS_PEM_PARSE_C)
1261c2c66affSColin Finck mbedtls_pem_init( &pem );
1262c2c66affSColin Finck
1263c2c66affSColin Finck #if defined(MBEDTLS_RSA_C)
1264c2c66affSColin Finck /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1265cbda039fSThomas Faber if( key[keylen - 1] != '\0' )
1266c2c66affSColin Finck ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1267c2c66affSColin Finck else
1268c2c66affSColin Finck ret = mbedtls_pem_read_buffer( &pem,
1269c2c66affSColin Finck "-----BEGIN RSA PRIVATE KEY-----",
1270c2c66affSColin Finck "-----END RSA PRIVATE KEY-----",
1271c2c66affSColin Finck key, pwd, pwdlen, &len );
1272c2c66affSColin Finck
1273c2c66affSColin Finck if( ret == 0 )
1274c2c66affSColin Finck {
1275d9e6c9b5SThomas Faber pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
1276c2c66affSColin Finck if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
1277c2c66affSColin Finck ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
1278c2c66affSColin Finck pem.buf, pem.buflen ) ) != 0 )
1279c2c66affSColin Finck {
1280c2c66affSColin Finck mbedtls_pk_free( pk );
1281c2c66affSColin Finck }
1282c2c66affSColin Finck
1283c2c66affSColin Finck mbedtls_pem_free( &pem );
1284c2c66affSColin Finck return( ret );
1285c2c66affSColin Finck }
1286c2c66affSColin Finck else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH )
1287c2c66affSColin Finck return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
1288c2c66affSColin Finck else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED )
1289c2c66affSColin Finck return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
1290c2c66affSColin Finck else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
1291c2c66affSColin Finck return( ret );
1292c2c66affSColin Finck #endif /* MBEDTLS_RSA_C */
1293c2c66affSColin Finck
1294c2c66affSColin Finck #if defined(MBEDTLS_ECP_C)
1295c2c66affSColin Finck /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1296cbda039fSThomas Faber if( key[keylen - 1] != '\0' )
1297c2c66affSColin Finck ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1298c2c66affSColin Finck else
1299c2c66affSColin Finck ret = mbedtls_pem_read_buffer( &pem,
1300c2c66affSColin Finck "-----BEGIN EC PRIVATE KEY-----",
1301c2c66affSColin Finck "-----END EC PRIVATE KEY-----",
1302c2c66affSColin Finck key, pwd, pwdlen, &len );
1303c2c66affSColin Finck if( ret == 0 )
1304c2c66affSColin Finck {
1305d9e6c9b5SThomas Faber pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
1306c2c66affSColin Finck
1307c2c66affSColin Finck if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
1308c2c66affSColin Finck ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
1309c2c66affSColin Finck pem.buf, pem.buflen ) ) != 0 )
1310c2c66affSColin Finck {
1311c2c66affSColin Finck mbedtls_pk_free( pk );
1312c2c66affSColin Finck }
1313c2c66affSColin Finck
1314c2c66affSColin Finck mbedtls_pem_free( &pem );
1315c2c66affSColin Finck return( ret );
1316c2c66affSColin Finck }
1317c2c66affSColin Finck else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH )
1318c2c66affSColin Finck return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
1319c2c66affSColin Finck else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED )
1320c2c66affSColin Finck return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
1321c2c66affSColin Finck else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
1322c2c66affSColin Finck return( ret );
1323c2c66affSColin Finck #endif /* MBEDTLS_ECP_C */
1324c2c66affSColin Finck
1325c2c66affSColin Finck /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1326cbda039fSThomas Faber if( key[keylen - 1] != '\0' )
1327c2c66affSColin Finck ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1328c2c66affSColin Finck else
1329c2c66affSColin Finck ret = mbedtls_pem_read_buffer( &pem,
1330c2c66affSColin Finck "-----BEGIN PRIVATE KEY-----",
1331c2c66affSColin Finck "-----END PRIVATE KEY-----",
1332c2c66affSColin Finck key, NULL, 0, &len );
1333c2c66affSColin Finck if( ret == 0 )
1334c2c66affSColin Finck {
1335c2c66affSColin Finck if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk,
1336c2c66affSColin Finck pem.buf, pem.buflen ) ) != 0 )
1337c2c66affSColin Finck {
1338c2c66affSColin Finck mbedtls_pk_free( pk );
1339c2c66affSColin Finck }
1340c2c66affSColin Finck
1341c2c66affSColin Finck mbedtls_pem_free( &pem );
1342c2c66affSColin Finck return( ret );
1343c2c66affSColin Finck }
1344c2c66affSColin Finck else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
1345c2c66affSColin Finck return( ret );
1346c2c66affSColin Finck
1347c2c66affSColin Finck #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
1348c2c66affSColin Finck /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1349cbda039fSThomas Faber if( key[keylen - 1] != '\0' )
1350c2c66affSColin Finck ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1351c2c66affSColin Finck else
1352c2c66affSColin Finck ret = mbedtls_pem_read_buffer( &pem,
1353c2c66affSColin Finck "-----BEGIN ENCRYPTED PRIVATE KEY-----",
1354c2c66affSColin Finck "-----END ENCRYPTED PRIVATE KEY-----",
1355c2c66affSColin Finck key, NULL, 0, &len );
1356c2c66affSColin Finck if( ret == 0 )
1357c2c66affSColin Finck {
1358c2c66affSColin Finck if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk,
1359c2c66affSColin Finck pem.buf, pem.buflen,
1360c2c66affSColin Finck pwd, pwdlen ) ) != 0 )
1361c2c66affSColin Finck {
1362c2c66affSColin Finck mbedtls_pk_free( pk );
1363c2c66affSColin Finck }
1364c2c66affSColin Finck
1365c2c66affSColin Finck mbedtls_pem_free( &pem );
1366c2c66affSColin Finck return( ret );
1367c2c66affSColin Finck }
1368c2c66affSColin Finck else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
1369c2c66affSColin Finck return( ret );
1370c2c66affSColin Finck #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
1371c2c66affSColin Finck #else
1372c2c66affSColin Finck ((void) pwd);
1373c2c66affSColin Finck ((void) pwdlen);
1374c2c66affSColin Finck #endif /* MBEDTLS_PEM_PARSE_C */
1375c2c66affSColin Finck
1376c2c66affSColin Finck /*
1377c2c66affSColin Finck * At this point we only know it's not a PEM formatted key. Could be any
1378c2c66affSColin Finck * of the known DER encoded private key formats
1379c2c66affSColin Finck *
1380c2c66affSColin Finck * We try the different DER format parsers to see if one passes without
1381c2c66affSColin Finck * error
1382c2c66affSColin Finck */
1383c2c66affSColin Finck #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
1384c2c66affSColin Finck {
1385d9e6c9b5SThomas Faber unsigned char *key_copy;
1386d9e6c9b5SThomas Faber
1387d9e6c9b5SThomas Faber if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL )
1388d9e6c9b5SThomas Faber return( MBEDTLS_ERR_PK_ALLOC_FAILED );
1389d9e6c9b5SThomas Faber
1390d9e6c9b5SThomas Faber memcpy( key_copy, key, keylen );
1391d9e6c9b5SThomas Faber
1392d9e6c9b5SThomas Faber ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen,
1393d9e6c9b5SThomas Faber pwd, pwdlen );
1394d9e6c9b5SThomas Faber
1395cbda039fSThomas Faber mbedtls_platform_zeroize( key_copy, keylen );
1396d9e6c9b5SThomas Faber mbedtls_free( key_copy );
1397c2c66affSColin Finck }
1398c2c66affSColin Finck
1399d9e6c9b5SThomas Faber if( ret == 0 )
1400d9e6c9b5SThomas Faber return( 0 );
1401d9e6c9b5SThomas Faber
1402c2c66affSColin Finck mbedtls_pk_free( pk );
14030ba5bc40SThomas Faber mbedtls_pk_init( pk );
1404c2c66affSColin Finck
1405c2c66affSColin Finck if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
1406c2c66affSColin Finck {
1407c2c66affSColin Finck return( ret );
1408c2c66affSColin Finck }
1409c2c66affSColin Finck #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
1410c2c66affSColin Finck
1411c2c66affSColin Finck if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
1412c2c66affSColin Finck return( 0 );
1413c2c66affSColin Finck
1414c2c66affSColin Finck mbedtls_pk_free( pk );
14150ba5bc40SThomas Faber mbedtls_pk_init( pk );
1416c2c66affSColin Finck
1417c2c66affSColin Finck #if defined(MBEDTLS_RSA_C)
1418c2c66affSColin Finck
1419d9e6c9b5SThomas Faber pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
14200ba5bc40SThomas Faber if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
14210ba5bc40SThomas Faber pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 )
1422c2c66affSColin Finck {
1423c2c66affSColin Finck return( 0 );
1424c2c66affSColin Finck }
1425c2c66affSColin Finck
14260ba5bc40SThomas Faber mbedtls_pk_free( pk );
14270ba5bc40SThomas Faber mbedtls_pk_init( pk );
1428c2c66affSColin Finck #endif /* MBEDTLS_RSA_C */
1429c2c66affSColin Finck
1430c2c66affSColin Finck #if defined(MBEDTLS_ECP_C)
1431d9e6c9b5SThomas Faber pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
14320ba5bc40SThomas Faber if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
14330ba5bc40SThomas Faber pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
14340ba5bc40SThomas Faber key, keylen ) == 0 )
1435c2c66affSColin Finck {
1436c2c66affSColin Finck return( 0 );
1437c2c66affSColin Finck }
14380ba5bc40SThomas Faber mbedtls_pk_free( pk );
1439c2c66affSColin Finck #endif /* MBEDTLS_ECP_C */
1440c2c66affSColin Finck
14410ba5bc40SThomas Faber /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
14420ba5bc40SThomas Faber * it is ok to leave the PK context initialized but not
14430ba5bc40SThomas Faber * freed: It is the caller's responsibility to call pk_init()
14440ba5bc40SThomas Faber * before calling this function, and to call pk_free()
14450ba5bc40SThomas Faber * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
14460ba5bc40SThomas Faber * isn't, this leads to mbedtls_pk_free() being called
14470ba5bc40SThomas Faber * twice, once here and once by the caller, but this is
14480ba5bc40SThomas Faber * also ok and in line with the mbedtls_pk_free() calls
14490ba5bc40SThomas Faber * on failed PEM parsing attempts. */
14500ba5bc40SThomas Faber
1451c2c66affSColin Finck return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
1452c2c66affSColin Finck }
1453c2c66affSColin Finck
1454c2c66affSColin Finck /*
1455c2c66affSColin Finck * Parse a public key
1456c2c66affSColin Finck */
mbedtls_pk_parse_public_key(mbedtls_pk_context * ctx,const unsigned char * key,size_t keylen)1457c2c66affSColin Finck int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
1458c2c66affSColin Finck const unsigned char *key, size_t keylen )
1459c2c66affSColin Finck {
1460c2c66affSColin Finck int ret;
1461c2c66affSColin Finck unsigned char *p;
1462cbda039fSThomas Faber #if defined(MBEDTLS_RSA_C)
1463cbda039fSThomas Faber const mbedtls_pk_info_t *pk_info;
1464cbda039fSThomas Faber #endif
1465c2c66affSColin Finck #if defined(MBEDTLS_PEM_PARSE_C)
1466c2c66affSColin Finck size_t len;
1467c2c66affSColin Finck mbedtls_pem_context pem;
1468cbda039fSThomas Faber #endif
1469c2c66affSColin Finck
1470cbda039fSThomas Faber PK_VALIDATE_RET( ctx != NULL );
1471cbda039fSThomas Faber if( keylen == 0 )
1472cbda039fSThomas Faber return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
1473cbda039fSThomas Faber PK_VALIDATE_RET( key != NULL || keylen == 0 );
1474cbda039fSThomas Faber
1475cbda039fSThomas Faber #if defined(MBEDTLS_PEM_PARSE_C)
1476c2c66affSColin Finck mbedtls_pem_init( &pem );
1477cbda039fSThomas Faber #if defined(MBEDTLS_RSA_C)
1478cbda039fSThomas Faber /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1479cbda039fSThomas Faber if( key[keylen - 1] != '\0' )
1480cbda039fSThomas Faber ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1481cbda039fSThomas Faber else
1482cbda039fSThomas Faber ret = mbedtls_pem_read_buffer( &pem,
1483cbda039fSThomas Faber "-----BEGIN RSA PUBLIC KEY-----",
1484cbda039fSThomas Faber "-----END RSA PUBLIC KEY-----",
1485cbda039fSThomas Faber key, NULL, 0, &len );
1486cbda039fSThomas Faber
1487cbda039fSThomas Faber if( ret == 0 )
1488cbda039fSThomas Faber {
1489cbda039fSThomas Faber p = pem.buf;
1490cbda039fSThomas Faber if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
1491cbda039fSThomas Faber return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
1492cbda039fSThomas Faber
1493cbda039fSThomas Faber if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
1494cbda039fSThomas Faber return( ret );
1495cbda039fSThomas Faber
1496cbda039fSThomas Faber if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 )
1497cbda039fSThomas Faber mbedtls_pk_free( ctx );
1498cbda039fSThomas Faber
1499cbda039fSThomas Faber mbedtls_pem_free( &pem );
1500cbda039fSThomas Faber return( ret );
1501cbda039fSThomas Faber }
1502cbda039fSThomas Faber else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
1503cbda039fSThomas Faber {
1504cbda039fSThomas Faber mbedtls_pem_free( &pem );
1505cbda039fSThomas Faber return( ret );
1506cbda039fSThomas Faber }
1507cbda039fSThomas Faber #endif /* MBEDTLS_RSA_C */
1508c2c66affSColin Finck
1509c2c66affSColin Finck /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1510cbda039fSThomas Faber if( key[keylen - 1] != '\0' )
1511c2c66affSColin Finck ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1512c2c66affSColin Finck else
1513c2c66affSColin Finck ret = mbedtls_pem_read_buffer( &pem,
1514c2c66affSColin Finck "-----BEGIN PUBLIC KEY-----",
1515c2c66affSColin Finck "-----END PUBLIC KEY-----",
1516c2c66affSColin Finck key, NULL, 0, &len );
1517c2c66affSColin Finck
1518c2c66affSColin Finck if( ret == 0 )
1519c2c66affSColin Finck {
1520c2c66affSColin Finck /*
1521c2c66affSColin Finck * Was PEM encoded
1522c2c66affSColin Finck */
1523cbda039fSThomas Faber p = pem.buf;
1524cbda039fSThomas Faber
1525cbda039fSThomas Faber ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx );
1526cbda039fSThomas Faber mbedtls_pem_free( &pem );
1527cbda039fSThomas Faber return( ret );
1528c2c66affSColin Finck }
1529c2c66affSColin Finck else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
1530c2c66affSColin Finck {
1531c2c66affSColin Finck mbedtls_pem_free( &pem );
1532c2c66affSColin Finck return( ret );
1533c2c66affSColin Finck }
1534cbda039fSThomas Faber mbedtls_pem_free( &pem );
1535c2c66affSColin Finck #endif /* MBEDTLS_PEM_PARSE_C */
1536cbda039fSThomas Faber
1537cbda039fSThomas Faber #if defined(MBEDTLS_RSA_C)
1538cbda039fSThomas Faber if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
1539cbda039fSThomas Faber return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
1540cbda039fSThomas Faber
1541cbda039fSThomas Faber if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
1542cbda039fSThomas Faber return( ret );
1543cbda039fSThomas Faber
1544cbda039fSThomas Faber p = (unsigned char *)key;
1545cbda039fSThomas Faber ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) );
1546cbda039fSThomas Faber if( ret == 0 )
1547cbda039fSThomas Faber {
1548cbda039fSThomas Faber return( ret );
1549cbda039fSThomas Faber }
1550cbda039fSThomas Faber mbedtls_pk_free( ctx );
1551cbda039fSThomas Faber if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
1552cbda039fSThomas Faber {
1553cbda039fSThomas Faber return( ret );
1554cbda039fSThomas Faber }
1555cbda039fSThomas Faber #endif /* MBEDTLS_RSA_C */
1556c2c66affSColin Finck p = (unsigned char *) key;
1557c2c66affSColin Finck
1558c2c66affSColin Finck ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx );
1559c2c66affSColin Finck
1560c2c66affSColin Finck return( ret );
1561c2c66affSColin Finck }
1562c2c66affSColin Finck
1563c2c66affSColin Finck #endif /* MBEDTLS_PK_PARSE_C */
1564