blob: deaff0b3102781bfb17b8a27e4d46e560eeb9908 [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;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001238 PK_VALIDATE_RET(pk != NULL);
1239 if (keylen == 0) {
1240 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1241 }
1242 PK_VALIDATE_RET(key != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001243
1244#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001245 mbedtls_pem_init(&pem);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001248 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001249 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001250 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001251 } else {
1252 ret = mbedtls_pem_read_buffer(&pem,
1253 "-----BEGIN RSA PRIVATE KEY-----",
1254 "-----END RSA PRIVATE KEY-----",
1255 key, pwd, pwdlen, &len);
1256 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001257
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001258 if (ret == 0) {
1259 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1260 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1261 (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk),
1262 pem.buf, pem.buflen)) != 0) {
1263 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001264 }
1265
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001266 mbedtls_pem_free(&pem);
1267 return ret;
1268 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1269 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1270 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1271 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1272 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1273 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001274 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001278 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001279 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001280 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001281 } else {
1282 ret = mbedtls_pem_read_buffer(&pem,
1283 "-----BEGIN EC PRIVATE KEY-----",
1284 "-----END EC PRIVATE KEY-----",
1285 key, pwd, pwdlen, &len);
1286 }
1287 if (ret == 0) {
1288 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001289
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001290 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1291 (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
1292 pem.buf, pem.buflen)) != 0) {
1293 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001294 }
1295
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001296 mbedtls_pem_free(&pem);
1297 return ret;
1298 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1299 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1300 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1301 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1302 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1303 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001304 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001305#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001306
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001307 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001308 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001309 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001310 } else {
1311 ret = mbedtls_pem_read_buffer(&pem,
1312 "-----BEGIN PRIVATE KEY-----",
1313 "-----END PRIVATE KEY-----",
1314 key, NULL, 0, &len);
1315 }
1316 if (ret == 0) {
1317 if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk,
1318 pem.buf, pem.buflen)) != 0) {
1319 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001320 }
1321
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001322 mbedtls_pem_free(&pem);
1323 return ret;
1324 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1325 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001326 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001329 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001330 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001331 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001332 } else {
1333 ret = mbedtls_pem_read_buffer(&pem,
1334 "-----BEGIN ENCRYPTED PRIVATE KEY-----",
1335 "-----END ENCRYPTED PRIVATE KEY-----",
1336 key, NULL, 0, &len);
1337 }
1338 if (ret == 0) {
1339 if ((ret = pk_parse_key_pkcs8_encrypted_der(pk,
1340 pem.buf, pem.buflen,
1341 pwd, pwdlen)) != 0) {
1342 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001343 }
1344
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001345 mbedtls_pem_free(&pem);
1346 return ret;
1347 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1348 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001349 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001351#else
1352 ((void) pwd);
1353 ((void) pwdlen);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001355
1356 /*
Brian J Murray2adecba2016-11-06 04:45:15 -08001357 * At this point we only know it's not a PEM formatted key. Could be any
1358 * of the known DER encoded private key formats
1359 *
1360 * We try the different DER format parsers to see if one passes without
1361 * error
1362 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001364 {
Hanno Beckerfab35692017-08-25 13:38:26 +01001365 unsigned char *key_copy;
1366
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001367 if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) {
1368 return MBEDTLS_ERR_PK_ALLOC_FAILED;
1369 }
Hanno Beckerfab35692017-08-25 13:38:26 +01001370
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001371 memcpy(key_copy, key, keylen);
Hanno Beckerfab35692017-08-25 13:38:26 +01001372
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001373 ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
1374 pwd, pwdlen);
Hanno Beckerfab35692017-08-25 13:38:26 +01001375
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001376 mbedtls_platform_zeroize(key_copy, keylen);
1377 mbedtls_free(key_copy);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001378 }
1379
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001380 if (ret == 0) {
1381 return 0;
1382 }
Hanno Beckerfab35692017-08-25 13:38:26 +01001383
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001384 mbedtls_pk_free(pk);
1385 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001386
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001387 if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {
1388 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001389 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001391
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001392 ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen);
1393 if (ret == 0) {
1394 return 0;
Kenneth Soerensenc4e950e2019-01-03 12:39:29 +01001395 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001396
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001397 mbedtls_pk_free(pk);
1398 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001401
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001402 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1403 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1404 pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
1405 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001406 }
1407
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001408 mbedtls_pk_free(pk);
1409 mbedtls_pk_init(pk);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412#if defined(MBEDTLS_ECP_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001413 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1414 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1415 pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
1416 key, keylen) == 0) {
1417 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001418 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001419 mbedtls_pk_free(pk);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420#endif /* MBEDTLS_ECP_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001421
Hanno Becker780f0a42018-10-10 11:23:33 +01001422 /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
1423 * it is ok to leave the PK context initialized but not
1424 * freed: It is the caller's responsibility to call pk_init()
1425 * before calling this function, and to call pk_free()
1426 * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
1427 * isn't, this leads to mbedtls_pk_free() being called
1428 * twice, once here and once by the caller, but this is
1429 * also ok and in line with the mbedtls_pk_free() calls
1430 * on failed PEM parsing attempts. */
1431
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001432 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001433}
1434
1435/*
1436 * Parse a public key
1437 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001438int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
1439 const unsigned char *key, size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001440{
Janos Follath24eed8d2019-11-22 13:21:35 +00001441 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001442 unsigned char *p;
Ron Eldor5472d432017-10-17 09:49:00 +03001443#if defined(MBEDTLS_RSA_C)
1444 const mbedtls_pk_info_t *pk_info;
1445#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001447 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001449#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001450
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001451 PK_VALIDATE_RET(ctx != NULL);
1452 if (keylen == 0) {
1453 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1454 }
1455 PK_VALIDATE_RET(key != NULL || keylen == 0);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001456
1457#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001458 mbedtls_pem_init(&pem);
Ron Eldord0c56de2017-10-10 17:03:08 +03001459#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001460 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001461 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001462 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001463 } else {
1464 ret = mbedtls_pem_read_buffer(&pem,
1465 "-----BEGIN RSA PUBLIC KEY-----",
1466 "-----END RSA PUBLIC KEY-----",
1467 key, NULL, 0, &len);
Ron Eldord0c56de2017-10-10 17:03:08 +03001468 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001469
1470 if (ret == 0) {
1471 p = pem.buf;
1472 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1473 mbedtls_pem_free(&pem);
1474 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1475 }
1476
1477 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1478 mbedtls_pem_free(&pem);
1479 return ret;
1480 }
1481
1482 if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) {
1483 mbedtls_pk_free(ctx);
1484 }
1485
1486 mbedtls_pem_free(&pem);
1487 return ret;
1488 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1489 mbedtls_pem_free(&pem);
1490 return ret;
Ron Eldord0c56de2017-10-10 17:03:08 +03001491 }
1492#endif /* MBEDTLS_RSA_C */
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001493
1494 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001495 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001496 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001497 } else {
1498 ret = mbedtls_pem_read_buffer(&pem,
1499 "-----BEGIN PUBLIC KEY-----",
1500 "-----END PUBLIC KEY-----",
1501 key, NULL, 0, &len);
1502 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001503
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001504 if (ret == 0) {
Paul Bakker1a7550a2013-09-15 13:01:22 +02001505 /*
1506 * Was PEM encoded
1507 */
Ron Eldor40b14a82017-10-16 19:30:00 +03001508 p = pem.buf;
1509
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001510 ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
1511 mbedtls_pem_free(&pem);
1512 return ret;
1513 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1514 mbedtls_pem_free(&pem);
1515 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001516 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001517 mbedtls_pem_free(&pem);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518#endif /* MBEDTLS_PEM_PARSE_C */
Ron Eldor40b14a82017-10-16 19:30:00 +03001519
1520#if defined(MBEDTLS_RSA_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001521 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1522 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Ron Eldor40b14a82017-10-16 19:30:00 +03001523 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001524
1525 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1526 return ret;
1527 }
1528
1529 p = (unsigned char *) key;
1530 ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
1531 if (ret == 0) {
1532 return ret;
1533 }
1534 mbedtls_pk_free(ctx);
1535 if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
1536 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
1537 return ret;
Ron Eldor40b14a82017-10-16 19:30:00 +03001538 }
1539#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001540 p = (unsigned char *) key;
1541
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001542 ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001543
Gilles Peskine1b6c09a2023-01-11 14:52:35 +01001544 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001545}
1546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547#endif /* MBEDTLS_PK_PARSE_C */