blob: 4f6ee139862d6f1d11d6ed6c5edbd1fd1da7b0f9 [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
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker1a7550a2013-09-15 13:01:22 +02006 */
7
Gilles Peskinedb09ef62020-06-03 01:43:33 +02008#include "common.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +02009
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020010#if defined(MBEDTLS_PK_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +020011
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000012#include "mbedtls/pk.h"
13#include "mbedtls/asn1.h"
14#include "mbedtls/oid.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050015#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard5fcbe4c2023-07-06 13:02:51 +020016#include "mbedtls/platform.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000017#include "mbedtls/error.h"
Tomi Fontanilles851d8df2023-12-19 15:44:52 +020018#include "mbedtls/ecp.h"
Valerio Setti3cc486a2023-11-30 08:09:47 +010019#include "pk_internal.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020020
Rich Evans00ab4702015-02-06 13:43:58 +000021#include <string.h>
22
Manuel Pégourié-Gonnard5fcbe4c2023-07-06 13:02:51 +020023#if defined(MBEDTLS_USE_PSA_CRYPTO)
24#include "mbedtls/psa_util.h"
25#include "psa/crypto.h"
26#endif
27
Manuel Pégourié-Gonnardda88c382023-07-06 12:31:43 +020028/* Key types */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/rsa.h"
Valerio Settib328c442024-01-23 10:48:45 +010031#include "rsa_internal.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020032#endif
Manuel Pégourié-Gonnardda88c382023-07-06 12:31:43 +020033
34/* Extended formats */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/pem.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020037#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/pkcs5.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020040#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_PKCS12_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000042#include "mbedtls/pkcs12.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020043#endif
44
Manuel Pégourié-Gonnard997a95e2023-07-26 15:18:30 +020045#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
46
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +020047/***********************************************************************
Paul Bakker1a7550a2013-09-15 13:01:22 +020048 *
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +020049 * Low-level ECC parsing: optional support for SpecifiedECDomain
50 *
51 * There are two functions here that are used by the rest of the code:
Manuel Pégourié-Gonnardf1b76332023-08-02 12:14:19 +020052 * - pk_ecc_tag_is_speficied_ec_domain()
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +020053 * - pk_ecc_group_id_from_specified()
54 *
55 * All the other functions are internal to this section.
56 *
57 * The two "public" functions have a dummy variant provided
58 * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an
59 * abstraction layer for this macro, which should not appear outside
60 * this section.
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +020061 *
62 **********************************************************************/
63
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +020064#if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
65/* See the "real" version for documentation */
Manuel Pégourié-Gonnardf1b76332023-08-02 12:14:19 +020066static int pk_ecc_tag_is_specified_ec_domain(int tag)
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +020067{
68 (void) tag;
69 return 0;
70}
71
72/* See the "real" version for documentation */
73static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
74 mbedtls_ecp_group_id *grp_id)
75{
76 (void) params;
77 (void) grp_id;
78 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
79}
80#else /* MBEDTLS_PK_PARSE_EC_EXTENDED */
81/*
82 * Tell if the passed tag might be the start of SpecifiedECDomain
83 * (that is, a sequence).
84 */
Manuel Pégourié-Gonnardf1b76332023-08-02 12:14:19 +020085static int pk_ecc_tag_is_specified_ec_domain(int tag)
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +020086{
87 return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
88}
89
Paul Bakker1a7550a2013-09-15 13:01:22 +020090/*
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +010091 * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
92 * WARNING: the resulting group should only be used with
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +020093 * pk_ecc_group_id_from_specified(), since its base point may not be set correctly
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +010094 * if it was encoded compressed.
95 *
96 * SpecifiedECDomain ::= SEQUENCE {
97 * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
98 * fieldID FieldID {{FieldTypes}},
99 * curve Curve,
100 * base ECPoint,
101 * order INTEGER,
102 * cofactor INTEGER OPTIONAL,
103 * hash HashAlgorithm OPTIONAL,
104 * ...
105 * }
106 *
107 * We only support prime-field as field type, and ignore hash and cofactor.
108 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100109static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100110{
Janos Follath24eed8d2019-11-22 13:21:35 +0000111 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100112 unsigned char *p = params->p;
Jethro Beekman01672442023-04-19 14:08:14 +0200113 const unsigned char *const end = params->p + params->len;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100114 const unsigned char *end_field, *end_curve;
115 size_t len;
116 int ver;
117
118 /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) {
120 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
121 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100122
Gilles Peskine449bd832023-01-11 14:50:10 +0100123 if (ver < 1 || ver > 3) {
124 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
125 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100126
127 /*
128 * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
129 * fieldType FIELD-ID.&id({IOSet}),
130 * parameters FIELD-ID.&Type({IOSet}{@fieldType})
131 * }
132 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
134 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
135 return ret;
136 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100137
138 end_field = p + len;
139
140 /*
141 * FIELD-ID ::= TYPE-IDENTIFIER
142 * FieldTypes FIELD-ID ::= {
143 * { Prime-p IDENTIFIED BY prime-field } |
144 * { Characteristic-two IDENTIFIED BY characteristic-two-field }
145 * }
146 * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
147 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) {
149 return ret;
150 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) ||
153 memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) {
154 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100155 }
156
157 p += len;
158
159 /* Prime-p ::= INTEGER -- Field of size p. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) {
161 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
162 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100163
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 grp->pbits = mbedtls_mpi_bitlen(&grp->P);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 if (p != end_field) {
167 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
168 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
169 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100170
171 /*
172 * Curve ::= SEQUENCE {
173 * a FieldElement,
174 * b FieldElement,
175 * seed BIT STRING OPTIONAL
176 * -- Shall be present if used in SpecifiedECDomain
177 * -- with version equal to ecdpVer2 or ecdpVer3
178 * }
179 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
181 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
182 return ret;
183 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100184
185 end_curve = p + len;
186
187 /*
188 * FieldElement ::= OCTET STRING
189 * containing an integer in the case of a prime field
190 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
192 (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) {
193 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100194 }
195
196 p += len;
197
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
199 (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) {
200 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100201 }
202
203 p += len;
204
205 /* Ignore seed BIT STRING OPTIONAL */
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100207 p += len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100209
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 if (p != end_curve) {
211 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
212 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
213 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100214
215 /*
216 * ECPoint ::= OCTET STRING
217 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
219 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
220 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G,
223 (const unsigned char *) p, len)) != 0) {
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100224 /*
225 * If we can't read the point because it's compressed, cheat by
226 * reading only the X coordinate and the parity bit of Y.
227 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
229 (p[0] != 0x02 && p[0] != 0x03) ||
230 len != mbedtls_mpi_size(&grp->P) + 1 ||
231 mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 ||
232 mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 ||
233 mbedtls_mpi_lset(&grp->G.Z, 1) != 0) {
234 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100235 }
236 }
237
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100238 p += len;
239
240 /*
241 * order INTEGER
242 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) {
244 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
245 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100246
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 grp->nbits = mbedtls_mpi_bitlen(&grp->N);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100248
249 /*
250 * Allow optional elements by purposefully not enforcing p == end here.
251 */
252
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 return 0;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100254}
255
256/*
257 * Find the group id associated with an (almost filled) group as generated by
258 * pk_group_from_specified(), or return an error if unknown.
259 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100260static 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 +0100261{
Manuel Pégourié-Gonnard5b8c4092014-03-27 14:59:42 +0100262 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 mbedtls_ecp_group ref;
264 const mbedtls_ecp_group_id *id;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100265
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 mbedtls_ecp_group_init(&ref);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100267
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100269 /* Load the group associated to that id */
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 mbedtls_ecp_group_free(&ref);
271 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id));
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100272
273 /* Compare to the group we were given, starting with easy tests */
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 if (grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
275 mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 &&
276 mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 &&
277 mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 &&
278 mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 &&
279 mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 &&
280 mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 &&
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100281 /* For Y we may only know the parity bit, so compare only that */
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 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 +0100283 break;
284 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100285 }
286
287cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100288 mbedtls_ecp_group_free(&ref);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100289
290 *grp_id = *id;
291
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100297}
298
299/*
300 * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
301 */
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +0200302static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
303 mbedtls_ecp_group_id *grp_id)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100304{
Janos Follath24eed8d2019-11-22 13:21:35 +0000305 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100307
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 mbedtls_ecp_group_init(&grp);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100309
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 if ((ret = pk_group_from_specified(params, &grp)) != 0) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100311 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100313
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 ret = pk_group_id_from_group(&grp, grp_id);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100315
316cleanup:
Minos Galanakis8692ec82023-01-20 15:27:32 +0000317 /* The API respecting lifecycle for mbedtls_ecp_group struct is
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +0200318 * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the
Minos Galanakis8692ec82023-01-20 15:27:32 +0000319 * temporary grp breaks that flow and it's members are populated
320 * by pk_group_id_from_group(). As such mbedtls_ecp_group_free()
321 * which is assuming a group populated by _setup() may not clean-up
322 * properly -> Manually free it's members.
323 */
Minos Galanakisc8e381a2023-01-19 16:08:34 +0000324 mbedtls_mpi_free(&grp.N);
325 mbedtls_mpi_free(&grp.P);
326 mbedtls_mpi_free(&grp.A);
327 mbedtls_mpi_free(&grp.B);
328 mbedtls_ecp_point_free(&grp.G);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100329
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100331}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100333
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +0200334/***********************************************************************
335 *
336 * Unsorted (yet!) from this point on until the next section header
337 *
338 **********************************************************************/
Valerio Setti4064dbb2023-05-17 15:33:07 +0200339
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200340/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200341 *
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200342 * ECParameters ::= CHOICE {
343 * namedCurve OBJECT IDENTIFIER
344 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
345 * -- implicitCurve NULL
346 * }
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200347 */
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200348static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
349 mbedtls_asn1_buf *params)
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200350{
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200351 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200352
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200353 if (end - *p < 1) {
354 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
355 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200356 }
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200357
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +0200358 /* Acceptable tags: OID for namedCurve, or specifiedECDomain */
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200359 params->tag = **p;
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +0200360 if (params->tag != MBEDTLS_ASN1_OID &&
Manuel Pégourié-Gonnardf1b76332023-08-02 12:14:19 +0200361 !pk_ecc_tag_is_specified_ec_domain(params->tag)) {
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200362 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
363 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
364 }
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200365
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200366 if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200367 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
368 }
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200369
370 params->p = *p;
371 *p += params->len;
372
373 if (*p != end) {
374 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
375 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
376 }
377
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200378 return 0;
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200379}
380
381/*
Paul Bakker1a7550a2013-09-15 13:01:22 +0200382 * Use EC parameters to initialise an EC group
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100383 *
384 * ECParameters ::= CHOICE {
385 * namedCurve OBJECT IDENTIFIER
386 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
387 * -- implicitCurve NULL
Paul Bakker1a7550a2013-09-15 13:01:22 +0200388 */
Valerio Setti4064dbb2023-05-17 15:33:07 +0200389static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200390{
Janos Follath24eed8d2019-11-22 13:21:35 +0000391 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 mbedtls_ecp_group_id grp_id;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200393
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 if (params->tag == MBEDTLS_ASN1_OID) {
395 if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) {
396 return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
397 }
398 } else {
Manuel Pégourié-Gonnard12ea63a2023-07-27 12:20:16 +0200399 ret = pk_ecc_group_id_from_specified(params, &grp_id);
400 if (ret != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 return ret;
402 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100403 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200404
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100405 return mbedtls_pk_ecc_set_group(pk, grp_id);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200406}
407
Jethro Beekman01672442023-04-19 14:08:14 +0200408#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
409
410/*
411 * Load an RFC8410 EC key, which doesn't have any parameters
412 */
413static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params,
414 mbedtls_ecp_group_id grp_id,
Valerio Setti4064dbb2023-05-17 15:33:07 +0200415 mbedtls_pk_context *pk)
Jethro Beekman01672442023-04-19 14:08:14 +0200416{
417 if (params->tag != 0 || params->len != 0) {
418 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
419 }
420
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100421 return mbedtls_pk_ecc_set_group(pk, grp_id);
Jethro Beekman01672442023-04-19 14:08:14 +0200422}
423
424/*
425 * Parse an RFC 8410 encoded private EC key
426 *
427 * CurvePrivateKey ::= OCTET STRING
428 */
Valerio Setti4064dbb2023-05-17 15:33:07 +0200429static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
Jethro Beekman01672442023-04-19 14:08:14 +0200430 unsigned char *key, size_t keylen, const unsigned char *end,
431 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
432{
433 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
434 size_t len;
435
436 if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
437 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
438 }
439
440 if (key + len != end) {
441 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
442 }
443
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200444 /*
445 * Load the private key
446 */
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100447 ret = mbedtls_pk_ecc_set_key(pk, key, len);
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200448 if (ret != 0) {
Valerio Setti00e8dd12023-05-18 18:56:59 +0200449 return ret;
450 }
Jethro Beekman01672442023-04-19 14:08:14 +0200451
Valerio Setti4064dbb2023-05-17 15:33:07 +0200452 /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,
453 * which never contain a public key. As such, derive the public key
454 * unconditionally. */
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100455 if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
Jethro Beekman01672442023-04-19 14:08:14 +0200456 return ret;
457 }
458
Jethro Beekman01672442023-04-19 14:08:14 +0200459 return 0;
460}
461#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
Valerio Setti4064dbb2023-05-17 15:33:07 +0200462
Valerio Setti81d75122023-06-14 14:49:33 +0200463#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200464
Paul Bakker1a7550a2013-09-15 13:01:22 +0200465/* Get a PK algorithm identifier
466 *
467 * AlgorithmIdentifier ::= SEQUENCE {
468 * algorithm OBJECT IDENTIFIER,
469 * parameters ANY DEFINED BY algorithm OPTIONAL }
470 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100471static int pk_get_pk_alg(unsigned char **p,
472 const unsigned char *end,
Jethro Beekman01672442023-04-19 14:08:14 +0200473 mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params,
474 mbedtls_ecp_group_id *ec_grp_id)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200475{
Janos Follath24eed8d2019-11-22 13:21:35 +0000476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 mbedtls_asn1_buf alg_oid;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200478
Gilles Peskine449bd832023-01-11 14:50:10 +0100479 memset(params, 0, sizeof(mbedtls_asn1_buf));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200480
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) {
482 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
483 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200484
Jethro Beekman01672442023-04-19 14:08:14 +0200485 ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg);
Valerio Setti81d75122023-06-14 14:49:33 +0200486#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Jethro Beekman01672442023-04-19 14:08:14 +0200487 if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
488 ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id);
489 if (ret == 0) {
490 *pk_alg = MBEDTLS_PK_ECKEY;
491 }
492 }
493#else
494 (void) ec_grp_id;
495#endif
496 if (ret != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
498 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200499
500 /*
501 * No parameters with RSA (only for EC)
502 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 if (*pk_alg == MBEDTLS_PK_RSA &&
504 ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) ||
505 params->len != 0)) {
506 return MBEDTLS_ERR_PK_INVALID_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200507 }
508
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200510}
511
512/*
513 * SubjectPublicKeyInfo ::= SEQUENCE {
514 * algorithm AlgorithmIdentifier,
515 * subjectPublicKey BIT STRING }
516 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100517int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
518 mbedtls_pk_context *pk)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200519{
Janos Follath24eed8d2019-11-22 13:21:35 +0000520 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200521 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_asn1_buf alg_params;
523 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
Jethro Beekman01672442023-04-19 14:08:14 +0200524 mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200526
Gilles Peskine449bd832023-01-11 14:50:10 +0100527 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
528 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
529 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200530 }
531
532 end = *p + len;
533
Jethro Beekman01672442023-04-19 14:08:14 +0200534 if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100535 return ret;
536 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200537
Gilles Peskine449bd832023-01-11 14:50:10 +0100538 if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
539 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
540 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200541
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 if (*p + len != end) {
543 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
544 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
545 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200546
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
548 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
549 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200550
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
552 return ret;
553 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555#if defined(MBEDTLS_RSA_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 if (pk_alg == MBEDTLS_PK_RSA) {
Valerio Setti201e6432024-02-01 17:19:37 +0100557 ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p));
Valerio Setti5922cb92024-02-02 09:21:25 +0100558 if (ret == 0) {
559 /* On success all the input has been consumed by the parsing function. */
560 *p += end - *p;
Valerio Setti5a198922024-02-02 13:59:51 +0100561 } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) &&
562 (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) {
Valerio Setti5922cb92024-02-02 09:21:25 +0100563 /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */
564 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
565 } else {
566 ret = MBEDTLS_ERR_PK_INVALID_PUBKEY;
567 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200568 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569#endif /* MBEDTLS_RSA_C */
Valerio Setti81d75122023-06-14 14:49:33 +0200570#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Gilles Peskine449bd832023-01-11 14:50:10 +0100571 if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
Jethro Beekman01672442023-04-19 14:08:14 +0200572#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
Valerio Setti00e8dd12023-05-18 18:56:59 +0200573 if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
Valerio Setti4064dbb2023-05-17 15:33:07 +0200574 ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk);
Jethro Beekman01672442023-04-19 14:08:14 +0200575 } else
576#endif
577 {
Valerio Setti4064dbb2023-05-17 15:33:07 +0200578 ret = pk_use_ecparams(&alg_params, pk);
Jethro Beekman01672442023-04-19 14:08:14 +0200579 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 if (ret == 0) {
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100581 ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
Manuel Pégourié-Gonnarde4c883b2023-07-26 23:31:01 +0200582 *p += end - *p;
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200584 } else
Valerio Setti81d75122023-06-14 14:49:33 +0200585#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Gilles Peskine449bd832023-01-11 14:50:10 +0100586 ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 if (ret == 0 && *p != end) {
589 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
590 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
591 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200592
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 if (ret != 0) {
594 mbedtls_pk_free(pk);
595 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200596
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200598}
599
Valerio Setti81d75122023-06-14 14:49:33 +0200600#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200601/*
602 * Parse a SEC1 encoded private EC key
603 */
Valerio Setti4064dbb2023-05-17 15:33:07 +0200604static int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
Gilles Peskine449bd832023-01-11 14:50:10 +0100605 const unsigned char *key, size_t keylen,
606 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200607{
Janos Follath24eed8d2019-11-22 13:21:35 +0000608 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100609 int version, pubkey_done;
Jethro Beekman01672442023-04-19 14:08:14 +0200610 size_t len, d_len;
Leonid Rozenboima3008e72022-04-21 17:28:18 -0700611 mbedtls_asn1_buf params = { 0, 0, NULL };
Paul Bakker1a7550a2013-09-15 13:01:22 +0200612 unsigned char *p = (unsigned char *) key;
Jethro Beekman01672442023-04-19 14:08:14 +0200613 unsigned char *d;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200614 unsigned char *end = p + keylen;
615 unsigned char *end2;
616
617 /*
618 * RFC 5915, or SEC1 Appendix C.4
619 *
620 * ECPrivateKey ::= SEQUENCE {
621 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
622 * privateKey OCTET STRING,
623 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
624 * publicKey [1] BIT STRING OPTIONAL
625 * }
626 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100627 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
628 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
629 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200630 }
631
632 end = p + len;
633
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
635 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
636 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200637
Gilles Peskine449bd832023-01-11 14:50:10 +0100638 if (version != 1) {
639 return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
640 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200641
Gilles Peskine449bd832023-01-11 14:50:10 +0100642 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
643 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
644 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200645
Valerio Setti6b062ee2023-06-30 17:32:57 +0200646 /* Keep a reference to the position fo the private key. It will be used
647 * later in this function. */
Jethro Beekman01672442023-04-19 14:08:14 +0200648 d = p;
649 d_len = len;
Valerio Setti00e8dd12023-05-18 18:56:59 +0200650
Paul Bakker1a7550a2013-09-15 13:01:22 +0200651 p += len;
652
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200653 pubkey_done = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100654 if (p != end) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200655 /*
656 * Is 'parameters' present?
657 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
659 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
660 0)) == 0) {
661 if ((ret = pk_get_ecparams(&p, p + len, &params)) != 0 ||
Valerio Setti4064dbb2023-05-17 15:33:07 +0200662 (ret = pk_use_ecparams(&params, pk)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100663 return ret;
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200664 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100665 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100667 }
Jethro Beekmand2df9362018-02-16 13:11:04 -0800668 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200669
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200670 /*
671 * Load the private key
672 */
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100673 ret = mbedtls_pk_ecc_set_key(pk, d, d_len);
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200674 if (ret != 0) {
Manuel Pégourié-Gonnard6db11d52023-07-25 11:20:48 +0200675 return ret;
676 }
Valerio Setti6b062ee2023-06-30 17:32:57 +0200677
Gilles Peskine449bd832023-01-11 14:50:10 +0100678 if (p != end) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200679 /*
680 * Is 'publickey' present? If not, or if we can't read it (eg because it
681 * is compressed), create it from the private key.
682 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
684 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
685 1)) == 0) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200686 end2 = p + len;
687
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) {
689 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
690 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200691
Gilles Peskine449bd832023-01-11 14:50:10 +0100692 if (p + len != end2) {
693 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
694 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
695 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200696
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100697 if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200698 pubkey_done = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 } else {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200700 /*
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100701 * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200702 * is if the point format is not recognized.
703 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100704 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
705 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
706 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200707 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +0200710 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200711 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100712
Valerio Setti34f67552023-04-03 15:19:18 +0200713 if (!pubkey_done) {
Valerio Setti3bfad3a2024-02-01 11:28:27 +0100714 if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
Valerio Setti520c0382023-04-07 11:38:09 +0200715 return ret;
Valerio Setti34f67552023-04-03 15:19:18 +0200716 }
Manuel Pégourié-Gonnardff29f9c2013-09-18 16:13:02 +0200717 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200718
Gilles Peskine449bd832023-01-11 14:50:10 +0100719 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200720}
Valerio Setti81d75122023-06-14 14:49:33 +0200721#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200722
Manuel Pégourié-Gonnard212517b2023-07-26 12:05:38 +0200723/***********************************************************************
724 *
725 * PKCS#8 parsing functions
726 *
727 **********************************************************************/
728
Paul Bakker1a7550a2013-09-15 13:01:22 +0200729/*
730 * Parse an unencrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +0100731 *
732 * Notes:
733 *
734 * - This function does not own the key buffer. It is the
735 * responsibility of the caller to take care of zeroizing
736 * and freeing it after use.
737 *
738 * - The function is responsible for freeing the provided
739 * PK context on failure.
740 *
Paul Bakker1a7550a2013-09-15 13:01:22 +0200741 */
742static int pk_parse_key_pkcs8_unencrypted_der(
Gilles Peskine449bd832023-01-11 14:50:10 +0100743 mbedtls_pk_context *pk,
744 const unsigned char *key, size_t keylen,
745 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200746{
747 int ret, version;
748 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 mbedtls_asn1_buf params;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200750 unsigned char *p = (unsigned char *) key;
751 unsigned char *end = p + keylen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
Jethro Beekman01672442023-04-19 14:08:14 +0200753 mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200754 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200755
Valerio Setti81d75122023-06-14 14:49:33 +0200756#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Manuel Pégourié-Gonnard609ab642021-06-16 14:29:11 +0200757 (void) f_rng;
758 (void) p_rng;
759#endif
760
Paul Bakker1a7550a2013-09-15 13:01:22 +0200761 /*
Hanno Becker9c6cb382017-09-05 10:08:01 +0100762 * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200763 *
764 * PrivateKeyInfo ::= SEQUENCE {
765 * version Version,
766 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
767 * privateKey PrivateKey,
768 * attributes [0] IMPLICIT Attributes OPTIONAL }
769 *
770 * Version ::= INTEGER
771 * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
772 * PrivateKey ::= OCTET STRING
773 *
774 * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
775 */
776
Gilles Peskine449bd832023-01-11 14:50:10 +0100777 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
778 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
779 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200780 }
781
782 end = p + len;
783
Gilles Peskine449bd832023-01-11 14:50:10 +0100784 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
785 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Chris Jonesfdb588b2021-04-14 18:15:24 +0100786 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200787
Gilles Peskine449bd832023-01-11 14:50:10 +0100788 if (version != 0) {
789 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
790 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200791
Jethro Beekman01672442023-04-19 14:08:14 +0200792 if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params, &ec_grp_id)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100793 return ret;
794 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200795
Gilles Peskine449bd832023-01-11 14:50:10 +0100796 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
797 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
798 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200799
Gilles Peskine449bd832023-01-11 14:50:10 +0100800 if (len < 1) {
801 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
802 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
803 }
804
805 if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
806 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
807 }
808
809 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
810 return ret;
811 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200813#if defined(MBEDTLS_RSA_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100814 if (pk_alg == MBEDTLS_PK_RSA) {
Valerio Setti135ebde2024-02-01 17:00:29 +0100815 if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100816 mbedtls_pk_free(pk);
817 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200818 }
819 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820#endif /* MBEDTLS_RSA_C */
Valerio Setti81d75122023-06-14 14:49:33 +0200821#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Gilles Peskine449bd832023-01-11 14:50:10 +0100822 if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
Jethro Beekman01672442023-04-19 14:08:14 +0200823#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
Valerio Setti00e8dd12023-05-18 18:56:59 +0200824 if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
Valerio Setti4064dbb2023-05-17 15:33:07 +0200825 if ((ret =
826 pk_use_ecparams_rfc8410(&params, ec_grp_id, pk)) != 0 ||
Jethro Beekman01672442023-04-19 14:08:14 +0200827 (ret =
Valerio Setti4064dbb2023-05-17 15:33:07 +0200828 pk_parse_key_rfc8410_der(pk, p, len, end, f_rng,
Jethro Beekman01672442023-04-19 14:08:14 +0200829 p_rng)) != 0) {
830 mbedtls_pk_free(pk);
831 return ret;
832 }
833 } else
834#endif
835 {
Valerio Setti4064dbb2023-05-17 15:33:07 +0200836 if ((ret = pk_use_ecparams(&params, pk)) != 0 ||
837 (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) {
Jethro Beekman01672442023-04-19 14:08:14 +0200838 mbedtls_pk_free(pk);
839 return ret;
840 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200841 }
842 } else
Valerio Setti81d75122023-06-14 14:49:33 +0200843#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Gilles Peskine449bd832023-01-11 14:50:10 +0100844 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200845
Waleed Elmelegyc9f40402023-08-08 15:28:15 +0100846 end = p + len;
847 if (end != (key + keylen)) {
848 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
849 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
850 }
Waleed Elmelegyd5278962023-09-12 14:42:49 +0100851
Gilles Peskine449bd832023-01-11 14:50:10 +0100852 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200853}
854
855/*
856 * Parse an encrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +0100857 *
858 * To save space, the decryption happens in-place on the given key buffer.
859 * Also, while this function may modify the keybuffer, it doesn't own it,
860 * and instead it is the responsibility of the caller to zeroize and properly
861 * free it after use.
862 *
Paul Bakker1a7550a2013-09-15 13:01:22 +0200863 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Waleed Elmelegy1db5cda2023-09-20 18:00:48 +0100865MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(
Gilles Peskine449bd832023-01-11 14:50:10 +0100866 mbedtls_pk_context *pk,
867 unsigned char *key, size_t keylen,
868 const unsigned char *pwd, size_t pwdlen,
869 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200870{
Paul Bakkerf4cf80b2014-04-17 17:19:56 +0200871 int ret, decrypted = 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200872 size_t len;
Hanno Beckerfab35692017-08-25 13:38:26 +0100873 unsigned char *buf;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200874 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 mbedtls_asn1_buf pbe_alg_oid, pbe_params;
Valerio Settie581e142023-12-29 16:35:07 +0100876#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_cipher_type_t cipher_alg;
878 mbedtls_md_type_t md_alg;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200879#endif
Waleed Elmelegyc9f40402023-08-08 15:28:15 +0100880 size_t outlen = 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200881
Hanno Becker2aa80a72017-09-07 15:28:45 +0100882 p = key;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200883 end = p + keylen;
884
Gilles Peskine449bd832023-01-11 14:50:10 +0100885 if (pwdlen == 0) {
886 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
887 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200888
889 /*
Hanno Beckerf04111f2017-09-29 19:18:42 +0100890 * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200891 *
892 * EncryptedPrivateKeyInfo ::= SEQUENCE {
893 * encryptionAlgorithm EncryptionAlgorithmIdentifier,
894 * encryptedData EncryptedData
895 * }
896 *
897 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
898 *
899 * EncryptedData ::= OCTET STRING
900 *
901 * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
Hanno Beckerb8d16572017-09-07 15:29:01 +0100902 *
Paul Bakker1a7550a2013-09-15 13:01:22 +0200903 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100904 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
905 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
906 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200907 }
908
909 end = p + len;
910
Gilles Peskine449bd832023-01-11 14:50:10 +0100911 if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) {
912 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
913 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200914
Gilles Peskine449bd832023-01-11 14:50:10 +0100915 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
916 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
917 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200918
Hanno Beckerfab35692017-08-25 13:38:26 +0100919 buf = p;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200920
921 /*
Hanno Beckerb8d16572017-09-07 15:29:01 +0100922 * Decrypt EncryptedData with appropriate PBE
Paul Bakker1a7550a2013-09-15 13:01:22 +0200923 */
Valerio Settie581e142023-12-29 16:35:07 +0100924#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100925 if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
Waleed Elmelegyd5278962023-09-12 14:42:49 +0100926 if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
Waleed Elmelegy5e48cad2023-09-12 14:52:48 +0100927 cipher_alg, md_alg,
928 pwd, pwdlen, p, len, buf, len, &outlen)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100929 if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
930 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
931 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200932
Gilles Peskine449bd832023-01-11 14:50:10 +0100933 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200934 }
Waleed Elmelegyd5278962023-09-12 14:42:49 +0100935
Paul Bakkerf4cf80b2014-04-17 17:19:56 +0200936 decrypted = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100937 } else
Valerio Settie581e142023-12-29 16:35:07 +0100938#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
939#if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100940 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
Waleed Elmelegyc9f40402023-08-08 15:28:15 +0100941 if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
942 p, len, buf, len, &outlen)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100943 if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
944 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
945 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200946
Gilles Peskine449bd832023-01-11 14:50:10 +0100947 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200948 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +0200949
950 decrypted = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100951 } else
Valerio Settie581e142023-12-29 16:35:07 +0100952#endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +0200953 {
954 ((void) pwd);
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +0200955 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200956
Gilles Peskine449bd832023-01-11 14:50:10 +0100957 if (decrypted == 0) {
958 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
959 }
Waleed Elmelegyc9f40402023-08-08 15:28:15 +0100960 return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200961}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200963
Manuel Pégourié-Gonnard212517b2023-07-26 12:05:38 +0200964/***********************************************************************
965 *
966 * Top-level functions, with format auto-discovery
967 *
968 **********************************************************************/
969
Paul Bakker1a7550a2013-09-15 13:01:22 +0200970/*
971 * Parse a private key
972 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100973int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
974 const unsigned char *key, size_t keylen,
975 const unsigned char *pwd, size_t pwdlen,
976 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200977{
Janos Follath24eed8d2019-11-22 13:21:35 +0000978 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200979 const mbedtls_pk_info_t *pk_info;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200981 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200982 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500983#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +0200984
Gilles Peskine449bd832023-01-11 14:50:10 +0100985 if (keylen == 0) {
986 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
987 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500988
989#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100990 mbedtls_pem_init(&pem);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200993 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +0100994 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200995 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +0100996 } else {
997 ret = mbedtls_pem_read_buffer(&pem,
Valerio Setti854c7372023-11-28 08:37:57 +0100998 PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA,
Gilles Peskine449bd832023-01-11 14:50:10 +0100999 key, pwd, pwdlen, &len);
1000 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001001
Gilles Peskine449bd832023-01-11 14:50:10 +01001002 if (ret == 0) {
1003 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1004 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
Valerio Setti135ebde2024-02-01 17:00:29 +01001005 (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk),
Valerio Settifd49a462024-01-23 08:35:11 +01001006 pem.buf, pem.buflen)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001007 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001008 }
1009
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 mbedtls_pem_free(&pem);
1011 return ret;
1012 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1013 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1014 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1015 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1016 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1017 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001018 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001020
Valerio Setti81d75122023-06-14 14:49:33 +02001021#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001022 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001023 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001024 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001025 } else {
1026 ret = mbedtls_pem_read_buffer(&pem,
Valerio Setti854c7372023-11-28 08:37:57 +01001027 PEM_BEGIN_PRIVATE_KEY_EC,
1028 PEM_END_PRIVATE_KEY_EC,
Gilles Peskine449bd832023-01-11 14:50:10 +01001029 key, pwd, pwdlen, &len);
1030 }
1031 if (ret == 0) {
1032 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001033
Gilles Peskine449bd832023-01-11 14:50:10 +01001034 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
Valerio Setti4064dbb2023-05-17 15:33:07 +02001035 (ret = pk_parse_key_sec1_der(pk,
Gilles Peskine449bd832023-01-11 14:50:10 +01001036 pem.buf, pem.buflen,
1037 f_rng, p_rng)) != 0) {
1038 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001039 }
1040
Gilles Peskine449bd832023-01-11 14:50:10 +01001041 mbedtls_pem_free(&pem);
1042 return ret;
1043 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1044 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1045 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1046 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1047 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1048 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001049 }
Valerio Setti81d75122023-06-14 14:49:33 +02001050#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001051
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001052 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001053 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001054 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001055 } else {
1056 ret = mbedtls_pem_read_buffer(&pem,
Valerio Setti854c7372023-11-28 08:37:57 +01001057 PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8,
Gilles Peskine449bd832023-01-11 14:50:10 +01001058 key, NULL, 0, &len);
1059 }
1060 if (ret == 0) {
1061 if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk,
1062 pem.buf, pem.buflen, f_rng, p_rng)) != 0) {
1063 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001064 }
1065
Gilles Peskine449bd832023-01-11 14:50:10 +01001066 mbedtls_pem_free(&pem);
1067 return ret;
1068 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1069 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001070 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001073 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001074 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001075 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001076 } else {
1077 ret = mbedtls_pem_read_buffer(&pem,
Valerio Setti854c7372023-11-28 08:37:57 +01001078 PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8,
1079 PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8,
Gilles Peskine449bd832023-01-11 14:50:10 +01001080 key, NULL, 0, &len);
1081 }
1082 if (ret == 0) {
Waleed Elmelegy1db5cda2023-09-20 18:00:48 +01001083 if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
1084 pwd, pwdlen, f_rng, p_rng)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001085 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001086 }
1087
Gilles Peskine449bd832023-01-11 14:50:10 +01001088 mbedtls_pem_free(&pem);
1089 return ret;
1090 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1091 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001092 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001094#else
1095 ((void) pwd);
1096 ((void) pwdlen);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001097#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001098
1099 /*
Brian J Murray2adecba2016-11-06 04:45:15 -08001100 * At this point we only know it's not a PEM formatted key. Could be any
1101 * of the known DER encoded private key formats
1102 *
1103 * We try the different DER format parsers to see if one passes without
1104 * error
1105 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001107 if (pwdlen != 0) {
Hanno Beckerfab35692017-08-25 13:38:26 +01001108 unsigned char *key_copy;
1109
Gilles Peskine449bd832023-01-11 14:50:10 +01001110 if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) {
1111 return MBEDTLS_ERR_PK_ALLOC_FAILED;
1112 }
Hanno Beckerfab35692017-08-25 13:38:26 +01001113
Gilles Peskine449bd832023-01-11 14:50:10 +01001114 memcpy(key_copy, key, keylen);
Hanno Beckerfab35692017-08-25 13:38:26 +01001115
Waleed Elmelegy1db5cda2023-09-20 18:00:48 +01001116 ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
1117 pwd, pwdlen, f_rng, p_rng);
Hanno Beckerfab35692017-08-25 13:38:26 +01001118
Tom Cosgroveca8c61b2023-07-17 15:17:40 +01001119 mbedtls_zeroize_and_free(key_copy, keylen);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001120 }
1121
Gilles Peskine449bd832023-01-11 14:50:10 +01001122 if (ret == 0) {
1123 return 0;
1124 }
Hanno Beckerfab35692017-08-25 13:38:26 +01001125
Gilles Peskine449bd832023-01-11 14:50:10 +01001126 mbedtls_pk_free(pk);
1127 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001128
Gilles Peskine449bd832023-01-11 14:50:10 +01001129 if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {
1130 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001131 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng);
1135 if (ret == 0) {
1136 return 0;
Manuel Pégourié-Gonnard84dea012021-06-15 11:29:26 +02001137 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001138
Gilles Peskine449bd832023-01-11 14:50:10 +01001139 mbedtls_pk_free(pk);
1140 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001142#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001143
Gilles Peskine449bd832023-01-11 14:50:10 +01001144 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1145 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
Valerio Setti135ebde2024-02-01 17:00:29 +01001146 mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001147 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001148 }
1149
Gilles Peskine449bd832023-01-11 14:50:10 +01001150 mbedtls_pk_free(pk);
1151 mbedtls_pk_init(pk);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001153
Valerio Setti81d75122023-06-14 14:49:33 +02001154#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Gilles Peskine449bd832023-01-11 14:50:10 +01001155 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1156 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
Valerio Setti4064dbb2023-05-17 15:33:07 +02001157 pk_parse_key_sec1_der(pk,
Gilles Peskine449bd832023-01-11 14:50:10 +01001158 key, keylen, f_rng, p_rng) == 0) {
1159 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001160 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001161 mbedtls_pk_free(pk);
Valerio Setti81d75122023-06-14 14:49:33 +02001162#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001163
Valerio Setti81d75122023-06-14 14:49:33 +02001164 /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't,
Hanno Becker780f0a42018-10-10 11:23:33 +01001165 * it is ok to leave the PK context initialized but not
1166 * freed: It is the caller's responsibility to call pk_init()
1167 * before calling this function, and to call pk_free()
Valerio Setti81d75122023-06-14 14:49:33 +02001168 * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C
Hanno Becker780f0a42018-10-10 11:23:33 +01001169 * isn't, this leads to mbedtls_pk_free() being called
1170 * twice, once here and once by the caller, but this is
1171 * also ok and in line with the mbedtls_pk_free() calls
1172 * on failed PEM parsing attempts. */
1173
Gilles Peskine449bd832023-01-11 14:50:10 +01001174 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001175}
1176
1177/*
1178 * Parse a public key
1179 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001180int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
1181 const unsigned char *key, size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001182{
Janos Follath24eed8d2019-11-22 13:21:35 +00001183 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001184 unsigned char *p;
Ron Eldor5472d432017-10-17 09:49:00 +03001185#if defined(MBEDTLS_RSA_C)
1186 const mbedtls_pk_info_t *pk_info;
1187#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001188#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001189 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001190 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001191#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001192
Gilles Peskine449bd832023-01-11 14:50:10 +01001193 if (keylen == 0) {
1194 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1195 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001196
1197#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001198 mbedtls_pem_init(&pem);
Ron Eldord0c56de2017-10-10 17:03:08 +03001199#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001200 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001201 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001202 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001203 } else {
1204 ret = mbedtls_pem_read_buffer(&pem,
Valerio Setti854c7372023-11-28 08:37:57 +01001205 PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA,
Gilles Peskine449bd832023-01-11 14:50:10 +01001206 key, NULL, 0, &len);
Ron Eldord0c56de2017-10-10 17:03:08 +03001207 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001208
1209 if (ret == 0) {
1210 p = pem.buf;
1211 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1212 mbedtls_pem_free(&pem);
1213 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1214 }
1215
1216 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1217 mbedtls_pem_free(&pem);
1218 return ret;
1219 }
1220
Valerio Setti201e6432024-02-01 17:19:37 +01001221 if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001222 mbedtls_pk_free(ctx);
1223 }
1224
1225 mbedtls_pem_free(&pem);
1226 return ret;
1227 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1228 mbedtls_pem_free(&pem);
1229 return ret;
Ron Eldord0c56de2017-10-10 17:03:08 +03001230 }
1231#endif /* MBEDTLS_RSA_C */
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001232
1233 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001234 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001235 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001236 } else {
1237 ret = mbedtls_pem_read_buffer(&pem,
Valerio Setti854c7372023-11-28 08:37:57 +01001238 PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
Gilles Peskine449bd832023-01-11 14:50:10 +01001239 key, NULL, 0, &len);
1240 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001241
Gilles Peskine449bd832023-01-11 14:50:10 +01001242 if (ret == 0) {
Paul Bakker1a7550a2013-09-15 13:01:22 +02001243 /*
1244 * Was PEM encoded
1245 */
Ron Eldor40b14a82017-10-16 19:30:00 +03001246 p = pem.buf;
1247
Jethro Beekman01672442023-04-19 14:08:14 +02001248 ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
Gilles Peskine449bd832023-01-11 14:50:10 +01001249 mbedtls_pem_free(&pem);
1250 return ret;
1251 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1252 mbedtls_pem_free(&pem);
1253 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001254 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001255 mbedtls_pem_free(&pem);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256#endif /* MBEDTLS_PEM_PARSE_C */
Ron Eldor40b14a82017-10-16 19:30:00 +03001257
1258#if defined(MBEDTLS_RSA_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001259 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1260 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Ron Eldor40b14a82017-10-16 19:30:00 +03001261 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001262
1263 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1264 return ret;
1265 }
1266
1267 p = (unsigned char *) key;
Valerio Setti201e6432024-02-01 17:19:37 +01001268 ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen);
Gilles Peskine449bd832023-01-11 14:50:10 +01001269 if (ret == 0) {
1270 return ret;
1271 }
1272 mbedtls_pk_free(ctx);
Valerio Settidccfd362024-01-23 17:07:59 +01001273 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001274 return ret;
Ron Eldor40b14a82017-10-16 19:30:00 +03001275 }
1276#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001277 p = (unsigned char *) key;
1278
Gilles Peskine449bd832023-01-11 14:50:10 +01001279 ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001280
Gilles Peskine449bd832023-01-11 14:50:10 +01001281 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001282}
1283
Manuel Pégourié-Gonnard212517b2023-07-26 12:05:38 +02001284/***********************************************************************
1285 *
1286 * Top-level functions, with filesystem support
1287 *
1288 **********************************************************************/
1289
1290#if defined(MBEDTLS_FS_IO)
1291/*
1292 * Load all data from a file into a given buffer.
1293 *
1294 * The file is expected to contain either PEM or DER encoded data.
1295 * A terminating null byte is always appended. It is included in the announced
1296 * length only if the data looks like it is PEM encoded.
1297 */
1298int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
1299{
1300 FILE *f;
1301 long size;
1302
1303 if ((f = fopen(path, "rb")) == NULL) {
1304 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1305 }
1306
1307 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
1308 mbedtls_setbuf(f, NULL);
1309
1310 fseek(f, 0, SEEK_END);
1311 if ((size = ftell(f)) == -1) {
1312 fclose(f);
1313 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1314 }
1315 fseek(f, 0, SEEK_SET);
1316
1317 *n = (size_t) size;
1318
1319 if (*n + 1 == 0 ||
1320 (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
1321 fclose(f);
1322 return MBEDTLS_ERR_PK_ALLOC_FAILED;
1323 }
1324
1325 if (fread(*buf, 1, *n, f) != *n) {
1326 fclose(f);
1327
1328 mbedtls_zeroize_and_free(*buf, *n);
1329
1330 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1331 }
1332
1333 fclose(f);
1334
1335 (*buf)[*n] = '\0';
1336
1337 if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
1338 ++*n;
1339 }
1340
1341 return 0;
1342}
1343
1344/*
1345 * Load and parse a private key
1346 */
1347int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
1348 const char *path, const char *pwd,
1349 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1350{
1351 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1352 size_t n;
1353 unsigned char *buf;
1354
1355 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1356 return ret;
1357 }
1358
1359 if (pwd == NULL) {
1360 ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
1361 } else {
1362 ret = mbedtls_pk_parse_key(ctx, buf, n,
1363 (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
1364 }
1365
1366 mbedtls_zeroize_and_free(buf, n);
1367
1368 return ret;
1369}
1370
1371/*
1372 * Load and parse a public key
1373 */
1374int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
1375{
1376 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1377 size_t n;
1378 unsigned char *buf;
1379
1380 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1381 return ret;
1382 }
1383
1384 ret = mbedtls_pk_parse_public_key(ctx, buf, n);
1385
1386 mbedtls_zeroize_and_free(buf, n);
1387
1388 return ret;
1389}
1390#endif /* MBEDTLS_FS_IO */
1391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392#endif /* MBEDTLS_PK_PARSE_C */