1817466cbSJens Wiklander /*
2817466cbSJens Wiklander * Public Key layer for parsing key files and structures
3817466cbSJens Wiklander *
47901324dSJerome Forissier * Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6817466cbSJens Wiklander */
7817466cbSJens Wiklander
87901324dSJerome Forissier #include "common.h"
9817466cbSJens Wiklander
10817466cbSJens Wiklander #if defined(MBEDTLS_PK_PARSE_C)
11817466cbSJens Wiklander
12817466cbSJens Wiklander #include "mbedtls/pk.h"
13817466cbSJens Wiklander #include "mbedtls/asn1.h"
14817466cbSJens Wiklander #include "mbedtls/oid.h"
153d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
16*b0563631STom Van Eyck #include "mbedtls/platform.h"
1711fa71b9SJerome Forissier #include "mbedtls/error.h"
18*b0563631STom Van Eyck #include "mbedtls/ecp.h"
19*b0563631STom Van Eyck #include "pk_internal.h"
20817466cbSJens Wiklander
21817466cbSJens Wiklander #include <string.h>
22817466cbSJens Wiklander
23*b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
24*b0563631STom Van Eyck #include "mbedtls/psa_util.h"
25*b0563631STom Van Eyck #include "psa/crypto.h"
26*b0563631STom Van Eyck #endif
27*b0563631STom Van Eyck
28*b0563631STom Van Eyck /* Key types */
29817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
30817466cbSJens Wiklander #include "mbedtls/rsa.h"
31*b0563631STom Van Eyck #include "rsa_internal.h"
32817466cbSJens Wiklander #endif
33*b0563631STom Van Eyck
34*b0563631STom Van Eyck /* Extended formats */
35817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
36817466cbSJens Wiklander #include "mbedtls/pem.h"
37817466cbSJens Wiklander #endif
38817466cbSJens Wiklander #if defined(MBEDTLS_PKCS5_C)
39817466cbSJens Wiklander #include "mbedtls/pkcs5.h"
40817466cbSJens Wiklander #endif
41817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C)
42817466cbSJens Wiklander #include "mbedtls/pkcs12.h"
43817466cbSJens Wiklander #endif
44817466cbSJens Wiklander
45*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
46817466cbSJens Wiklander
47*b0563631STom Van Eyck /***********************************************************************
48817466cbSJens Wiklander *
49*b0563631STom Van Eyck * Low-level ECC parsing: optional support for SpecifiedECDomain
50*b0563631STom Van Eyck *
51*b0563631STom Van Eyck * There are two functions here that are used by the rest of the code:
52*b0563631STom Van Eyck * - pk_ecc_tag_is_speficied_ec_domain()
53*b0563631STom Van Eyck * - pk_ecc_group_id_from_specified()
54*b0563631STom Van Eyck *
55*b0563631STom Van Eyck * All the other functions are internal to this section.
56*b0563631STom Van Eyck *
57*b0563631STom Van Eyck * The two "public" functions have a dummy variant provided
58*b0563631STom Van Eyck * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an
59*b0563631STom Van Eyck * abstraction layer for this macro, which should not appear outside
60*b0563631STom Van Eyck * this section.
61*b0563631STom Van Eyck *
62*b0563631STom Van Eyck **********************************************************************/
63*b0563631STom Van Eyck
64*b0563631STom Van Eyck #if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
65*b0563631STom Van Eyck /* See the "real" version for documentation */
pk_ecc_tag_is_specified_ec_domain(int tag)66*b0563631STom Van Eyck static int pk_ecc_tag_is_specified_ec_domain(int tag)
67817466cbSJens Wiklander {
68*b0563631STom Van Eyck (void) tag;
6932b31808SJens Wiklander return 0;
70817466cbSJens Wiklander }
71817466cbSJens Wiklander
72*b0563631STom Van Eyck /* See the "real" version for documentation */
pk_ecc_group_id_from_specified(const mbedtls_asn1_buf * params,mbedtls_ecp_group_id * grp_id)73*b0563631STom Van Eyck static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
74*b0563631STom Van Eyck mbedtls_ecp_group_id *grp_id)
75*b0563631STom Van Eyck {
76*b0563631STom Van Eyck (void) params;
77*b0563631STom Van Eyck (void) grp_id;
78*b0563631STom Van Eyck return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
79*b0563631STom Van Eyck }
80*b0563631STom Van Eyck #else /* MBEDTLS_PK_PARSE_EC_EXTENDED */
81817466cbSJens Wiklander /*
82*b0563631STom Van Eyck * Tell if the passed tag might be the start of SpecifiedECDomain
83*b0563631STom Van Eyck * (that is, a sequence).
84817466cbSJens Wiklander */
pk_ecc_tag_is_specified_ec_domain(int tag)85*b0563631STom Van Eyck static int pk_ecc_tag_is_specified_ec_domain(int tag)
86817466cbSJens Wiklander {
87*b0563631STom Van Eyck return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
8832b31808SJens Wiklander }
893d3b0591SJens Wiklander
90817466cbSJens Wiklander /*
91817466cbSJens Wiklander * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
92817466cbSJens Wiklander * WARNING: the resulting group should only be used with
93*b0563631STom Van Eyck * pk_ecc_group_id_from_specified(), since its base point may not be set correctly
94817466cbSJens Wiklander * if it was encoded compressed.
95817466cbSJens Wiklander *
96817466cbSJens Wiklander * SpecifiedECDomain ::= SEQUENCE {
97817466cbSJens Wiklander * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
98817466cbSJens Wiklander * fieldID FieldID {{FieldTypes}},
99817466cbSJens Wiklander * curve Curve,
100817466cbSJens Wiklander * base ECPoint,
101817466cbSJens Wiklander * order INTEGER,
102817466cbSJens Wiklander * cofactor INTEGER OPTIONAL,
103817466cbSJens Wiklander * hash HashAlgorithm OPTIONAL,
104817466cbSJens Wiklander * ...
105817466cbSJens Wiklander * }
106817466cbSJens Wiklander *
107817466cbSJens Wiklander * We only support prime-field as field type, and ignore hash and cofactor.
108817466cbSJens Wiklander */
pk_group_from_specified(const mbedtls_asn1_buf * params,mbedtls_ecp_group * grp)109817466cbSJens Wiklander static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
110817466cbSJens Wiklander {
11111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
112817466cbSJens Wiklander unsigned char *p = params->p;
113817466cbSJens Wiklander const unsigned char *const end = params->p + params->len;
114817466cbSJens Wiklander const unsigned char *end_field, *end_curve;
115817466cbSJens Wiklander size_t len;
116817466cbSJens Wiklander int ver;
117817466cbSJens Wiklander
118817466cbSJens Wiklander /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
11932b31808SJens Wiklander if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) {
12032b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
12132b31808SJens Wiklander }
122817466cbSJens Wiklander
12332b31808SJens Wiklander if (ver < 1 || ver > 3) {
12432b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
12532b31808SJens Wiklander }
126817466cbSJens Wiklander
127817466cbSJens Wiklander /*
128817466cbSJens Wiklander * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
129817466cbSJens Wiklander * fieldType FIELD-ID.&id({IOSet}),
130817466cbSJens Wiklander * parameters FIELD-ID.&Type({IOSet}{@fieldType})
131817466cbSJens Wiklander * }
132817466cbSJens Wiklander */
133817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
13432b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
13532b31808SJens Wiklander return ret;
13632b31808SJens Wiklander }
137817466cbSJens Wiklander
138817466cbSJens Wiklander end_field = p + len;
139817466cbSJens Wiklander
140817466cbSJens Wiklander /*
141817466cbSJens Wiklander * FIELD-ID ::= TYPE-IDENTIFIER
142817466cbSJens Wiklander * FieldTypes FIELD-ID ::= {
143817466cbSJens Wiklander * { Prime-p IDENTIFIED BY prime-field } |
144817466cbSJens Wiklander * { Characteristic-two IDENTIFIED BY characteristic-two-field }
145817466cbSJens Wiklander * }
146817466cbSJens Wiklander * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
147817466cbSJens Wiklander */
14832b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) {
14932b31808SJens Wiklander return ret;
15032b31808SJens Wiklander }
151817466cbSJens Wiklander
152817466cbSJens Wiklander if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) ||
15332b31808SJens Wiklander memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) {
15432b31808SJens Wiklander return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
155817466cbSJens Wiklander }
156817466cbSJens Wiklander
157817466cbSJens Wiklander p += len;
158817466cbSJens Wiklander
159817466cbSJens Wiklander /* Prime-p ::= INTEGER -- Field of size p. */
16032b31808SJens Wiklander if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) {
16132b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
16232b31808SJens Wiklander }
163817466cbSJens Wiklander
164817466cbSJens Wiklander grp->pbits = mbedtls_mpi_bitlen(&grp->P);
165817466cbSJens Wiklander
16632b31808SJens Wiklander if (p != end_field) {
16732b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
16832b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
16932b31808SJens Wiklander }
170817466cbSJens Wiklander
171817466cbSJens Wiklander /*
172817466cbSJens Wiklander * Curve ::= SEQUENCE {
173817466cbSJens Wiklander * a FieldElement,
174817466cbSJens Wiklander * b FieldElement,
175817466cbSJens Wiklander * seed BIT STRING OPTIONAL
176817466cbSJens Wiklander * -- Shall be present if used in SpecifiedECDomain
177817466cbSJens Wiklander * -- with version equal to ecdpVer2 or ecdpVer3
178817466cbSJens Wiklander * }
179817466cbSJens Wiklander */
180817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
18132b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
18232b31808SJens Wiklander return ret;
18332b31808SJens Wiklander }
184817466cbSJens Wiklander
185817466cbSJens Wiklander end_curve = p + len;
186817466cbSJens Wiklander
187817466cbSJens Wiklander /*
188817466cbSJens Wiklander * FieldElement ::= OCTET STRING
189817466cbSJens Wiklander * containing an integer in the case of a prime field
190817466cbSJens Wiklander */
191817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
19232b31808SJens Wiklander (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) {
19332b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
194817466cbSJens Wiklander }
195817466cbSJens Wiklander
196817466cbSJens Wiklander p += len;
197817466cbSJens Wiklander
198817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
19932b31808SJens Wiklander (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) {
20032b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
201817466cbSJens Wiklander }
202817466cbSJens Wiklander
203817466cbSJens Wiklander p += len;
204817466cbSJens Wiklander
205817466cbSJens Wiklander /* Ignore seed BIT STRING OPTIONAL */
20632b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) {
207817466cbSJens Wiklander p += len;
20832b31808SJens Wiklander }
209817466cbSJens Wiklander
21032b31808SJens Wiklander if (p != end_curve) {
21132b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
21232b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
21332b31808SJens Wiklander }
214817466cbSJens Wiklander
215817466cbSJens Wiklander /*
216817466cbSJens Wiklander * ECPoint ::= OCTET STRING
217817466cbSJens Wiklander */
21832b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
21932b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
22032b31808SJens Wiklander }
221817466cbSJens Wiklander
222817466cbSJens Wiklander if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G,
22332b31808SJens Wiklander (const unsigned char *) p, len)) != 0) {
224817466cbSJens Wiklander /*
225817466cbSJens Wiklander * If we can't read the point because it's compressed, cheat by
226817466cbSJens Wiklander * reading only the X coordinate and the parity bit of Y.
227817466cbSJens Wiklander */
228817466cbSJens Wiklander if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
229817466cbSJens Wiklander (p[0] != 0x02 && p[0] != 0x03) ||
230817466cbSJens Wiklander len != mbedtls_mpi_size(&grp->P) + 1 ||
231817466cbSJens Wiklander mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 ||
232817466cbSJens Wiklander mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 ||
23332b31808SJens Wiklander mbedtls_mpi_lset(&grp->G.Z, 1) != 0) {
23432b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
235817466cbSJens Wiklander }
236817466cbSJens Wiklander }
237817466cbSJens Wiklander
238817466cbSJens Wiklander p += len;
239817466cbSJens Wiklander
240817466cbSJens Wiklander /*
241817466cbSJens Wiklander * order INTEGER
242817466cbSJens Wiklander */
24332b31808SJens Wiklander if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) {
24432b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
24532b31808SJens Wiklander }
246817466cbSJens Wiklander
247817466cbSJens Wiklander grp->nbits = mbedtls_mpi_bitlen(&grp->N);
248817466cbSJens Wiklander
249817466cbSJens Wiklander /*
250817466cbSJens Wiklander * Allow optional elements by purposefully not enforcing p == end here.
251817466cbSJens Wiklander */
252817466cbSJens Wiklander
25332b31808SJens Wiklander return 0;
254817466cbSJens Wiklander }
255817466cbSJens Wiklander
256817466cbSJens Wiklander /*
257817466cbSJens Wiklander * Find the group id associated with an (almost filled) group as generated by
258817466cbSJens Wiklander * pk_group_from_specified(), or return an error if unknown.
259817466cbSJens Wiklander */
pk_group_id_from_group(const mbedtls_ecp_group * grp,mbedtls_ecp_group_id * grp_id)260817466cbSJens Wiklander static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id)
261817466cbSJens Wiklander {
262817466cbSJens Wiklander int ret = 0;
263817466cbSJens Wiklander mbedtls_ecp_group ref;
264817466cbSJens Wiklander const mbedtls_ecp_group_id *id;
265817466cbSJens Wiklander
266817466cbSJens Wiklander mbedtls_ecp_group_init(&ref);
267817466cbSJens Wiklander
26832b31808SJens Wiklander for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) {
269817466cbSJens Wiklander /* Load the group associated to that id */
270817466cbSJens Wiklander mbedtls_ecp_group_free(&ref);
271817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id));
272817466cbSJens Wiklander
273817466cbSJens Wiklander /* Compare to the group we were given, starting with easy tests */
274817466cbSJens Wiklander if (grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
275817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 &&
276817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 &&
277817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 &&
278817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 &&
279817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 &&
280817466cbSJens Wiklander mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 &&
281817466cbSJens Wiklander /* For Y we may only know the parity bit, so compare only that */
28232b31808SJens Wiklander mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) {
283817466cbSJens Wiklander break;
284817466cbSJens Wiklander }
285817466cbSJens Wiklander }
286817466cbSJens Wiklander
287817466cbSJens Wiklander cleanup:
288817466cbSJens Wiklander mbedtls_ecp_group_free(&ref);
289817466cbSJens Wiklander
290817466cbSJens Wiklander *grp_id = *id;
291817466cbSJens Wiklander
29232b31808SJens Wiklander if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) {
293817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
29432b31808SJens Wiklander }
295817466cbSJens Wiklander
29632b31808SJens Wiklander return ret;
297817466cbSJens Wiklander }
298817466cbSJens Wiklander
299817466cbSJens Wiklander /*
300817466cbSJens Wiklander * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
301817466cbSJens Wiklander */
pk_ecc_group_id_from_specified(const mbedtls_asn1_buf * params,mbedtls_ecp_group_id * grp_id)302*b0563631STom Van Eyck static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
303817466cbSJens Wiklander mbedtls_ecp_group_id *grp_id)
304817466cbSJens Wiklander {
30511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
306817466cbSJens Wiklander mbedtls_ecp_group grp;
307817466cbSJens Wiklander
308817466cbSJens Wiklander mbedtls_ecp_group_init(&grp);
309817466cbSJens Wiklander
31032b31808SJens Wiklander if ((ret = pk_group_from_specified(params, &grp)) != 0) {
311817466cbSJens Wiklander goto cleanup;
31232b31808SJens Wiklander }
313817466cbSJens Wiklander
314817466cbSJens Wiklander ret = pk_group_id_from_group(&grp, grp_id);
315817466cbSJens Wiklander
316817466cbSJens Wiklander cleanup:
31732b31808SJens Wiklander /* The API respecting lifecycle for mbedtls_ecp_group struct is
318*b0563631STom Van Eyck * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the
31932b31808SJens Wiklander * temporary grp breaks that flow and it's members are populated
32032b31808SJens Wiklander * by pk_group_id_from_group(). As such mbedtls_ecp_group_free()
32132b31808SJens Wiklander * which is assuming a group populated by _setup() may not clean-up
32232b31808SJens Wiklander * properly -> Manually free it's members.
32332b31808SJens Wiklander */
32432b31808SJens Wiklander mbedtls_mpi_free(&grp.N);
32532b31808SJens Wiklander mbedtls_mpi_free(&grp.P);
32632b31808SJens Wiklander mbedtls_mpi_free(&grp.A);
32732b31808SJens Wiklander mbedtls_mpi_free(&grp.B);
32832b31808SJens Wiklander mbedtls_ecp_point_free(&grp.G);
329817466cbSJens Wiklander
33032b31808SJens Wiklander return ret;
331817466cbSJens Wiklander }
332817466cbSJens Wiklander #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
333817466cbSJens Wiklander
334*b0563631STom Van Eyck /***********************************************************************
335*b0563631STom Van Eyck *
336*b0563631STom Van Eyck * Unsorted (yet!) from this point on until the next section header
337*b0563631STom Van Eyck *
338*b0563631STom Van Eyck **********************************************************************/
339*b0563631STom Van Eyck
340*b0563631STom Van Eyck /* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
341*b0563631STom Van Eyck *
342*b0563631STom Van Eyck * ECParameters ::= CHOICE {
343*b0563631STom Van Eyck * namedCurve OBJECT IDENTIFIER
344*b0563631STom Van Eyck * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
345*b0563631STom Van Eyck * -- implicitCurve NULL
346*b0563631STom Van Eyck * }
347*b0563631STom Van Eyck */
pk_get_ecparams(unsigned char ** p,const unsigned char * end,mbedtls_asn1_buf * params)348*b0563631STom Van Eyck static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
349*b0563631STom Van Eyck mbedtls_asn1_buf *params)
350*b0563631STom Van Eyck {
351*b0563631STom Van Eyck int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
352*b0563631STom Van Eyck
353*b0563631STom Van Eyck if (end - *p < 1) {
354*b0563631STom Van Eyck return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
355*b0563631STom Van Eyck MBEDTLS_ERR_ASN1_OUT_OF_DATA);
356*b0563631STom Van Eyck }
357*b0563631STom Van Eyck
358*b0563631STom Van Eyck /* Acceptable tags: OID for namedCurve, or specifiedECDomain */
359*b0563631STom Van Eyck params->tag = **p;
360*b0563631STom Van Eyck if (params->tag != MBEDTLS_ASN1_OID &&
361*b0563631STom Van Eyck !pk_ecc_tag_is_specified_ec_domain(params->tag)) {
362*b0563631STom Van Eyck return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
363*b0563631STom Van Eyck MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
364*b0563631STom Van Eyck }
365*b0563631STom Van Eyck
366*b0563631STom Van Eyck if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) {
367*b0563631STom Van Eyck return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
368*b0563631STom Van Eyck }
369*b0563631STom Van Eyck
370*b0563631STom Van Eyck params->p = *p;
371*b0563631STom Van Eyck *p += params->len;
372*b0563631STom Van Eyck
373*b0563631STom Van Eyck if (*p != end) {
374*b0563631STom Van Eyck return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
375*b0563631STom Van Eyck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
376*b0563631STom Van Eyck }
377*b0563631STom Van Eyck
378*b0563631STom Van Eyck return 0;
379*b0563631STom Van Eyck }
380*b0563631STom Van Eyck
381817466cbSJens Wiklander /*
382817466cbSJens Wiklander * Use EC parameters to initialise an EC group
383817466cbSJens Wiklander *
384817466cbSJens Wiklander * ECParameters ::= CHOICE {
385817466cbSJens Wiklander * namedCurve OBJECT IDENTIFIER
386817466cbSJens Wiklander * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
387817466cbSJens Wiklander * -- implicitCurve NULL
388817466cbSJens Wiklander */
pk_use_ecparams(const mbedtls_asn1_buf * params,mbedtls_pk_context * pk)389*b0563631STom Van Eyck static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk)
390817466cbSJens Wiklander {
39111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
392817466cbSJens Wiklander mbedtls_ecp_group_id grp_id;
393817466cbSJens Wiklander
39432b31808SJens Wiklander if (params->tag == MBEDTLS_ASN1_OID) {
39532b31808SJens Wiklander if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) {
39632b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
397817466cbSJens Wiklander }
39832b31808SJens Wiklander } else {
399*b0563631STom Van Eyck ret = pk_ecc_group_id_from_specified(params, &grp_id);
400*b0563631STom Van Eyck if (ret != 0) {
40132b31808SJens Wiklander return ret;
40232b31808SJens Wiklander }
403817466cbSJens Wiklander }
404817466cbSJens Wiklander
405*b0563631STom Van Eyck return mbedtls_pk_ecc_set_group(pk, grp_id);
406*b0563631STom Van Eyck }
407*b0563631STom Van Eyck
408*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
409*b0563631STom Van Eyck
410817466cbSJens Wiklander /*
411*b0563631STom Van Eyck * Load an RFC8410 EC key, which doesn't have any parameters
412817466cbSJens Wiklander */
pk_use_ecparams_rfc8410(const mbedtls_asn1_buf * params,mbedtls_ecp_group_id grp_id,mbedtls_pk_context * pk)413*b0563631STom Van Eyck static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params,
414*b0563631STom Van Eyck mbedtls_ecp_group_id grp_id,
415*b0563631STom Van Eyck mbedtls_pk_context *pk)
416817466cbSJens Wiklander {
417*b0563631STom Van Eyck if (params->tag != 0 || params->len != 0) {
418*b0563631STom Van Eyck return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
419*b0563631STom Van Eyck }
420817466cbSJens Wiklander
421*b0563631STom Van Eyck return mbedtls_pk_ecc_set_group(pk, grp_id);
422817466cbSJens Wiklander }
423817466cbSJens Wiklander
424817466cbSJens Wiklander /*
425*b0563631STom Van Eyck * Parse an RFC 8410 encoded private EC key
426*b0563631STom Van Eyck *
427*b0563631STom Van Eyck * CurvePrivateKey ::= OCTET STRING
428817466cbSJens Wiklander */
pk_parse_key_rfc8410_der(mbedtls_pk_context * pk,unsigned char * key,size_t keylen,const unsigned char * end,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)429*b0563631STom Van Eyck static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
430*b0563631STom Van Eyck unsigned char *key, size_t keylen, const unsigned char *end,
431*b0563631STom Van Eyck int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
432817466cbSJens Wiklander {
43311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
434817466cbSJens Wiklander size_t len;
435817466cbSJens Wiklander
436*b0563631STom Van Eyck if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
437*b0563631STom Van Eyck return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
43832b31808SJens Wiklander }
439817466cbSJens Wiklander
440*b0563631STom Van Eyck if (key + len != end) {
441*b0563631STom Van Eyck return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
44232b31808SJens Wiklander }
443817466cbSJens Wiklander
444*b0563631STom Van Eyck /*
445*b0563631STom Van Eyck * Load the private key
446*b0563631STom Van Eyck */
447*b0563631STom Van Eyck ret = mbedtls_pk_ecc_set_key(pk, key, len);
448*b0563631STom Van Eyck if (ret != 0) {
449*b0563631STom Van Eyck return ret;
45032b31808SJens Wiklander }
451817466cbSJens Wiklander
452*b0563631STom Van Eyck /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,
453*b0563631STom Van Eyck * which never contain a public key. As such, derive the public key
454*b0563631STom Van Eyck * unconditionally. */
455*b0563631STom Van Eyck if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
456*b0563631STom Van Eyck return ret;
45732b31808SJens Wiklander }
458817466cbSJens Wiklander
45932b31808SJens Wiklander return 0;
460817466cbSJens Wiklander }
461*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
462*b0563631STom Van Eyck
463*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
464817466cbSJens Wiklander
465817466cbSJens Wiklander /* Get a PK algorithm identifier
466817466cbSJens Wiklander *
467817466cbSJens Wiklander * AlgorithmIdentifier ::= SEQUENCE {
468817466cbSJens Wiklander * algorithm OBJECT IDENTIFIER,
469817466cbSJens Wiklander * parameters ANY DEFINED BY algorithm OPTIONAL }
470817466cbSJens Wiklander */
pk_get_pk_alg(unsigned char ** p,const unsigned char * end,mbedtls_pk_type_t * pk_alg,mbedtls_asn1_buf * params,mbedtls_ecp_group_id * ec_grp_id)471817466cbSJens Wiklander static int pk_get_pk_alg(unsigned char **p,
472817466cbSJens Wiklander const unsigned char *end,
473*b0563631STom Van Eyck mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params,
474*b0563631STom Van Eyck mbedtls_ecp_group_id *ec_grp_id)
475817466cbSJens Wiklander {
47611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
477817466cbSJens Wiklander mbedtls_asn1_buf alg_oid;
478817466cbSJens Wiklander
479817466cbSJens Wiklander memset(params, 0, sizeof(mbedtls_asn1_buf));
480817466cbSJens Wiklander
48132b31808SJens Wiklander if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) {
48232b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
48332b31808SJens Wiklander }
484817466cbSJens Wiklander
485*b0563631STom Van Eyck ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg);
486*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
487*b0563631STom Van Eyck if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
488*b0563631STom Van Eyck ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id);
489*b0563631STom Van Eyck if (ret == 0) {
490*b0563631STom Van Eyck *pk_alg = MBEDTLS_PK_ECKEY;
491*b0563631STom Van Eyck }
492*b0563631STom Van Eyck }
493*b0563631STom Van Eyck #else
494*b0563631STom Van Eyck (void) ec_grp_id;
495*b0563631STom Van Eyck #endif
496*b0563631STom Van Eyck if (ret != 0) {
49732b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
49832b31808SJens Wiklander }
499817466cbSJens Wiklander
500817466cbSJens Wiklander /*
501817466cbSJens Wiklander * No parameters with RSA (only for EC)
502817466cbSJens Wiklander */
503817466cbSJens Wiklander if (*pk_alg == MBEDTLS_PK_RSA &&
504817466cbSJens Wiklander ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) ||
50532b31808SJens Wiklander params->len != 0)) {
50632b31808SJens Wiklander return MBEDTLS_ERR_PK_INVALID_ALG;
507817466cbSJens Wiklander }
508817466cbSJens Wiklander
50932b31808SJens Wiklander return 0;
510817466cbSJens Wiklander }
511817466cbSJens Wiklander
512817466cbSJens Wiklander /*
513817466cbSJens Wiklander * SubjectPublicKeyInfo ::= SEQUENCE {
514817466cbSJens Wiklander * algorithm AlgorithmIdentifier,
515817466cbSJens Wiklander * subjectPublicKey BIT STRING }
516817466cbSJens Wiklander */
mbedtls_pk_parse_subpubkey(unsigned char ** p,const unsigned char * end,mbedtls_pk_context * pk)517817466cbSJens Wiklander int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
518817466cbSJens Wiklander mbedtls_pk_context *pk)
519817466cbSJens Wiklander {
52011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
521817466cbSJens Wiklander size_t len;
522817466cbSJens Wiklander mbedtls_asn1_buf alg_params;
523817466cbSJens Wiklander mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
524*b0563631STom Van Eyck mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
525817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info;
526817466cbSJens Wiklander
527817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(p, end, &len,
52832b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
52932b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
530817466cbSJens Wiklander }
531817466cbSJens Wiklander
532817466cbSJens Wiklander end = *p + len;
533817466cbSJens Wiklander
534*b0563631STom Van Eyck if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) {
53532b31808SJens Wiklander return ret;
53632b31808SJens Wiklander }
537817466cbSJens Wiklander
53832b31808SJens Wiklander if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
53932b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
54032b31808SJens Wiklander }
541817466cbSJens Wiklander
54232b31808SJens Wiklander if (*p + len != end) {
54332b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
54432b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
54532b31808SJens Wiklander }
546817466cbSJens Wiklander
54732b31808SJens Wiklander if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
54832b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
54932b31808SJens Wiklander }
550817466cbSJens Wiklander
55132b31808SJens Wiklander if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
55232b31808SJens Wiklander return ret;
55332b31808SJens Wiklander }
554817466cbSJens Wiklander
555817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
55632b31808SJens Wiklander if (pk_alg == MBEDTLS_PK_RSA) {
557*b0563631STom Van Eyck ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p));
55832b31808SJens Wiklander if (ret == 0) {
559*b0563631STom Van Eyck /* On success all the input has been consumed by the parsing function. */
560*b0563631STom Van Eyck *p += end - *p;
561*b0563631STom Van Eyck } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) &&
562*b0563631STom Van Eyck (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) {
563*b0563631STom Van Eyck /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */
564*b0563631STom Van Eyck ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
565*b0563631STom Van Eyck } else {
566*b0563631STom Van Eyck ret = MBEDTLS_ERR_PK_INVALID_PUBKEY;
56732b31808SJens Wiklander }
568817466cbSJens Wiklander } else
569*b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
570*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
571*b0563631STom Van Eyck if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
572*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
573*b0563631STom Van Eyck if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
574*b0563631STom Van Eyck ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk);
575*b0563631STom Van Eyck } else
576*b0563631STom Van Eyck #endif
577*b0563631STom Van Eyck {
578*b0563631STom Van Eyck ret = pk_use_ecparams(&alg_params, pk);
579*b0563631STom Van Eyck }
580*b0563631STom Van Eyck if (ret == 0) {
581*b0563631STom Van Eyck ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
582*b0563631STom Van Eyck *p += end - *p;
583*b0563631STom Van Eyck }
584*b0563631STom Van Eyck } else
585*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
586817466cbSJens Wiklander ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
587817466cbSJens Wiklander
58832b31808SJens Wiklander if (ret == 0 && *p != end) {
5897901324dSJerome Forissier ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
5907901324dSJerome Forissier MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
59132b31808SJens Wiklander }
592817466cbSJens Wiklander
59332b31808SJens Wiklander if (ret != 0) {
594817466cbSJens Wiklander mbedtls_pk_free(pk);
59532b31808SJens Wiklander }
596817466cbSJens Wiklander
59732b31808SJens Wiklander return ret;
598817466cbSJens Wiklander }
599817466cbSJens Wiklander
600*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
601817466cbSJens Wiklander /*
602817466cbSJens Wiklander * Parse a SEC1 encoded private EC key
603817466cbSJens Wiklander */
pk_parse_key_sec1_der(mbedtls_pk_context * pk,const unsigned char * key,size_t keylen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)604*b0563631STom Van Eyck static int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
60532b31808SJens Wiklander const unsigned char *key, size_t keylen,
60632b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
607817466cbSJens Wiklander {
60811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
609817466cbSJens Wiklander int version, pubkey_done;
610*b0563631STom Van Eyck size_t len, d_len;
61132b31808SJens Wiklander mbedtls_asn1_buf params = { 0, 0, NULL };
612817466cbSJens Wiklander unsigned char *p = (unsigned char *) key;
613*b0563631STom Van Eyck unsigned char *d;
614817466cbSJens Wiklander unsigned char *end = p + keylen;
615817466cbSJens Wiklander unsigned char *end2;
616817466cbSJens Wiklander
617817466cbSJens Wiklander /*
618817466cbSJens Wiklander * RFC 5915, or SEC1 Appendix C.4
619817466cbSJens Wiklander *
620817466cbSJens Wiklander * ECPrivateKey ::= SEQUENCE {
621817466cbSJens Wiklander * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
622817466cbSJens Wiklander * privateKey OCTET STRING,
623817466cbSJens Wiklander * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
624817466cbSJens Wiklander * publicKey [1] BIT STRING OPTIONAL
625817466cbSJens Wiklander * }
626817466cbSJens Wiklander */
627817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
62832b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
62932b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
630817466cbSJens Wiklander }
631817466cbSJens Wiklander
632817466cbSJens Wiklander end = p + len;
633817466cbSJens Wiklander
63432b31808SJens Wiklander if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
63532b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
63632b31808SJens Wiklander }
637817466cbSJens Wiklander
63832b31808SJens Wiklander if (version != 1) {
63932b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
64032b31808SJens Wiklander }
641817466cbSJens Wiklander
64232b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
64332b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
64432b31808SJens Wiklander }
645817466cbSJens Wiklander
646*b0563631STom Van Eyck /* Keep a reference to the position fo the private key. It will be used
647*b0563631STom Van Eyck * later in this function. */
648*b0563631STom Van Eyck d = p;
649*b0563631STom Van Eyck d_len = len;
650817466cbSJens Wiklander
651817466cbSJens Wiklander p += len;
652817466cbSJens Wiklander
653817466cbSJens Wiklander pubkey_done = 0;
65432b31808SJens Wiklander if (p != end) {
655817466cbSJens Wiklander /*
656817466cbSJens Wiklander * Is 'parameters' present?
657817466cbSJens Wiklander */
658817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
65932b31808SJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
66032b31808SJens Wiklander 0)) == 0) {
661817466cbSJens Wiklander if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 ||
662*b0563631STom Van Eyck (ret = pk_use_ecparams(¶ms, pk)) != 0) {
66332b31808SJens Wiklander return ret;
664817466cbSJens Wiklander }
66532b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
66632b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
667817466cbSJens Wiklander }
6683d3b0591SJens Wiklander }
669817466cbSJens Wiklander
670*b0563631STom Van Eyck /*
671*b0563631STom Van Eyck * Load the private key
672*b0563631STom Van Eyck */
673*b0563631STom Van Eyck ret = mbedtls_pk_ecc_set_key(pk, d, d_len);
674*b0563631STom Van Eyck if (ret != 0) {
675*b0563631STom Van Eyck return ret;
676*b0563631STom Van Eyck }
677*b0563631STom Van Eyck
67832b31808SJens Wiklander if (p != end) {
679817466cbSJens Wiklander /*
680817466cbSJens Wiklander * Is 'publickey' present? If not, or if we can't read it (eg because it
681817466cbSJens Wiklander * is compressed), create it from the private key.
682817466cbSJens Wiklander */
683817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
68432b31808SJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
68532b31808SJens Wiklander 1)) == 0) {
686817466cbSJens Wiklander end2 = p + len;
687817466cbSJens Wiklander
68832b31808SJens Wiklander if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) {
68932b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
69032b31808SJens Wiklander }
691817466cbSJens Wiklander
69232b31808SJens Wiklander if (p + len != end2) {
69332b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
69432b31808SJens Wiklander MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
69532b31808SJens Wiklander }
696817466cbSJens Wiklander
697*b0563631STom Van Eyck if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
698817466cbSJens Wiklander pubkey_done = 1;
69932b31808SJens Wiklander } else {
700817466cbSJens Wiklander /*
701*b0563631STom Van Eyck * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above
702817466cbSJens Wiklander * is if the point format is not recognized.
703817466cbSJens Wiklander */
70432b31808SJens Wiklander if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
70532b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
706817466cbSJens Wiklander }
707817466cbSJens Wiklander }
70832b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
70932b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
710817466cbSJens Wiklander }
711817466cbSJens Wiklander }
712817466cbSJens Wiklander
713*b0563631STom Van Eyck if (!pubkey_done) {
714*b0563631STom Van Eyck if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
71532b31808SJens Wiklander return ret;
716817466cbSJens Wiklander }
717*b0563631STom Van Eyck }
718817466cbSJens Wiklander
71932b31808SJens Wiklander return 0;
720817466cbSJens Wiklander }
721*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
722*b0563631STom Van Eyck
723*b0563631STom Van Eyck /***********************************************************************
724*b0563631STom Van Eyck *
725*b0563631STom Van Eyck * PKCS#8 parsing functions
726*b0563631STom Van Eyck *
727*b0563631STom Van Eyck **********************************************************************/
728817466cbSJens Wiklander
729817466cbSJens Wiklander /*
730817466cbSJens Wiklander * Parse an unencrypted PKCS#8 encoded private key
7313d3b0591SJens Wiklander *
7323d3b0591SJens Wiklander * Notes:
7333d3b0591SJens Wiklander *
7343d3b0591SJens Wiklander * - This function does not own the key buffer. It is the
7353d3b0591SJens Wiklander * responsibility of the caller to take care of zeroizing
7363d3b0591SJens Wiklander * and freeing it after use.
7373d3b0591SJens Wiklander *
7383d3b0591SJens Wiklander * - The function is responsible for freeing the provided
7393d3b0591SJens Wiklander * PK context on failure.
7403d3b0591SJens Wiklander *
741817466cbSJens Wiklander */
pk_parse_key_pkcs8_unencrypted_der(mbedtls_pk_context * pk,const unsigned char * key,size_t keylen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)742817466cbSJens Wiklander static int pk_parse_key_pkcs8_unencrypted_der(
743817466cbSJens Wiklander mbedtls_pk_context *pk,
74432b31808SJens Wiklander const unsigned char *key, size_t keylen,
74532b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
746817466cbSJens Wiklander {
747817466cbSJens Wiklander int ret, version;
748817466cbSJens Wiklander size_t len;
749817466cbSJens Wiklander mbedtls_asn1_buf params;
750817466cbSJens Wiklander unsigned char *p = (unsigned char *) key;
751817466cbSJens Wiklander unsigned char *end = p + keylen;
752817466cbSJens Wiklander mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
753*b0563631STom Van Eyck mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
754817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info;
755817466cbSJens Wiklander
756*b0563631STom Van Eyck #if !defined(MBEDTLS_PK_HAVE_ECC_KEYS)
75732b31808SJens Wiklander (void) f_rng;
75832b31808SJens Wiklander (void) p_rng;
75932b31808SJens Wiklander #endif
76032b31808SJens Wiklander
761817466cbSJens Wiklander /*
7623d3b0591SJens Wiklander * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
763817466cbSJens Wiklander *
764817466cbSJens Wiklander * PrivateKeyInfo ::= SEQUENCE {
765817466cbSJens Wiklander * version Version,
766817466cbSJens Wiklander * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
767817466cbSJens Wiklander * privateKey PrivateKey,
768817466cbSJens Wiklander * attributes [0] IMPLICIT Attributes OPTIONAL }
769817466cbSJens Wiklander *
770817466cbSJens Wiklander * Version ::= INTEGER
771817466cbSJens Wiklander * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
772817466cbSJens Wiklander * PrivateKey ::= OCTET STRING
773817466cbSJens Wiklander *
774817466cbSJens Wiklander * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
775817466cbSJens Wiklander */
776817466cbSJens Wiklander
777817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
77832b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
77932b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
780817466cbSJens Wiklander }
781817466cbSJens Wiklander
782817466cbSJens Wiklander end = p + len;
783817466cbSJens Wiklander
78432b31808SJens Wiklander if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
78532b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
7867901324dSJerome Forissier }
787817466cbSJens Wiklander
78832b31808SJens Wiklander if (version != 0) {
78932b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
79032b31808SJens Wiklander }
791817466cbSJens Wiklander
792*b0563631STom Van Eyck if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms, &ec_grp_id)) != 0) {
79332b31808SJens Wiklander return ret;
79432b31808SJens Wiklander }
795817466cbSJens Wiklander
79632b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
79732b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
79832b31808SJens Wiklander }
799817466cbSJens Wiklander
80032b31808SJens Wiklander if (len < 1) {
80132b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
80232b31808SJens Wiklander MBEDTLS_ERR_ASN1_OUT_OF_DATA);
80332b31808SJens Wiklander }
80432b31808SJens Wiklander
80532b31808SJens Wiklander if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
80632b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
80732b31808SJens Wiklander }
80832b31808SJens Wiklander
80932b31808SJens Wiklander if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
81032b31808SJens Wiklander return ret;
81132b31808SJens Wiklander }
812817466cbSJens Wiklander
813817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
81432b31808SJens Wiklander if (pk_alg == MBEDTLS_PK_RSA) {
815*b0563631STom Van Eyck if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) {
816817466cbSJens Wiklander mbedtls_pk_free(pk);
81732b31808SJens Wiklander return ret;
818817466cbSJens Wiklander }
819817466cbSJens Wiklander } else
820817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */
821*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
82232b31808SJens Wiklander if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
823*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
824*b0563631STom Van Eyck if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
825*b0563631STom Van Eyck if ((ret =
826*b0563631STom Van Eyck pk_use_ecparams_rfc8410(¶ms, ec_grp_id, pk)) != 0 ||
827*b0563631STom Van Eyck (ret =
828*b0563631STom Van Eyck pk_parse_key_rfc8410_der(pk, p, len, end, f_rng,
829*b0563631STom Van Eyck p_rng)) != 0) {
830817466cbSJens Wiklander mbedtls_pk_free(pk);
83132b31808SJens Wiklander return ret;
832817466cbSJens Wiklander }
833817466cbSJens Wiklander } else
834*b0563631STom Van Eyck #endif
835*b0563631STom Van Eyck {
836*b0563631STom Van Eyck if ((ret = pk_use_ecparams(¶ms, pk)) != 0 ||
837*b0563631STom Van Eyck (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) {
838*b0563631STom Van Eyck mbedtls_pk_free(pk);
839*b0563631STom Van Eyck return ret;
840*b0563631STom Van Eyck }
841*b0563631STom Van Eyck }
842*b0563631STom Van Eyck } else
843*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
84432b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
845817466cbSJens Wiklander
846*b0563631STom Van Eyck end = p + len;
847*b0563631STom Van Eyck if (end != (key + keylen)) {
848*b0563631STom Van Eyck return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
849*b0563631STom Van Eyck MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
850*b0563631STom Van Eyck }
851*b0563631STom Van Eyck
85232b31808SJens Wiklander return 0;
853817466cbSJens Wiklander }
854817466cbSJens Wiklander
855817466cbSJens Wiklander /*
856817466cbSJens Wiklander * Parse an encrypted PKCS#8 encoded private key
8573d3b0591SJens Wiklander *
8583d3b0591SJens Wiklander * To save space, the decryption happens in-place on the given key buffer.
8593d3b0591SJens Wiklander * Also, while this function may modify the keybuffer, it doesn't own it,
8603d3b0591SJens Wiklander * and instead it is the responsibility of the caller to zeroize and properly
8613d3b0591SJens Wiklander * free it after use.
8623d3b0591SJens Wiklander *
863817466cbSJens Wiklander */
864817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
mbedtls_pk_parse_key_pkcs8_encrypted_der(mbedtls_pk_context * pk,unsigned char * key,size_t keylen,const unsigned char * pwd,size_t pwdlen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)865*b0563631STom Van Eyck MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(
866817466cbSJens Wiklander mbedtls_pk_context *pk,
8673d3b0591SJens Wiklander unsigned char *key, size_t keylen,
86832b31808SJens Wiklander const unsigned char *pwd, size_t pwdlen,
86932b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
870817466cbSJens Wiklander {
871817466cbSJens Wiklander int ret, decrypted = 0;
872817466cbSJens Wiklander size_t len;
8733d3b0591SJens Wiklander unsigned char *buf;
874817466cbSJens Wiklander unsigned char *p, *end;
875817466cbSJens Wiklander mbedtls_asn1_buf pbe_alg_oid, pbe_params;
876*b0563631STom Van Eyck #if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
877817466cbSJens Wiklander mbedtls_cipher_type_t cipher_alg;
878817466cbSJens Wiklander mbedtls_md_type_t md_alg;
879817466cbSJens Wiklander #endif
880*b0563631STom Van Eyck size_t outlen = 0;
881817466cbSJens Wiklander
8823d3b0591SJens Wiklander p = key;
883817466cbSJens Wiklander end = p + keylen;
884817466cbSJens Wiklander
88532b31808SJens Wiklander if (pwdlen == 0) {
88632b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
88732b31808SJens Wiklander }
888817466cbSJens Wiklander
889817466cbSJens Wiklander /*
8903d3b0591SJens Wiklander * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
891817466cbSJens Wiklander *
892817466cbSJens Wiklander * EncryptedPrivateKeyInfo ::= SEQUENCE {
893817466cbSJens Wiklander * encryptionAlgorithm EncryptionAlgorithmIdentifier,
894817466cbSJens Wiklander * encryptedData EncryptedData
895817466cbSJens Wiklander * }
896817466cbSJens Wiklander *
897817466cbSJens Wiklander * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
898817466cbSJens Wiklander *
899817466cbSJens Wiklander * EncryptedData ::= OCTET STRING
900817466cbSJens Wiklander *
901817466cbSJens Wiklander * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
9023d3b0591SJens Wiklander *
903817466cbSJens Wiklander */
904817466cbSJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
90532b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
90632b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
907817466cbSJens Wiklander }
908817466cbSJens Wiklander
909817466cbSJens Wiklander end = p + len;
910817466cbSJens Wiklander
91132b31808SJens Wiklander if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) {
91232b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
91332b31808SJens Wiklander }
914817466cbSJens Wiklander
91532b31808SJens Wiklander if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
91632b31808SJens Wiklander return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
91732b31808SJens Wiklander }
918817466cbSJens Wiklander
9193d3b0591SJens Wiklander buf = p;
920817466cbSJens Wiklander
921817466cbSJens Wiklander /*
9223d3b0591SJens Wiklander * Decrypt EncryptedData with appropriate PBE
923817466cbSJens Wiklander */
924*b0563631STom Van Eyck #if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
92532b31808SJens Wiklander if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
926*b0563631STom Van Eyck if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
927817466cbSJens Wiklander cipher_alg, md_alg,
928*b0563631STom Van Eyck pwd, pwdlen, p, len, buf, len, &outlen)) != 0) {
92932b31808SJens Wiklander if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
93032b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
93132b31808SJens Wiklander }
932817466cbSJens Wiklander
93332b31808SJens Wiklander return ret;
934817466cbSJens Wiklander }
935817466cbSJens Wiklander
936817466cbSJens Wiklander decrypted = 1;
93732b31808SJens Wiklander } else
938*b0563631STom Van Eyck #endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
939*b0563631STom Van Eyck #if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
94032b31808SJens Wiklander if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
941*b0563631STom Van Eyck if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
942*b0563631STom Van Eyck p, len, buf, len, &outlen)) != 0) {
94332b31808SJens Wiklander if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
94432b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
94532b31808SJens Wiklander }
946817466cbSJens Wiklander
94732b31808SJens Wiklander return ret;
948817466cbSJens Wiklander }
949817466cbSJens Wiklander
950817466cbSJens Wiklander decrypted = 1;
95132b31808SJens Wiklander } else
952*b0563631STom Van Eyck #endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
953817466cbSJens Wiklander {
954817466cbSJens Wiklander ((void) pwd);
955817466cbSJens Wiklander }
956817466cbSJens Wiklander
95732b31808SJens Wiklander if (decrypted == 0) {
95832b31808SJens Wiklander return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
95932b31808SJens Wiklander }
960*b0563631STom Van Eyck return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng);
961817466cbSJens Wiklander }
962817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
963817466cbSJens Wiklander
964*b0563631STom Van Eyck /***********************************************************************
965*b0563631STom Van Eyck *
966*b0563631STom Van Eyck * Top-level functions, with format auto-discovery
967*b0563631STom Van Eyck *
968*b0563631STom Van Eyck **********************************************************************/
969*b0563631STom Van Eyck
970817466cbSJens Wiklander /*
971817466cbSJens Wiklander * Parse a private key
972817466cbSJens Wiklander */
mbedtls_pk_parse_key(mbedtls_pk_context * pk,const unsigned char * key,size_t keylen,const unsigned char * pwd,size_t pwdlen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)973817466cbSJens Wiklander int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
974817466cbSJens Wiklander const unsigned char *key, size_t keylen,
97532b31808SJens Wiklander const unsigned char *pwd, size_t pwdlen,
97632b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
977817466cbSJens Wiklander {
97811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
979817466cbSJens Wiklander const mbedtls_pk_info_t *pk_info;
980817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
981817466cbSJens Wiklander size_t len;
982817466cbSJens Wiklander mbedtls_pem_context pem;
9833d3b0591SJens Wiklander #endif
984817466cbSJens Wiklander
98532b31808SJens Wiklander if (keylen == 0) {
98632b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
98732b31808SJens Wiklander }
9883d3b0591SJens Wiklander
9893d3b0591SJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
990817466cbSJens Wiklander mbedtls_pem_init(&pem);
991817466cbSJens Wiklander
992817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
993817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
99432b31808SJens Wiklander if (key[keylen - 1] != '\0') {
995817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
99632b31808SJens Wiklander } else {
997817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem,
998*b0563631STom Van Eyck PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA,
999817466cbSJens Wiklander key, pwd, pwdlen, &len);
100032b31808SJens Wiklander }
1001817466cbSJens Wiklander
100232b31808SJens Wiklander if (ret == 0) {
10033d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1004817466cbSJens Wiklander if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1005*b0563631STom Van Eyck (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk),
100632b31808SJens Wiklander pem.buf, pem.buflen)) != 0) {
1007817466cbSJens Wiklander mbedtls_pk_free(pk);
1008817466cbSJens Wiklander }
1009817466cbSJens Wiklander
1010817466cbSJens Wiklander mbedtls_pem_free(&pem);
101132b31808SJens Wiklander return ret;
101232b31808SJens Wiklander } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
101332b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
101432b31808SJens Wiklander } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
101532b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
101632b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
101732b31808SJens Wiklander return ret;
1018817466cbSJens Wiklander }
1019817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */
1020817466cbSJens Wiklander
1021*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
1022817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
102332b31808SJens Wiklander if (key[keylen - 1] != '\0') {
1024817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
102532b31808SJens Wiklander } else {
1026817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem,
1027*b0563631STom Van Eyck PEM_BEGIN_PRIVATE_KEY_EC,
1028*b0563631STom Van Eyck PEM_END_PRIVATE_KEY_EC,
1029817466cbSJens Wiklander key, pwd, pwdlen, &len);
103032b31808SJens Wiklander }
103132b31808SJens Wiklander if (ret == 0) {
10323d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1033817466cbSJens Wiklander
1034817466cbSJens Wiklander if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1035*b0563631STom Van Eyck (ret = pk_parse_key_sec1_der(pk,
103632b31808SJens Wiklander pem.buf, pem.buflen,
103732b31808SJens Wiklander f_rng, p_rng)) != 0) {
1038817466cbSJens Wiklander mbedtls_pk_free(pk);
1039817466cbSJens Wiklander }
1040817466cbSJens Wiklander
1041817466cbSJens Wiklander mbedtls_pem_free(&pem);
104232b31808SJens Wiklander return ret;
104332b31808SJens Wiklander } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
104432b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
104532b31808SJens Wiklander } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
104632b31808SJens Wiklander return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
104732b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
104832b31808SJens Wiklander return ret;
1049817466cbSJens Wiklander }
1050*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
1051817466cbSJens Wiklander
1052817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
105332b31808SJens Wiklander if (key[keylen - 1] != '\0') {
1054817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
105532b31808SJens Wiklander } else {
1056817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem,
1057*b0563631STom Van Eyck PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8,
1058817466cbSJens Wiklander key, NULL, 0, &len);
105932b31808SJens Wiklander }
106032b31808SJens Wiklander if (ret == 0) {
1061817466cbSJens Wiklander if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk,
106232b31808SJens Wiklander pem.buf, pem.buflen, f_rng, p_rng)) != 0) {
1063817466cbSJens Wiklander mbedtls_pk_free(pk);
1064817466cbSJens Wiklander }
1065817466cbSJens Wiklander
1066817466cbSJens Wiklander mbedtls_pem_free(&pem);
106732b31808SJens Wiklander return ret;
106832b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
106932b31808SJens Wiklander return ret;
1070817466cbSJens Wiklander }
1071817466cbSJens Wiklander
1072817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
1073817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
107432b31808SJens Wiklander if (key[keylen - 1] != '\0') {
1075817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
107632b31808SJens Wiklander } else {
1077817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem,
1078*b0563631STom Van Eyck PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8,
1079*b0563631STom Van Eyck PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8,
1080817466cbSJens Wiklander key, NULL, 0, &len);
108132b31808SJens Wiklander }
108232b31808SJens Wiklander if (ret == 0) {
1083*b0563631STom Van Eyck if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
108432b31808SJens Wiklander pwd, pwdlen, f_rng, p_rng)) != 0) {
1085817466cbSJens Wiklander mbedtls_pk_free(pk);
1086817466cbSJens Wiklander }
1087817466cbSJens Wiklander
1088817466cbSJens Wiklander mbedtls_pem_free(&pem);
108932b31808SJens Wiklander return ret;
109032b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
109132b31808SJens Wiklander return ret;
1092817466cbSJens Wiklander }
1093817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
1094817466cbSJens Wiklander #else
1095817466cbSJens Wiklander ((void) pwd);
1096817466cbSJens Wiklander ((void) pwdlen);
1097817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */
1098817466cbSJens Wiklander
1099817466cbSJens Wiklander /*
1100817466cbSJens Wiklander * At this point we only know it's not a PEM formatted key. Could be any
1101817466cbSJens Wiklander * of the known DER encoded private key formats
1102817466cbSJens Wiklander *
1103817466cbSJens Wiklander * We try the different DER format parsers to see if one passes without
1104817466cbSJens Wiklander * error
1105817466cbSJens Wiklander */
1106817466cbSJens Wiklander #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
110732b31808SJens Wiklander if (pwdlen != 0) {
11083d3b0591SJens Wiklander unsigned char *key_copy;
11093d3b0591SJens Wiklander
111032b31808SJens Wiklander if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) {
111132b31808SJens Wiklander return MBEDTLS_ERR_PK_ALLOC_FAILED;
111232b31808SJens Wiklander }
11133d3b0591SJens Wiklander
11143d3b0591SJens Wiklander memcpy(key_copy, key, keylen);
11153d3b0591SJens Wiklander
1116*b0563631STom Van Eyck ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
111732b31808SJens Wiklander pwd, pwdlen, f_rng, p_rng);
11183d3b0591SJens Wiklander
1119*b0563631STom Van Eyck mbedtls_zeroize_and_free(key_copy, keylen);
1120817466cbSJens Wiklander }
1121817466cbSJens Wiklander
112232b31808SJens Wiklander if (ret == 0) {
112332b31808SJens Wiklander return 0;
112432b31808SJens Wiklander }
11253d3b0591SJens Wiklander
1126817466cbSJens Wiklander mbedtls_pk_free(pk);
11273d3b0591SJens Wiklander mbedtls_pk_init(pk);
1128817466cbSJens Wiklander
112932b31808SJens Wiklander if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {
113032b31808SJens Wiklander return ret;
1131817466cbSJens Wiklander }
1132817466cbSJens Wiklander #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
1133817466cbSJens Wiklander
113432b31808SJens Wiklander ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng);
113532b31808SJens Wiklander if (ret == 0) {
113632b31808SJens Wiklander return 0;
1137039e02dfSJerome Forissier }
1138817466cbSJens Wiklander
1139817466cbSJens Wiklander mbedtls_pk_free(pk);
11403d3b0591SJens Wiklander mbedtls_pk_init(pk);
1141817466cbSJens Wiklander
1142817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
1143817466cbSJens Wiklander
11443d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
11453d3b0591SJens Wiklander if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1146*b0563631STom Van Eyck mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
114732b31808SJens Wiklander return 0;
1148817466cbSJens Wiklander }
1149817466cbSJens Wiklander
1150817466cbSJens Wiklander mbedtls_pk_free(pk);
11513d3b0591SJens Wiklander mbedtls_pk_init(pk);
1152817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */
1153817466cbSJens Wiklander
1154*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
11553d3b0591SJens Wiklander pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
11563d3b0591SJens Wiklander if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1157*b0563631STom Van Eyck pk_parse_key_sec1_der(pk,
115832b31808SJens Wiklander key, keylen, f_rng, p_rng) == 0) {
115932b31808SJens Wiklander return 0;
1160817466cbSJens Wiklander }
1161817466cbSJens Wiklander mbedtls_pk_free(pk);
1162*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
1163817466cbSJens Wiklander
1164*b0563631STom Van Eyck /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't,
11653d3b0591SJens Wiklander * it is ok to leave the PK context initialized but not
11663d3b0591SJens Wiklander * freed: It is the caller's responsibility to call pk_init()
11673d3b0591SJens Wiklander * before calling this function, and to call pk_free()
1168*b0563631STom Van Eyck * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C
11693d3b0591SJens Wiklander * isn't, this leads to mbedtls_pk_free() being called
11703d3b0591SJens Wiklander * twice, once here and once by the caller, but this is
11713d3b0591SJens Wiklander * also ok and in line with the mbedtls_pk_free() calls
11723d3b0591SJens Wiklander * on failed PEM parsing attempts. */
11733d3b0591SJens Wiklander
117432b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1175817466cbSJens Wiklander }
1176817466cbSJens Wiklander
1177817466cbSJens Wiklander /*
1178817466cbSJens Wiklander * Parse a public key
1179817466cbSJens Wiklander */
mbedtls_pk_parse_public_key(mbedtls_pk_context * ctx,const unsigned char * key,size_t keylen)1180817466cbSJens Wiklander int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
1181817466cbSJens Wiklander const unsigned char *key, size_t keylen)
1182817466cbSJens Wiklander {
118311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1184817466cbSJens Wiklander unsigned char *p;
11853d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C)
11863d3b0591SJens Wiklander const mbedtls_pk_info_t *pk_info;
11873d3b0591SJens Wiklander #endif
1188817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
1189817466cbSJens Wiklander size_t len;
1190817466cbSJens Wiklander mbedtls_pem_context pem;
11913d3b0591SJens Wiklander #endif
1192817466cbSJens Wiklander
119332b31808SJens Wiklander if (keylen == 0) {
119432b31808SJens Wiklander return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
119532b31808SJens Wiklander }
11963d3b0591SJens Wiklander
11973d3b0591SJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
1198817466cbSJens Wiklander mbedtls_pem_init(&pem);
11993d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C)
12003d3b0591SJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
120132b31808SJens Wiklander if (key[keylen - 1] != '\0') {
12023d3b0591SJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
120332b31808SJens Wiklander } else {
12043d3b0591SJens Wiklander ret = mbedtls_pem_read_buffer(&pem,
1205*b0563631STom Van Eyck PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA,
12063d3b0591SJens Wiklander key, NULL, 0, &len);
120732b31808SJens Wiklander }
12083d3b0591SJens Wiklander
120932b31808SJens Wiklander if (ret == 0) {
12103d3b0591SJens Wiklander p = pem.buf;
121132b31808SJens Wiklander if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1212039e02dfSJerome Forissier mbedtls_pem_free(&pem);
121332b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1214039e02dfSJerome Forissier }
12153d3b0591SJens Wiklander
121632b31808SJens Wiklander if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1217039e02dfSJerome Forissier mbedtls_pem_free(&pem);
121832b31808SJens Wiklander return ret;
1219039e02dfSJerome Forissier }
12203d3b0591SJens Wiklander
1221*b0563631STom Van Eyck if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) {
12223d3b0591SJens Wiklander mbedtls_pk_free(ctx);
122332b31808SJens Wiklander }
12243d3b0591SJens Wiklander
12253d3b0591SJens Wiklander mbedtls_pem_free(&pem);
122632b31808SJens Wiklander return ret;
122732b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
12283d3b0591SJens Wiklander mbedtls_pem_free(&pem);
122932b31808SJens Wiklander return ret;
12303d3b0591SJens Wiklander }
12313d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_C */
1232817466cbSJens Wiklander
1233817466cbSJens Wiklander /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
123432b31808SJens Wiklander if (key[keylen - 1] != '\0') {
1235817466cbSJens Wiklander ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
123632b31808SJens Wiklander } else {
1237817466cbSJens Wiklander ret = mbedtls_pem_read_buffer(&pem,
1238*b0563631STom Van Eyck PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
1239817466cbSJens Wiklander key, NULL, 0, &len);
124032b31808SJens Wiklander }
1241817466cbSJens Wiklander
124232b31808SJens Wiklander if (ret == 0) {
1243817466cbSJens Wiklander /*
1244817466cbSJens Wiklander * Was PEM encoded
1245817466cbSJens Wiklander */
12463d3b0591SJens Wiklander p = pem.buf;
12473d3b0591SJens Wiklander
12483d3b0591SJens Wiklander ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
12493d3b0591SJens Wiklander mbedtls_pem_free(&pem);
125032b31808SJens Wiklander return ret;
125132b31808SJens Wiklander } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1252817466cbSJens Wiklander mbedtls_pem_free(&pem);
125332b31808SJens Wiklander return ret;
1254817466cbSJens Wiklander }
12553d3b0591SJens Wiklander mbedtls_pem_free(&pem);
1256817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */
12573d3b0591SJens Wiklander
12583d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_C)
125932b31808SJens Wiklander if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
126032b31808SJens Wiklander return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
126132b31808SJens Wiklander }
12623d3b0591SJens Wiklander
126332b31808SJens Wiklander if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
126432b31808SJens Wiklander return ret;
126532b31808SJens Wiklander }
12663d3b0591SJens Wiklander
12673d3b0591SJens Wiklander p = (unsigned char *) key;
1268*b0563631STom Van Eyck ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen);
126932b31808SJens Wiklander if (ret == 0) {
127032b31808SJens Wiklander return ret;
12713d3b0591SJens Wiklander }
12723d3b0591SJens Wiklander mbedtls_pk_free(ctx);
1273*b0563631STom Van Eyck if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
127432b31808SJens Wiklander return ret;
12753d3b0591SJens Wiklander }
12763d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_C */
1277817466cbSJens Wiklander p = (unsigned char *) key;
1278817466cbSJens Wiklander
1279817466cbSJens Wiklander ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);
1280817466cbSJens Wiklander
128132b31808SJens Wiklander return ret;
1282817466cbSJens Wiklander }
1283817466cbSJens Wiklander
1284*b0563631STom Van Eyck /***********************************************************************
1285*b0563631STom Van Eyck *
1286*b0563631STom Van Eyck * Top-level functions, with filesystem support
1287*b0563631STom Van Eyck *
1288*b0563631STom Van Eyck **********************************************************************/
1289*b0563631STom Van Eyck
1290*b0563631STom Van Eyck #if defined(MBEDTLS_FS_IO)
1291*b0563631STom Van Eyck /*
1292*b0563631STom Van Eyck * Load all data from a file into a given buffer.
1293*b0563631STom Van Eyck *
1294*b0563631STom Van Eyck * The file is expected to contain either PEM or DER encoded data.
1295*b0563631STom Van Eyck * A terminating null byte is always appended. It is included in the announced
1296*b0563631STom Van Eyck * length only if the data looks like it is PEM encoded.
1297*b0563631STom Van Eyck */
mbedtls_pk_load_file(const char * path,unsigned char ** buf,size_t * n)1298*b0563631STom Van Eyck int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
1299*b0563631STom Van Eyck {
1300*b0563631STom Van Eyck FILE *f;
1301*b0563631STom Van Eyck long size;
1302*b0563631STom Van Eyck
1303*b0563631STom Van Eyck if ((f = fopen(path, "rb")) == NULL) {
1304*b0563631STom Van Eyck return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1305*b0563631STom Van Eyck }
1306*b0563631STom Van Eyck
1307*b0563631STom Van Eyck /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
1308*b0563631STom Van Eyck mbedtls_setbuf(f, NULL);
1309*b0563631STom Van Eyck
1310*b0563631STom Van Eyck fseek(f, 0, SEEK_END);
1311*b0563631STom Van Eyck if ((size = ftell(f)) == -1) {
1312*b0563631STom Van Eyck fclose(f);
1313*b0563631STom Van Eyck return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1314*b0563631STom Van Eyck }
1315*b0563631STom Van Eyck fseek(f, 0, SEEK_SET);
1316*b0563631STom Van Eyck
1317*b0563631STom Van Eyck *n = (size_t) size;
1318*b0563631STom Van Eyck
1319*b0563631STom Van Eyck if (*n + 1 == 0 ||
1320*b0563631STom Van Eyck (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
1321*b0563631STom Van Eyck fclose(f);
1322*b0563631STom Van Eyck return MBEDTLS_ERR_PK_ALLOC_FAILED;
1323*b0563631STom Van Eyck }
1324*b0563631STom Van Eyck
1325*b0563631STom Van Eyck if (fread(*buf, 1, *n, f) != *n) {
1326*b0563631STom Van Eyck fclose(f);
1327*b0563631STom Van Eyck
1328*b0563631STom Van Eyck mbedtls_zeroize_and_free(*buf, *n);
1329*b0563631STom Van Eyck
1330*b0563631STom Van Eyck return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1331*b0563631STom Van Eyck }
1332*b0563631STom Van Eyck
1333*b0563631STom Van Eyck fclose(f);
1334*b0563631STom Van Eyck
1335*b0563631STom Van Eyck (*buf)[*n] = '\0';
1336*b0563631STom Van Eyck
1337*b0563631STom Van Eyck if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
1338*b0563631STom Van Eyck ++*n;
1339*b0563631STom Van Eyck }
1340*b0563631STom Van Eyck
1341*b0563631STom Van Eyck return 0;
1342*b0563631STom Van Eyck }
1343*b0563631STom Van Eyck
1344*b0563631STom Van Eyck /*
1345*b0563631STom Van Eyck * Load and parse a private key
1346*b0563631STom Van Eyck */
mbedtls_pk_parse_keyfile(mbedtls_pk_context * ctx,const char * path,const char * pwd,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)1347*b0563631STom Van Eyck int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
1348*b0563631STom Van Eyck const char *path, const char *pwd,
1349*b0563631STom Van Eyck int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1350*b0563631STom Van Eyck {
1351*b0563631STom Van Eyck int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1352*b0563631STom Van Eyck size_t n;
1353*b0563631STom Van Eyck unsigned char *buf;
1354*b0563631STom Van Eyck
1355*b0563631STom Van Eyck if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1356*b0563631STom Van Eyck return ret;
1357*b0563631STom Van Eyck }
1358*b0563631STom Van Eyck
1359*b0563631STom Van Eyck if (pwd == NULL) {
1360*b0563631STom Van Eyck ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
1361*b0563631STom Van Eyck } else {
1362*b0563631STom Van Eyck ret = mbedtls_pk_parse_key(ctx, buf, n,
1363*b0563631STom Van Eyck (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
1364*b0563631STom Van Eyck }
1365*b0563631STom Van Eyck
1366*b0563631STom Van Eyck mbedtls_zeroize_and_free(buf, n);
1367*b0563631STom Van Eyck
1368*b0563631STom Van Eyck return ret;
1369*b0563631STom Van Eyck }
1370*b0563631STom Van Eyck
1371*b0563631STom Van Eyck /*
1372*b0563631STom Van Eyck * Load and parse a public key
1373*b0563631STom Van Eyck */
mbedtls_pk_parse_public_keyfile(mbedtls_pk_context * ctx,const char * path)1374*b0563631STom Van Eyck int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
1375*b0563631STom Van Eyck {
1376*b0563631STom Van Eyck int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1377*b0563631STom Van Eyck size_t n;
1378*b0563631STom Van Eyck unsigned char *buf;
1379*b0563631STom Van Eyck
1380*b0563631STom Van Eyck if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1381*b0563631STom Van Eyck return ret;
1382*b0563631STom Van Eyck }
1383*b0563631STom Van Eyck
1384*b0563631STom Van Eyck ret = mbedtls_pk_parse_public_key(ctx, buf, n);
1385*b0563631STom Van Eyck
1386*b0563631STom Van Eyck mbedtls_zeroize_and_free(buf, n);
1387*b0563631STom Van Eyck
1388*b0563631STom Van Eyck return ret;
1389*b0563631STom Van Eyck }
1390*b0563631STom Van Eyck #endif /* MBEDTLS_FS_IO */
1391*b0563631STom Van Eyck
1392817466cbSJens Wiklander #endif /* MBEDTLS_PK_PARSE_C */
1393