blob: efd14c155eee93470aafcd5eacf075d1e561b1f0 [file] [log] [blame]
Paul Bakker1a7550a2013-09-15 13:01:22 +02001/*
2 * Public Key layer for parsing key files and structures
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
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 */
19
Gilles Peskinedb09ef62020-06-03 01:43:33 +020020#include "common.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020022#if defined(MBEDTLS_PK_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +020023
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020024# include "mbedtls/pk.h"
25# include "mbedtls/asn1.h"
26# include "mbedtls/oid.h"
27# include "mbedtls/platform_util.h"
28# include "mbedtls/error.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020029
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020030# include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000031
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020032# if defined(MBEDTLS_RSA_C)
33# include "mbedtls/rsa.h"
34# endif
35# if defined(MBEDTLS_ECP_C)
36# include "mbedtls/ecp.h"
37# endif
38# if defined(MBEDTLS_ECDSA_C)
39# include "mbedtls/ecdsa.h"
40# endif
41# if defined(MBEDTLS_PEM_PARSE_C)
42# include "mbedtls/pem.h"
43# endif
44# if defined(MBEDTLS_PKCS5_C)
45# include "mbedtls/pkcs5.h"
46# endif
47# if defined(MBEDTLS_PKCS12_C)
48# include "mbedtls/pkcs12.h"
49# endif
Paul Bakker1a7550a2013-09-15 13:01:22 +020050
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020051# if defined(MBEDTLS_PLATFORM_C)
52# include "mbedtls/platform.h"
53# else
54# include <stdlib.h>
55# define mbedtls_calloc calloc
56# define mbedtls_free free
57# endif
Paul Bakker1a7550a2013-09-15 13:01:22 +020058
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050059/* Parameter validation macros based on platform_util.h */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020060# define PK_VALIDATE_RET(cond) \
61 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA)
62# define PK_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050063
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020064# if defined(MBEDTLS_FS_IO)
Paul Bakker1a7550a2013-09-15 13:01:22 +020065/*
66 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +020067 *
68 * The file is expected to contain either PEM or DER encoded data.
69 * A terminating null byte is always appended. It is included in the announced
70 * length only if the data looks like it is PEM encoded.
Paul Bakker1a7550a2013-09-15 13:01:22 +020071 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020072int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
Paul Bakker1a7550a2013-09-15 13:01:22 +020073{
74 FILE *f;
75 long size;
76
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020077 PK_VALIDATE_RET(path != NULL);
78 PK_VALIDATE_RET(buf != NULL);
79 PK_VALIDATE_RET(n != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050080
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020081 if ((f = fopen(path, "rb")) == NULL)
82 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
Paul Bakker1a7550a2013-09-15 13:01:22 +020083
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020084 fseek(f, 0, SEEK_END);
85 if ((size = ftell(f)) == -1) {
86 fclose(f);
87 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
Paul Bakker1a7550a2013-09-15 13:01:22 +020088 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020089 fseek(f, 0, SEEK_SET);
Paul Bakker1a7550a2013-09-15 13:01:22 +020090
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020091 *n = (size_t)size;
Paul Bakker1a7550a2013-09-15 13:01:22 +020092
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020093 if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
94 fclose(f);
95 return MBEDTLS_ERR_PK_ALLOC_FAILED;
Paul Bakker1a7550a2013-09-15 13:01:22 +020096 }
97
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020098 if (fread(*buf, 1, *n, f) != *n) {
99 fclose(f);
Andres Amaya Garcia1f2666f2017-06-26 10:36:20 +0100100
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200101 mbedtls_platform_zeroize(*buf, *n);
102 mbedtls_free(*buf);
Andres Amaya Garcia1f2666f2017-06-26 10:36:20 +0100103
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200104 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200105 }
106
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200107 fclose(f);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200108
109 (*buf)[*n] = '\0';
110
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200111 if (strstr((const char *)*buf, "-----BEGIN ") != NULL)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200112 ++*n;
113
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200114 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200115}
116
117/*
118 * Load and parse a private key
119 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200120int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
121 const char *path,
122 const char *pwd,
123 int (*f_rng)(void *, unsigned char *, size_t),
124 void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200125{
Janos Follath24eed8d2019-11-22 13:21:35 +0000126 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200127 size_t n;
128 unsigned char *buf;
129
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200130 PK_VALIDATE_RET(ctx != NULL);
131 PK_VALIDATE_RET(path != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500132
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200133 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0)
134 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200135
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200136 if (pwd == NULL)
137 ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200138 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200139 ret = mbedtls_pk_parse_key(ctx, buf, n, (const unsigned char *)pwd,
140 strlen(pwd), f_rng, p_rng);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200141
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200142 mbedtls_platform_zeroize(buf, n);
143 mbedtls_free(buf);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200144
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200145 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200146}
147
148/*
149 * Load and parse a public key
150 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200151int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200152{
Janos Follath24eed8d2019-11-22 13:21:35 +0000153 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200154 size_t n;
155 unsigned char *buf;
156
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200157 PK_VALIDATE_RET(ctx != NULL);
158 PK_VALIDATE_RET(path != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500159
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200160 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0)
161 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200162
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200163 ret = mbedtls_pk_parse_public_key(ctx, buf, n);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200164
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200165 mbedtls_platform_zeroize(buf, n);
166 mbedtls_free(buf);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200167
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200168 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200169}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200170# endif /* MBEDTLS_FS_IO */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200171
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200172# if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
Paul Bakker1a7550a2013-09-15 13:01:22 +0200174 *
175 * ECParameters ::= CHOICE {
176 * namedCurve OBJECT IDENTIFIER
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100177 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200178 * -- implicitCurve NULL
Paul Bakker1a7550a2013-09-15 13:01:22 +0200179 * }
180 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200181static int pk_get_ecparams(unsigned char **p,
182 const unsigned char *end,
183 mbedtls_asn1_buf *params)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200184{
Janos Follath24eed8d2019-11-22 13:21:35 +0000185 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200186
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200187 if (end - *p < 1)
188 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
189 MBEDTLS_ERR_ASN1_OUT_OF_DATA));
Sanne Woudab2b29d52017-08-21 15:58:12 +0100190
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100191 /* Tag may be either OID or SEQUENCE */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200192 params->tag = **p;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200193 if (params->tag != MBEDTLS_ASN1_OID
194# if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
195 && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
196# endif
197 ) {
198 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
199 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG));
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100200 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200201
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200202 if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {
203 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100204 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200205
206 params->p = *p;
207 *p += params->len;
208
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200209 if (*p != end)
210 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
211 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200212
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200213 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200214}
215
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200216# if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200217/*
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100218 * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
219 * WARNING: the resulting group should only be used with
220 * pk_group_id_from_specified(), since its base point may not be set correctly
221 * if it was encoded compressed.
222 *
223 * SpecifiedECDomain ::= SEQUENCE {
224 * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
225 * fieldID FieldID {{FieldTypes}},
226 * curve Curve,
227 * base ECPoint,
228 * order INTEGER,
229 * cofactor INTEGER OPTIONAL,
230 * hash HashAlgorithm OPTIONAL,
231 * ...
232 * }
233 *
234 * We only support prime-field as field type, and ignore hash and cofactor.
235 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200236static int pk_group_from_specified(const mbedtls_asn1_buf *params,
237 mbedtls_ecp_group *grp)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100238{
Janos Follath24eed8d2019-11-22 13:21:35 +0000239 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100240 unsigned char *p = params->p;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200241 const unsigned char *const end = params->p + params->len;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100242 const unsigned char *end_field, *end_curve;
243 size_t len;
244 int ver;
245
246 /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200247 if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0)
248 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100249
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200250 if (ver < 1 || ver > 3)
251 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100252
253 /*
254 * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
255 * fieldType FIELD-ID.&id({IOSet}),
256 * parameters FIELD-ID.&Type({IOSet}{@fieldType})
257 * }
258 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200259 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
260 MBEDTLS_ASN1_CONSTRUCTED |
261 MBEDTLS_ASN1_SEQUENCE)) != 0)
262 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100263
264 end_field = p + len;
265
266 /*
267 * FIELD-ID ::= TYPE-IDENTIFIER
268 * FieldTypes FIELD-ID ::= {
269 * { Prime-p IDENTIFIED BY prime-field } |
270 * { Characteristic-two IDENTIFIED BY characteristic-two-field }
271 * }
272 * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
273 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200274 if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) !=
275 0)
276 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100277
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200278 if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) ||
279 memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) {
280 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100281 }
282
283 p += len;
284
285 /* Prime-p ::= INTEGER -- Field of size p. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200286 if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0)
287 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100288
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200289 grp->pbits = mbedtls_mpi_bitlen(&grp->P);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100290
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200291 if (p != end_field)
292 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
293 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH));
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100294
295 /*
296 * Curve ::= SEQUENCE {
297 * a FieldElement,
298 * b FieldElement,
299 * seed BIT STRING OPTIONAL
300 * -- Shall be present if used in SpecifiedECDomain
301 * -- with version equal to ecdpVer2 or ecdpVer3
302 * }
303 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200304 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
305 MBEDTLS_ASN1_CONSTRUCTED |
306 MBEDTLS_ASN1_SEQUENCE)) != 0)
307 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100308
309 end_curve = p + len;
310
311 /*
312 * FieldElement ::= OCTET STRING
313 * containing an integer in the case of a prime field
314 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200315 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len,
316 MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
317 (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) {
318 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100319 }
320
321 p += len;
322
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200323 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len,
324 MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
325 (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) {
326 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100327 }
328
329 p += len;
330
331 /* Ignore seed BIT STRING OPTIONAL */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200332 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len,
333 MBEDTLS_ASN1_BIT_STRING)) == 0)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100334 p += len;
335
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200336 if (p != end_curve)
337 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
338 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH));
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100339
340 /*
341 * ECPoint ::= OCTET STRING
342 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200343 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
344 MBEDTLS_ASN1_OCTET_STRING)) != 0)
345 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100346
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200347 if ((ret = mbedtls_ecp_point_read_binary(
348 grp, &grp->G, (const unsigned char *)p, len)) != 0) {
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100349 /*
350 * If we can't read the point because it's compressed, cheat by
351 * reading only the X coordinate and the parity bit of Y.
352 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200353 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
354 (p[0] != 0x02 && p[0] != 0x03) ||
355 len != mbedtls_mpi_size(&grp->P) + 1 ||
356 mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 ||
357 mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 ||
358 mbedtls_mpi_lset(&grp->G.Z, 1) != 0) {
359 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100360 }
361 }
362
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100363 p += len;
364
365 /*
366 * order INTEGER
367 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200368 if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0)
369 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100370
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200371 grp->nbits = mbedtls_mpi_bitlen(&grp->N);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100372
373 /*
374 * Allow optional elements by purposefully not enforcing p == end here.
375 */
376
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200377 return 0;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100378}
379
380/*
381 * Find the group id associated with an (almost filled) group as generated by
382 * pk_group_from_specified(), or return an error if unknown.
383 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200384static int pk_group_id_from_group(const mbedtls_ecp_group *grp,
385 mbedtls_ecp_group_id *grp_id)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100386{
Manuel Pégourié-Gonnard5b8c4092014-03-27 14:59:42 +0100387 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388 mbedtls_ecp_group ref;
389 const mbedtls_ecp_group_id *id;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100390
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200391 mbedtls_ecp_group_init(&ref);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100392
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200393 for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100394 /* Load the group associated to that id */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200395 mbedtls_ecp_group_free(&ref);
396 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id));
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100397
398 /* Compare to the group we were given, starting with easy tests */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200399 if (grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
400 mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 &&
401 mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 &&
402 mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 &&
403 mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 &&
404 mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 &&
405 mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 &&
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100406 /* For Y we may only know the parity bit, so compare only that */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200407 mbedtls_mpi_get_bit(&grp->G.Y, 0) ==
408 mbedtls_mpi_get_bit(&ref.G.Y, 0)) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100409 break;
410 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100411 }
412
413cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200414 mbedtls_ecp_group_free(&ref);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100415
416 *grp_id = *id;
417
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200418 if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100420
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200421 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100422}
423
424/*
425 * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
426 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200427static int pk_group_id_from_specified(const mbedtls_asn1_buf *params,
428 mbedtls_ecp_group_id *grp_id)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100429{
Janos Follath24eed8d2019-11-22 13:21:35 +0000430 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100432
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200433 mbedtls_ecp_group_init(&grp);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100434
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200435 if ((ret = pk_group_from_specified(params, &grp)) != 0)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100436 goto cleanup;
437
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200438 ret = pk_group_id_from_group(&grp, grp_id);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100439
440cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200441 mbedtls_ecp_group_free(&grp);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100442
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200443 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100444}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200445# endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100446
447/*
Paul Bakker1a7550a2013-09-15 13:01:22 +0200448 * Use EC parameters to initialise an EC group
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100449 *
450 * ECParameters ::= CHOICE {
451 * namedCurve OBJECT IDENTIFIER
452 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
453 * -- implicitCurve NULL
Paul Bakker1a7550a2013-09-15 13:01:22 +0200454 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200455static int pk_use_ecparams(const mbedtls_asn1_buf *params,
456 mbedtls_ecp_group *grp)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200457{
Janos Follath24eed8d2019-11-22 13:21:35 +0000458 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 mbedtls_ecp_group_id grp_id;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200460
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200461 if (params->tag == MBEDTLS_ASN1_OID) {
462 if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0)
463 return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
464 } else {
465# if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
466 if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0)
467 return ret;
468# else
469 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
470# endif
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100471 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200472
473 /*
474 * grp may already be initilialized; if so, make sure IDs match
475 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200476 if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id)
477 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200478
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200479 if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0)
480 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200481
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200482 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200483}
484
485/*
486 * EC public key is an EC point
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100487 *
488 * The caller is responsible for clearing the structure upon failure if
489 * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
Paul Bakker1a7550a2013-09-15 13:01:22 +0200491 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200492static int pk_get_ecpubkey(unsigned char **p,
493 const unsigned char *end,
494 mbedtls_ecp_keypair *key)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200495{
Janos Follath24eed8d2019-11-22 13:21:35 +0000496 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200497
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200498 if ((ret = mbedtls_ecp_point_read_binary(
499 &key->grp, &key->Q, (const unsigned char *)*p, end - *p)) == 0) {
500 ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200501 }
502
503 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 * We know mbedtls_ecp_point_read_binary consumed all bytes or failed
Paul Bakker1a7550a2013-09-15 13:01:22 +0200505 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200506 *p = (unsigned char *)end;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200507
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200508 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200509}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200510# endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200511
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200512# if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200513/*
514 * RSAPublicKey ::= SEQUENCE {
515 * modulus INTEGER, -- n
516 * publicExponent INTEGER -- e
517 * }
518 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200519static int pk_get_rsapubkey(unsigned char **p,
520 const unsigned char *end,
521 mbedtls_rsa_context *rsa)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200522{
Janos Follath24eed8d2019-11-22 13:21:35 +0000523 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200524 size_t len;
525
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200526 if ((ret = mbedtls_asn1_get_tag(
527 p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
528 0)
529 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200530
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200531 if (*p + len != end)
532 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
533 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200534
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100535 /* Import N */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200536 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0)
537 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200538
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200539 if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0, NULL, 0,
540 NULL, 0)) != 0)
541 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100542
543 *p += len;
544
545 /* Import E */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200546 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0)
547 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100548
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200549 if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
550 *p, len)) != 0)
551 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100552
553 *p += len;
554
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200555 if (mbedtls_rsa_complete(rsa) != 0 || mbedtls_rsa_check_pubkey(rsa) != 0) {
556 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
Hanno Becker895c5ab2018-01-05 08:08:09 +0000557 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100558
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200559 if (*p != end)
560 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
561 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200562
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200563 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200564}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200565# endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200566
567/* Get a PK algorithm identifier
568 *
569 * AlgorithmIdentifier ::= SEQUENCE {
570 * algorithm OBJECT IDENTIFIER,
571 * parameters ANY DEFINED BY algorithm OPTIONAL }
572 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200573static int pk_get_pk_alg(unsigned char **p,
574 const unsigned char *end,
575 mbedtls_pk_type_t *pk_alg,
576 mbedtls_asn1_buf *params)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200577{
Janos Follath24eed8d2019-11-22 13:21:35 +0000578 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 mbedtls_asn1_buf alg_oid;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200580
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200581 memset(params, 0, sizeof(mbedtls_asn1_buf));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200582
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200583 if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0)
584 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200585
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200586 if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0)
587 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200588
589 /*
590 * No parameters with RSA (only for EC)
591 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200592 if (*pk_alg == MBEDTLS_PK_RSA &&
593 ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) ||
594 params->len != 0)) {
595 return MBEDTLS_ERR_PK_INVALID_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200596 }
597
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200598 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200599}
600
601/*
602 * SubjectPublicKeyInfo ::= SEQUENCE {
603 * algorithm AlgorithmIdentifier,
604 * subjectPublicKey BIT STRING }
605 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200606int mbedtls_pk_parse_subpubkey(unsigned char **p,
607 const unsigned char *end,
608 mbedtls_pk_context *pk)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200609{
Janos Follath24eed8d2019-11-22 13:21:35 +0000610 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200611 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 mbedtls_asn1_buf alg_params;
613 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
614 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200615
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200616 PK_VALIDATE_RET(p != NULL);
617 PK_VALIDATE_RET(*p != NULL);
618 PK_VALIDATE_RET(end != NULL);
619 PK_VALIDATE_RET(pk != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500620
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200621 if ((ret = mbedtls_asn1_get_tag(
622 p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
623 0) {
624 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200625 }
626
627 end = *p + len;
628
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200629 if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0)
630 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200631
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200632 if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0)
633 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200634
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200635 if (*p + len != end)
636 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
637 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200638
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200639 if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL)
640 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200641
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200642 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0)
643 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200644
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200645# if defined(MBEDTLS_RSA_C)
646 if (pk_alg == MBEDTLS_PK_RSA) {
647 ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200648 } else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200649# endif /* MBEDTLS_RSA_C */
650# if defined(MBEDTLS_ECP_C)
651 if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
652 ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp);
653 if (ret == 0)
654 ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200655 } else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200656# endif /* MBEDTLS_ECP_C */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200658
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200659 if (ret == 0 && *p != end)
660 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
661 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200662
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200663 if (ret != 0)
664 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200665
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200666 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200667}
668
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200669# if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200670/*
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100671 * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
672 *
673 * The value zero is:
674 * - never a valid value for an RSA parameter
675 * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
676 *
677 * Since values can't be omitted in PKCS#1, passing a zero value to
678 * rsa_complete() would be incorrect, so reject zero values early.
679 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200680static int asn1_get_nonzero_mpi(unsigned char **p,
681 const unsigned char *end,
682 mbedtls_mpi *X)
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100683{
684 int ret;
685
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200686 ret = mbedtls_asn1_get_mpi(p, end, X);
687 if (ret != 0)
688 return ret;
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100689
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200690 if (mbedtls_mpi_cmp_int(X, 0) == 0)
691 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100692
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200693 return 0;
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100694}
695
696/*
Paul Bakker1a7550a2013-09-15 13:01:22 +0200697 * Parse a PKCS#1 encoded private RSA key
698 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200699static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa,
700 const unsigned char *key,
701 size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200702{
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100703 int ret, version;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200704 size_t len;
705 unsigned char *p, *end;
706
Hanno Beckerefa14e82017-10-11 19:45:19 +0100707 mbedtls_mpi T;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200708 mbedtls_mpi_init(&T);
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100709
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200710 p = (unsigned char *)key;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200711 end = p + keylen;
712
713 /*
714 * This function parses the RSAPrivateKey (PKCS#1)
715 *
716 * RSAPrivateKey ::= SEQUENCE {
717 * version Version,
718 * modulus INTEGER, -- n
719 * publicExponent INTEGER, -- e
720 * privateExponent INTEGER, -- d
721 * prime1 INTEGER, -- p
722 * prime2 INTEGER, -- q
723 * exponent1 INTEGER, -- d mod (p-1)
724 * exponent2 INTEGER, -- d mod (q-1)
725 * coefficient INTEGER, -- (inverse of q) mod p
726 * otherPrimeInfos OtherPrimeInfos OPTIONAL
727 * }
728 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200729 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
730 MBEDTLS_ASN1_CONSTRUCTED |
731 MBEDTLS_ASN1_SEQUENCE)) != 0) {
732 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200733 }
734
735 end = p + len;
736
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200737 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
738 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200739 }
740
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200741 if (version != 0) {
742 return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200743 }
744
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100745 /* Import N */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200746 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
747 (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, NULL, NULL)) != 0)
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100748 goto cleanup;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200749
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100750 /* Import E */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200751 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
752 (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, NULL, &T)) != 0)
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100753 goto cleanup;
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100754
755 /* Import D */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200756 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
757 (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, &T, NULL)) != 0)
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100758 goto cleanup;
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100759
760 /* Import P */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200761 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
762 (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, NULL, NULL)) != 0)
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100763 goto cleanup;
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100764
765 /* Import Q */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200766 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
767 (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, NULL, NULL)) != 0)
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100768 goto cleanup;
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100769
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200770# if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
Jack Lloyd8c2631b2020-01-23 17:23:52 -0500771 /*
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200772 * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
773 * that they can be easily recomputed from D, P and Q. However by
774 * parsing them from the PKCS1 structure it is possible to avoid
775 * recalculating them which both reduces the overhead of loading
776 * RSA private keys into memory and also avoids side channels which
777 * can arise when computing those values, since all of D, P, and Q
778 * are secret. See https://eprint.iacr.org/2020/055 for a
779 * description of one such attack.
780 */
Jack Lloyd8c2631b2020-01-23 17:23:52 -0500781
Jack Lloyd80cc8112020-01-22 17:34:29 -0500782 /* Import DP */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200783 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
784 (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0)
785 goto cleanup;
Jack Lloyd80cc8112020-01-22 17:34:29 -0500786
787 /* Import DQ */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200788 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
789 (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0)
790 goto cleanup;
Jack Lloyd80cc8112020-01-22 17:34:29 -0500791
792 /* Import QP */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200793 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
794 (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0)
795 goto cleanup;
Jack Lloyd2e9eef42020-01-28 14:43:52 -0500796
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200797# else
Jack Lloyd60239752020-01-27 17:53:36 -0500798 /* Verify existance of the CRT params */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200799 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
800 (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
801 (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0)
802 goto cleanup;
803# endif
Jack Lloyd80cc8112020-01-22 17:34:29 -0500804
Manuel Pégourié-Gonnardc4226792020-02-14 11:28:47 +0100805 /* rsa_complete() doesn't complete anything with the default
806 * implementation but is still called:
807 * - for the benefit of alternative implementation that may want to
808 * pre-compute stuff beyond what's provided (eg Montgomery factors)
809 * - as is also sanity-checks the key
810 *
811 * Furthermore, we also check the public part for consistency with
812 * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
813 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200814 if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
815 (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100816 goto cleanup;
Manuel Pégourié-Gonnardc4226792020-02-14 11:28:47 +0100817 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100818
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200819 if (p != end) {
820 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
821 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200822 }
823
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100824cleanup:
825
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200826 mbedtls_mpi_free(&T);
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100827
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200828 if (ret != 0) {
Hanno Beckerefa14e82017-10-11 19:45:19 +0100829 /* Wrap error code if it's coming from a lower level */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200830 if ((ret & 0xff80) == 0)
831 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100832 else
833 ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
834
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200835 mbedtls_rsa_free(rsa);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200836 }
837
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200838 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200839}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200840# endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200841
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200842# if defined(MBEDTLS_ECP_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200843/*
844 * Parse a SEC1 encoded private EC key
845 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200846static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
847 const unsigned char *key,
848 size_t keylen,
849 int (*f_rng)(void *, unsigned char *, size_t),
850 void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200851{
Janos Follath24eed8d2019-11-22 13:21:35 +0000852 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100853 int version, pubkey_done;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200854 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200855 mbedtls_asn1_buf params;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200856 unsigned char *p = (unsigned char *)key;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200857 unsigned char *end = p + keylen;
858 unsigned char *end2;
859
860 /*
861 * RFC 5915, or SEC1 Appendix C.4
862 *
863 * ECPrivateKey ::= SEQUENCE {
864 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
865 * privateKey OCTET STRING,
866 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
867 * publicKey [1] BIT STRING OPTIONAL
868 * }
869 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200870 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
871 MBEDTLS_ASN1_CONSTRUCTED |
872 MBEDTLS_ASN1_SEQUENCE)) != 0) {
873 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200874 }
875
876 end = p + len;
877
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200878 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0)
879 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200880
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200881 if (version != 1)
882 return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200883
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200884 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
885 MBEDTLS_ASN1_OCTET_STRING)) != 0)
886 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200887
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200888 if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) {
889 mbedtls_ecp_keypair_free(eck);
890 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200891 }
892
893 p += len;
894
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200895 pubkey_done = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200896 if (p != end) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200897 /*
898 * Is 'parameters' present?
899 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200900 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
901 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
902 MBEDTLS_ASN1_CONSTRUCTED | 0)) ==
903 0) {
904 if ((ret = pk_get_ecparams(&p, p + len, &params)) != 0 ||
905 (ret = pk_use_ecparams(&params, &eck->grp)) != 0) {
906 mbedtls_ecp_keypair_free(eck);
907 return ret;
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200908 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200909 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
910 mbedtls_ecp_keypair_free(eck);
911 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100912 }
Jethro Beekmand2df9362018-02-16 13:11:04 -0800913 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200914
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200915 if (p != end) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200916 /*
917 * Is 'publickey' present? If not, or if we can't read it (eg because it
918 * is compressed), create it from the private key.
919 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200920 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
921 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
922 MBEDTLS_ASN1_CONSTRUCTED | 1)) ==
923 0) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200924 end2 = p + len;
925
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200926 if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0)
927 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
928 ret);
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200929
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200930 if (p + len != end2)
931 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
932 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH));
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200933
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200934 if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0)
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200935 pubkey_done = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200936 else {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200937 /*
938 * The only acceptable failure mode of pk_get_ecpubkey() above
939 * is if the point format is not recognized.
940 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200941 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE)
942 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200943 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200944 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
945 mbedtls_ecp_keypair_free(eck);
946 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200947 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200948 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100949
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200950 if (!pubkey_done &&
951 (ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng,
952 p_rng)) != 0) {
953 mbedtls_ecp_keypair_free(eck);
954 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardff29f9c2013-09-18 16:13:02 +0200955 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200956
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200957 if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) {
958 mbedtls_ecp_keypair_free(eck);
959 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200960 }
961
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200962 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200963}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200964# endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200965
966/*
967 * Parse an unencrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +0100968 *
969 * Notes:
970 *
971 * - This function does not own the key buffer. It is the
972 * responsibility of the caller to take care of zeroizing
973 * and freeing it after use.
974 *
975 * - The function is responsible for freeing the provided
976 * PK context on failure.
977 *
Paul Bakker1a7550a2013-09-15 13:01:22 +0200978 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200979static int pk_parse_key_pkcs8_unencrypted_der(mbedtls_pk_context *pk,
980 const unsigned char *key,
981 size_t keylen,
982 int (*f_rng)(void *,
983 unsigned char *,
984 size_t),
985 void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200986{
987 int ret, version;
988 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989 mbedtls_asn1_buf params;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200990 unsigned char *p = (unsigned char *)key;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200991 unsigned char *end = p + keylen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
993 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200994
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200995# if !defined(MBEDTLS_ECP_C)
996 (void)f_rng;
997 (void)p_rng;
998# endif
Manuel Pégourié-Gonnard609ab642021-06-16 14:29:11 +0200999
Paul Bakker1a7550a2013-09-15 13:01:22 +02001000 /*
Hanno Becker9c6cb382017-09-05 10:08:01 +01001001 * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001002 *
1003 * PrivateKeyInfo ::= SEQUENCE {
1004 * version Version,
1005 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
1006 * privateKey PrivateKey,
1007 * attributes [0] IMPLICIT Attributes OPTIONAL }
1008 *
1009 * Version ::= INTEGER
1010 * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
1011 * PrivateKey ::= OCTET STRING
1012 *
1013 * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
1014 */
1015
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001016 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1017 MBEDTLS_ASN1_CONSTRUCTED |
1018 MBEDTLS_ASN1_SEQUENCE)) != 0) {
1019 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001020 }
1021
1022 end = p + len;
1023
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001024 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0)
1025 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001026
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001027 if (version != 0)
1028 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001029
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001030 if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params)) != 0) {
1031 return ret;
Chris Jonesfdb588b2021-04-14 18:15:24 +01001032 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001033
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001034 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1035 MBEDTLS_ASN1_OCTET_STRING)) != 0)
1036 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001037
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001038 if (len < 1)
1039 return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
1040 MBEDTLS_ERR_ASN1_OUT_OF_DATA));
Paul Bakker1a7550a2013-09-15 13:01:22 +02001041
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001042 if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL)
1043 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001044
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001045 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0)
1046 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001047
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001048# if defined(MBEDTLS_RSA_C)
1049 if (pk_alg == MBEDTLS_PK_RSA) {
1050 if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) {
1051 mbedtls_pk_free(pk);
1052 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001053 }
1054 } else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001055# endif /* MBEDTLS_RSA_C */
1056# if defined(MBEDTLS_ECP_C)
1057 if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
1058 if ((ret = pk_use_ecparams(&params, &mbedtls_pk_ec(*pk)->grp)) != 0 ||
1059 (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len, f_rng,
1060 p_rng)) != 0) {
1061 mbedtls_pk_free(pk);
1062 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001063 }
1064 } else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001065# endif /* MBEDTLS_ECP_C */
1066 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001067
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001068 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001069}
1070
1071/*
1072 * Parse an encrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +01001073 *
1074 * To save space, the decryption happens in-place on the given key buffer.
1075 * Also, while this function may modify the keybuffer, it doesn't own it,
1076 * and instead it is the responsibility of the caller to zeroize and properly
1077 * free it after use.
1078 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001079 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001080# if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
1081static int
1082pk_parse_key_pkcs8_encrypted_der(mbedtls_pk_context *pk,
1083 unsigned char *key,
1084 size_t keylen,
1085 const unsigned char *pwd,
1086 size_t pwdlen,
1087 int (*f_rng)(void *, unsigned char *, size_t),
1088 void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001089{
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001090 int ret, decrypted = 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001091 size_t len;
Hanno Beckerfab35692017-08-25 13:38:26 +01001092 unsigned char *buf;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001093 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 mbedtls_asn1_buf pbe_alg_oid, pbe_params;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001095# if defined(MBEDTLS_PKCS12_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096 mbedtls_cipher_type_t cipher_alg;
1097 mbedtls_md_type_t md_alg;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001098# endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001099
Hanno Becker2aa80a72017-09-07 15:28:45 +01001100 p = key;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001101 end = p + keylen;
1102
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001103 if (pwdlen == 0)
1104 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001105
1106 /*
Hanno Beckerf04111f2017-09-29 19:18:42 +01001107 * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001108 *
1109 * EncryptedPrivateKeyInfo ::= SEQUENCE {
1110 * encryptionAlgorithm EncryptionAlgorithmIdentifier,
1111 * encryptedData EncryptedData
1112 * }
1113 *
1114 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
1115 *
1116 * EncryptedData ::= OCTET STRING
1117 *
1118 * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
Hanno Beckerb8d16572017-09-07 15:29:01 +01001119 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001120 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001121 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1122 MBEDTLS_ASN1_CONSTRUCTED |
1123 MBEDTLS_ASN1_SEQUENCE)) != 0) {
1124 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001125 }
1126
1127 end = p + len;
1128
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001129 if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0)
1130 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001131
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001132 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1133 MBEDTLS_ASN1_OCTET_STRING)) != 0)
1134 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001135
Hanno Beckerfab35692017-08-25 13:38:26 +01001136 buf = p;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001137
1138 /*
Hanno Beckerb8d16572017-09-07 15:29:01 +01001139 * Decrypt EncryptedData with appropriate PBE
Paul Bakker1a7550a2013-09-15 13:01:22 +02001140 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001141# if defined(MBEDTLS_PKCS12_C)
1142 if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) ==
1143 0) {
1144 if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
1145 cipher_alg, md_alg, pwd, pwdlen, p, len,
1146 buf)) != 0) {
1147 if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH)
1148 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001149
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001150 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001151 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001152
1153 decrypted = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001154 } else
1155# endif /* MBEDTLS_PKCS12_C */
1156# if defined(MBEDTLS_PKCS5_C)
1157 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
1158 if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd,
1159 pwdlen, p, len, buf)) != 0) {
1160 if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH)
1161 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001162
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001163 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001164 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001165
1166 decrypted = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001167 } else
1168# endif /* MBEDTLS_PKCS5_C */
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +02001169 {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001170 ((void)pwd);
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +02001171 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001172
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001173 if (decrypted == 0)
1174 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001175
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001176 return pk_parse_key_pkcs8_unencrypted_der(pk, buf, len, f_rng, p_rng);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001177}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001178# endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001179
1180/*
1181 * Parse a private key
1182 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001183int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
1184 const unsigned char *key,
1185 size_t keylen,
1186 const unsigned char *pwd,
1187 size_t pwdlen,
1188 int (*f_rng)(void *, unsigned char *, size_t),
1189 void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001190{
Janos Follath24eed8d2019-11-22 13:21:35 +00001191 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 const mbedtls_pk_info_t *pk_info;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001193# if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001194 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195 mbedtls_pem_context pem;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001196# endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001197
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001198 PK_VALIDATE_RET(pk != NULL);
1199 if (keylen == 0)
1200 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1201 PK_VALIDATE_RET(key != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001202
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001203# if defined(MBEDTLS_PEM_PARSE_C)
1204 mbedtls_pem_init(&pem);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001205
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001206# if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001207 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001208 if (key[keylen - 1] != '\0')
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001209 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1210 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001211 ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN RSA PRIVATE KEY-----",
1212 "-----END RSA PRIVATE KEY-----", key, pwd,
1213 pwdlen, &len);
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001214
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001215 if (ret == 0) {
1216 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1217 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1218 (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), pem.buf,
1219 pem.buflen)) != 0) {
1220 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001221 }
1222
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001223 mbedtls_pem_free(&pem);
1224 return ret;
1225 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH)
1226 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1227 else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED)
1228 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1229 else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT)
1230 return ret;
1231# endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001232
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001233# if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001234 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001235 if (key[keylen - 1] != '\0')
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001236 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1237 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001238 ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN EC PRIVATE KEY-----",
1239 "-----END EC PRIVATE KEY-----", key, pwd,
1240 pwdlen, &len);
1241 if (ret == 0) {
1242 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001243
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001244 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1245 (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), pem.buf,
1246 pem.buflen, f_rng, p_rng)) != 0) {
1247 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001248 }
1249
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001250 mbedtls_pem_free(&pem);
1251 return ret;
1252 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH)
1253 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1254 else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED)
1255 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1256 else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT)
1257 return ret;
1258# endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001259
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001260 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001261 if (key[keylen - 1] != '\0')
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001262 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1263 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001264 ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN PRIVATE KEY-----",
1265 "-----END PRIVATE KEY-----", key, NULL, 0,
1266 &len);
1267 if (ret == 0) {
1268 if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, pem.buf, pem.buflen,
1269 f_rng, p_rng)) != 0) {
1270 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001271 }
1272
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001273 mbedtls_pem_free(&pem);
1274 return ret;
1275 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT)
1276 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001277
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001278# if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001279 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001280 if (key[keylen - 1] != '\0')
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001281 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1282 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001283 ret = mbedtls_pem_read_buffer(&pem,
1284 "-----BEGIN ENCRYPTED PRIVATE KEY-----",
1285 "-----END ENCRYPTED PRIVATE KEY-----",
1286 key, NULL, 0, &len);
1287 if (ret == 0) {
1288 if ((ret = pk_parse_key_pkcs8_encrypted_der(
1289 pk, pem.buf, pem.buflen, pwd, pwdlen, f_rng, p_rng)) != 0) {
1290 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001291 }
1292
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001293 mbedtls_pem_free(&pem);
1294 return ret;
1295 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT)
1296 return ret;
1297# endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
1298# else
1299 ((void)pwd);
1300 ((void)pwdlen);
1301# endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001302
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001303 /*
1304 * At this point we only know it's not a PEM formatted key. Could be any
1305 * of the known DER encoded private key formats
1306 *
1307 * We try the different DER format parsers to see if one passes without
1308 * error
1309 */
1310# if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001311 {
Hanno Beckerfab35692017-08-25 13:38:26 +01001312 unsigned char *key_copy;
1313
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001314 if ((key_copy = mbedtls_calloc(1, keylen)) == NULL)
1315 return MBEDTLS_ERR_PK_ALLOC_FAILED;
Hanno Beckerfab35692017-08-25 13:38:26 +01001316
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001317 memcpy(key_copy, key, keylen);
Hanno Beckerfab35692017-08-25 13:38:26 +01001318
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001319 ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, pwd,
1320 pwdlen, f_rng, p_rng);
Hanno Beckerfab35692017-08-25 13:38:26 +01001321
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001322 mbedtls_platform_zeroize(key_copy, keylen);
1323 mbedtls_free(key_copy);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001324 }
1325
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001326 if (ret == 0)
1327 return 0;
Hanno Beckerfab35692017-08-25 13:38:26 +01001328
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001329 mbedtls_pk_free(pk);
1330 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001331
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001332 if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {
1333 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001334 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001335# endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001336
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001337 if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng,
1338 p_rng)) == 0) {
1339 return 0;
Manuel Pégourié-Gonnard84dea012021-06-15 11:29:26 +02001340 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001341
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001342 mbedtls_pk_free(pk);
1343 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001344
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001345# if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001346
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001347 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1348 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1349 pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
1350 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001351 }
1352
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001353 mbedtls_pk_free(pk);
1354 mbedtls_pk_init(pk);
1355# endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001356
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001357# if defined(MBEDTLS_ECP_C)
1358 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1359 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1360 pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), key, keylen, f_rng, p_rng) ==
1361 0) {
1362 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001363 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001364 mbedtls_pk_free(pk);
1365# endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001366
Hanno Becker780f0a42018-10-10 11:23:33 +01001367 /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
1368 * it is ok to leave the PK context initialized but not
1369 * freed: It is the caller's responsibility to call pk_init()
1370 * before calling this function, and to call pk_free()
1371 * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
1372 * isn't, this leads to mbedtls_pk_free() being called
1373 * twice, once here and once by the caller, but this is
1374 * also ok and in line with the mbedtls_pk_free() calls
1375 * on failed PEM parsing attempts. */
1376
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001377 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001378}
1379
1380/*
1381 * Parse a public key
1382 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001383int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
1384 const unsigned char *key,
1385 size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001386{
Janos Follath24eed8d2019-11-22 13:21:35 +00001387 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001388 unsigned char *p;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001389# if defined(MBEDTLS_RSA_C)
Ron Eldor5472d432017-10-17 09:49:00 +03001390 const mbedtls_pk_info_t *pk_info;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001391# endif
1392# if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001393 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 mbedtls_pem_context pem;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001395# endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001396
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001397 PK_VALIDATE_RET(ctx != NULL);
1398 if (keylen == 0)
1399 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1400 PK_VALIDATE_RET(key != NULL || keylen == 0);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001401
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001402# if defined(MBEDTLS_PEM_PARSE_C)
1403 mbedtls_pem_init(&pem);
1404# if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001405 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001406 if (key[keylen - 1] != '\0')
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001407 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1408 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001409 ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN RSA PUBLIC KEY-----",
1410 "-----END RSA PUBLIC KEY-----", key, NULL,
1411 0, &len);
Ron Eldord0c56de2017-10-10 17:03:08 +03001412
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001413 if (ret == 0) {
Ron Eldor84df1ae2017-10-16 17:11:52 +03001414 p = pem.buf;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001415 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL)
1416 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Ron Eldord0c56de2017-10-10 17:03:08 +03001417
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001418 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0)
1419 return ret;
Ron Eldord0c56de2017-10-10 17:03:08 +03001420
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001421 if ((ret = pk_get_rsapubkey(&p, p + pem.buflen,
1422 mbedtls_pk_rsa(*ctx))) != 0)
1423 mbedtls_pk_free(ctx);
Ron Eldor3f2da842017-10-17 15:50:30 +03001424
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001425 mbedtls_pem_free(&pem);
1426 return ret;
1427 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1428 mbedtls_pem_free(&pem);
1429 return ret;
Ron Eldord0c56de2017-10-10 17:03:08 +03001430 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001431# endif /* MBEDTLS_RSA_C */
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001432
1433 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001434 if (key[keylen - 1] != '\0')
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001435 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1436 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001437 ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN PUBLIC KEY-----",
1438 "-----END PUBLIC KEY-----", key, NULL, 0,
1439 &len);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001440
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001441 if (ret == 0) {
Paul Bakker1a7550a2013-09-15 13:01:22 +02001442 /*
1443 * Was PEM encoded
1444 */
Ron Eldor40b14a82017-10-16 19:30:00 +03001445 p = pem.buf;
1446
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001447 ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
1448 mbedtls_pem_free(&pem);
1449 return ret;
1450 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1451 mbedtls_pem_free(&pem);
1452 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001453 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001454 mbedtls_pem_free(&pem);
1455# endif /* MBEDTLS_PEM_PARSE_C */
Ron Eldor40b14a82017-10-16 19:30:00 +03001456
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001457# if defined(MBEDTLS_RSA_C)
1458 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL)
1459 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Ron Eldor40b14a82017-10-16 19:30:00 +03001460
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001461 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0)
1462 return ret;
Ron Eldor40b14a82017-10-16 19:30:00 +03001463
Ron Eldor9566ff72018-02-07 18:59:41 +02001464 p = (unsigned char *)key;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001465 ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
1466 if (ret == 0) {
1467 return ret;
Ron Eldor40b14a82017-10-16 19:30:00 +03001468 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001469 mbedtls_pk_free(ctx);
1470 if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
1471 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
1472 return ret;
Ron Eldor40b14a82017-10-16 19:30:00 +03001473 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001474# endif /* MBEDTLS_RSA_C */
1475 p = (unsigned char *)key;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001476
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001477 ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001478
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02001479 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001480}
1481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482#endif /* MBEDTLS_PK_PARSE_C */