1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  Public Key layer for parsing key files and structures
3a8e1175bSopenharmony_ci *
4a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
5a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6a8e1175bSopenharmony_ci */
7a8e1175bSopenharmony_ci
8a8e1175bSopenharmony_ci#include "common.h"
9a8e1175bSopenharmony_ci
10a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_PARSE_C)
11a8e1175bSopenharmony_ci
12a8e1175bSopenharmony_ci#include "mbedtls/pk.h"
13a8e1175bSopenharmony_ci#include "mbedtls/asn1.h"
14a8e1175bSopenharmony_ci#include "mbedtls/oid.h"
15a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h"
16a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
17a8e1175bSopenharmony_ci#include "mbedtls/error.h"
18a8e1175bSopenharmony_ci#include "mbedtls/ecp.h"
19a8e1175bSopenharmony_ci#include "pk_internal.h"
20a8e1175bSopenharmony_ci
21a8e1175bSopenharmony_ci#include <string.h>
22a8e1175bSopenharmony_ci
23a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
24a8e1175bSopenharmony_ci#include "mbedtls/psa_util.h"
25a8e1175bSopenharmony_ci#include "psa/crypto.h"
26a8e1175bSopenharmony_ci#endif
27a8e1175bSopenharmony_ci
28a8e1175bSopenharmony_ci/* Key types */
29a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
30a8e1175bSopenharmony_ci#include "mbedtls/rsa.h"
31a8e1175bSopenharmony_ci#include "rsa_internal.h"
32a8e1175bSopenharmony_ci#endif
33a8e1175bSopenharmony_ci
34a8e1175bSopenharmony_ci/* Extended formats */
35a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
36a8e1175bSopenharmony_ci#include "mbedtls/pem.h"
37a8e1175bSopenharmony_ci#endif
38a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS5_C)
39a8e1175bSopenharmony_ci#include "mbedtls/pkcs5.h"
40a8e1175bSopenharmony_ci#endif
41a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C)
42a8e1175bSopenharmony_ci#include "mbedtls/pkcs12.h"
43a8e1175bSopenharmony_ci#endif
44a8e1175bSopenharmony_ci
45a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
46a8e1175bSopenharmony_ci
47a8e1175bSopenharmony_ci/***********************************************************************
48a8e1175bSopenharmony_ci *
49a8e1175bSopenharmony_ci *      Low-level ECC parsing: optional support for SpecifiedECDomain
50a8e1175bSopenharmony_ci *
51a8e1175bSopenharmony_ci * There are two functions here that are used by the rest of the code:
52a8e1175bSopenharmony_ci * - pk_ecc_tag_is_speficied_ec_domain()
53a8e1175bSopenharmony_ci * - pk_ecc_group_id_from_specified()
54a8e1175bSopenharmony_ci *
55a8e1175bSopenharmony_ci * All the other functions are internal to this section.
56a8e1175bSopenharmony_ci *
57a8e1175bSopenharmony_ci * The two "public" functions have a dummy variant provided
58a8e1175bSopenharmony_ci * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an
59a8e1175bSopenharmony_ci * abstraction layer for this macro, which should not appear outside
60a8e1175bSopenharmony_ci * this section.
61a8e1175bSopenharmony_ci *
62a8e1175bSopenharmony_ci **********************************************************************/
63a8e1175bSopenharmony_ci
64a8e1175bSopenharmony_ci#if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
65a8e1175bSopenharmony_ci/* See the "real" version for documentation */
66a8e1175bSopenharmony_cistatic int pk_ecc_tag_is_specified_ec_domain(int tag)
67a8e1175bSopenharmony_ci{
68a8e1175bSopenharmony_ci    (void) tag;
69a8e1175bSopenharmony_ci    return 0;
70a8e1175bSopenharmony_ci}
71a8e1175bSopenharmony_ci
72a8e1175bSopenharmony_ci/* See the "real" version for documentation */
73a8e1175bSopenharmony_cistatic int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
74a8e1175bSopenharmony_ci                                          mbedtls_ecp_group_id *grp_id)
75a8e1175bSopenharmony_ci{
76a8e1175bSopenharmony_ci    (void) params;
77a8e1175bSopenharmony_ci    (void) grp_id;
78a8e1175bSopenharmony_ci    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
79a8e1175bSopenharmony_ci}
80a8e1175bSopenharmony_ci#else /* MBEDTLS_PK_PARSE_EC_EXTENDED */
81a8e1175bSopenharmony_ci/*
82a8e1175bSopenharmony_ci * Tell if the passed tag might be the start of SpecifiedECDomain
83a8e1175bSopenharmony_ci * (that is, a sequence).
84a8e1175bSopenharmony_ci */
85a8e1175bSopenharmony_cistatic int pk_ecc_tag_is_specified_ec_domain(int tag)
86a8e1175bSopenharmony_ci{
87a8e1175bSopenharmony_ci    return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
88a8e1175bSopenharmony_ci}
89a8e1175bSopenharmony_ci
90a8e1175bSopenharmony_ci/*
91a8e1175bSopenharmony_ci * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
92a8e1175bSopenharmony_ci * WARNING: the resulting group should only be used with
93a8e1175bSopenharmony_ci * pk_ecc_group_id_from_specified(), since its base point may not be set correctly
94a8e1175bSopenharmony_ci * if it was encoded compressed.
95a8e1175bSopenharmony_ci *
96a8e1175bSopenharmony_ci *  SpecifiedECDomain ::= SEQUENCE {
97a8e1175bSopenharmony_ci *      version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
98a8e1175bSopenharmony_ci *      fieldID FieldID {{FieldTypes}},
99a8e1175bSopenharmony_ci *      curve Curve,
100a8e1175bSopenharmony_ci *      base ECPoint,
101a8e1175bSopenharmony_ci *      order INTEGER,
102a8e1175bSopenharmony_ci *      cofactor INTEGER OPTIONAL,
103a8e1175bSopenharmony_ci *      hash HashAlgorithm OPTIONAL,
104a8e1175bSopenharmony_ci *      ...
105a8e1175bSopenharmony_ci *  }
106a8e1175bSopenharmony_ci *
107a8e1175bSopenharmony_ci * We only support prime-field as field type, and ignore hash and cofactor.
108a8e1175bSopenharmony_ci */
109a8e1175bSopenharmony_cistatic int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
110a8e1175bSopenharmony_ci{
111a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
112a8e1175bSopenharmony_ci    unsigned char *p = params->p;
113a8e1175bSopenharmony_ci    const unsigned char *const end = params->p + params->len;
114a8e1175bSopenharmony_ci    const unsigned char *end_field, *end_curve;
115a8e1175bSopenharmony_ci    size_t len;
116a8e1175bSopenharmony_ci    int ver;
117a8e1175bSopenharmony_ci
118a8e1175bSopenharmony_ci    /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
119a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) {
120a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
121a8e1175bSopenharmony_ci    }
122a8e1175bSopenharmony_ci
123a8e1175bSopenharmony_ci    if (ver < 1 || ver > 3) {
124a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
125a8e1175bSopenharmony_ci    }
126a8e1175bSopenharmony_ci
127a8e1175bSopenharmony_ci    /*
128a8e1175bSopenharmony_ci     * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
129a8e1175bSopenharmony_ci     *       fieldType FIELD-ID.&id({IOSet}),
130a8e1175bSopenharmony_ci     *       parameters FIELD-ID.&Type({IOSet}{@fieldType})
131a8e1175bSopenharmony_ci     * }
132a8e1175bSopenharmony_ci     */
133a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
134a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
135a8e1175bSopenharmony_ci        return ret;
136a8e1175bSopenharmony_ci    }
137a8e1175bSopenharmony_ci
138a8e1175bSopenharmony_ci    end_field = p + len;
139a8e1175bSopenharmony_ci
140a8e1175bSopenharmony_ci    /*
141a8e1175bSopenharmony_ci     * FIELD-ID ::= TYPE-IDENTIFIER
142a8e1175bSopenharmony_ci     * FieldTypes FIELD-ID ::= {
143a8e1175bSopenharmony_ci     *       { Prime-p IDENTIFIED BY prime-field } |
144a8e1175bSopenharmony_ci     *       { Characteristic-two IDENTIFIED BY characteristic-two-field }
145a8e1175bSopenharmony_ci     * }
146a8e1175bSopenharmony_ci     * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
147a8e1175bSopenharmony_ci     */
148a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) {
149a8e1175bSopenharmony_ci        return ret;
150a8e1175bSopenharmony_ci    }
151a8e1175bSopenharmony_ci
152a8e1175bSopenharmony_ci    if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) ||
153a8e1175bSopenharmony_ci        memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) {
154a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
155a8e1175bSopenharmony_ci    }
156a8e1175bSopenharmony_ci
157a8e1175bSopenharmony_ci    p += len;
158a8e1175bSopenharmony_ci
159a8e1175bSopenharmony_ci    /* Prime-p ::= INTEGER -- Field of size p. */
160a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) {
161a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
162a8e1175bSopenharmony_ci    }
163a8e1175bSopenharmony_ci
164a8e1175bSopenharmony_ci    grp->pbits = mbedtls_mpi_bitlen(&grp->P);
165a8e1175bSopenharmony_ci
166a8e1175bSopenharmony_ci    if (p != end_field) {
167a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
168a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
169a8e1175bSopenharmony_ci    }
170a8e1175bSopenharmony_ci
171a8e1175bSopenharmony_ci    /*
172a8e1175bSopenharmony_ci     * Curve ::= SEQUENCE {
173a8e1175bSopenharmony_ci     *       a FieldElement,
174a8e1175bSopenharmony_ci     *       b FieldElement,
175a8e1175bSopenharmony_ci     *       seed BIT STRING OPTIONAL
176a8e1175bSopenharmony_ci     *       -- Shall be present if used in SpecifiedECDomain
177a8e1175bSopenharmony_ci     *       -- with version equal to ecdpVer2 or ecdpVer3
178a8e1175bSopenharmony_ci     * }
179a8e1175bSopenharmony_ci     */
180a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
181a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
182a8e1175bSopenharmony_ci        return ret;
183a8e1175bSopenharmony_ci    }
184a8e1175bSopenharmony_ci
185a8e1175bSopenharmony_ci    end_curve = p + len;
186a8e1175bSopenharmony_ci
187a8e1175bSopenharmony_ci    /*
188a8e1175bSopenharmony_ci     * FieldElement ::= OCTET STRING
189a8e1175bSopenharmony_ci     * containing an integer in the case of a prime field
190a8e1175bSopenharmony_ci     */
191a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
192a8e1175bSopenharmony_ci        (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) {
193a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
194a8e1175bSopenharmony_ci    }
195a8e1175bSopenharmony_ci
196a8e1175bSopenharmony_ci    p += len;
197a8e1175bSopenharmony_ci
198a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
199a8e1175bSopenharmony_ci        (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) {
200a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
201a8e1175bSopenharmony_ci    }
202a8e1175bSopenharmony_ci
203a8e1175bSopenharmony_ci    p += len;
204a8e1175bSopenharmony_ci
205a8e1175bSopenharmony_ci    /* Ignore seed BIT STRING OPTIONAL */
206a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) {
207a8e1175bSopenharmony_ci        p += len;
208a8e1175bSopenharmony_ci    }
209a8e1175bSopenharmony_ci
210a8e1175bSopenharmony_ci    if (p != end_curve) {
211a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
212a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
213a8e1175bSopenharmony_ci    }
214a8e1175bSopenharmony_ci
215a8e1175bSopenharmony_ci    /*
216a8e1175bSopenharmony_ci     * ECPoint ::= OCTET STRING
217a8e1175bSopenharmony_ci     */
218a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
219a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
220a8e1175bSopenharmony_ci    }
221a8e1175bSopenharmony_ci
222a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G,
223a8e1175bSopenharmony_ci                                             (const unsigned char *) p, len)) != 0) {
224a8e1175bSopenharmony_ci        /*
225a8e1175bSopenharmony_ci         * If we can't read the point because it's compressed, cheat by
226a8e1175bSopenharmony_ci         * reading only the X coordinate and the parity bit of Y.
227a8e1175bSopenharmony_ci         */
228a8e1175bSopenharmony_ci        if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
229a8e1175bSopenharmony_ci            (p[0] != 0x02 && p[0] != 0x03) ||
230a8e1175bSopenharmony_ci            len != mbedtls_mpi_size(&grp->P) + 1 ||
231a8e1175bSopenharmony_ci            mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 ||
232a8e1175bSopenharmony_ci            mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 ||
233a8e1175bSopenharmony_ci            mbedtls_mpi_lset(&grp->G.Z, 1) != 0) {
234a8e1175bSopenharmony_ci            return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
235a8e1175bSopenharmony_ci        }
236a8e1175bSopenharmony_ci    }
237a8e1175bSopenharmony_ci
238a8e1175bSopenharmony_ci    p += len;
239a8e1175bSopenharmony_ci
240a8e1175bSopenharmony_ci    /*
241a8e1175bSopenharmony_ci     * order INTEGER
242a8e1175bSopenharmony_ci     */
243a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) {
244a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
245a8e1175bSopenharmony_ci    }
246a8e1175bSopenharmony_ci
247a8e1175bSopenharmony_ci    grp->nbits = mbedtls_mpi_bitlen(&grp->N);
248a8e1175bSopenharmony_ci
249a8e1175bSopenharmony_ci    /*
250a8e1175bSopenharmony_ci     * Allow optional elements by purposefully not enforcing p == end here.
251a8e1175bSopenharmony_ci     */
252a8e1175bSopenharmony_ci
253a8e1175bSopenharmony_ci    return 0;
254a8e1175bSopenharmony_ci}
255a8e1175bSopenharmony_ci
256a8e1175bSopenharmony_ci/*
257a8e1175bSopenharmony_ci * Find the group id associated with an (almost filled) group as generated by
258a8e1175bSopenharmony_ci * pk_group_from_specified(), or return an error if unknown.
259a8e1175bSopenharmony_ci */
260a8e1175bSopenharmony_cistatic int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id)
261a8e1175bSopenharmony_ci{
262a8e1175bSopenharmony_ci    int ret = 0;
263a8e1175bSopenharmony_ci    mbedtls_ecp_group ref;
264a8e1175bSopenharmony_ci    const mbedtls_ecp_group_id *id;
265a8e1175bSopenharmony_ci
266a8e1175bSopenharmony_ci    mbedtls_ecp_group_init(&ref);
267a8e1175bSopenharmony_ci
268a8e1175bSopenharmony_ci    for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) {
269a8e1175bSopenharmony_ci        /* Load the group associated to that id */
270a8e1175bSopenharmony_ci        mbedtls_ecp_group_free(&ref);
271a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id));
272a8e1175bSopenharmony_ci
273a8e1175bSopenharmony_ci        /* Compare to the group we were given, starting with easy tests */
274a8e1175bSopenharmony_ci        if (grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
275a8e1175bSopenharmony_ci            mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 &&
276a8e1175bSopenharmony_ci            mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 &&
277a8e1175bSopenharmony_ci            mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 &&
278a8e1175bSopenharmony_ci            mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 &&
279a8e1175bSopenharmony_ci            mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 &&
280a8e1175bSopenharmony_ci            mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 &&
281a8e1175bSopenharmony_ci            /* For Y we may only know the parity bit, so compare only that */
282a8e1175bSopenharmony_ci            mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) {
283a8e1175bSopenharmony_ci            break;
284a8e1175bSopenharmony_ci        }
285a8e1175bSopenharmony_ci    }
286a8e1175bSopenharmony_ci
287a8e1175bSopenharmony_cicleanup:
288a8e1175bSopenharmony_ci    mbedtls_ecp_group_free(&ref);
289a8e1175bSopenharmony_ci
290a8e1175bSopenharmony_ci    *grp_id = *id;
291a8e1175bSopenharmony_ci
292a8e1175bSopenharmony_ci    if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) {
293a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
294a8e1175bSopenharmony_ci    }
295a8e1175bSopenharmony_ci
296a8e1175bSopenharmony_ci    return ret;
297a8e1175bSopenharmony_ci}
298a8e1175bSopenharmony_ci
299a8e1175bSopenharmony_ci/*
300a8e1175bSopenharmony_ci * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
301a8e1175bSopenharmony_ci */
302a8e1175bSopenharmony_cistatic int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
303a8e1175bSopenharmony_ci                                          mbedtls_ecp_group_id *grp_id)
304a8e1175bSopenharmony_ci{
305a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
306a8e1175bSopenharmony_ci    mbedtls_ecp_group grp;
307a8e1175bSopenharmony_ci
308a8e1175bSopenharmony_ci    mbedtls_ecp_group_init(&grp);
309a8e1175bSopenharmony_ci
310a8e1175bSopenharmony_ci    if ((ret = pk_group_from_specified(params, &grp)) != 0) {
311a8e1175bSopenharmony_ci        goto cleanup;
312a8e1175bSopenharmony_ci    }
313a8e1175bSopenharmony_ci
314a8e1175bSopenharmony_ci    ret = pk_group_id_from_group(&grp, grp_id);
315a8e1175bSopenharmony_ci
316a8e1175bSopenharmony_cicleanup:
317a8e1175bSopenharmony_ci    /* The API respecting lifecycle for mbedtls_ecp_group struct is
318a8e1175bSopenharmony_ci     * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the
319a8e1175bSopenharmony_ci     * temporary grp breaks that flow and it's members are populated
320a8e1175bSopenharmony_ci     * by pk_group_id_from_group(). As such mbedtls_ecp_group_free()
321a8e1175bSopenharmony_ci     * which is assuming a group populated by _setup() may not clean-up
322a8e1175bSopenharmony_ci     * properly -> Manually free it's members.
323a8e1175bSopenharmony_ci     */
324a8e1175bSopenharmony_ci    mbedtls_mpi_free(&grp.N);
325a8e1175bSopenharmony_ci    mbedtls_mpi_free(&grp.P);
326a8e1175bSopenharmony_ci    mbedtls_mpi_free(&grp.A);
327a8e1175bSopenharmony_ci    mbedtls_mpi_free(&grp.B);
328a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&grp.G);
329a8e1175bSopenharmony_ci
330a8e1175bSopenharmony_ci    return ret;
331a8e1175bSopenharmony_ci}
332a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
333a8e1175bSopenharmony_ci
334a8e1175bSopenharmony_ci/***********************************************************************
335a8e1175bSopenharmony_ci *
336a8e1175bSopenharmony_ci * Unsorted (yet!) from this point on until the next section header
337a8e1175bSopenharmony_ci *
338a8e1175bSopenharmony_ci **********************************************************************/
339a8e1175bSopenharmony_ci
340a8e1175bSopenharmony_ci/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
341a8e1175bSopenharmony_ci *
342a8e1175bSopenharmony_ci * ECParameters ::= CHOICE {
343a8e1175bSopenharmony_ci *   namedCurve         OBJECT IDENTIFIER
344a8e1175bSopenharmony_ci *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
345a8e1175bSopenharmony_ci *   -- implicitCurve   NULL
346a8e1175bSopenharmony_ci * }
347a8e1175bSopenharmony_ci */
348a8e1175bSopenharmony_cistatic int pk_get_ecparams(unsigned char **p, const unsigned char *end,
349a8e1175bSopenharmony_ci                           mbedtls_asn1_buf *params)
350a8e1175bSopenharmony_ci{
351a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
352a8e1175bSopenharmony_ci
353a8e1175bSopenharmony_ci    if (end - *p < 1) {
354a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
355a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
356a8e1175bSopenharmony_ci    }
357a8e1175bSopenharmony_ci
358a8e1175bSopenharmony_ci    /* Acceptable tags: OID for namedCurve, or specifiedECDomain */
359a8e1175bSopenharmony_ci    params->tag = **p;
360a8e1175bSopenharmony_ci    if (params->tag != MBEDTLS_ASN1_OID &&
361a8e1175bSopenharmony_ci        !pk_ecc_tag_is_specified_ec_domain(params->tag)) {
362a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
363a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
364a8e1175bSopenharmony_ci    }
365a8e1175bSopenharmony_ci
366a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {
367a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
368a8e1175bSopenharmony_ci    }
369a8e1175bSopenharmony_ci
370a8e1175bSopenharmony_ci    params->p = *p;
371a8e1175bSopenharmony_ci    *p += params->len;
372a8e1175bSopenharmony_ci
373a8e1175bSopenharmony_ci    if (*p != end) {
374a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
375a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
376a8e1175bSopenharmony_ci    }
377a8e1175bSopenharmony_ci
378a8e1175bSopenharmony_ci    return 0;
379a8e1175bSopenharmony_ci}
380a8e1175bSopenharmony_ci
381a8e1175bSopenharmony_ci/*
382a8e1175bSopenharmony_ci * Use EC parameters to initialise an EC group
383a8e1175bSopenharmony_ci *
384a8e1175bSopenharmony_ci * ECParameters ::= CHOICE {
385a8e1175bSopenharmony_ci *   namedCurve         OBJECT IDENTIFIER
386a8e1175bSopenharmony_ci *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
387a8e1175bSopenharmony_ci *   -- implicitCurve   NULL
388a8e1175bSopenharmony_ci */
389a8e1175bSopenharmony_cistatic int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk)
390a8e1175bSopenharmony_ci{
391a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
392a8e1175bSopenharmony_ci    mbedtls_ecp_group_id grp_id;
393a8e1175bSopenharmony_ci
394a8e1175bSopenharmony_ci    if (params->tag == MBEDTLS_ASN1_OID) {
395a8e1175bSopenharmony_ci        if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) {
396a8e1175bSopenharmony_ci            return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
397a8e1175bSopenharmony_ci        }
398a8e1175bSopenharmony_ci    } else {
399a8e1175bSopenharmony_ci        ret = pk_ecc_group_id_from_specified(params, &grp_id);
400a8e1175bSopenharmony_ci        if (ret != 0) {
401a8e1175bSopenharmony_ci            return ret;
402a8e1175bSopenharmony_ci        }
403a8e1175bSopenharmony_ci    }
404a8e1175bSopenharmony_ci
405a8e1175bSopenharmony_ci    return mbedtls_pk_ecc_set_group(pk, grp_id);
406a8e1175bSopenharmony_ci}
407a8e1175bSopenharmony_ci
408a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
409a8e1175bSopenharmony_ci
410a8e1175bSopenharmony_ci/*
411a8e1175bSopenharmony_ci * Load an RFC8410 EC key, which doesn't have any parameters
412a8e1175bSopenharmony_ci */
413a8e1175bSopenharmony_cistatic int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params,
414a8e1175bSopenharmony_ci                                   mbedtls_ecp_group_id grp_id,
415a8e1175bSopenharmony_ci                                   mbedtls_pk_context *pk)
416a8e1175bSopenharmony_ci{
417a8e1175bSopenharmony_ci    if (params->tag != 0 || params->len != 0) {
418a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
419a8e1175bSopenharmony_ci    }
420a8e1175bSopenharmony_ci
421a8e1175bSopenharmony_ci    return mbedtls_pk_ecc_set_group(pk, grp_id);
422a8e1175bSopenharmony_ci}
423a8e1175bSopenharmony_ci
424a8e1175bSopenharmony_ci/*
425a8e1175bSopenharmony_ci * Parse an RFC 8410 encoded private EC key
426a8e1175bSopenharmony_ci *
427a8e1175bSopenharmony_ci * CurvePrivateKey ::= OCTET STRING
428a8e1175bSopenharmony_ci */
429a8e1175bSopenharmony_cistatic int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
430a8e1175bSopenharmony_ci                                    unsigned char *key, size_t keylen, const unsigned char *end,
431a8e1175bSopenharmony_ci                                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
432a8e1175bSopenharmony_ci{
433a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
434a8e1175bSopenharmony_ci    size_t len;
435a8e1175bSopenharmony_ci
436a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
437a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
438a8e1175bSopenharmony_ci    }
439a8e1175bSopenharmony_ci
440a8e1175bSopenharmony_ci    if (key + len != end) {
441a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
442a8e1175bSopenharmony_ci    }
443a8e1175bSopenharmony_ci
444a8e1175bSopenharmony_ci    /*
445a8e1175bSopenharmony_ci     * Load the private key
446a8e1175bSopenharmony_ci     */
447a8e1175bSopenharmony_ci    ret = mbedtls_pk_ecc_set_key(pk, key, len);
448a8e1175bSopenharmony_ci    if (ret != 0) {
449a8e1175bSopenharmony_ci        return ret;
450a8e1175bSopenharmony_ci    }
451a8e1175bSopenharmony_ci
452a8e1175bSopenharmony_ci    /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,
453a8e1175bSopenharmony_ci     * which never contain a public key. As such, derive the public key
454a8e1175bSopenharmony_ci     * unconditionally. */
455a8e1175bSopenharmony_ci    if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
456a8e1175bSopenharmony_ci        return ret;
457a8e1175bSopenharmony_ci    }
458a8e1175bSopenharmony_ci
459a8e1175bSopenharmony_ci    return 0;
460a8e1175bSopenharmony_ci}
461a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
462a8e1175bSopenharmony_ci
463a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
464a8e1175bSopenharmony_ci
465a8e1175bSopenharmony_ci/* Get a PK algorithm identifier
466a8e1175bSopenharmony_ci *
467a8e1175bSopenharmony_ci *  AlgorithmIdentifier  ::=  SEQUENCE  {
468a8e1175bSopenharmony_ci *       algorithm               OBJECT IDENTIFIER,
469a8e1175bSopenharmony_ci *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
470a8e1175bSopenharmony_ci */
471a8e1175bSopenharmony_cistatic int pk_get_pk_alg(unsigned char **p,
472a8e1175bSopenharmony_ci                         const unsigned char *end,
473a8e1175bSopenharmony_ci                         mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params,
474a8e1175bSopenharmony_ci                         mbedtls_ecp_group_id *ec_grp_id)
475a8e1175bSopenharmony_ci{
476a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
477a8e1175bSopenharmony_ci    mbedtls_asn1_buf alg_oid;
478a8e1175bSopenharmony_ci
479a8e1175bSopenharmony_ci    memset(params, 0, sizeof(mbedtls_asn1_buf));
480a8e1175bSopenharmony_ci
481a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) {
482a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
483a8e1175bSopenharmony_ci    }
484a8e1175bSopenharmony_ci
485a8e1175bSopenharmony_ci    ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg);
486a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
487a8e1175bSopenharmony_ci    if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
488a8e1175bSopenharmony_ci        ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id);
489a8e1175bSopenharmony_ci        if (ret == 0) {
490a8e1175bSopenharmony_ci            *pk_alg = MBEDTLS_PK_ECKEY;
491a8e1175bSopenharmony_ci        }
492a8e1175bSopenharmony_ci    }
493a8e1175bSopenharmony_ci#else
494a8e1175bSopenharmony_ci    (void) ec_grp_id;
495a8e1175bSopenharmony_ci#endif
496a8e1175bSopenharmony_ci    if (ret != 0) {
497a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
498a8e1175bSopenharmony_ci    }
499a8e1175bSopenharmony_ci
500a8e1175bSopenharmony_ci    /*
501a8e1175bSopenharmony_ci     * No parameters with RSA (only for EC)
502a8e1175bSopenharmony_ci     */
503a8e1175bSopenharmony_ci    if (*pk_alg == MBEDTLS_PK_RSA &&
504a8e1175bSopenharmony_ci        ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) ||
505a8e1175bSopenharmony_ci         params->len != 0)) {
506a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_INVALID_ALG;
507a8e1175bSopenharmony_ci    }
508a8e1175bSopenharmony_ci
509a8e1175bSopenharmony_ci    return 0;
510a8e1175bSopenharmony_ci}
511a8e1175bSopenharmony_ci
512a8e1175bSopenharmony_ci/*
513a8e1175bSopenharmony_ci *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
514a8e1175bSopenharmony_ci *       algorithm            AlgorithmIdentifier,
515a8e1175bSopenharmony_ci *       subjectPublicKey     BIT STRING }
516a8e1175bSopenharmony_ci */
517a8e1175bSopenharmony_ciint mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
518a8e1175bSopenharmony_ci                               mbedtls_pk_context *pk)
519a8e1175bSopenharmony_ci{
520a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
521a8e1175bSopenharmony_ci    size_t len;
522a8e1175bSopenharmony_ci    mbedtls_asn1_buf alg_params;
523a8e1175bSopenharmony_ci    mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
524a8e1175bSopenharmony_ci    mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
525a8e1175bSopenharmony_ci    const mbedtls_pk_info_t *pk_info;
526a8e1175bSopenharmony_ci
527a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
528a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
529a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
530a8e1175bSopenharmony_ci    }
531a8e1175bSopenharmony_ci
532a8e1175bSopenharmony_ci    end = *p + len;
533a8e1175bSopenharmony_ci
534a8e1175bSopenharmony_ci    if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) {
535a8e1175bSopenharmony_ci        return ret;
536a8e1175bSopenharmony_ci    }
537a8e1175bSopenharmony_ci
538a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
539a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
540a8e1175bSopenharmony_ci    }
541a8e1175bSopenharmony_ci
542a8e1175bSopenharmony_ci    if (*p + len != end) {
543a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
544a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
545a8e1175bSopenharmony_ci    }
546a8e1175bSopenharmony_ci
547a8e1175bSopenharmony_ci    if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
548a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
549a8e1175bSopenharmony_ci    }
550a8e1175bSopenharmony_ci
551a8e1175bSopenharmony_ci    if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
552a8e1175bSopenharmony_ci        return ret;
553a8e1175bSopenharmony_ci    }
554a8e1175bSopenharmony_ci
555a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
556a8e1175bSopenharmony_ci    if (pk_alg == MBEDTLS_PK_RSA) {
557a8e1175bSopenharmony_ci        ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p));
558a8e1175bSopenharmony_ci        if (ret == 0) {
559a8e1175bSopenharmony_ci            /* On success all the input has been consumed by the parsing function. */
560a8e1175bSopenharmony_ci            *p += end - *p;
561a8e1175bSopenharmony_ci        } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) &&
562a8e1175bSopenharmony_ci                   (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) {
563a8e1175bSopenharmony_ci            /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */
564a8e1175bSopenharmony_ci            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
565a8e1175bSopenharmony_ci        } else {
566a8e1175bSopenharmony_ci            ret = MBEDTLS_ERR_PK_INVALID_PUBKEY;
567a8e1175bSopenharmony_ci        }
568a8e1175bSopenharmony_ci    } else
569a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
570a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
571a8e1175bSopenharmony_ci    if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
572a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
573a8e1175bSopenharmony_ci        if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
574a8e1175bSopenharmony_ci            ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk);
575a8e1175bSopenharmony_ci        } else
576a8e1175bSopenharmony_ci#endif
577a8e1175bSopenharmony_ci        {
578a8e1175bSopenharmony_ci            ret = pk_use_ecparams(&alg_params, pk);
579a8e1175bSopenharmony_ci        }
580a8e1175bSopenharmony_ci        if (ret == 0) {
581a8e1175bSopenharmony_ci            ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
582a8e1175bSopenharmony_ci            *p += end - *p;
583a8e1175bSopenharmony_ci        }
584a8e1175bSopenharmony_ci    } else
585a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
586a8e1175bSopenharmony_ci    ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
587a8e1175bSopenharmony_ci
588a8e1175bSopenharmony_ci    if (ret == 0 && *p != end) {
589a8e1175bSopenharmony_ci        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
590a8e1175bSopenharmony_ci                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
591a8e1175bSopenharmony_ci    }
592a8e1175bSopenharmony_ci
593a8e1175bSopenharmony_ci    if (ret != 0) {
594a8e1175bSopenharmony_ci        mbedtls_pk_free(pk);
595a8e1175bSopenharmony_ci    }
596a8e1175bSopenharmony_ci
597a8e1175bSopenharmony_ci    return ret;
598a8e1175bSopenharmony_ci}
599a8e1175bSopenharmony_ci
600a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
601a8e1175bSopenharmony_ci/*
602a8e1175bSopenharmony_ci * Parse a SEC1 encoded private EC key
603a8e1175bSopenharmony_ci */
604a8e1175bSopenharmony_cistatic int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
605a8e1175bSopenharmony_ci                                 const unsigned char *key, size_t keylen,
606a8e1175bSopenharmony_ci                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
607a8e1175bSopenharmony_ci{
608a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
609a8e1175bSopenharmony_ci    int version, pubkey_done;
610a8e1175bSopenharmony_ci    size_t len, d_len;
611a8e1175bSopenharmony_ci    mbedtls_asn1_buf params = { 0, 0, NULL };
612a8e1175bSopenharmony_ci    unsigned char *p = (unsigned char *) key;
613a8e1175bSopenharmony_ci    unsigned char *d;
614a8e1175bSopenharmony_ci    unsigned char *end = p + keylen;
615a8e1175bSopenharmony_ci    unsigned char *end2;
616a8e1175bSopenharmony_ci
617a8e1175bSopenharmony_ci    /*
618a8e1175bSopenharmony_ci     * RFC 5915, or SEC1 Appendix C.4
619a8e1175bSopenharmony_ci     *
620a8e1175bSopenharmony_ci     * ECPrivateKey ::= SEQUENCE {
621a8e1175bSopenharmony_ci     *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
622a8e1175bSopenharmony_ci     *      privateKey     OCTET STRING,
623a8e1175bSopenharmony_ci     *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
624a8e1175bSopenharmony_ci     *      publicKey  [1] BIT STRING OPTIONAL
625a8e1175bSopenharmony_ci     *    }
626a8e1175bSopenharmony_ci     */
627a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
628a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
629a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
630a8e1175bSopenharmony_ci    }
631a8e1175bSopenharmony_ci
632a8e1175bSopenharmony_ci    end = p + len;
633a8e1175bSopenharmony_ci
634a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
635a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
636a8e1175bSopenharmony_ci    }
637a8e1175bSopenharmony_ci
638a8e1175bSopenharmony_ci    if (version != 1) {
639a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
640a8e1175bSopenharmony_ci    }
641a8e1175bSopenharmony_ci
642a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
643a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
644a8e1175bSopenharmony_ci    }
645a8e1175bSopenharmony_ci
646a8e1175bSopenharmony_ci    /* Keep a reference to the position fo the private key. It will be used
647a8e1175bSopenharmony_ci     * later in this function. */
648a8e1175bSopenharmony_ci    d = p;
649a8e1175bSopenharmony_ci    d_len = len;
650a8e1175bSopenharmony_ci
651a8e1175bSopenharmony_ci    p += len;
652a8e1175bSopenharmony_ci
653a8e1175bSopenharmony_ci    pubkey_done = 0;
654a8e1175bSopenharmony_ci    if (p != end) {
655a8e1175bSopenharmony_ci        /*
656a8e1175bSopenharmony_ci         * Is 'parameters' present?
657a8e1175bSopenharmony_ci         */
658a8e1175bSopenharmony_ci        if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
659a8e1175bSopenharmony_ci                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
660a8e1175bSopenharmony_ci                                        0)) == 0) {
661a8e1175bSopenharmony_ci            if ((ret = pk_get_ecparams(&p, p + len, &params)) != 0 ||
662a8e1175bSopenharmony_ci                (ret = pk_use_ecparams(&params, pk)) != 0) {
663a8e1175bSopenharmony_ci                return ret;
664a8e1175bSopenharmony_ci            }
665a8e1175bSopenharmony_ci        } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
666a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
667a8e1175bSopenharmony_ci        }
668a8e1175bSopenharmony_ci    }
669a8e1175bSopenharmony_ci
670a8e1175bSopenharmony_ci    /*
671a8e1175bSopenharmony_ci     * Load the private key
672a8e1175bSopenharmony_ci     */
673a8e1175bSopenharmony_ci    ret = mbedtls_pk_ecc_set_key(pk, d, d_len);
674a8e1175bSopenharmony_ci    if (ret != 0) {
675a8e1175bSopenharmony_ci        return ret;
676a8e1175bSopenharmony_ci    }
677a8e1175bSopenharmony_ci
678a8e1175bSopenharmony_ci    if (p != end) {
679a8e1175bSopenharmony_ci        /*
680a8e1175bSopenharmony_ci         * Is 'publickey' present? If not, or if we can't read it (eg because it
681a8e1175bSopenharmony_ci         * is compressed), create it from the private key.
682a8e1175bSopenharmony_ci         */
683a8e1175bSopenharmony_ci        if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
684a8e1175bSopenharmony_ci                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
685a8e1175bSopenharmony_ci                                        1)) == 0) {
686a8e1175bSopenharmony_ci            end2 = p + len;
687a8e1175bSopenharmony_ci
688a8e1175bSopenharmony_ci            if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) {
689a8e1175bSopenharmony_ci                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
690a8e1175bSopenharmony_ci            }
691a8e1175bSopenharmony_ci
692a8e1175bSopenharmony_ci            if (p + len != end2) {
693a8e1175bSopenharmony_ci                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
694a8e1175bSopenharmony_ci                                         MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
695a8e1175bSopenharmony_ci            }
696a8e1175bSopenharmony_ci
697a8e1175bSopenharmony_ci            if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
698a8e1175bSopenharmony_ci                pubkey_done = 1;
699a8e1175bSopenharmony_ci            } else {
700a8e1175bSopenharmony_ci                /*
701a8e1175bSopenharmony_ci                 * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above
702a8e1175bSopenharmony_ci                 * is if the point format is not recognized.
703a8e1175bSopenharmony_ci                 */
704a8e1175bSopenharmony_ci                if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
705a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
706a8e1175bSopenharmony_ci                }
707a8e1175bSopenharmony_ci            }
708a8e1175bSopenharmony_ci        } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
709a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
710a8e1175bSopenharmony_ci        }
711a8e1175bSopenharmony_ci    }
712a8e1175bSopenharmony_ci
713a8e1175bSopenharmony_ci    if (!pubkey_done) {
714a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
715a8e1175bSopenharmony_ci            return ret;
716a8e1175bSopenharmony_ci        }
717a8e1175bSopenharmony_ci    }
718a8e1175bSopenharmony_ci
719a8e1175bSopenharmony_ci    return 0;
720a8e1175bSopenharmony_ci}
721a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
722a8e1175bSopenharmony_ci
723a8e1175bSopenharmony_ci/***********************************************************************
724a8e1175bSopenharmony_ci *
725a8e1175bSopenharmony_ci *      PKCS#8 parsing functions
726a8e1175bSopenharmony_ci *
727a8e1175bSopenharmony_ci **********************************************************************/
728a8e1175bSopenharmony_ci
729a8e1175bSopenharmony_ci/*
730a8e1175bSopenharmony_ci * Parse an unencrypted PKCS#8 encoded private key
731a8e1175bSopenharmony_ci *
732a8e1175bSopenharmony_ci * Notes:
733a8e1175bSopenharmony_ci *
734a8e1175bSopenharmony_ci * - This function does not own the key buffer. It is the
735a8e1175bSopenharmony_ci *   responsibility of the caller to take care of zeroizing
736a8e1175bSopenharmony_ci *   and freeing it after use.
737a8e1175bSopenharmony_ci *
738a8e1175bSopenharmony_ci * - The function is responsible for freeing the provided
739a8e1175bSopenharmony_ci *   PK context on failure.
740a8e1175bSopenharmony_ci *
741a8e1175bSopenharmony_ci */
742a8e1175bSopenharmony_cistatic int pk_parse_key_pkcs8_unencrypted_der(
743a8e1175bSopenharmony_ci    mbedtls_pk_context *pk,
744a8e1175bSopenharmony_ci    const unsigned char *key, size_t keylen,
745a8e1175bSopenharmony_ci    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
746a8e1175bSopenharmony_ci{
747a8e1175bSopenharmony_ci    int ret, version;
748a8e1175bSopenharmony_ci    size_t len;
749a8e1175bSopenharmony_ci    mbedtls_asn1_buf params;
750a8e1175bSopenharmony_ci    unsigned char *p = (unsigned char *) key;
751a8e1175bSopenharmony_ci    unsigned char *end = p + keylen;
752a8e1175bSopenharmony_ci    mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
753a8e1175bSopenharmony_ci    mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
754a8e1175bSopenharmony_ci    const mbedtls_pk_info_t *pk_info;
755a8e1175bSopenharmony_ci
756a8e1175bSopenharmony_ci#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS)
757a8e1175bSopenharmony_ci    (void) f_rng;
758a8e1175bSopenharmony_ci    (void) p_rng;
759a8e1175bSopenharmony_ci#endif
760a8e1175bSopenharmony_ci
761a8e1175bSopenharmony_ci    /*
762a8e1175bSopenharmony_ci     * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
763a8e1175bSopenharmony_ci     *
764a8e1175bSopenharmony_ci     *    PrivateKeyInfo ::= SEQUENCE {
765a8e1175bSopenharmony_ci     *      version                   Version,
766a8e1175bSopenharmony_ci     *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
767a8e1175bSopenharmony_ci     *      privateKey                PrivateKey,
768a8e1175bSopenharmony_ci     *      attributes           [0]  IMPLICIT Attributes OPTIONAL }
769a8e1175bSopenharmony_ci     *
770a8e1175bSopenharmony_ci     *    Version ::= INTEGER
771a8e1175bSopenharmony_ci     *    PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
772a8e1175bSopenharmony_ci     *    PrivateKey ::= OCTET STRING
773a8e1175bSopenharmony_ci     *
774a8e1175bSopenharmony_ci     *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
775a8e1175bSopenharmony_ci     */
776a8e1175bSopenharmony_ci
777a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
778a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
779a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
780a8e1175bSopenharmony_ci    }
781a8e1175bSopenharmony_ci
782a8e1175bSopenharmony_ci    end = p + len;
783a8e1175bSopenharmony_ci
784a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
785a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
786a8e1175bSopenharmony_ci    }
787a8e1175bSopenharmony_ci
788a8e1175bSopenharmony_ci    if (version != 0) {
789a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
790a8e1175bSopenharmony_ci    }
791a8e1175bSopenharmony_ci
792a8e1175bSopenharmony_ci    if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params, &ec_grp_id)) != 0) {
793a8e1175bSopenharmony_ci        return ret;
794a8e1175bSopenharmony_ci    }
795a8e1175bSopenharmony_ci
796a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
797a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
798a8e1175bSopenharmony_ci    }
799a8e1175bSopenharmony_ci
800a8e1175bSopenharmony_ci    if (len < 1) {
801a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
802a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
803a8e1175bSopenharmony_ci    }
804a8e1175bSopenharmony_ci
805a8e1175bSopenharmony_ci    if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
806a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
807a8e1175bSopenharmony_ci    }
808a8e1175bSopenharmony_ci
809a8e1175bSopenharmony_ci    if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
810a8e1175bSopenharmony_ci        return ret;
811a8e1175bSopenharmony_ci    }
812a8e1175bSopenharmony_ci
813a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
814a8e1175bSopenharmony_ci    if (pk_alg == MBEDTLS_PK_RSA) {
815a8e1175bSopenharmony_ci        if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) {
816a8e1175bSopenharmony_ci            mbedtls_pk_free(pk);
817a8e1175bSopenharmony_ci            return ret;
818a8e1175bSopenharmony_ci        }
819a8e1175bSopenharmony_ci    } else
820a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
821a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
822a8e1175bSopenharmony_ci    if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
823a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
824a8e1175bSopenharmony_ci        if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
825a8e1175bSopenharmony_ci            if ((ret =
826a8e1175bSopenharmony_ci                     pk_use_ecparams_rfc8410(&params, ec_grp_id, pk)) != 0 ||
827a8e1175bSopenharmony_ci                (ret =
828a8e1175bSopenharmony_ci                     pk_parse_key_rfc8410_der(pk, p, len, end, f_rng,
829a8e1175bSopenharmony_ci                                              p_rng)) != 0) {
830a8e1175bSopenharmony_ci                mbedtls_pk_free(pk);
831a8e1175bSopenharmony_ci                return ret;
832a8e1175bSopenharmony_ci            }
833a8e1175bSopenharmony_ci        } else
834a8e1175bSopenharmony_ci#endif
835a8e1175bSopenharmony_ci        {
836a8e1175bSopenharmony_ci            if ((ret = pk_use_ecparams(&params, pk)) != 0 ||
837a8e1175bSopenharmony_ci                (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) {
838a8e1175bSopenharmony_ci                mbedtls_pk_free(pk);
839a8e1175bSopenharmony_ci                return ret;
840a8e1175bSopenharmony_ci            }
841a8e1175bSopenharmony_ci        }
842a8e1175bSopenharmony_ci    } else
843a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
844a8e1175bSopenharmony_ci    return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
845a8e1175bSopenharmony_ci
846a8e1175bSopenharmony_ci    end = p + len;
847a8e1175bSopenharmony_ci    if (end != (key + keylen)) {
848a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
849a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
850a8e1175bSopenharmony_ci    }
851a8e1175bSopenharmony_ci
852a8e1175bSopenharmony_ci    return 0;
853a8e1175bSopenharmony_ci}
854a8e1175bSopenharmony_ci
855a8e1175bSopenharmony_ci/*
856a8e1175bSopenharmony_ci * Parse an encrypted PKCS#8 encoded private key
857a8e1175bSopenharmony_ci *
858a8e1175bSopenharmony_ci * To save space, the decryption happens in-place on the given key buffer.
859a8e1175bSopenharmony_ci * Also, while this function may modify the keybuffer, it doesn't own it,
860a8e1175bSopenharmony_ci * and instead it is the responsibility of the caller to zeroize and properly
861a8e1175bSopenharmony_ci * free it after use.
862a8e1175bSopenharmony_ci *
863a8e1175bSopenharmony_ci */
864a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
865a8e1175bSopenharmony_ciMBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(
866a8e1175bSopenharmony_ci    mbedtls_pk_context *pk,
867a8e1175bSopenharmony_ci    unsigned char *key, size_t keylen,
868a8e1175bSopenharmony_ci    const unsigned char *pwd, size_t pwdlen,
869a8e1175bSopenharmony_ci    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
870a8e1175bSopenharmony_ci{
871a8e1175bSopenharmony_ci    int ret, decrypted = 0;
872a8e1175bSopenharmony_ci    size_t len;
873a8e1175bSopenharmony_ci    unsigned char *buf;
874a8e1175bSopenharmony_ci    unsigned char *p, *end;
875a8e1175bSopenharmony_ci    mbedtls_asn1_buf pbe_alg_oid, pbe_params;
876a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
877a8e1175bSopenharmony_ci    mbedtls_cipher_type_t cipher_alg;
878a8e1175bSopenharmony_ci    mbedtls_md_type_t md_alg;
879a8e1175bSopenharmony_ci#endif
880a8e1175bSopenharmony_ci    size_t outlen = 0;
881a8e1175bSopenharmony_ci
882a8e1175bSopenharmony_ci    p = key;
883a8e1175bSopenharmony_ci    end = p + keylen;
884a8e1175bSopenharmony_ci
885a8e1175bSopenharmony_ci    if (pwdlen == 0) {
886a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
887a8e1175bSopenharmony_ci    }
888a8e1175bSopenharmony_ci
889a8e1175bSopenharmony_ci    /*
890a8e1175bSopenharmony_ci     * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
891a8e1175bSopenharmony_ci     *
892a8e1175bSopenharmony_ci     *  EncryptedPrivateKeyInfo ::= SEQUENCE {
893a8e1175bSopenharmony_ci     *    encryptionAlgorithm  EncryptionAlgorithmIdentifier,
894a8e1175bSopenharmony_ci     *    encryptedData        EncryptedData
895a8e1175bSopenharmony_ci     *  }
896a8e1175bSopenharmony_ci     *
897a8e1175bSopenharmony_ci     *  EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
898a8e1175bSopenharmony_ci     *
899a8e1175bSopenharmony_ci     *  EncryptedData ::= OCTET STRING
900a8e1175bSopenharmony_ci     *
901a8e1175bSopenharmony_ci     *  The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
902a8e1175bSopenharmony_ci     *
903a8e1175bSopenharmony_ci     */
904a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
905a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
906a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
907a8e1175bSopenharmony_ci    }
908a8e1175bSopenharmony_ci
909a8e1175bSopenharmony_ci    end = p + len;
910a8e1175bSopenharmony_ci
911a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) {
912a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
913a8e1175bSopenharmony_ci    }
914a8e1175bSopenharmony_ci
915a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
916a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
917a8e1175bSopenharmony_ci    }
918a8e1175bSopenharmony_ci
919a8e1175bSopenharmony_ci    buf = p;
920a8e1175bSopenharmony_ci
921a8e1175bSopenharmony_ci    /*
922a8e1175bSopenharmony_ci     * Decrypt EncryptedData with appropriate PBE
923a8e1175bSopenharmony_ci     */
924a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
925a8e1175bSopenharmony_ci    if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
926a8e1175bSopenharmony_ci        if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
927a8e1175bSopenharmony_ci                                          cipher_alg, md_alg,
928a8e1175bSopenharmony_ci                                          pwd, pwdlen, p, len, buf, len, &outlen)) != 0) {
929a8e1175bSopenharmony_ci            if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
930a8e1175bSopenharmony_ci                return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
931a8e1175bSopenharmony_ci            }
932a8e1175bSopenharmony_ci
933a8e1175bSopenharmony_ci            return ret;
934a8e1175bSopenharmony_ci        }
935a8e1175bSopenharmony_ci
936a8e1175bSopenharmony_ci        decrypted = 1;
937a8e1175bSopenharmony_ci    } else
938a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
939a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
940a8e1175bSopenharmony_ci    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
941a8e1175bSopenharmony_ci        if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
942a8e1175bSopenharmony_ci                                           p, len, buf, len, &outlen)) != 0) {
943a8e1175bSopenharmony_ci            if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
944a8e1175bSopenharmony_ci                return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
945a8e1175bSopenharmony_ci            }
946a8e1175bSopenharmony_ci
947a8e1175bSopenharmony_ci            return ret;
948a8e1175bSopenharmony_ci        }
949a8e1175bSopenharmony_ci
950a8e1175bSopenharmony_ci        decrypted = 1;
951a8e1175bSopenharmony_ci    } else
952a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
953a8e1175bSopenharmony_ci    {
954a8e1175bSopenharmony_ci        ((void) pwd);
955a8e1175bSopenharmony_ci    }
956a8e1175bSopenharmony_ci
957a8e1175bSopenharmony_ci    if (decrypted == 0) {
958a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
959a8e1175bSopenharmony_ci    }
960a8e1175bSopenharmony_ci    return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng);
961a8e1175bSopenharmony_ci}
962a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
963a8e1175bSopenharmony_ci
964a8e1175bSopenharmony_ci/***********************************************************************
965a8e1175bSopenharmony_ci *
966a8e1175bSopenharmony_ci *      Top-level functions, with format auto-discovery
967a8e1175bSopenharmony_ci *
968a8e1175bSopenharmony_ci **********************************************************************/
969a8e1175bSopenharmony_ci
970a8e1175bSopenharmony_ci/*
971a8e1175bSopenharmony_ci * Parse a private key
972a8e1175bSopenharmony_ci */
973a8e1175bSopenharmony_ciint mbedtls_pk_parse_key(mbedtls_pk_context *pk,
974a8e1175bSopenharmony_ci                         const unsigned char *key, size_t keylen,
975a8e1175bSopenharmony_ci                         const unsigned char *pwd, size_t pwdlen,
976a8e1175bSopenharmony_ci                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
977a8e1175bSopenharmony_ci{
978a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
979a8e1175bSopenharmony_ci    const mbedtls_pk_info_t *pk_info;
980a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
981a8e1175bSopenharmony_ci    size_t len;
982a8e1175bSopenharmony_ci    mbedtls_pem_context pem;
983a8e1175bSopenharmony_ci#endif
984a8e1175bSopenharmony_ci
985a8e1175bSopenharmony_ci    if (keylen == 0) {
986a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
987a8e1175bSopenharmony_ci    }
988a8e1175bSopenharmony_ci
989a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
990a8e1175bSopenharmony_ci    mbedtls_pem_init(&pem);
991a8e1175bSopenharmony_ci
992a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
993a8e1175bSopenharmony_ci    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
994a8e1175bSopenharmony_ci    if (key[keylen - 1] != '\0') {
995a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
996a8e1175bSopenharmony_ci    } else {
997a8e1175bSopenharmony_ci        ret = mbedtls_pem_read_buffer(&pem,
998a8e1175bSopenharmony_ci                                      PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA,
999a8e1175bSopenharmony_ci                                      key, pwd, pwdlen, &len);
1000a8e1175bSopenharmony_ci    }
1001a8e1175bSopenharmony_ci
1002a8e1175bSopenharmony_ci    if (ret == 0) {
1003a8e1175bSopenharmony_ci        pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1004a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1005a8e1175bSopenharmony_ci            (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk),
1006a8e1175bSopenharmony_ci                                         pem.buf, pem.buflen)) != 0) {
1007a8e1175bSopenharmony_ci            mbedtls_pk_free(pk);
1008a8e1175bSopenharmony_ci        }
1009a8e1175bSopenharmony_ci
1010a8e1175bSopenharmony_ci        mbedtls_pem_free(&pem);
1011a8e1175bSopenharmony_ci        return ret;
1012a8e1175bSopenharmony_ci    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1013a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1014a8e1175bSopenharmony_ci    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1015a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1016a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1017a8e1175bSopenharmony_ci        return ret;
1018a8e1175bSopenharmony_ci    }
1019a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
1020a8e1175bSopenharmony_ci
1021a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
1022a8e1175bSopenharmony_ci    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1023a8e1175bSopenharmony_ci    if (key[keylen - 1] != '\0') {
1024a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1025a8e1175bSopenharmony_ci    } else {
1026a8e1175bSopenharmony_ci        ret = mbedtls_pem_read_buffer(&pem,
1027a8e1175bSopenharmony_ci                                      PEM_BEGIN_PRIVATE_KEY_EC,
1028a8e1175bSopenharmony_ci                                      PEM_END_PRIVATE_KEY_EC,
1029a8e1175bSopenharmony_ci                                      key, pwd, pwdlen, &len);
1030a8e1175bSopenharmony_ci    }
1031a8e1175bSopenharmony_ci    if (ret == 0) {
1032a8e1175bSopenharmony_ci        pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1033a8e1175bSopenharmony_ci
1034a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
1035a8e1175bSopenharmony_ci            (ret = pk_parse_key_sec1_der(pk,
1036a8e1175bSopenharmony_ci                                         pem.buf, pem.buflen,
1037a8e1175bSopenharmony_ci                                         f_rng, p_rng)) != 0) {
1038a8e1175bSopenharmony_ci            mbedtls_pk_free(pk);
1039a8e1175bSopenharmony_ci        }
1040a8e1175bSopenharmony_ci
1041a8e1175bSopenharmony_ci        mbedtls_pem_free(&pem);
1042a8e1175bSopenharmony_ci        return ret;
1043a8e1175bSopenharmony_ci    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
1044a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
1045a8e1175bSopenharmony_ci    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
1046a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
1047a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1048a8e1175bSopenharmony_ci        return ret;
1049a8e1175bSopenharmony_ci    }
1050a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
1051a8e1175bSopenharmony_ci
1052a8e1175bSopenharmony_ci    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1053a8e1175bSopenharmony_ci    if (key[keylen - 1] != '\0') {
1054a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1055a8e1175bSopenharmony_ci    } else {
1056a8e1175bSopenharmony_ci        ret = mbedtls_pem_read_buffer(&pem,
1057a8e1175bSopenharmony_ci                                      PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8,
1058a8e1175bSopenharmony_ci                                      key, NULL, 0, &len);
1059a8e1175bSopenharmony_ci    }
1060a8e1175bSopenharmony_ci    if (ret == 0) {
1061a8e1175bSopenharmony_ci        if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk,
1062a8e1175bSopenharmony_ci                                                      pem.buf, pem.buflen, f_rng, p_rng)) != 0) {
1063a8e1175bSopenharmony_ci            mbedtls_pk_free(pk);
1064a8e1175bSopenharmony_ci        }
1065a8e1175bSopenharmony_ci
1066a8e1175bSopenharmony_ci        mbedtls_pem_free(&pem);
1067a8e1175bSopenharmony_ci        return ret;
1068a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1069a8e1175bSopenharmony_ci        return ret;
1070a8e1175bSopenharmony_ci    }
1071a8e1175bSopenharmony_ci
1072a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
1073a8e1175bSopenharmony_ci    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1074a8e1175bSopenharmony_ci    if (key[keylen - 1] != '\0') {
1075a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1076a8e1175bSopenharmony_ci    } else {
1077a8e1175bSopenharmony_ci        ret = mbedtls_pem_read_buffer(&pem,
1078a8e1175bSopenharmony_ci                                      PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8,
1079a8e1175bSopenharmony_ci                                      PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8,
1080a8e1175bSopenharmony_ci                                      key, NULL, 0, &len);
1081a8e1175bSopenharmony_ci    }
1082a8e1175bSopenharmony_ci    if (ret == 0) {
1083a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
1084a8e1175bSopenharmony_ci                                                            pwd, pwdlen, f_rng, p_rng)) != 0) {
1085a8e1175bSopenharmony_ci            mbedtls_pk_free(pk);
1086a8e1175bSopenharmony_ci        }
1087a8e1175bSopenharmony_ci
1088a8e1175bSopenharmony_ci        mbedtls_pem_free(&pem);
1089a8e1175bSopenharmony_ci        return ret;
1090a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1091a8e1175bSopenharmony_ci        return ret;
1092a8e1175bSopenharmony_ci    }
1093a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
1094a8e1175bSopenharmony_ci#else
1095a8e1175bSopenharmony_ci    ((void) pwd);
1096a8e1175bSopenharmony_ci    ((void) pwdlen);
1097a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_PARSE_C */
1098a8e1175bSopenharmony_ci
1099a8e1175bSopenharmony_ci    /*
1100a8e1175bSopenharmony_ci     * At this point we only know it's not a PEM formatted key. Could be any
1101a8e1175bSopenharmony_ci     * of the known DER encoded private key formats
1102a8e1175bSopenharmony_ci     *
1103a8e1175bSopenharmony_ci     * We try the different DER format parsers to see if one passes without
1104a8e1175bSopenharmony_ci     * error
1105a8e1175bSopenharmony_ci     */
1106a8e1175bSopenharmony_ci#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
1107a8e1175bSopenharmony_ci    if (pwdlen != 0) {
1108a8e1175bSopenharmony_ci        unsigned char *key_copy;
1109a8e1175bSopenharmony_ci
1110a8e1175bSopenharmony_ci        if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) {
1111a8e1175bSopenharmony_ci            return MBEDTLS_ERR_PK_ALLOC_FAILED;
1112a8e1175bSopenharmony_ci        }
1113a8e1175bSopenharmony_ci
1114a8e1175bSopenharmony_ci        memcpy(key_copy, key, keylen);
1115a8e1175bSopenharmony_ci
1116a8e1175bSopenharmony_ci        ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
1117a8e1175bSopenharmony_ci                                                       pwd, pwdlen, f_rng, p_rng);
1118a8e1175bSopenharmony_ci
1119a8e1175bSopenharmony_ci        mbedtls_zeroize_and_free(key_copy, keylen);
1120a8e1175bSopenharmony_ci    }
1121a8e1175bSopenharmony_ci
1122a8e1175bSopenharmony_ci    if (ret == 0) {
1123a8e1175bSopenharmony_ci        return 0;
1124a8e1175bSopenharmony_ci    }
1125a8e1175bSopenharmony_ci
1126a8e1175bSopenharmony_ci    mbedtls_pk_free(pk);
1127a8e1175bSopenharmony_ci    mbedtls_pk_init(pk);
1128a8e1175bSopenharmony_ci
1129a8e1175bSopenharmony_ci    if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {
1130a8e1175bSopenharmony_ci        return ret;
1131a8e1175bSopenharmony_ci    }
1132a8e1175bSopenharmony_ci#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
1133a8e1175bSopenharmony_ci
1134a8e1175bSopenharmony_ci    ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng);
1135a8e1175bSopenharmony_ci    if (ret == 0) {
1136a8e1175bSopenharmony_ci        return 0;
1137a8e1175bSopenharmony_ci    }
1138a8e1175bSopenharmony_ci
1139a8e1175bSopenharmony_ci    mbedtls_pk_free(pk);
1140a8e1175bSopenharmony_ci    mbedtls_pk_init(pk);
1141a8e1175bSopenharmony_ci
1142a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
1143a8e1175bSopenharmony_ci
1144a8e1175bSopenharmony_ci    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
1145a8e1175bSopenharmony_ci    if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1146a8e1175bSopenharmony_ci        mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
1147a8e1175bSopenharmony_ci        return 0;
1148a8e1175bSopenharmony_ci    }
1149a8e1175bSopenharmony_ci
1150a8e1175bSopenharmony_ci    mbedtls_pk_free(pk);
1151a8e1175bSopenharmony_ci    mbedtls_pk_init(pk);
1152a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
1153a8e1175bSopenharmony_ci
1154a8e1175bSopenharmony_ci#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
1155a8e1175bSopenharmony_ci    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
1156a8e1175bSopenharmony_ci    if (mbedtls_pk_setup(pk, pk_info) == 0 &&
1157a8e1175bSopenharmony_ci        pk_parse_key_sec1_der(pk,
1158a8e1175bSopenharmony_ci                              key, keylen, f_rng, p_rng) == 0) {
1159a8e1175bSopenharmony_ci        return 0;
1160a8e1175bSopenharmony_ci    }
1161a8e1175bSopenharmony_ci    mbedtls_pk_free(pk);
1162a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
1163a8e1175bSopenharmony_ci
1164a8e1175bSopenharmony_ci    /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't,
1165a8e1175bSopenharmony_ci     * it is ok to leave the PK context initialized but not
1166a8e1175bSopenharmony_ci     * freed: It is the caller's responsibility to call pk_init()
1167a8e1175bSopenharmony_ci     * before calling this function, and to call pk_free()
1168a8e1175bSopenharmony_ci     * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C
1169a8e1175bSopenharmony_ci     * isn't, this leads to mbedtls_pk_free() being called
1170a8e1175bSopenharmony_ci     * twice, once here and once by the caller, but this is
1171a8e1175bSopenharmony_ci     * also ok and in line with the mbedtls_pk_free() calls
1172a8e1175bSopenharmony_ci     * on failed PEM parsing attempts. */
1173a8e1175bSopenharmony_ci
1174a8e1175bSopenharmony_ci    return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1175a8e1175bSopenharmony_ci}
1176a8e1175bSopenharmony_ci
1177a8e1175bSopenharmony_ci/*
1178a8e1175bSopenharmony_ci * Parse a public key
1179a8e1175bSopenharmony_ci */
1180a8e1175bSopenharmony_ciint mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
1181a8e1175bSopenharmony_ci                                const unsigned char *key, size_t keylen)
1182a8e1175bSopenharmony_ci{
1183a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1184a8e1175bSopenharmony_ci    unsigned char *p;
1185a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
1186a8e1175bSopenharmony_ci    const mbedtls_pk_info_t *pk_info;
1187a8e1175bSopenharmony_ci#endif
1188a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
1189a8e1175bSopenharmony_ci    size_t len;
1190a8e1175bSopenharmony_ci    mbedtls_pem_context pem;
1191a8e1175bSopenharmony_ci#endif
1192a8e1175bSopenharmony_ci
1193a8e1175bSopenharmony_ci    if (keylen == 0) {
1194a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
1195a8e1175bSopenharmony_ci    }
1196a8e1175bSopenharmony_ci
1197a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
1198a8e1175bSopenharmony_ci    mbedtls_pem_init(&pem);
1199a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
1200a8e1175bSopenharmony_ci    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1201a8e1175bSopenharmony_ci    if (key[keylen - 1] != '\0') {
1202a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1203a8e1175bSopenharmony_ci    } else {
1204a8e1175bSopenharmony_ci        ret = mbedtls_pem_read_buffer(&pem,
1205a8e1175bSopenharmony_ci                                      PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA,
1206a8e1175bSopenharmony_ci                                      key, NULL, 0, &len);
1207a8e1175bSopenharmony_ci    }
1208a8e1175bSopenharmony_ci
1209a8e1175bSopenharmony_ci    if (ret == 0) {
1210a8e1175bSopenharmony_ci        p = pem.buf;
1211a8e1175bSopenharmony_ci        if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1212a8e1175bSopenharmony_ci            mbedtls_pem_free(&pem);
1213a8e1175bSopenharmony_ci            return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1214a8e1175bSopenharmony_ci        }
1215a8e1175bSopenharmony_ci
1216a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1217a8e1175bSopenharmony_ci            mbedtls_pem_free(&pem);
1218a8e1175bSopenharmony_ci            return ret;
1219a8e1175bSopenharmony_ci        }
1220a8e1175bSopenharmony_ci
1221a8e1175bSopenharmony_ci        if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) {
1222a8e1175bSopenharmony_ci            mbedtls_pk_free(ctx);
1223a8e1175bSopenharmony_ci        }
1224a8e1175bSopenharmony_ci
1225a8e1175bSopenharmony_ci        mbedtls_pem_free(&pem);
1226a8e1175bSopenharmony_ci        return ret;
1227a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1228a8e1175bSopenharmony_ci        mbedtls_pem_free(&pem);
1229a8e1175bSopenharmony_ci        return ret;
1230a8e1175bSopenharmony_ci    }
1231a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
1232a8e1175bSopenharmony_ci
1233a8e1175bSopenharmony_ci    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
1234a8e1175bSopenharmony_ci    if (key[keylen - 1] != '\0') {
1235a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
1236a8e1175bSopenharmony_ci    } else {
1237a8e1175bSopenharmony_ci        ret = mbedtls_pem_read_buffer(&pem,
1238a8e1175bSopenharmony_ci                                      PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
1239a8e1175bSopenharmony_ci                                      key, NULL, 0, &len);
1240a8e1175bSopenharmony_ci    }
1241a8e1175bSopenharmony_ci
1242a8e1175bSopenharmony_ci    if (ret == 0) {
1243a8e1175bSopenharmony_ci        /*
1244a8e1175bSopenharmony_ci         * Was PEM encoded
1245a8e1175bSopenharmony_ci         */
1246a8e1175bSopenharmony_ci        p = pem.buf;
1247a8e1175bSopenharmony_ci
1248a8e1175bSopenharmony_ci        ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
1249a8e1175bSopenharmony_ci        mbedtls_pem_free(&pem);
1250a8e1175bSopenharmony_ci        return ret;
1251a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1252a8e1175bSopenharmony_ci        mbedtls_pem_free(&pem);
1253a8e1175bSopenharmony_ci        return ret;
1254a8e1175bSopenharmony_ci    }
1255a8e1175bSopenharmony_ci    mbedtls_pem_free(&pem);
1256a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_PARSE_C */
1257a8e1175bSopenharmony_ci
1258a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
1259a8e1175bSopenharmony_ci    if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
1260a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
1261a8e1175bSopenharmony_ci    }
1262a8e1175bSopenharmony_ci
1263a8e1175bSopenharmony_ci    if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
1264a8e1175bSopenharmony_ci        return ret;
1265a8e1175bSopenharmony_ci    }
1266a8e1175bSopenharmony_ci
1267a8e1175bSopenharmony_ci    p = (unsigned char *) key;
1268a8e1175bSopenharmony_ci    ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen);
1269a8e1175bSopenharmony_ci    if (ret == 0) {
1270a8e1175bSopenharmony_ci        return ret;
1271a8e1175bSopenharmony_ci    }
1272a8e1175bSopenharmony_ci    mbedtls_pk_free(ctx);
1273a8e1175bSopenharmony_ci    if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
1274a8e1175bSopenharmony_ci        return ret;
1275a8e1175bSopenharmony_ci    }
1276a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
1277a8e1175bSopenharmony_ci    p = (unsigned char *) key;
1278a8e1175bSopenharmony_ci
1279a8e1175bSopenharmony_ci    ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);
1280a8e1175bSopenharmony_ci
1281a8e1175bSopenharmony_ci    return ret;
1282a8e1175bSopenharmony_ci}
1283a8e1175bSopenharmony_ci
1284a8e1175bSopenharmony_ci/***********************************************************************
1285a8e1175bSopenharmony_ci *
1286a8e1175bSopenharmony_ci *      Top-level functions, with filesystem support
1287a8e1175bSopenharmony_ci *
1288a8e1175bSopenharmony_ci **********************************************************************/
1289a8e1175bSopenharmony_ci
1290a8e1175bSopenharmony_ci#if defined(MBEDTLS_FS_IO)
1291a8e1175bSopenharmony_ci/*
1292a8e1175bSopenharmony_ci * Load all data from a file into a given buffer.
1293a8e1175bSopenharmony_ci *
1294a8e1175bSopenharmony_ci * The file is expected to contain either PEM or DER encoded data.
1295a8e1175bSopenharmony_ci * A terminating null byte is always appended. It is included in the announced
1296a8e1175bSopenharmony_ci * length only if the data looks like it is PEM encoded.
1297a8e1175bSopenharmony_ci */
1298a8e1175bSopenharmony_ciint mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
1299a8e1175bSopenharmony_ci{
1300a8e1175bSopenharmony_ci    FILE *f;
1301a8e1175bSopenharmony_ci    long size;
1302a8e1175bSopenharmony_ci
1303a8e1175bSopenharmony_ci    if ((f = fopen(path, "rb")) == NULL) {
1304a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1305a8e1175bSopenharmony_ci    }
1306a8e1175bSopenharmony_ci
1307a8e1175bSopenharmony_ci    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
1308a8e1175bSopenharmony_ci    mbedtls_setbuf(f, NULL);
1309a8e1175bSopenharmony_ci
1310a8e1175bSopenharmony_ci    fseek(f, 0, SEEK_END);
1311a8e1175bSopenharmony_ci    if ((size = ftell(f)) == -1) {
1312a8e1175bSopenharmony_ci        fclose(f);
1313a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1314a8e1175bSopenharmony_ci    }
1315a8e1175bSopenharmony_ci    fseek(f, 0, SEEK_SET);
1316a8e1175bSopenharmony_ci
1317a8e1175bSopenharmony_ci    *n = (size_t) size;
1318a8e1175bSopenharmony_ci
1319a8e1175bSopenharmony_ci    if (*n + 1 == 0 ||
1320a8e1175bSopenharmony_ci        (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
1321a8e1175bSopenharmony_ci        fclose(f);
1322a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_ALLOC_FAILED;
1323a8e1175bSopenharmony_ci    }
1324a8e1175bSopenharmony_ci
1325a8e1175bSopenharmony_ci    if (fread(*buf, 1, *n, f) != *n) {
1326a8e1175bSopenharmony_ci        fclose(f);
1327a8e1175bSopenharmony_ci
1328a8e1175bSopenharmony_ci        mbedtls_zeroize_and_free(*buf, *n);
1329a8e1175bSopenharmony_ci
1330a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
1331a8e1175bSopenharmony_ci    }
1332a8e1175bSopenharmony_ci
1333a8e1175bSopenharmony_ci    fclose(f);
1334a8e1175bSopenharmony_ci
1335a8e1175bSopenharmony_ci    (*buf)[*n] = '\0';
1336a8e1175bSopenharmony_ci
1337a8e1175bSopenharmony_ci    if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
1338a8e1175bSopenharmony_ci        ++*n;
1339a8e1175bSopenharmony_ci    }
1340a8e1175bSopenharmony_ci
1341a8e1175bSopenharmony_ci    return 0;
1342a8e1175bSopenharmony_ci}
1343a8e1175bSopenharmony_ci
1344a8e1175bSopenharmony_ci/*
1345a8e1175bSopenharmony_ci * Load and parse a private key
1346a8e1175bSopenharmony_ci */
1347a8e1175bSopenharmony_ciint mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
1348a8e1175bSopenharmony_ci                             const char *path, const char *pwd,
1349a8e1175bSopenharmony_ci                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1350a8e1175bSopenharmony_ci{
1351a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1352a8e1175bSopenharmony_ci    size_t n;
1353a8e1175bSopenharmony_ci    unsigned char *buf;
1354a8e1175bSopenharmony_ci
1355a8e1175bSopenharmony_ci    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1356a8e1175bSopenharmony_ci        return ret;
1357a8e1175bSopenharmony_ci    }
1358a8e1175bSopenharmony_ci
1359a8e1175bSopenharmony_ci    if (pwd == NULL) {
1360a8e1175bSopenharmony_ci        ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
1361a8e1175bSopenharmony_ci    } else {
1362a8e1175bSopenharmony_ci        ret = mbedtls_pk_parse_key(ctx, buf, n,
1363a8e1175bSopenharmony_ci                                   (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
1364a8e1175bSopenharmony_ci    }
1365a8e1175bSopenharmony_ci
1366a8e1175bSopenharmony_ci    mbedtls_zeroize_and_free(buf, n);
1367a8e1175bSopenharmony_ci
1368a8e1175bSopenharmony_ci    return ret;
1369a8e1175bSopenharmony_ci}
1370a8e1175bSopenharmony_ci
1371a8e1175bSopenharmony_ci/*
1372a8e1175bSopenharmony_ci * Load and parse a public key
1373a8e1175bSopenharmony_ci */
1374a8e1175bSopenharmony_ciint mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
1375a8e1175bSopenharmony_ci{
1376a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1377a8e1175bSopenharmony_ci    size_t n;
1378a8e1175bSopenharmony_ci    unsigned char *buf;
1379a8e1175bSopenharmony_ci
1380a8e1175bSopenharmony_ci    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1381a8e1175bSopenharmony_ci        return ret;
1382a8e1175bSopenharmony_ci    }
1383a8e1175bSopenharmony_ci
1384a8e1175bSopenharmony_ci    ret = mbedtls_pk_parse_public_key(ctx, buf, n);
1385a8e1175bSopenharmony_ci
1386a8e1175bSopenharmony_ci    mbedtls_zeroize_and_free(buf, n);
1387a8e1175bSopenharmony_ci
1388a8e1175bSopenharmony_ci    return ret;
1389a8e1175bSopenharmony_ci}
1390a8e1175bSopenharmony_ci#endif /* MBEDTLS_FS_IO */
1391a8e1175bSopenharmony_ci
1392a8e1175bSopenharmony_ci#endif /* MBEDTLS_PK_PARSE_C */
1393