blob: 76fe0c81e476da9bd083a97b07ce3d25b91ff100 [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
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000024#include "mbedtls/pk.h"
25#include "mbedtls/asn1.h"
26#include "mbedtls/oid.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050027#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000028#include "mbedtls/error.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020029
Rich Evans00ab4702015-02-06 13:43:58 +000030#include <string.h>
31
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/rsa.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020034#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/ecp.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020037#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_ECDSA_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/ecdsa.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020040#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000042#include "mbedtls/pem.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020043#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/pkcs5.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020046#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#if defined(MBEDTLS_PKCS12_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000048#include "mbedtls/pkcs12.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020049#endif
50
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000051#include "mbedtls/platform.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020052
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050053/* Parameter validation macros based on platform_util.h */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010054#define PK_VALIDATE_RET(cond) \
55 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA)
56#define PK_VALIDATE(cond) \
57 MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050058
Gilles Peskine832f3492017-11-30 11:42:12 +010059#if defined(MBEDTLS_FS_IO)
Paul Bakker1a7550a2013-09-15 13:01:22 +020060/*
61 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +020062 *
63 * The file is expected to contain either PEM or DER encoded data.
64 * A terminating null byte is always appended. It is included in the announced
65 * length only if the data looks like it is PEM encoded.
Paul Bakker1a7550a2013-09-15 13:01:22 +020066 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
Paul Bakker1a7550a2013-09-15 13:01:22 +020068{
69 FILE *f;
70 long size;
71
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010072 PK_VALIDATE_RET(path != NULL);
73 PK_VALIDATE_RET(buf != NULL);
74 PK_VALIDATE_RET(n != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050075
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010076 if ((f = fopen(path, "rb")) == NULL) {
77 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
Paul Bakker1a7550a2013-09-15 13:01:22 +020078 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010079
80 fseek(f, 0, SEEK_END);
81 if ((size = ftell(f)) == -1) {
82 fclose(f);
83 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
84 }
85 fseek(f, 0, SEEK_SET);
Paul Bakker1a7550a2013-09-15 13:01:22 +020086
87 *n = (size_t) size;
88
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010089 if (*n + 1 == 0 ||
90 (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
91 fclose(f);
92 return MBEDTLS_ERR_PK_ALLOC_FAILED;
Paul Bakker1a7550a2013-09-15 13:01:22 +020093 }
94
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010095 if (fread(*buf, 1, *n, f) != *n) {
96 fclose(f);
Andres Amaya Garcia1f2666f2017-06-26 10:36:20 +010097
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010098 mbedtls_platform_zeroize(*buf, *n);
99 mbedtls_free(*buf);
Andres Amaya Garcia1f2666f2017-06-26 10:36:20 +0100100
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100101 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200102 }
103
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100104 fclose(f);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200105
106 (*buf)[*n] = '\0';
107
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100108 if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200109 ++*n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100110 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200111
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100112 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200113}
114
115/*
116 * Load and parse a private key
117 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100118int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
119 const char *path, const char *pwd)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200120{
Janos Follath24eed8d2019-11-22 13:21:35 +0000121 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200122 size_t n;
123 unsigned char *buf;
124
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100125 PK_VALIDATE_RET(ctx != NULL);
126 PK_VALIDATE_RET(path != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500127
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100128 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
129 return ret;
130 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200131
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100132 if (pwd == NULL) {
133 ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0);
134 } else {
135 ret = mbedtls_pk_parse_key(ctx, buf, n,
136 (const unsigned char *) pwd, strlen(pwd));
137 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200138
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139 mbedtls_platform_zeroize(buf, n);
140 mbedtls_free(buf);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200141
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100142 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200143}
144
145/*
146 * Load and parse a public key
147 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100148int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200149{
Janos Follath24eed8d2019-11-22 13:21:35 +0000150 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200151 size_t n;
152 unsigned char *buf;
153
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100154 PK_VALIDATE_RET(ctx != NULL);
155 PK_VALIDATE_RET(path != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500156
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100157 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
158 return ret;
159 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200160
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100161 ret = mbedtls_pk_parse_public_key(ctx, buf, n);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200162
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100163 mbedtls_platform_zeroize(buf, n);
164 mbedtls_free(buf);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200165
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200167}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168#endif /* MBEDTLS_FS_IO */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170#if defined(MBEDTLS_ECP_C)
171/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
Paul Bakker1a7550a2013-09-15 13:01:22 +0200172 *
173 * ECParameters ::= CHOICE {
174 * namedCurve OBJECT IDENTIFIER
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100175 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200176 * -- implicitCurve NULL
Paul Bakker1a7550a2013-09-15 13:01:22 +0200177 * }
178 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100179static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
180 mbedtls_asn1_buf *params)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200181{
Janos Follath24eed8d2019-11-22 13:21:35 +0000182 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200183
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100184 if (end - *p < 1) {
185 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
186 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
187 }
Sanne Woudab2b29d52017-08-21 15:58:12 +0100188
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100189 /* Tag may be either OID or SEQUENCE */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200190 params->tag = **p;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100191 if (params->tag != MBEDTLS_ASN1_OID
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100193 && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
Manuel Pégourié-Gonnard6fac3512014-03-19 16:39:52 +0100194#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100195 ) {
196 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
197 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100198 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200199
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200 if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {
201 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100202 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200203
204 params->p = *p;
205 *p += params->len;
206
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100207 if (*p != end) {
208 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
209 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
210 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200211
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100212 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200213}
214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200216/*
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100217 * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
218 * WARNING: the resulting group should only be used with
219 * pk_group_id_from_specified(), since its base point may not be set correctly
220 * if it was encoded compressed.
221 *
222 * SpecifiedECDomain ::= SEQUENCE {
223 * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
224 * fieldID FieldID {{FieldTypes}},
225 * curve Curve,
226 * base ECPoint,
227 * order INTEGER,
228 * cofactor INTEGER OPTIONAL,
229 * hash HashAlgorithm OPTIONAL,
230 * ...
231 * }
232 *
233 * We only support prime-field as field type, and ignore hash and cofactor.
234 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100235static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100236{
Janos Follath24eed8d2019-11-22 13:21:35 +0000237 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100238 unsigned char *p = params->p;
239 const unsigned char * const end = params->p + params->len;
240 const unsigned char *end_field, *end_curve;
241 size_t len;
242 int ver;
243
244 /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100245 if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) {
246 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
247 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100248
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100249 if (ver < 1 || ver > 3) {
250 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
251 }
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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100259 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
260 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
261 return ret;
262 }
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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100274 if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) {
275 return ret;
276 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100277
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100278 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. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286 if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) {
287 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
288 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100289
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100290 grp->pbits = mbedtls_mpi_bitlen(&grp->P);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100291
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100292 if (p != end_field) {
293 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
294 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
295 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100296
297 /*
298 * Curve ::= SEQUENCE {
299 * a FieldElement,
300 * b FieldElement,
301 * seed BIT STRING OPTIONAL
302 * -- Shall be present if used in SpecifiedECDomain
303 * -- with version equal to ecdpVer2 or ecdpVer3
304 * }
305 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
307 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
308 return ret;
309 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100310
311 end_curve = p + len;
312
313 /*
314 * FieldElement ::= OCTET STRING
315 * containing an integer in the case of a prime field
316 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100317 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
318 (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) {
319 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100320 }
321
322 p += len;
323
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100324 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100332 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100333 p += len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100334 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100335
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100336 if (p != end_curve) {
337 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
338 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
339 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100340
341 /*
342 * ECPoint ::= OCTET STRING
343 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
345 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
346 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100347
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100348 if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G,
349 (const unsigned char *) p, len)) != 0) {
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100350 /*
351 * If we can't read the point because it's compressed, cheat by
352 * reading only the X coordinate and the parity bit of Y.
353 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100354 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
355 (p[0] != 0x02 && p[0] != 0x03) ||
356 len != mbedtls_mpi_size(&grp->P) + 1 ||
357 mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 ||
358 mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 ||
359 mbedtls_mpi_lset(&grp->G.Z, 1) != 0) {
360 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100361 }
362 }
363
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100364 p += len;
365
366 /*
367 * order INTEGER
368 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100369 if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) {
370 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
371 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100372
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100373 grp->nbits = mbedtls_mpi_bitlen(&grp->N);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100374
375 /*
376 * Allow optional elements by purposefully not enforcing p == end here.
377 */
378
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100379 return 0;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100380}
381
382/*
383 * Find the group id associated with an (almost filled) group as generated by
384 * pk_group_from_specified(), or return an error if unknown.
385 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100386static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100387{
Manuel Pégourié-Gonnard5b8c4092014-03-27 14:59:42 +0100388 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 mbedtls_ecp_group ref;
390 const mbedtls_ecp_group_id *id;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100391
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100392 mbedtls_ecp_group_init(&ref);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100393
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100394 for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100395 /* Load the group associated to that id */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100396 mbedtls_ecp_group_free(&ref);
397 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id));
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100398
399 /* Compare to the group we were given, starting with easy tests */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100400 if (grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
401 mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 &&
402 mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 &&
403 mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 &&
404 mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 &&
405 mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 &&
406 mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 &&
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100407 /* For Y we may only know the parity bit, so compare only that */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100408 mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100409 break;
410 }
411
412 }
413
414cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100415 mbedtls_ecp_group_free(&ref);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100416
417 *grp_id = *id;
418
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100419 if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100421 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100422
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100423 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100424}
425
426/*
427 * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
428 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100429static int pk_group_id_from_specified(const mbedtls_asn1_buf *params,
430 mbedtls_ecp_group_id *grp_id)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100431{
Janos Follath24eed8d2019-11-22 13:21:35 +0000432 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100434
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100435 mbedtls_ecp_group_init(&grp);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100436
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437 if ((ret = pk_group_from_specified(params, &grp)) != 0) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100438 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100439 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100440
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100441 ret = pk_group_id_from_group(&grp, grp_id);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100442
443cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100444 mbedtls_ecp_group_free(&grp);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100445
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100446 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100447}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100449
450/*
Paul Bakker1a7550a2013-09-15 13:01:22 +0200451 * Use EC parameters to initialise an EC group
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100452 *
453 * ECParameters ::= CHOICE {
454 * namedCurve OBJECT IDENTIFIER
455 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
456 * -- implicitCurve NULL
Paul Bakker1a7550a2013-09-15 13:01:22 +0200457 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100458static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200459{
Janos Follath24eed8d2019-11-22 13:21:35 +0000460 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 mbedtls_ecp_group_id grp_id;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200462
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100463 if (params->tag == MBEDTLS_ASN1_OID) {
464 if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) {
465 return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
466 }
467 } else {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100469 if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) {
470 return ret;
471 }
Manuel Pégourié-Gonnard6fac3512014-03-19 16:39:52 +0100472#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100473 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnard6fac3512014-03-19 16:39:52 +0100474#endif
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100475 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200476
477 /*
Shaun Case0e7791f2021-12-20 21:14:10 -0800478 * grp may already be initialized; if so, make sure IDs match
Paul Bakker1a7550a2013-09-15 13:01:22 +0200479 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100480 if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id) {
481 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
482 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200483
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100484 if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0) {
485 return ret;
486 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200487
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100488 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200489}
490
491/*
492 * EC public key is an EC point
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100493 *
494 * The caller is responsible for clearing the structure upon failure if
495 * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
Paul Bakker1a7550a2013-09-15 13:01:22 +0200497 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100498static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end,
499 mbedtls_ecp_keypair *key)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200500{
Janos Follath24eed8d2019-11-22 13:21:35 +0000501 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200502
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100503 if ((ret = mbedtls_ecp_point_read_binary(&key->grp, &key->Q,
504 (const unsigned char *) *p, end - *p)) == 0) {
505 ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200506 }
507
508 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 * We know mbedtls_ecp_point_read_binary consumed all bytes or failed
Paul Bakker1a7550a2013-09-15 13:01:22 +0200510 */
511 *p = (unsigned char *) end;
512
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100513 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200514}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200518/*
519 * RSAPublicKey ::= SEQUENCE {
520 * modulus INTEGER, -- n
521 * publicExponent INTEGER -- e
522 * }
523 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100524static int pk_get_rsapubkey(unsigned char **p,
525 const unsigned char *end,
526 mbedtls_rsa_context *rsa)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200527{
Janos Follath24eed8d2019-11-22 13:21:35 +0000528 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200529 size_t len;
530
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100531 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
532 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
533 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
534 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200535
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100536 if (*p + len != end) {
537 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
538 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
539 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200540
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100541 /* Import N */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100542 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
543 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
544 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200545
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100546 if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0,
547 NULL, 0, NULL, 0)) != 0) {
548 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
549 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100550
551 *p += len;
552
553 /* Import E */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100554 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
555 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
556 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100557
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100558 if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
559 NULL, 0, *p, len)) != 0) {
560 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
561 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100562
563 *p += len;
564
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100565 if (mbedtls_rsa_complete(rsa) != 0 ||
566 mbedtls_rsa_check_pubkey(rsa) != 0) {
567 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
Hanno Becker895c5ab2018-01-05 08:08:09 +0000568 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100569
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100570 if (*p != end) {
571 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
572 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
573 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200574
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100575 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200576}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200578
579/* Get a PK algorithm identifier
580 *
581 * AlgorithmIdentifier ::= SEQUENCE {
582 * algorithm OBJECT IDENTIFIER,
583 * parameters ANY DEFINED BY algorithm OPTIONAL }
584 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100585static int pk_get_pk_alg(unsigned char **p,
586 const unsigned char *end,
587 mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200588{
Janos Follath24eed8d2019-11-22 13:21:35 +0000589 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 mbedtls_asn1_buf alg_oid;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200591
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100592 memset(params, 0, sizeof(mbedtls_asn1_buf));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200593
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100594 if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) {
595 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
596 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200597
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100598 if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0) {
599 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
600 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200601
602 /*
603 * No parameters with RSA (only for EC)
604 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100605 if (*pk_alg == MBEDTLS_PK_RSA &&
606 ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) ||
607 params->len != 0)) {
608 return MBEDTLS_ERR_PK_INVALID_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200609 }
610
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100611 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200612}
613
614/*
615 * SubjectPublicKeyInfo ::= SEQUENCE {
616 * algorithm AlgorithmIdentifier,
617 * subjectPublicKey BIT STRING }
618 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100619int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
620 mbedtls_pk_context *pk)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200621{
Janos Follath24eed8d2019-11-22 13:21:35 +0000622 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200623 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 mbedtls_asn1_buf alg_params;
625 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
626 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200627
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100628 PK_VALIDATE_RET(p != NULL);
629 PK_VALIDATE_RET(*p != NULL);
630 PK_VALIDATE_RET(end != NULL);
631 PK_VALIDATE_RET(pk != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500632
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100633 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
634 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
635 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200636 }
637
638 end = *p + len;
639
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640 if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0) {
641 return ret;
642 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200643
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100644 if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
645 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
646 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200647
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100648 if (*p + len != end) {
649 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
650 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
651 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200652
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100653 if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
654 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
655 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200656
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100657 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
658 return ret;
659 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661#if defined(MBEDTLS_RSA_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100662 if (pk_alg == MBEDTLS_PK_RSA) {
663 ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200664 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665#endif /* MBEDTLS_RSA_C */
666#if defined(MBEDTLS_ECP_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100667 if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
668 ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp);
669 if (ret == 0) {
670 ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk));
671 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200672 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#endif /* MBEDTLS_ECP_C */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100674 ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200675
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100676 if (ret == 0 && *p != end) {
677 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
678 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
679 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200680
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100681 if (ret != 0) {
682 mbedtls_pk_free(pk);
683 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200684
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100685 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200686}
687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200689/*
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100690 * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
691 *
692 * The value zero is:
693 * - never a valid value for an RSA parameter
694 * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
695 *
696 * Since values can't be omitted in PKCS#1, passing a zero value to
697 * rsa_complete() would be incorrect, so reject zero values early.
698 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100699static int asn1_get_nonzero_mpi(unsigned char **p,
700 const unsigned char *end,
701 mbedtls_mpi *X)
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100702{
703 int ret;
704
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100705 ret = mbedtls_asn1_get_mpi(p, end, X);
706 if (ret != 0) {
707 return ret;
708 }
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100709
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100710 if (mbedtls_mpi_cmp_int(X, 0) == 0) {
711 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
712 }
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100713
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100714 return 0;
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100715}
716
717/*
Paul Bakker1a7550a2013-09-15 13:01:22 +0200718 * Parse a PKCS#1 encoded private RSA key
719 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100720static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa,
721 const unsigned char *key,
722 size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200723{
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100724 int ret, version;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200725 size_t len;
726 unsigned char *p, *end;
727
Hanno Beckerefa14e82017-10-11 19:45:19 +0100728 mbedtls_mpi T;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100729 mbedtls_mpi_init(&T);
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100730
Paul Bakker1a7550a2013-09-15 13:01:22 +0200731 p = (unsigned char *) key;
732 end = p + keylen;
733
734 /*
735 * This function parses the RSAPrivateKey (PKCS#1)
736 *
737 * RSAPrivateKey ::= SEQUENCE {
738 * version Version,
739 * modulus INTEGER, -- n
740 * publicExponent INTEGER, -- e
741 * privateExponent INTEGER, -- d
742 * prime1 INTEGER, -- p
743 * prime2 INTEGER, -- q
744 * exponent1 INTEGER, -- d mod (p-1)
745 * exponent2 INTEGER, -- d mod (q-1)
746 * coefficient INTEGER, -- (inverse of q) mod p
747 * otherPrimeInfos OtherPrimeInfos OPTIONAL
748 * }
749 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100750 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
751 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
752 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200753 }
754
755 end = p + len;
756
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100757 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
758 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200759 }
760
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100761 if (version != 0) {
762 return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200763 }
764
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100765 /* Import N */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100766 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
767 (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
768 NULL, NULL)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100769 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100770 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200771
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100772 /* Import E */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100773 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
774 (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
775 NULL, &T)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100776 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100777 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100778
779 /* Import D */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100780 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
781 (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
782 &T, NULL)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100783 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100784 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100785
786 /* Import P */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100787 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
788 (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
789 NULL, NULL)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100790 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100791 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100792
793 /* Import Q */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100794 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
795 (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
796 NULL, NULL)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100797 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100798 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100799
Manuel Pégourié-Gonnardbbb5a0a2020-02-18 10:22:54 +0100800#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
Jack Lloyd8c2631b2020-01-23 17:23:52 -0500801 /*
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100802 * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
803 * that they can be easily recomputed from D, P and Q. However by
804 * parsing them from the PKCS1 structure it is possible to avoid
805 * recalculating them which both reduces the overhead of loading
806 * RSA private keys into memory and also avoids side channels which
807 * can arise when computing those values, since all of D, P, and Q
808 * are secret. See https://eprint.iacr.org/2020/055 for a
809 * description of one such attack.
810 */
Jack Lloyd8c2631b2020-01-23 17:23:52 -0500811
Jack Lloyd80cc8112020-01-22 17:34:29 -0500812 /* Import DP */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100813 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
814 (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
815 goto cleanup;
816 }
Jack Lloyd80cc8112020-01-22 17:34:29 -0500817
818 /* Import DQ */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100819 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
820 (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
821 goto cleanup;
822 }
Jack Lloyd80cc8112020-01-22 17:34:29 -0500823
824 /* Import QP */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100825 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
826 (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
827 goto cleanup;
828 }
Jack Lloyd2e9eef42020-01-28 14:43:52 -0500829
Jack Lloyd60239752020-01-27 17:53:36 -0500830#else
Shaun Case0e7791f2021-12-20 21:14:10 -0800831 /* Verify existence of the CRT params */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100832 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
833 (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
834 (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
835 goto cleanup;
836 }
Jack Lloyd60239752020-01-27 17:53:36 -0500837#endif
Jack Lloyd80cc8112020-01-22 17:34:29 -0500838
Manuel Pégourié-Gonnardc4226792020-02-14 11:28:47 +0100839 /* rsa_complete() doesn't complete anything with the default
840 * implementation but is still called:
841 * - for the benefit of alternative implementation that may want to
842 * pre-compute stuff beyond what's provided (eg Montgomery factors)
843 * - as is also sanity-checks the key
844 *
845 * Furthermore, we also check the public part for consistency with
846 * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
847 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100848 if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
849 (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100850 goto cleanup;
Manuel Pégourié-Gonnardc4226792020-02-14 11:28:47 +0100851 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100852
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100853 if (p != end) {
854 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
855 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200856 }
857
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100858cleanup:
859
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100860 mbedtls_mpi_free(&T);
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100861
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100862 if (ret != 0) {
Hanno Beckerefa14e82017-10-11 19:45:19 +0100863 /* Wrap error code if it's coming from a lower level */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100864 if ((ret & 0xff80) == 0) {
865 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
866 } else {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100867 ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100868 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100869
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100870 mbedtls_rsa_free(rsa);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200871 }
872
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100873 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200874}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877#if defined(MBEDTLS_ECP_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200878/*
879 * Parse a SEC1 encoded private EC key
880 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100881static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
882 const unsigned char *key,
883 size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200884{
Janos Follath24eed8d2019-11-22 13:21:35 +0000885 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100886 int version, pubkey_done;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200887 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888 mbedtls_asn1_buf params;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200889 unsigned char *p = (unsigned char *) key;
890 unsigned char *end = p + keylen;
891 unsigned char *end2;
892
893 /*
894 * RFC 5915, or SEC1 Appendix C.4
895 *
896 * ECPrivateKey ::= SEQUENCE {
897 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
898 * privateKey OCTET STRING,
899 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
900 * publicKey [1] BIT STRING OPTIONAL
901 * }
902 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100903 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
904 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
905 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200906 }
907
908 end = p + len;
909
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100910 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
911 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
912 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200913
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100914 if (version != 1) {
915 return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
916 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200917
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100918 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
919 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
920 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200921
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100922 if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) {
923 mbedtls_ecp_keypair_free(eck);
924 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200925 }
926
927 p += len;
928
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200929 pubkey_done = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100930 if (p != end) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200931 /*
932 * Is 'parameters' present?
933 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100934 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
935 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
936 0)) == 0) {
937 if ((ret = pk_get_ecparams(&p, p + len, &params)) != 0 ||
938 (ret = pk_use_ecparams(&params, &eck->grp)) != 0) {
939 mbedtls_ecp_keypair_free(eck);
940 return ret;
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200941 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100942 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
943 mbedtls_ecp_keypair_free(eck);
944 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100945 }
Jethro Beekmand2df9362018-02-16 13:11:04 -0800946 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200947
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100948 if (p != end) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200949 /*
950 * Is 'publickey' present? If not, or if we can't read it (eg because it
951 * is compressed), create it from the private key.
952 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100953 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
954 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
955 1)) == 0) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200956 end2 = p + len;
957
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100958 if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) {
959 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
960 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200961
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100962 if (p + len != end2) {
963 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
964 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
965 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200966
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100967 if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200968 pubkey_done = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100969 } else {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200970 /*
971 * The only acceptable failure mode of pk_get_ecpubkey() above
972 * is if the point format is not recognized.
973 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100974 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
975 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
976 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200977 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100978 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
979 mbedtls_ecp_keypair_free(eck);
980 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200981 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200982 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100983
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100984 if (!pubkey_done &&
985 (ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G,
986 NULL, NULL)) != 0) {
987 mbedtls_ecp_keypair_free(eck);
988 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardff29f9c2013-09-18 16:13:02 +0200989 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200990
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100991 if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) {
992 mbedtls_ecp_keypair_free(eck);
993 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200994 }
995
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100996 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200997}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200999
1000/*
1001 * Parse an unencrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +01001002 *
1003 * Notes:
1004 *
1005 * - This function does not own the key buffer. It is the
1006 * responsibility of the caller to take care of zeroizing
1007 * and freeing it after use.
1008 *
1009 * - The function is responsible for freeing the provided
1010 * PK context on failure.
1011 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001012 */
1013static int pk_parse_key_pkcs8_unencrypted_der(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001014 mbedtls_pk_context *pk,
1015 const unsigned char *key,
1016 size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001017{
1018 int ret, version;
1019 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 mbedtls_asn1_buf params;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001021 unsigned char *p = (unsigned char *) key;
1022 unsigned char *end = p + keylen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
1024 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001025
1026 /*
Hanno Becker9c6cb382017-09-05 10:08:01 +01001027 * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001028 *
1029 * PrivateKeyInfo ::= SEQUENCE {
1030 * version Version,
1031 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
1032 * privateKey PrivateKey,
1033 * attributes [0] IMPLICIT Attributes OPTIONAL }
1034 *
1035 * Version ::= INTEGER
1036 * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
1037 * PrivateKey ::= OCTET STRING
1038 *
1039 * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
1040 */
1041
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001042 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1043 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1044 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001045 }
1046
1047 end = p + len;
1048
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001049 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
1050 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Chris Jonesfdb588b2021-04-14 18:15:24 +01001051 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001052
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001053 if (version != 0) {
1054 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
1055 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001056
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001057 if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params)) != 0) {
1058 return ret;
1059 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001060
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001061 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1062 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1063 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001064
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001065 if (len < 1) {
1066 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
1067 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
1068 }
1069
1070 if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
1071 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1072 }
1073
1074 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
1075 return ret;
1076 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078#if defined(MBEDTLS_RSA_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001079 if (pk_alg == MBEDTLS_PK_RSA) {
1080 if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) {
1081 mbedtls_pk_free(pk);
1082 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001083 }
1084 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085#endif /* MBEDTLS_RSA_C */
1086#if defined(MBEDTLS_ECP_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001087 if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
1088 if ((ret = pk_use_ecparams(&params, &mbedtls_pk_ec(*pk)->grp)) != 0 ||
1089 (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len)) != 0) {
1090 mbedtls_pk_free(pk);
1091 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001092 }
1093 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094#endif /* MBEDTLS_ECP_C */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001095 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001096
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001097 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001098}
1099
1100/*
1101 * Parse an encrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +01001102 *
1103 * To save space, the decryption happens in-place on the given key buffer.
1104 * Also, while this function may modify the keybuffer, it doesn't own it,
1105 * and instead it is the responsibility of the caller to zeroize and properly
1106 * free it after use.
1107 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001108 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001110static int pk_parse_key_pkcs8_encrypted_der(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001111 mbedtls_pk_context *pk,
1112 unsigned char *key, size_t keylen,
1113 const unsigned char *pwd, size_t pwdlen)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001114{
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001115 int ret, decrypted = 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001116 size_t len;
Hanno Beckerfab35692017-08-25 13:38:26 +01001117 unsigned char *buf;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001118 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119 mbedtls_asn1_buf pbe_alg_oid, pbe_params;
1120#if defined(MBEDTLS_PKCS12_C)
1121 mbedtls_cipher_type_t cipher_alg;
1122 mbedtls_md_type_t md_alg;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001123#endif
1124
Hanno Becker2aa80a72017-09-07 15:28:45 +01001125 p = key;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001126 end = p + keylen;
1127
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001128 if (pwdlen == 0) {
1129 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1130 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001131
1132 /*
Hanno Beckerf04111f2017-09-29 19:18:42 +01001133 * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001134 *
1135 * EncryptedPrivateKeyInfo ::= SEQUENCE {
1136 * encryptionAlgorithm EncryptionAlgorithmIdentifier,
1137 * encryptedData EncryptedData
1138 * }
1139 *
1140 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
1141 *
1142 * EncryptedData ::= OCTET STRING
1143 *
1144 * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
Hanno Beckerb8d16572017-09-07 15:29:01 +01001145 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001146 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001147 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1148 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1149 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001150 }
1151
1152 end = p + len;
1153
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001154 if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) {
1155 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1156 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001157
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001158 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1159 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1160 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001161
Hanno Beckerfab35692017-08-25 13:38:26 +01001162 buf = p;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001163
1164 /*
Hanno Beckerb8d16572017-09-07 15:29:01 +01001165 * Decrypt EncryptedData with appropriate PBE
Paul Bakker1a7550a2013-09-15 13:01:22 +02001166 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167#if defined(MBEDTLS_PKCS12_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001168 if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
1169 if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
1170 cipher_alg, md_alg,
1171 pwd, pwdlen, p, len, buf)) != 0) {
1172 if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
1173 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1174 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001175
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001176 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001177 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001178
1179 decrypted = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001180 } else if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid) == 0) {
1181 if ((ret = mbedtls_pkcs12_pbe_sha1_rc4_128(&pbe_params,
1182 MBEDTLS_PKCS12_PBE_DECRYPT,
1183 pwd, pwdlen,
1184 p, len, buf)) != 0) {
1185 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001186 }
1187
1188 // Best guess for password mismatch when using RC4. If first tag is
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189 // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
Paul Bakker1a7550a2013-09-15 13:01:22 +02001190 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001191 if (*buf != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
1192 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001193 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001194
1195 decrypted = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001196 } else
1197#endif /* MBEDTLS_PKCS12_C */
1198#if defined(MBEDTLS_PKCS5_C)
1199 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
1200 if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
1201 p, len, buf)) != 0) {
1202 if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
1203 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1204 }
1205
1206 return ret;
1207 }
1208
1209 decrypted = 1;
1210 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211#endif /* MBEDTLS_PKCS5_C */
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +02001212 {
1213 ((void) pwd);
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +02001214 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001215
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001216 if (decrypted == 0) {
1217 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
1218 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001219
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001220 return pk_parse_key_pkcs8_unencrypted_der(pk, buf, len);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001221}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001223
1224/*
1225 * Parse a private key
1226 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001227int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
1228 const unsigned char *key, size_t keylen,
1229 const unsigned char *pwd, size_t pwdlen)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001230{
Janos Follath24eed8d2019-11-22 13:21:35 +00001231 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Dave Rodgman94210b12023-06-28 14:08:07 +01001232 const mbedtls_pk_info_t *pk_info;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001234 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001236#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001237
Dave Rodgman94210b12023-06-28 14:08:07 +01001238 (void) pk_info;
1239
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001240 PK_VALIDATE_RET(pk != NULL);
1241 if (keylen == 0) {
1242 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1243 }
1244 PK_VALIDATE_RET(key != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001245
1246#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001247 mbedtls_pem_init(&pem);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001250 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001251 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001252 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001253 } else {
1254 ret = mbedtls_pem_read_buffer(&pem,
1255 "-----BEGIN RSA PRIVATE KEY-----",
1256 "-----END RSA PRIVATE KEY-----",
1257 key, pwd, pwdlen, &len);
1258 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001259
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001260 if (ret == 0) {
1261 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1262 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1263 (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk),
1264 pem.buf, pem.buflen)) != 0) {
1265 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001266 }
1267
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001268 mbedtls_pem_free(&pem);
1269 return ret;
1270 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1271 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1272 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1273 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1274 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1275 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001276 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001279#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001280 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001281 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001282 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001283 } else {
1284 ret = mbedtls_pem_read_buffer(&pem,
1285 "-----BEGIN EC PRIVATE KEY-----",
1286 "-----END EC PRIVATE KEY-----",
1287 key, pwd, pwdlen, &len);
1288 }
1289 if (ret == 0) {
1290 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001291
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001292 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1293 (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
1294 pem.buf, pem.buflen)) != 0) {
1295 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001296 }
1297
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001298 mbedtls_pem_free(&pem);
1299 return ret;
1300 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1301 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1302 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1303 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1304 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1305 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001306 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001308
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001309 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001310 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001311 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001312 } else {
1313 ret = mbedtls_pem_read_buffer(&pem,
1314 "-----BEGIN PRIVATE KEY-----",
1315 "-----END PRIVATE KEY-----",
1316 key, NULL, 0, &len);
1317 }
1318 if (ret == 0) {
1319 if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk,
1320 pem.buf, pem.buflen)) != 0) {
1321 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001322 }
1323
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001324 mbedtls_pem_free(&pem);
1325 return ret;
1326 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1327 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001328 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001331 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001332 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001333 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001334 } else {
1335 ret = mbedtls_pem_read_buffer(&pem,
1336 "-----BEGIN ENCRYPTED PRIVATE KEY-----",
1337 "-----END ENCRYPTED PRIVATE KEY-----",
1338 key, NULL, 0, &len);
1339 }
1340 if (ret == 0) {
1341 if ((ret = pk_parse_key_pkcs8_encrypted_der(pk,
1342 pem.buf, pem.buflen,
1343 pwd, pwdlen)) != 0) {
1344 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001345 }
1346
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001347 mbedtls_pem_free(&pem);
1348 return ret;
1349 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1350 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001351 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001353#else
1354 ((void) pwd);
1355 ((void) pwdlen);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001356#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001357
1358 /*
Brian J Murray2adecba2016-11-06 04:45:15 -08001359 * At this point we only know it's not a PEM formatted key. Could be any
1360 * of the known DER encoded private key formats
1361 *
1362 * We try the different DER format parsers to see if one passes without
1363 * error
1364 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001366 {
Hanno Beckerfab35692017-08-25 13:38:26 +01001367 unsigned char *key_copy;
1368
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001369 if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) {
1370 return MBEDTLS_ERR_PK_ALLOC_FAILED;
1371 }
Hanno Beckerfab35692017-08-25 13:38:26 +01001372
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001373 memcpy(key_copy, key, keylen);
Hanno Beckerfab35692017-08-25 13:38:26 +01001374
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001375 ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
1376 pwd, pwdlen);
Hanno Beckerfab35692017-08-25 13:38:26 +01001377
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001378 mbedtls_platform_zeroize(key_copy, keylen);
1379 mbedtls_free(key_copy);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001380 }
1381
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001382 if (ret == 0) {
1383 return 0;
1384 }
Hanno Beckerfab35692017-08-25 13:38:26 +01001385
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001386 mbedtls_pk_free(pk);
1387 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001388
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001389 if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {
1390 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001391 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001393
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001394 ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen);
1395 if (ret == 0) {
1396 return 0;
Kenneth Soerensenc4e950e2019-01-03 12:39:29 +01001397 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001398
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001399 mbedtls_pk_free(pk);
1400 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001402#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001403
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001404 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1405 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1406 pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
1407 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001408 }
1409
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001410 mbedtls_pk_free(pk);
1411 mbedtls_pk_init(pk);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414#if defined(MBEDTLS_ECP_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001415 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1416 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1417 pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
1418 key, keylen) == 0) {
1419 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001420 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001421 mbedtls_pk_free(pk);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001423
Hanno Becker780f0a42018-10-10 11:23:33 +01001424 /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
1425 * it is ok to leave the PK context initialized but not
1426 * freed: It is the caller's responsibility to call pk_init()
1427 * before calling this function, and to call pk_free()
1428 * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
1429 * isn't, this leads to mbedtls_pk_free() being called
1430 * twice, once here and once by the caller, but this is
1431 * also ok and in line with the mbedtls_pk_free() calls
1432 * on failed PEM parsing attempts. */
1433
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001434 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001435}
1436
1437/*
1438 * Parse a public key
1439 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001440int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
1441 const unsigned char *key, size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001442{
Janos Follath24eed8d2019-11-22 13:21:35 +00001443 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001444 unsigned char *p;
Ron Eldor5472d432017-10-17 09:49:00 +03001445#if defined(MBEDTLS_RSA_C)
1446 const mbedtls_pk_info_t *pk_info;
1447#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001449 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001450 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001451#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001452
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001453 PK_VALIDATE_RET(ctx != NULL);
1454 if (keylen == 0) {
1455 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1456 }
1457 PK_VALIDATE_RET(key != NULL || keylen == 0);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001458
1459#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001460 mbedtls_pem_init(&pem);
Ron Eldord0c56de2017-10-10 17:03:08 +03001461#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001462 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001463 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001464 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001465 } else {
1466 ret = mbedtls_pem_read_buffer(&pem,
1467 "-----BEGIN RSA PUBLIC KEY-----",
1468 "-----END RSA PUBLIC KEY-----",
1469 key, NULL, 0, &len);
Ron Eldord0c56de2017-10-10 17:03:08 +03001470 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001471
1472 if (ret == 0) {
1473 p = pem.buf;
1474 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1475 mbedtls_pem_free(&pem);
1476 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1477 }
1478
1479 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1480 mbedtls_pem_free(&pem);
1481 return ret;
1482 }
1483
1484 if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) {
1485 mbedtls_pk_free(ctx);
1486 }
1487
1488 mbedtls_pem_free(&pem);
1489 return ret;
1490 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1491 mbedtls_pem_free(&pem);
1492 return ret;
Ron Eldord0c56de2017-10-10 17:03:08 +03001493 }
1494#endif /* MBEDTLS_RSA_C */
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001495
1496 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001497 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001498 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001499 } else {
1500 ret = mbedtls_pem_read_buffer(&pem,
1501 "-----BEGIN PUBLIC KEY-----",
1502 "-----END PUBLIC KEY-----",
1503 key, NULL, 0, &len);
1504 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001505
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001506 if (ret == 0) {
Paul Bakker1a7550a2013-09-15 13:01:22 +02001507 /*
1508 * Was PEM encoded
1509 */
Ron Eldor40b14a82017-10-16 19:30:00 +03001510 p = pem.buf;
1511
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001512 ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
1513 mbedtls_pem_free(&pem);
1514 return ret;
1515 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1516 mbedtls_pem_free(&pem);
1517 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001518 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001519 mbedtls_pem_free(&pem);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520#endif /* MBEDTLS_PEM_PARSE_C */
Ron Eldor40b14a82017-10-16 19:30:00 +03001521
1522#if defined(MBEDTLS_RSA_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001523 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1524 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Ron Eldor40b14a82017-10-16 19:30:00 +03001525 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001526
1527 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1528 return ret;
1529 }
1530
1531 p = (unsigned char *) key;
1532 ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
1533 if (ret == 0) {
1534 return ret;
1535 }
1536 mbedtls_pk_free(ctx);
1537 if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
1538 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
1539 return ret;
Ron Eldor40b14a82017-10-16 19:30:00 +03001540 }
1541#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001542 p = (unsigned char *) key;
1543
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001544 ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001545
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001546 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001547}
1548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549#endif /* MBEDTLS_PK_PARSE_C */