blob: a123743582ad458bf2e1f1664ec8331e3c4185c9 [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"
Manuel Pégourié-Gonnard5fcbe4c2023-07-06 13:02:51 +020028#include "mbedtls/platform.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000029#include "mbedtls/error.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020030
Rich Evans00ab4702015-02-06 13:43:58 +000031#include <string.h>
32
Manuel Pégourié-Gonnard5fcbe4c2023-07-06 13:02:51 +020033#if defined(MBEDTLS_USE_PSA_CRYPTO)
34#include "mbedtls/psa_util.h"
35#include "psa/crypto.h"
36#endif
37
Manuel Pégourié-Gonnardda88c382023-07-06 12:31:43 +020038/* Key types */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020039#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/rsa.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020041#endif
Valerio Setti81d75122023-06-14 14:49:33 +020042#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Manuel Pégourié-Gonnardda88c382023-07-06 12:31:43 +020043#include "mbedtls/ecp.h"
Valerio Setti4064dbb2023-05-17 15:33:07 +020044#include "pk_internal.h"
45#endif
Manuel Pégourié-Gonnardda88c382023-07-06 12:31:43 +020046
47/* Extended formats */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/pem.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020050#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/pkcs5.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020053#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#if defined(MBEDTLS_PKCS12_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000055#include "mbedtls/pkcs12.h"
Paul Bakker1a7550a2013-09-15 13:01:22 +020056#endif
57
Manuel Pégourié-Gonnard997a95e2023-07-26 15:18:30 +020058#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
59
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +020060/***********************************************************************
Paul Bakker1a7550a2013-09-15 13:01:22 +020061 *
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +020062 * ECC setters
63 *
64 * 1. This is an abstraction layer around MBEDTLS_PK_USE_PSA_EC_DATA:
65 * this macro will not appear outside this section.
66 * 2. All inputs are raw: no metadata, no ASN.1 until the next section.
67 *
68 **********************************************************************/
69
70/*
71 * Set the group used by this key.
Manuel Pégourié-Gonnardd1aa6422023-07-26 22:24:23 +020072 *
73 * [in/out] pk: in: must have been pk_setup() to an ECC type
74 * out: will have group (curve) information set
75 * [in] grp_in: a supported group ID (not NONE)
Paul Bakker1a7550a2013-09-15 13:01:22 +020076 */
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +020077static int pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
78{
79#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
80 size_t ec_bits;
81 psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);
82
83 /* group may already be initialized; if so, make sure IDs match */
84 if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||
85 (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {
86 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
87 }
88
89 /* set group */
90 pk->ec_family = ec_family;
91 pk->ec_bits = ec_bits;
92
93 return 0;
94#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
95 mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
96
97 /* grp may already be initialized; if so, make sure IDs match */
98 if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
99 mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
100 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
101 }
102
103 /* set group */
104 return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
105#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
106}
107
108/*
109 * Set the private key material
110 *
Manuel Pégourié-Gonnardd1aa6422023-07-26 22:24:23 +0200111 * [in/out] pk: in: must have the group set already, see pk_ecc_set_group().
112 * out: will have the private key set.
113 * [in] key, key_len: the raw private key (no ASN.1 wrapping).
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200114 */
115static int pk_ecc_set_key(mbedtls_pk_context *pk,
Manuel Pégourié-Gonnardd1aa6422023-07-26 22:24:23 +0200116 unsigned char *key, size_t key_len)
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200117{
118#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
119 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
120 psa_status_t status;
121
122 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));
123 psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
124 psa_key_usage_t flags = PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE;
125 /* Montgomery allows only ECDH, others ECDSA too */
126 if (pk->ec_family != PSA_ECC_FAMILY_MONTGOMERY) {
127 flags |= PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE;
128 psa_set_key_enrollment_algorithm(&attributes,
129 MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));
130 }
131 psa_set_key_usage_flags(&attributes, flags);
132
Manuel Pégourié-Gonnardd1aa6422023-07-26 22:24:23 +0200133 status = psa_import_key(&attributes, key, key_len, &pk->priv_id);
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200134 return psa_pk_status_to_mbedtls(status);
135
136#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
137
138 mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
Manuel Pégourié-Gonnardd1aa6422023-07-26 22:24:23 +0200139 int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200140 if (ret != 0) {
141 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
142 }
143 return 0;
144#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
145}
146
147/*
148 * Helper function for deriving a public key from its private counterpart.
149 *
150 * Note: the private key information is always available from pk,
151 * however for convenience the serialized version is also passed,
152 * as it's available at each calling site, and useful in some configs
153 * (as otherwise we're have to re-serialize it from the pk context).
154 */
155static int pk_derive_public_key(mbedtls_pk_context *pk,
156 const unsigned char *d, size_t d_len,
157 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
158{
159#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
160 psa_status_t status;
161 (void) f_rng;
162 (void) p_rng;
163 (void) d;
164 (void) d_len;
165
166 status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
167 &pk->pub_raw_len);
168 return psa_pk_status_to_mbedtls(status);
169#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */
170 int ret;
171 psa_status_t status;
172 (void) f_rng;
173 (void) p_rng;
174
175 mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
176 unsigned char key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
177 size_t key_len;
178 mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
179 psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
180 size_t curve_bits;
181 psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
182 psa_status_t destruction_status;
183
184 psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
185 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
186
187 status = psa_import_key(&key_attr, d, d_len, &key_id);
188 ret = psa_pk_status_to_mbedtls(status);
189 if (ret != 0) {
190 return ret;
191 }
192
193 status = psa_export_public_key(key_id, key_buf, sizeof(key_buf), &key_len);
194 ret = psa_pk_status_to_mbedtls(status);
195 destruction_status = psa_destroy_key(key_id);
196 if (ret != 0) {
197 return ret;
198 } else if (destruction_status != PSA_SUCCESS) {
199 return psa_pk_status_to_mbedtls(destruction_status);
200 }
201 return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, key_buf, key_len);
202#else /* MBEDTLS_USE_PSA_CRYPTO */
203 mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
204 (void) d;
205 (void) d_len;
206
207 return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
208#endif /* MBEDTLS_USE_PSA_CRYPTO */
209}
210
211#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
212/*
213 * Create a temporary ecp_keypair for converting an EC point in compressed
214 * format to an uncompressed one
215 *
216 * Consumes everything or fails - inherited from
217 * mbedtls_ecp_point_read_binary().
218 */
219static int pk_ecc_read_compressed(mbedtls_pk_context *pk,
220 const unsigned char *in_start, size_t in_len,
221 unsigned char *out_buf, size_t out_buf_size,
222 size_t *out_buf_len)
223{
224#if defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
225 mbedtls_ecp_keypair ecp_key;
226 mbedtls_ecp_group_id ecp_group_id;
227 int ret;
228
229 ecp_group_id = mbedtls_ecc_group_of_psa(pk->ec_family, pk->ec_bits, 0);
230
231 mbedtls_ecp_keypair_init(&ecp_key);
232 ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);
233 if (ret != 0) {
234 return ret;
235 }
236 ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,
237 in_start, in_len);
238 if (ret != 0) {
239 goto exit;
240 }
241 ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,
242 MBEDTLS_ECP_PF_UNCOMPRESSED,
243 out_buf_len, out_buf, out_buf_size);
244
245exit:
246 mbedtls_ecp_keypair_free(&ecp_key);
247 return ret;
248#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
249 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
250#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
251}
252#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
253
254/*
255 * EC public key is an EC point
256 *
257 * The caller is responsible for clearing the structure upon failure if
258 * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
259 * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
260 */
261static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end,
262 mbedtls_pk_context *pk)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200263{
Janos Follath24eed8d2019-11-22 13:21:35 +0000264 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200265
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200266#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
267 mbedtls_svc_key_id_t key;
268 psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
269 size_t len = (size_t) (end - *p);
270
271 if (len > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) {
272 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 }
Sanne Woudab2b29d52017-08-21 15:58:12 +0100274
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200275 if ((**p == 0x02) || (**p == 0x03)) {
276 /* Compressed format, not supported by PSA Crypto.
277 * Try converting using functions from ECP_LIGHT. */
278 ret = pk_ecc_read_compressed(pk, *p, len,
279 pk->pub_raw,
280 PSA_EXPORT_PUBLIC_KEY_MAX_SIZE,
281 &pk->pub_raw_len);
282 if (ret != 0) {
283 return ret;
284 }
285 } else {
286 /* Uncompressed format */
287 if (len > MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN) {
288 return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
289 }
290 memcpy(pk->pub_raw, *p, len);
291 pk->pub_raw_len = len;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100292 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200293
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200294 /* Validate the key by trying to importing it */
295 psa_set_key_usage_flags(&key_attrs, 0);
296 psa_set_key_algorithm(&key_attrs, PSA_ALG_ECDSA_ANY);
297 psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));
298 psa_set_key_bits(&key_attrs, pk->ec_bits);
299
300 if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,
301 &key) != PSA_SUCCESS) ||
302 (psa_destroy_key(key) != PSA_SUCCESS)) {
303 mbedtls_platform_zeroize(pk->pub_raw, MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN);
304 pk->pub_raw_len = 0;
305 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100306 }
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200307 ret = 0;
308#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
309 mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
310 if ((ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q,
311 (const unsigned char *) *p,
312 end - *p)) == 0) {
313 ret = mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 }
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200315#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200316
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200317 /*
318 * We know mbedtls_ecp_point_read_binary and pk_ecc_read_compressed either
319 * consumed all bytes or failed, and memcpy consumed all bytes too.
320 */
321 *p = (unsigned char *) end;
322
323 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200324}
325
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200326/***********************************************************************
327 *
328 * Unsorted (yet!) from this point on until the next section header
329 *
330 **********************************************************************/
331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200333/*
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100334 * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
335 * WARNING: the resulting group should only be used with
336 * pk_group_id_from_specified(), since its base point may not be set correctly
337 * if it was encoded compressed.
338 *
339 * SpecifiedECDomain ::= SEQUENCE {
340 * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
341 * fieldID FieldID {{FieldTypes}},
342 * curve Curve,
343 * base ECPoint,
344 * order INTEGER,
345 * cofactor INTEGER OPTIONAL,
346 * hash HashAlgorithm OPTIONAL,
347 * ...
348 * }
349 *
350 * We only support prime-field as field type, and ignore hash and cofactor.
351 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100352static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100353{
Janos Follath24eed8d2019-11-22 13:21:35 +0000354 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100355 unsigned char *p = params->p;
Jethro Beekman01672442023-04-19 14:08:14 +0200356 const unsigned char *const end = params->p + params->len;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100357 const unsigned char *end_field, *end_curve;
358 size_t len;
359 int ver;
360
361 /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) {
363 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
364 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 if (ver < 1 || ver > 3) {
367 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
368 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100369
370 /*
371 * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
372 * fieldType FIELD-ID.&id({IOSet}),
373 * parameters FIELD-ID.&Type({IOSet}{@fieldType})
374 * }
375 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
377 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
378 return ret;
379 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100380
381 end_field = p + len;
382
383 /*
384 * FIELD-ID ::= TYPE-IDENTIFIER
385 * FieldTypes FIELD-ID ::= {
386 * { Prime-p IDENTIFIED BY prime-field } |
387 * { Characteristic-two IDENTIFIED BY characteristic-two-field }
388 * }
389 * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
390 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100391 if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) {
392 return ret;
393 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100394
Gilles Peskine449bd832023-01-11 14:50:10 +0100395 if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) ||
396 memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) {
397 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100398 }
399
400 p += len;
401
402 /* Prime-p ::= INTEGER -- Field of size p. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) {
404 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
405 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100406
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 grp->pbits = mbedtls_mpi_bitlen(&grp->P);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100408
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 if (p != end_field) {
410 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
411 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
412 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100413
414 /*
415 * Curve ::= SEQUENCE {
416 * a FieldElement,
417 * b FieldElement,
418 * seed BIT STRING OPTIONAL
419 * -- Shall be present if used in SpecifiedECDomain
420 * -- with version equal to ecdpVer2 or ecdpVer3
421 * }
422 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
424 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
425 return ret;
426 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100427
428 end_curve = p + len;
429
430 /*
431 * FieldElement ::= OCTET STRING
432 * containing an integer in the case of a prime field
433 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
435 (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) {
436 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100437 }
438
439 p += len;
440
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
442 (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) {
443 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100444 }
445
446 p += len;
447
448 /* Ignore seed BIT STRING OPTIONAL */
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100450 p += len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100452
Gilles Peskine449bd832023-01-11 14:50:10 +0100453 if (p != end_curve) {
454 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
455 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
456 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100457
458 /*
459 * ECPoint ::= OCTET STRING
460 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
462 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
463 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100464
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G,
466 (const unsigned char *) p, len)) != 0) {
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100467 /*
468 * If we can't read the point because it's compressed, cheat by
469 * reading only the X coordinate and the parity bit of Y.
470 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
472 (p[0] != 0x02 && p[0] != 0x03) ||
473 len != mbedtls_mpi_size(&grp->P) + 1 ||
474 mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 ||
475 mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 ||
476 mbedtls_mpi_lset(&grp->G.Z, 1) != 0) {
477 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100478 }
479 }
480
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100481 p += len;
482
483 /*
484 * order INTEGER
485 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100486 if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) {
487 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
488 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100489
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 grp->nbits = mbedtls_mpi_bitlen(&grp->N);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100491
492 /*
493 * Allow optional elements by purposefully not enforcing p == end here.
494 */
495
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 return 0;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100497}
498
499/*
500 * Find the group id associated with an (almost filled) group as generated by
501 * pk_group_from_specified(), or return an error if unknown.
502 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100503static 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 +0100504{
Manuel Pégourié-Gonnard5b8c4092014-03-27 14:59:42 +0100505 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 mbedtls_ecp_group ref;
507 const mbedtls_ecp_group_id *id;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100508
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 mbedtls_ecp_group_init(&ref);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100510
Gilles Peskine449bd832023-01-11 14:50:10 +0100511 for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100512 /* Load the group associated to that id */
Gilles Peskine449bd832023-01-11 14:50:10 +0100513 mbedtls_ecp_group_free(&ref);
514 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id));
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100515
516 /* Compare to the group we were given, starting with easy tests */
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 if (grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
518 mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 &&
519 mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 &&
520 mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 &&
521 mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 &&
522 mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 &&
523 mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 &&
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100524 /* For Y we may only know the parity bit, so compare only that */
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 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 +0100526 break;
527 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100528 }
529
530cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100531 mbedtls_ecp_group_free(&ref);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100532
533 *grp_id = *id;
534
Gilles Peskine449bd832023-01-11 14:50:10 +0100535 if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100538
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100540}
541
542/*
543 * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
544 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100545static int pk_group_id_from_specified(const mbedtls_asn1_buf *params,
546 mbedtls_ecp_group_id *grp_id)
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100547{
Janos Follath24eed8d2019-11-22 13:21:35 +0000548 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100550
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 mbedtls_ecp_group_init(&grp);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100552
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 if ((ret = pk_group_from_specified(params, &grp)) != 0) {
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100554 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100556
Gilles Peskine449bd832023-01-11 14:50:10 +0100557 ret = pk_group_id_from_group(&grp, grp_id);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100558
559cleanup:
Minos Galanakis8692ec82023-01-20 15:27:32 +0000560 /* The API respecting lifecycle for mbedtls_ecp_group struct is
561 * _init(), _load() and _free(). In pk_group_id_from_specified() the
562 * temporary grp breaks that flow and it's members are populated
563 * by pk_group_id_from_group(). As such mbedtls_ecp_group_free()
564 * which is assuming a group populated by _setup() may not clean-up
565 * properly -> Manually free it's members.
566 */
Minos Galanakisc8e381a2023-01-19 16:08:34 +0000567 mbedtls_mpi_free(&grp.N);
568 mbedtls_mpi_free(&grp.P);
569 mbedtls_mpi_free(&grp.A);
570 mbedtls_mpi_free(&grp.B);
571 mbedtls_ecp_point_free(&grp.G);
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100572
Gilles Peskine449bd832023-01-11 14:50:10 +0100573 return ret;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100574}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100576
Valerio Setti4064dbb2023-05-17 15:33:07 +0200577
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200578/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200579 *
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200580 * ECParameters ::= CHOICE {
581 * namedCurve OBJECT IDENTIFIER
582 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
583 * -- implicitCurve NULL
584 * }
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200585 */
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200586static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
587 mbedtls_asn1_buf *params)
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200588{
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200589 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200590
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200591 if (end - *p < 1) {
592 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
593 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200594 }
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200595
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200596 /* Tag may be either OID or SEQUENCE */
597 params->tag = **p;
598 if (params->tag != MBEDTLS_ASN1_OID
599#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
600 && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
601#endif
602 ) {
603 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
604 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
605 }
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200606
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200607 if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200608 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
609 }
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200610
611 params->p = *p;
612 *p += params->len;
613
614 if (*p != end) {
615 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
616 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
617 }
618
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200619 return 0;
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200620}
621
622/*
Paul Bakker1a7550a2013-09-15 13:01:22 +0200623 * Use EC parameters to initialise an EC group
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100624 *
625 * ECParameters ::= CHOICE {
626 * namedCurve OBJECT IDENTIFIER
627 * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
628 * -- implicitCurve NULL
Paul Bakker1a7550a2013-09-15 13:01:22 +0200629 */
Valerio Setti4064dbb2023-05-17 15:33:07 +0200630static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200631{
Janos Follath24eed8d2019-11-22 13:21:35 +0000632 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 mbedtls_ecp_group_id grp_id;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200634
Gilles Peskine449bd832023-01-11 14:50:10 +0100635 if (params->tag == MBEDTLS_ASN1_OID) {
636 if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) {
637 return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
638 }
639 } else {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200640#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
Gilles Peskine449bd832023-01-11 14:50:10 +0100641 if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) {
642 return ret;
643 }
Manuel Pégourié-Gonnard6fac3512014-03-19 16:39:52 +0100644#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Manuel Pégourié-Gonnard6fac3512014-03-19 16:39:52 +0100646#endif
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +0100647 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200648
Manuel Pégourié-Gonnard25858522023-07-24 11:44:55 +0200649 return pk_ecc_set_group(pk, grp_id);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200650}
651
Jethro Beekman01672442023-04-19 14:08:14 +0200652#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
653
654/*
655 * Load an RFC8410 EC key, which doesn't have any parameters
656 */
657static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params,
658 mbedtls_ecp_group_id grp_id,
Valerio Setti4064dbb2023-05-17 15:33:07 +0200659 mbedtls_pk_context *pk)
Jethro Beekman01672442023-04-19 14:08:14 +0200660{
661 if (params->tag != 0 || params->len != 0) {
662 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
663 }
664
Manuel Pégourié-Gonnard25858522023-07-24 11:44:55 +0200665 return pk_ecc_set_group(pk, grp_id);
Jethro Beekman01672442023-04-19 14:08:14 +0200666}
667
668/*
669 * Parse an RFC 8410 encoded private EC key
670 *
671 * CurvePrivateKey ::= OCTET STRING
672 */
Valerio Setti4064dbb2023-05-17 15:33:07 +0200673static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
Jethro Beekman01672442023-04-19 14:08:14 +0200674 unsigned char *key, size_t keylen, const unsigned char *end,
675 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
676{
677 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
678 size_t len;
679
680 if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
681 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
682 }
683
684 if (key + len != end) {
685 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
686 }
687
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +0200688 /*
689 * Load the private key
690 */
691 ret = pk_ecc_set_key(pk, key, len);
692 if (ret != 0) {
Valerio Setti00e8dd12023-05-18 18:56:59 +0200693 return ret;
694 }
Jethro Beekman01672442023-04-19 14:08:14 +0200695
Valerio Setti4064dbb2023-05-17 15:33:07 +0200696 /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,
697 * which never contain a public key. As such, derive the public key
698 * unconditionally. */
699 if ((ret = pk_derive_public_key(pk, key, len, f_rng, p_rng)) != 0) {
Jethro Beekman01672442023-04-19 14:08:14 +0200700 return ret;
701 }
702
Jethro Beekman01672442023-04-19 14:08:14 +0200703 return 0;
704}
705#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
Valerio Setti4064dbb2023-05-17 15:33:07 +0200706
Valerio Setti81d75122023-06-14 14:49:33 +0200707#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200710/*
711 * RSAPublicKey ::= SEQUENCE {
712 * modulus INTEGER, -- n
713 * publicExponent INTEGER -- e
714 * }
715 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100716static int pk_get_rsapubkey(unsigned char **p,
717 const unsigned char *end,
718 mbedtls_rsa_context *rsa)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200719{
Janos Follath24eed8d2019-11-22 13:21:35 +0000720 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200721 size_t len;
722
Gilles Peskine449bd832023-01-11 14:50:10 +0100723 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
724 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
725 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
726 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200727
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 if (*p + len != end) {
729 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
730 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
731 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200732
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100733 /* Import N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
735 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
736 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200737
Gilles Peskine449bd832023-01-11 14:50:10 +0100738 if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0,
739 NULL, 0, NULL, 0)) != 0) {
740 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
741 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100742
743 *p += len;
744
745 /* Import E */
Gilles Peskine449bd832023-01-11 14:50:10 +0100746 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
747 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
748 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100749
Gilles Peskine449bd832023-01-11 14:50:10 +0100750 if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
751 NULL, 0, *p, len)) != 0) {
752 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
753 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100754
755 *p += len;
756
Gilles Peskine449bd832023-01-11 14:50:10 +0100757 if (mbedtls_rsa_complete(rsa) != 0 ||
758 mbedtls_rsa_check_pubkey(rsa) != 0) {
759 return MBEDTLS_ERR_PK_INVALID_PUBKEY;
Hanno Becker895c5ab2018-01-05 08:08:09 +0000760 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100761
Gilles Peskine449bd832023-01-11 14:50:10 +0100762 if (*p != end) {
763 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
764 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
765 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200766
Gilles Peskine449bd832023-01-11 14:50:10 +0100767 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200768}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +0200770
771/* Get a PK algorithm identifier
772 *
773 * AlgorithmIdentifier ::= SEQUENCE {
774 * algorithm OBJECT IDENTIFIER,
775 * parameters ANY DEFINED BY algorithm OPTIONAL }
776 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100777static int pk_get_pk_alg(unsigned char **p,
778 const unsigned char *end,
Jethro Beekman01672442023-04-19 14:08:14 +0200779 mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params,
780 mbedtls_ecp_group_id *ec_grp_id)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200781{
Janos Follath24eed8d2019-11-22 13:21:35 +0000782 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200783 mbedtls_asn1_buf alg_oid;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200784
Gilles Peskine449bd832023-01-11 14:50:10 +0100785 memset(params, 0, sizeof(mbedtls_asn1_buf));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200786
Gilles Peskine449bd832023-01-11 14:50:10 +0100787 if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) {
788 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
789 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200790
Jethro Beekman01672442023-04-19 14:08:14 +0200791 ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg);
Valerio Setti81d75122023-06-14 14:49:33 +0200792#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Jethro Beekman01672442023-04-19 14:08:14 +0200793 if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
794 ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id);
795 if (ret == 0) {
796 *pk_alg = MBEDTLS_PK_ECKEY;
797 }
798 }
799#else
800 (void) ec_grp_id;
801#endif
802 if (ret != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100803 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
804 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200805
806 /*
807 * No parameters with RSA (only for EC)
808 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100809 if (*pk_alg == MBEDTLS_PK_RSA &&
810 ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) ||
811 params->len != 0)) {
812 return MBEDTLS_ERR_PK_INVALID_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200813 }
814
Gilles Peskine449bd832023-01-11 14:50:10 +0100815 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200816}
817
Manuel Pégourié-Gonnard54708982023-07-26 15:38:36 +0200818/* Helper for Montgomery curves */
819#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
820#define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id) \
821 ((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448))
822#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
823
Paul Bakker1a7550a2013-09-15 13:01:22 +0200824/*
825 * SubjectPublicKeyInfo ::= SEQUENCE {
826 * algorithm AlgorithmIdentifier,
827 * subjectPublicKey BIT STRING }
828 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100829int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
830 mbedtls_pk_context *pk)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200831{
Janos Follath24eed8d2019-11-22 13:21:35 +0000832 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200833 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200834 mbedtls_asn1_buf alg_params;
835 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
Jethro Beekman01672442023-04-19 14:08:14 +0200836 mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200838
Gilles Peskine449bd832023-01-11 14:50:10 +0100839 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
840 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
841 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200842 }
843
844 end = *p + len;
845
Jethro Beekman01672442023-04-19 14:08:14 +0200846 if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100847 return ret;
848 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200849
Gilles Peskine449bd832023-01-11 14:50:10 +0100850 if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
851 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
852 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200853
Gilles Peskine449bd832023-01-11 14:50:10 +0100854 if (*p + len != end) {
855 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
856 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
857 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200858
Gilles Peskine449bd832023-01-11 14:50:10 +0100859 if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
860 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
861 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200862
Gilles Peskine449bd832023-01-11 14:50:10 +0100863 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
864 return ret;
865 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200866
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867#if defined(MBEDTLS_RSA_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100868 if (pk_alg == MBEDTLS_PK_RSA) {
869 ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk));
Paul Bakker1a7550a2013-09-15 13:01:22 +0200870 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871#endif /* MBEDTLS_RSA_C */
Valerio Setti81d75122023-06-14 14:49:33 +0200872#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Gilles Peskine449bd832023-01-11 14:50:10 +0100873 if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
Jethro Beekman01672442023-04-19 14:08:14 +0200874#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
Valerio Setti00e8dd12023-05-18 18:56:59 +0200875 if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
Valerio Setti4064dbb2023-05-17 15:33:07 +0200876 ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk);
Jethro Beekman01672442023-04-19 14:08:14 +0200877 } else
878#endif
879 {
Valerio Setti4064dbb2023-05-17 15:33:07 +0200880 ret = pk_use_ecparams(&alg_params, pk);
Jethro Beekman01672442023-04-19 14:08:14 +0200881 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100882 if (ret == 0) {
Valerio Setti4064dbb2023-05-17 15:33:07 +0200883 ret = pk_get_ecpubkey(p, end, pk);
Gilles Peskine449bd832023-01-11 14:50:10 +0100884 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200885 } else
Valerio Setti81d75122023-06-14 14:49:33 +0200886#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Gilles Peskine449bd832023-01-11 14:50:10 +0100887 ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200888
Gilles Peskine449bd832023-01-11 14:50:10 +0100889 if (ret == 0 && *p != end) {
890 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
891 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
892 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200893
Gilles Peskine449bd832023-01-11 14:50:10 +0100894 if (ret != 0) {
895 mbedtls_pk_free(pk);
896 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200897
Gilles Peskine449bd832023-01-11 14:50:10 +0100898 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200899}
900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200901#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200902/*
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100903 * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
904 *
905 * The value zero is:
906 * - never a valid value for an RSA parameter
907 * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
908 *
909 * Since values can't be omitted in PKCS#1, passing a zero value to
910 * rsa_complete() would be incorrect, so reject zero values early.
911 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100912static int asn1_get_nonzero_mpi(unsigned char **p,
913 const unsigned char *end,
914 mbedtls_mpi *X)
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100915{
916 int ret;
917
Gilles Peskine449bd832023-01-11 14:50:10 +0100918 ret = mbedtls_asn1_get_mpi(p, end, X);
919 if (ret != 0) {
920 return ret;
921 }
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100922
Gilles Peskine449bd832023-01-11 14:50:10 +0100923 if (mbedtls_mpi_cmp_int(X, 0) == 0) {
924 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
925 }
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100926
Gilles Peskine449bd832023-01-11 14:50:10 +0100927 return 0;
Manuel Pégourié-Gonnarda04a2c32020-02-18 10:12:14 +0100928}
929
930/*
Paul Bakker1a7550a2013-09-15 13:01:22 +0200931 * Parse a PKCS#1 encoded private RSA key
932 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100933static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa,
934 const unsigned char *key,
935 size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +0200936{
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100937 int ret, version;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200938 size_t len;
939 unsigned char *p, *end;
940
Hanno Beckerefa14e82017-10-11 19:45:19 +0100941 mbedtls_mpi T;
Gilles Peskine449bd832023-01-11 14:50:10 +0100942 mbedtls_mpi_init(&T);
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100943
Paul Bakker1a7550a2013-09-15 13:01:22 +0200944 p = (unsigned char *) key;
945 end = p + keylen;
946
947 /*
948 * This function parses the RSAPrivateKey (PKCS#1)
949 *
950 * RSAPrivateKey ::= SEQUENCE {
951 * version Version,
952 * modulus INTEGER, -- n
953 * publicExponent INTEGER, -- e
954 * privateExponent INTEGER, -- d
955 * prime1 INTEGER, -- p
956 * prime2 INTEGER, -- q
957 * exponent1 INTEGER, -- d mod (p-1)
958 * exponent2 INTEGER, -- d mod (q-1)
959 * coefficient INTEGER, -- (inverse of q) mod p
960 * otherPrimeInfos OtherPrimeInfos OPTIONAL
961 * }
962 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100963 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
964 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
965 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200966 }
967
968 end = p + len;
969
Gilles Peskine449bd832023-01-11 14:50:10 +0100970 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
971 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +0200972 }
973
Gilles Peskine449bd832023-01-11 14:50:10 +0100974 if (version != 0) {
975 return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
Paul Bakker1a7550a2013-09-15 13:01:22 +0200976 }
977
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100978 /* Import N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100979 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
980 (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
981 NULL, NULL)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100982 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100983 }
Paul Bakker1a7550a2013-09-15 13:01:22 +0200984
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100985 /* Import E */
Gilles Peskine449bd832023-01-11 14:50:10 +0100986 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
987 (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
988 NULL, &T)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100989 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100990 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100991
992 /* Import D */
Gilles Peskine449bd832023-01-11 14:50:10 +0100993 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
994 (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
995 &T, NULL)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100996 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100997 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +0100998
999 /* Import P */
Gilles Peskine449bd832023-01-11 14:50:10 +01001000 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
1001 (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
1002 NULL, NULL)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001003 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01001004 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001005
1006 /* Import Q */
Gilles Peskine449bd832023-01-11 14:50:10 +01001007 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
1008 (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
1009 NULL, NULL)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001010 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +01001011 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001012
Manuel Pégourié-Gonnardbbb5a0a2020-02-18 10:22:54 +01001013#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
Jack Lloyd8c2631b2020-01-23 17:23:52 -05001014 /*
Gilles Peskine449bd832023-01-11 14:50:10 +01001015 * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
1016 * that they can be easily recomputed from D, P and Q. However by
1017 * parsing them from the PKCS1 structure it is possible to avoid
1018 * recalculating them which both reduces the overhead of loading
1019 * RSA private keys into memory and also avoids side channels which
1020 * can arise when computing those values, since all of D, P, and Q
1021 * are secret. See https://eprint.iacr.org/2020/055 for a
1022 * description of one such attack.
1023 */
Jack Lloyd8c2631b2020-01-23 17:23:52 -05001024
Jack Lloyd80cc8112020-01-22 17:34:29 -05001025 /* Import DP */
Gilles Peskine449bd832023-01-11 14:50:10 +01001026 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
1027 (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
1028 goto cleanup;
1029 }
Jack Lloyd80cc8112020-01-22 17:34:29 -05001030
1031 /* Import DQ */
Gilles Peskine449bd832023-01-11 14:50:10 +01001032 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
1033 (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
1034 goto cleanup;
1035 }
Jack Lloyd80cc8112020-01-22 17:34:29 -05001036
1037 /* Import QP */
Gilles Peskine449bd832023-01-11 14:50:10 +01001038 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
1039 (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
1040 goto cleanup;
1041 }
Jack Lloyd2e9eef42020-01-28 14:43:52 -05001042
Jack Lloyd60239752020-01-27 17:53:36 -05001043#else
Shaun Case8b0ecbc2021-12-20 21:14:10 -08001044 /* Verify existence of the CRT params */
Gilles Peskine449bd832023-01-11 14:50:10 +01001045 if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
1046 (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
1047 (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
1048 goto cleanup;
1049 }
Jack Lloyd60239752020-01-27 17:53:36 -05001050#endif
Jack Lloyd80cc8112020-01-22 17:34:29 -05001051
Manuel Pégourié-Gonnardc4226792020-02-14 11:28:47 +01001052 /* rsa_complete() doesn't complete anything with the default
1053 * implementation but is still called:
1054 * - for the benefit of alternative implementation that may want to
1055 * pre-compute stuff beyond what's provided (eg Montgomery factors)
1056 * - as is also sanity-checks the key
1057 *
1058 * Furthermore, we also check the public part for consistency with
1059 * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
1060 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001061 if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
1062 (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001063 goto cleanup;
Manuel Pégourié-Gonnardc4226792020-02-14 11:28:47 +01001064 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001065
Gilles Peskine449bd832023-01-11 14:50:10 +01001066 if (p != end) {
1067 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
1068 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001069 }
1070
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001071cleanup:
1072
Gilles Peskine449bd832023-01-11 14:50:10 +01001073 mbedtls_mpi_free(&T);
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001074
Gilles Peskine449bd832023-01-11 14:50:10 +01001075 if (ret != 0) {
Hanno Beckerefa14e82017-10-11 19:45:19 +01001076 /* Wrap error code if it's coming from a lower level */
Gilles Peskine449bd832023-01-11 14:50:10 +01001077 if ((ret & 0xff80) == 0) {
1078 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1079 } else {
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001080 ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001081 }
Hanno Beckerd58c5b22017-08-22 14:33:21 +01001082
Gilles Peskine449bd832023-01-11 14:50:10 +01001083 mbedtls_rsa_free(rsa);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001084 }
1085
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001087}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001089
Valerio Setti81d75122023-06-14 14:49:33 +02001090#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001091/*
1092 * Parse a SEC1 encoded private EC key
1093 */
Valerio Setti4064dbb2023-05-17 15:33:07 +02001094static int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
Gilles Peskine449bd832023-01-11 14:50:10 +01001095 const unsigned char *key, size_t keylen,
1096 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001097{
Janos Follath24eed8d2019-11-22 13:21:35 +00001098 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +01001099 int version, pubkey_done;
Jethro Beekman01672442023-04-19 14:08:14 +02001100 size_t len, d_len;
Leonid Rozenboima3008e72022-04-21 17:28:18 -07001101 mbedtls_asn1_buf params = { 0, 0, NULL };
Paul Bakker1a7550a2013-09-15 13:01:22 +02001102 unsigned char *p = (unsigned char *) key;
Jethro Beekman01672442023-04-19 14:08:14 +02001103 unsigned char *d;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001104 unsigned char *end = p + keylen;
1105 unsigned char *end2;
1106
1107 /*
1108 * RFC 5915, or SEC1 Appendix C.4
1109 *
1110 * ECPrivateKey ::= SEQUENCE {
1111 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
1112 * privateKey OCTET STRING,
1113 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
1114 * publicKey [1] BIT STRING OPTIONAL
1115 * }
1116 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001117 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1118 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1119 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001120 }
1121
1122 end = p + len;
1123
Gilles Peskine449bd832023-01-11 14:50:10 +01001124 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
1125 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1126 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001127
Gilles Peskine449bd832023-01-11 14:50:10 +01001128 if (version != 1) {
1129 return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
1130 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001131
Gilles Peskine449bd832023-01-11 14:50:10 +01001132 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1133 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1134 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001135
Valerio Setti6b062ee2023-06-30 17:32:57 +02001136 /* Keep a reference to the position fo the private key. It will be used
1137 * later in this function. */
Jethro Beekman01672442023-04-19 14:08:14 +02001138 d = p;
1139 d_len = len;
Valerio Setti00e8dd12023-05-18 18:56:59 +02001140
Paul Bakker1a7550a2013-09-15 13:01:22 +02001141 p += len;
1142
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001143 pubkey_done = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +01001144 if (p != end) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001145 /*
1146 * Is 'parameters' present?
1147 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1149 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
1150 0)) == 0) {
1151 if ((ret = pk_get_ecparams(&p, p + len, &params)) != 0 ||
Valerio Setti4064dbb2023-05-17 15:33:07 +02001152 (ret = pk_use_ecparams(&params, pk)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001153 return ret;
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001154 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001155 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001156 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001157 }
Jethro Beekmand2df9362018-02-16 13:11:04 -08001158 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001159
Manuel Pégourié-Gonnarddcd98ff2023-07-25 11:58:31 +02001160 /*
1161 * Load the private key
1162 */
1163 ret = pk_ecc_set_key(pk, d, d_len);
1164 if (ret != 0) {
Manuel Pégourié-Gonnard6db11d52023-07-25 11:20:48 +02001165 return ret;
1166 }
Valerio Setti6b062ee2023-06-30 17:32:57 +02001167
Gilles Peskine449bd832023-01-11 14:50:10 +01001168 if (p != end) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001169 /*
1170 * Is 'publickey' present? If not, or if we can't read it (eg because it
1171 * is compressed), create it from the private key.
1172 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001173 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1174 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
1175 1)) == 0) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001176 end2 = p + len;
1177
Gilles Peskine449bd832023-01-11 14:50:10 +01001178 if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) {
1179 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1180 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001181
Gilles Peskine449bd832023-01-11 14:50:10 +01001182 if (p + len != end2) {
1183 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
1184 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1185 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001186
Valerio Setti4064dbb2023-05-17 15:33:07 +02001187 if ((ret = pk_get_ecpubkey(&p, end2, pk)) == 0) {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001188 pubkey_done = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001189 } else {
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001190 /*
1191 * The only acceptable failure mode of pk_get_ecpubkey() above
1192 * is if the point format is not recognized.
1193 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001194 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
1195 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1196 }
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001197 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001198 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001199 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Manuel Pégourié-Gonnard924cd102015-04-14 11:18:04 +02001200 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001201 }
Manuel Pégourié-Gonnardeab20d22014-03-14 17:58:42 +01001202
Valerio Setti34f67552023-04-03 15:19:18 +02001203 if (!pubkey_done) {
Valerio Setti4064dbb2023-05-17 15:33:07 +02001204 if ((ret = pk_derive_public_key(pk, d, d_len, f_rng, p_rng)) != 0) {
Valerio Setti520c0382023-04-07 11:38:09 +02001205 return ret;
Valerio Setti34f67552023-04-03 15:19:18 +02001206 }
Manuel Pégourié-Gonnardff29f9c2013-09-18 16:13:02 +02001207 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001208
Gilles Peskine449bd832023-01-11 14:50:10 +01001209 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001210}
Valerio Setti81d75122023-06-14 14:49:33 +02001211#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001212
Manuel Pégourié-Gonnard212517b2023-07-26 12:05:38 +02001213/***********************************************************************
1214 *
1215 * PKCS#8 parsing functions
1216 *
1217 **********************************************************************/
1218
Paul Bakker1a7550a2013-09-15 13:01:22 +02001219/*
1220 * Parse an unencrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +01001221 *
1222 * Notes:
1223 *
1224 * - This function does not own the key buffer. It is the
1225 * responsibility of the caller to take care of zeroizing
1226 * and freeing it after use.
1227 *
1228 * - The function is responsible for freeing the provided
1229 * PK context on failure.
1230 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001231 */
1232static int pk_parse_key_pkcs8_unencrypted_der(
Gilles Peskine449bd832023-01-11 14:50:10 +01001233 mbedtls_pk_context *pk,
1234 const unsigned char *key, size_t keylen,
1235 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001236{
1237 int ret, version;
1238 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 mbedtls_asn1_buf params;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001240 unsigned char *p = (unsigned char *) key;
1241 unsigned char *end = p + keylen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
Jethro Beekman01672442023-04-19 14:08:14 +02001243 mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001244 const mbedtls_pk_info_t *pk_info;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001245
Valerio Setti81d75122023-06-14 14:49:33 +02001246#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Manuel Pégourié-Gonnard609ab642021-06-16 14:29:11 +02001247 (void) f_rng;
1248 (void) p_rng;
1249#endif
1250
Paul Bakker1a7550a2013-09-15 13:01:22 +02001251 /*
Hanno Becker9c6cb382017-09-05 10:08:01 +01001252 * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001253 *
1254 * PrivateKeyInfo ::= SEQUENCE {
1255 * version Version,
1256 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
1257 * privateKey PrivateKey,
1258 * attributes [0] IMPLICIT Attributes OPTIONAL }
1259 *
1260 * Version ::= INTEGER
1261 * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
1262 * PrivateKey ::= OCTET STRING
1263 *
1264 * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
1265 */
1266
Gilles Peskine449bd832023-01-11 14:50:10 +01001267 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1268 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1269 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001270 }
1271
1272 end = p + len;
1273
Gilles Peskine449bd832023-01-11 14:50:10 +01001274 if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
1275 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Chris Jonesfdb588b2021-04-14 18:15:24 +01001276 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001277
Gilles Peskine449bd832023-01-11 14:50:10 +01001278 if (version != 0) {
1279 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
1280 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001281
Jethro Beekman01672442023-04-19 14:08:14 +02001282 if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params, &ec_grp_id)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001283 return ret;
1284 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001285
Gilles Peskine449bd832023-01-11 14:50:10 +01001286 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1287 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1288 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001289
Gilles Peskine449bd832023-01-11 14:50:10 +01001290 if (len < 1) {
1291 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
1292 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
1293 }
1294
1295 if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
1296 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1297 }
1298
1299 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
1300 return ret;
1301 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001303#if defined(MBEDTLS_RSA_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001304 if (pk_alg == MBEDTLS_PK_RSA) {
1305 if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) {
1306 mbedtls_pk_free(pk);
1307 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001308 }
1309 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310#endif /* MBEDTLS_RSA_C */
Valerio Setti81d75122023-06-14 14:49:33 +02001311#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Gilles Peskine449bd832023-01-11 14:50:10 +01001312 if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
Jethro Beekman01672442023-04-19 14:08:14 +02001313#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
Valerio Setti00e8dd12023-05-18 18:56:59 +02001314 if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
Valerio Setti4064dbb2023-05-17 15:33:07 +02001315 if ((ret =
1316 pk_use_ecparams_rfc8410(&params, ec_grp_id, pk)) != 0 ||
Jethro Beekman01672442023-04-19 14:08:14 +02001317 (ret =
Valerio Setti4064dbb2023-05-17 15:33:07 +02001318 pk_parse_key_rfc8410_der(pk, p, len, end, f_rng,
Jethro Beekman01672442023-04-19 14:08:14 +02001319 p_rng)) != 0) {
1320 mbedtls_pk_free(pk);
1321 return ret;
1322 }
1323 } else
1324#endif
1325 {
Valerio Setti4064dbb2023-05-17 15:33:07 +02001326 if ((ret = pk_use_ecparams(&params, pk)) != 0 ||
1327 (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) {
Jethro Beekman01672442023-04-19 14:08:14 +02001328 mbedtls_pk_free(pk);
1329 return ret;
1330 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001331 }
1332 } else
Valerio Setti81d75122023-06-14 14:49:33 +02001333#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001334 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001335
Waleed Elmelegyc9f40402023-08-08 15:28:15 +01001336 end = p + len;
1337 if (end != (key + keylen)) {
1338 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
1339 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1340 }
Waleed Elmelegyd5278962023-09-12 14:42:49 +01001341
Gilles Peskine449bd832023-01-11 14:50:10 +01001342 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001343}
1344
1345/*
1346 * Parse an encrypted PKCS#8 encoded private key
Hanno Beckerb4274212017-09-29 19:18:51 +01001347 *
1348 * To save space, the decryption happens in-place on the given key buffer.
1349 * Also, while this function may modify the keybuffer, it doesn't own it,
1350 * and instead it is the responsibility of the caller to zeroize and properly
1351 * free it after use.
1352 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Waleed Elmelegy1db5cda2023-09-20 18:00:48 +01001355MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(
Gilles Peskine449bd832023-01-11 14:50:10 +01001356 mbedtls_pk_context *pk,
1357 unsigned char *key, size_t keylen,
1358 const unsigned char *pwd, size_t pwdlen,
1359 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001360{
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001361 int ret, decrypted = 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001362 size_t len;
Hanno Beckerfab35692017-08-25 13:38:26 +01001363 unsigned char *buf;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001364 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 mbedtls_asn1_buf pbe_alg_oid, pbe_params;
1366#if defined(MBEDTLS_PKCS12_C)
1367 mbedtls_cipher_type_t cipher_alg;
1368 mbedtls_md_type_t md_alg;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001369#endif
Waleed Elmelegyc9f40402023-08-08 15:28:15 +01001370 size_t outlen = 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001371
Hanno Becker2aa80a72017-09-07 15:28:45 +01001372 p = key;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001373 end = p + keylen;
1374
Gilles Peskine449bd832023-01-11 14:50:10 +01001375 if (pwdlen == 0) {
1376 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1377 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001378
1379 /*
Hanno Beckerf04111f2017-09-29 19:18:42 +01001380 * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001381 *
1382 * EncryptedPrivateKeyInfo ::= SEQUENCE {
1383 * encryptionAlgorithm EncryptionAlgorithmIdentifier,
1384 * encryptedData EncryptedData
1385 * }
1386 *
1387 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
1388 *
1389 * EncryptedData ::= OCTET STRING
1390 *
1391 * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
Hanno Beckerb8d16572017-09-07 15:29:01 +01001392 *
Paul Bakker1a7550a2013-09-15 13:01:22 +02001393 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001394 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1395 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1396 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001397 }
1398
1399 end = p + len;
1400
Gilles Peskine449bd832023-01-11 14:50:10 +01001401 if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) {
1402 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1403 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001404
Gilles Peskine449bd832023-01-11 14:50:10 +01001405 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1406 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
1407 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001408
Hanno Beckerfab35692017-08-25 13:38:26 +01001409 buf = p;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001410
1411 /*
Hanno Beckerb8d16572017-09-07 15:29:01 +01001412 * Decrypt EncryptedData with appropriate PBE
Paul Bakker1a7550a2013-09-15 13:01:22 +02001413 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414#if defined(MBEDTLS_PKCS12_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001415 if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
Waleed Elmelegyd5278962023-09-12 14:42:49 +01001416 if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
Waleed Elmelegy5e48cad2023-09-12 14:52:48 +01001417 cipher_alg, md_alg,
1418 pwd, pwdlen, p, len, buf, len, &outlen)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001419 if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
1420 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1421 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001422
Gilles Peskine449bd832023-01-11 14:50:10 +01001423 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001424 }
Waleed Elmelegyd5278962023-09-12 14:42:49 +01001425
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001426 decrypted = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001427 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428#endif /* MBEDTLS_PKCS12_C */
1429#if defined(MBEDTLS_PKCS5_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001430 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
Waleed Elmelegyc9f40402023-08-08 15:28:15 +01001431 if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
1432 p, len, buf, len, &outlen)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001433 if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
1434 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1435 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001436
Gilles Peskine449bd832023-01-11 14:50:10 +01001437 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001438 }
Paul Bakkerf4cf80b2014-04-17 17:19:56 +02001439
1440 decrypted = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001441 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442#endif /* MBEDTLS_PKCS5_C */
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +02001443 {
1444 ((void) pwd);
Manuel Pégourié-Gonnard1032c1d2013-09-18 17:18:34 +02001445 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001446
Gilles Peskine449bd832023-01-11 14:50:10 +01001447 if (decrypted == 0) {
1448 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
1449 }
Waleed Elmelegyc9f40402023-08-08 15:28:15 +01001450 return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001451}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001453
Manuel Pégourié-Gonnard212517b2023-07-26 12:05:38 +02001454/***********************************************************************
1455 *
1456 * Top-level functions, with format auto-discovery
1457 *
1458 **********************************************************************/
1459
Paul Bakker1a7550a2013-09-15 13:01:22 +02001460/*
1461 * Parse a private key
1462 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001463int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
1464 const unsigned char *key, size_t keylen,
1465 const unsigned char *pwd, size_t pwdlen,
1466 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001467{
Janos Follath24eed8d2019-11-22 13:21:35 +00001468 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 const mbedtls_pk_info_t *pk_info;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001470#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001471 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001473#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001474
Gilles Peskine449bd832023-01-11 14:50:10 +01001475 if (keylen == 0) {
1476 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1477 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001478
1479#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001480 mbedtls_pem_init(&pem);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001483 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001484 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001485 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001486 } else {
1487 ret = mbedtls_pem_read_buffer(&pem,
1488 "-----BEGIN RSA PRIVATE KEY-----",
1489 "-----END RSA PRIVATE KEY-----",
1490 key, pwd, pwdlen, &len);
1491 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001492
Gilles Peskine449bd832023-01-11 14:50:10 +01001493 if (ret == 0) {
1494 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1495 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1496 (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk),
1497 pem.buf, pem.buflen)) != 0) {
1498 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001499 }
1500
Gilles Peskine449bd832023-01-11 14:50:10 +01001501 mbedtls_pem_free(&pem);
1502 return ret;
1503 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1504 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1505 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1506 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1507 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1508 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001509 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001511
Valerio Setti81d75122023-06-14 14:49:33 +02001512#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001513 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001514 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001515 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001516 } else {
1517 ret = mbedtls_pem_read_buffer(&pem,
1518 "-----BEGIN EC PRIVATE KEY-----",
1519 "-----END EC PRIVATE KEY-----",
1520 key, pwd, pwdlen, &len);
1521 }
1522 if (ret == 0) {
1523 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001524
Gilles Peskine449bd832023-01-11 14:50:10 +01001525 if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
Valerio Setti4064dbb2023-05-17 15:33:07 +02001526 (ret = pk_parse_key_sec1_der(pk,
Gilles Peskine449bd832023-01-11 14:50:10 +01001527 pem.buf, pem.buflen,
1528 f_rng, p_rng)) != 0) {
1529 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001530 }
1531
Gilles Peskine449bd832023-01-11 14:50:10 +01001532 mbedtls_pem_free(&pem);
1533 return ret;
1534 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1535 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1536 } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1537 return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1538 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1539 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001540 }
Valerio Setti81d75122023-06-14 14:49:33 +02001541#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001542
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001543 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001544 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001545 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001546 } else {
1547 ret = mbedtls_pem_read_buffer(&pem,
1548 "-----BEGIN PRIVATE KEY-----",
1549 "-----END PRIVATE KEY-----",
1550 key, NULL, 0, &len);
1551 }
1552 if (ret == 0) {
1553 if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk,
1554 pem.buf, pem.buflen, f_rng, p_rng)) != 0) {
1555 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001556 }
1557
Gilles Peskine449bd832023-01-11 14:50:10 +01001558 mbedtls_pem_free(&pem);
1559 return ret;
1560 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1561 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001562 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001565 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001566 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001567 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001568 } else {
1569 ret = mbedtls_pem_read_buffer(&pem,
1570 "-----BEGIN ENCRYPTED PRIVATE KEY-----",
1571 "-----END ENCRYPTED PRIVATE KEY-----",
1572 key, NULL, 0, &len);
1573 }
1574 if (ret == 0) {
Waleed Elmelegy1db5cda2023-09-20 18:00:48 +01001575 if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
1576 pwd, pwdlen, f_rng, p_rng)) != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +01001577 mbedtls_pk_free(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001578 }
1579
Gilles Peskine449bd832023-01-11 14:50:10 +01001580 mbedtls_pem_free(&pem);
1581 return ret;
1582 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1583 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001584 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001586#else
1587 ((void) pwd);
1588 ((void) pwdlen);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001590
1591 /*
Brian J Murray2adecba2016-11-06 04:45:15 -08001592 * At this point we only know it's not a PEM formatted key. Could be any
1593 * of the known DER encoded private key formats
1594 *
1595 * We try the different DER format parsers to see if one passes without
1596 * error
1597 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001599 if (pwdlen != 0) {
Hanno Beckerfab35692017-08-25 13:38:26 +01001600 unsigned char *key_copy;
1601
Gilles Peskine449bd832023-01-11 14:50:10 +01001602 if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) {
1603 return MBEDTLS_ERR_PK_ALLOC_FAILED;
1604 }
Hanno Beckerfab35692017-08-25 13:38:26 +01001605
Gilles Peskine449bd832023-01-11 14:50:10 +01001606 memcpy(key_copy, key, keylen);
Hanno Beckerfab35692017-08-25 13:38:26 +01001607
Waleed Elmelegy1db5cda2023-09-20 18:00:48 +01001608 ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
1609 pwd, pwdlen, f_rng, p_rng);
Hanno Beckerfab35692017-08-25 13:38:26 +01001610
Tom Cosgroveca8c61b2023-07-17 15:17:40 +01001611 mbedtls_zeroize_and_free(key_copy, keylen);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001612 }
1613
Gilles Peskine449bd832023-01-11 14:50:10 +01001614 if (ret == 0) {
1615 return 0;
1616 }
Hanno Beckerfab35692017-08-25 13:38:26 +01001617
Gilles Peskine449bd832023-01-11 14:50:10 +01001618 mbedtls_pk_free(pk);
1619 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001620
Gilles Peskine449bd832023-01-11 14:50:10 +01001621 if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {
1622 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001623 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001625
Gilles Peskine449bd832023-01-11 14:50:10 +01001626 ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng);
1627 if (ret == 0) {
1628 return 0;
Manuel Pégourié-Gonnard84dea012021-06-15 11:29:26 +02001629 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001630
Gilles Peskine449bd832023-01-11 14:50:10 +01001631 mbedtls_pk_free(pk);
1632 mbedtls_pk_init(pk);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634#if defined(MBEDTLS_RSA_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001635
Gilles Peskine449bd832023-01-11 14:50:10 +01001636 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1637 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1638 pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
1639 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001640 }
1641
Gilles Peskine449bd832023-01-11 14:50:10 +01001642 mbedtls_pk_free(pk);
1643 mbedtls_pk_init(pk);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001645
Valerio Setti81d75122023-06-14 14:49:33 +02001646#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
Gilles Peskine449bd832023-01-11 14:50:10 +01001647 pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1648 if (mbedtls_pk_setup(pk, pk_info) == 0 &&
Valerio Setti4064dbb2023-05-17 15:33:07 +02001649 pk_parse_key_sec1_der(pk,
Gilles Peskine449bd832023-01-11 14:50:10 +01001650 key, keylen, f_rng, p_rng) == 0) {
1651 return 0;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001652 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001653 mbedtls_pk_free(pk);
Valerio Setti81d75122023-06-14 14:49:33 +02001654#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001655
Valerio Setti81d75122023-06-14 14:49:33 +02001656 /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't,
Hanno Becker780f0a42018-10-10 11:23:33 +01001657 * it is ok to leave the PK context initialized but not
1658 * freed: It is the caller's responsibility to call pk_init()
1659 * before calling this function, and to call pk_free()
Valerio Setti81d75122023-06-14 14:49:33 +02001660 * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C
Hanno Becker780f0a42018-10-10 11:23:33 +01001661 * isn't, this leads to mbedtls_pk_free() being called
1662 * twice, once here and once by the caller, but this is
1663 * also ok and in line with the mbedtls_pk_free() calls
1664 * on failed PEM parsing attempts. */
1665
Gilles Peskine449bd832023-01-11 14:50:10 +01001666 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001667}
1668
1669/*
1670 * Parse a public key
1671 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001672int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
1673 const unsigned char *key, size_t keylen)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001674{
Janos Follath24eed8d2019-11-22 13:21:35 +00001675 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001676 unsigned char *p;
Ron Eldor5472d432017-10-17 09:49:00 +03001677#if defined(MBEDTLS_RSA_C)
1678 const mbedtls_pk_info_t *pk_info;
1679#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680#if defined(MBEDTLS_PEM_PARSE_C)
Paul Bakker1a7550a2013-09-15 13:01:22 +02001681 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001683#endif
Paul Bakker1a7550a2013-09-15 13:01:22 +02001684
Gilles Peskine449bd832023-01-11 14:50:10 +01001685 if (keylen == 0) {
1686 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1687 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -05001688
1689#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001690 mbedtls_pem_init(&pem);
Ron Eldord0c56de2017-10-10 17:03:08 +03001691#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001692 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001693 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001694 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001695 } else {
1696 ret = mbedtls_pem_read_buffer(&pem,
1697 "-----BEGIN RSA PUBLIC KEY-----",
1698 "-----END RSA PUBLIC KEY-----",
1699 key, NULL, 0, &len);
Ron Eldord0c56de2017-10-10 17:03:08 +03001700 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001701
1702 if (ret == 0) {
1703 p = pem.buf;
1704 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1705 mbedtls_pem_free(&pem);
1706 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1707 }
1708
1709 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1710 mbedtls_pem_free(&pem);
1711 return ret;
1712 }
1713
1714 if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) {
1715 mbedtls_pk_free(ctx);
1716 }
1717
1718 mbedtls_pem_free(&pem);
1719 return ret;
1720 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1721 mbedtls_pem_free(&pem);
1722 return ret;
Ron Eldord0c56de2017-10-10 17:03:08 +03001723 }
1724#endif /* MBEDTLS_RSA_C */
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001725
1726 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +01001727 if (key[keylen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001728 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +01001729 } else {
1730 ret = mbedtls_pem_read_buffer(&pem,
1731 "-----BEGIN PUBLIC KEY-----",
1732 "-----END PUBLIC KEY-----",
1733 key, NULL, 0, &len);
1734 }
Paul Bakker1a7550a2013-09-15 13:01:22 +02001735
Gilles Peskine449bd832023-01-11 14:50:10 +01001736 if (ret == 0) {
Paul Bakker1a7550a2013-09-15 13:01:22 +02001737 /*
1738 * Was PEM encoded
1739 */
Ron Eldor40b14a82017-10-16 19:30:00 +03001740 p = pem.buf;
1741
Jethro Beekman01672442023-04-19 14:08:14 +02001742 ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
Gilles Peskine449bd832023-01-11 14:50:10 +01001743 mbedtls_pem_free(&pem);
1744 return ret;
1745 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1746 mbedtls_pem_free(&pem);
1747 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001748 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001749 mbedtls_pem_free(&pem);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750#endif /* MBEDTLS_PEM_PARSE_C */
Ron Eldor40b14a82017-10-16 19:30:00 +03001751
1752#if defined(MBEDTLS_RSA_C)
Gilles Peskine449bd832023-01-11 14:50:10 +01001753 if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1754 return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
Ron Eldor40b14a82017-10-16 19:30:00 +03001755 }
Gilles Peskine449bd832023-01-11 14:50:10 +01001756
1757 if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1758 return ret;
1759 }
1760
1761 p = (unsigned char *) key;
1762 ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
1763 if (ret == 0) {
1764 return ret;
1765 }
1766 mbedtls_pk_free(ctx);
1767 if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
1768 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
1769 return ret;
Ron Eldor40b14a82017-10-16 19:30:00 +03001770 }
1771#endif /* MBEDTLS_RSA_C */
Paul Bakker1a7550a2013-09-15 13:01:22 +02001772 p = (unsigned char *) key;
1773
Gilles Peskine449bd832023-01-11 14:50:10 +01001774 ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);
Paul Bakker1a7550a2013-09-15 13:01:22 +02001775
Gilles Peskine449bd832023-01-11 14:50:10 +01001776 return ret;
Paul Bakker1a7550a2013-09-15 13:01:22 +02001777}
1778
Manuel Pégourié-Gonnard212517b2023-07-26 12:05:38 +02001779/***********************************************************************
1780 *
1781 * Top-level functions, with filesystem support
1782 *
1783 **********************************************************************/
1784
1785#if defined(MBEDTLS_FS_IO)
1786/*
1787 * Load all data from a file into a given buffer.
1788 *
1789 * The file is expected to contain either PEM or DER encoded data.
1790 * A terminating null byte is always appended. It is included in the announced
1791 * length only if the data looks like it is PEM encoded.
1792 */
1793int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
1794{
1795 FILE *f;
1796 long size;
1797
1798 if ((f = fopen(path, "rb")) == NULL) {
1799 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1800 }
1801
1802 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
1803 mbedtls_setbuf(f, NULL);
1804
1805 fseek(f, 0, SEEK_END);
1806 if ((size = ftell(f)) == -1) {
1807 fclose(f);
1808 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1809 }
1810 fseek(f, 0, SEEK_SET);
1811
1812 *n = (size_t) size;
1813
1814 if (*n + 1 == 0 ||
1815 (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
1816 fclose(f);
1817 return MBEDTLS_ERR_PK_ALLOC_FAILED;
1818 }
1819
1820 if (fread(*buf, 1, *n, f) != *n) {
1821 fclose(f);
1822
1823 mbedtls_zeroize_and_free(*buf, *n);
1824
1825 return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1826 }
1827
1828 fclose(f);
1829
1830 (*buf)[*n] = '\0';
1831
1832 if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
1833 ++*n;
1834 }
1835
1836 return 0;
1837}
1838
1839/*
1840 * Load and parse a private key
1841 */
1842int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
1843 const char *path, const char *pwd,
1844 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1845{
1846 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1847 size_t n;
1848 unsigned char *buf;
1849
1850 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1851 return ret;
1852 }
1853
1854 if (pwd == NULL) {
1855 ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
1856 } else {
1857 ret = mbedtls_pk_parse_key(ctx, buf, n,
1858 (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
1859 }
1860
1861 mbedtls_zeroize_and_free(buf, n);
1862
1863 return ret;
1864}
1865
1866/*
1867 * Load and parse a public key
1868 */
1869int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
1870{
1871 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1872 size_t n;
1873 unsigned char *buf;
1874
1875 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1876 return ret;
1877 }
1878
1879 ret = mbedtls_pk_parse_public_key(ctx, buf, n);
1880
1881 mbedtls_zeroize_and_free(buf, n);
1882
1883 return ret;
1884}
1885#endif /* MBEDTLS_FS_IO */
1886
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001887#endif /* MBEDTLS_PK_PARSE_C */