1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * Public Key layer for writing key files and structures
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi
8*62c56f98SSadaf Ebrahimi #include "common.h"
9*62c56f98SSadaf Ebrahimi
10*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_WRITE_C)
11*62c56f98SSadaf Ebrahimi
12*62c56f98SSadaf Ebrahimi #include "mbedtls/pk.h"
13*62c56f98SSadaf Ebrahimi #include "mbedtls/asn1write.h"
14*62c56f98SSadaf Ebrahimi #include "mbedtls/oid.h"
15*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
16*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
17*62c56f98SSadaf Ebrahimi #include "pk_internal.h"
18*62c56f98SSadaf Ebrahimi
19*62c56f98SSadaf Ebrahimi #include <string.h>
20*62c56f98SSadaf Ebrahimi
21*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
22*62c56f98SSadaf Ebrahimi #include "mbedtls/rsa.h"
23*62c56f98SSadaf Ebrahimi #endif
24*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_C)
25*62c56f98SSadaf Ebrahimi #include "mbedtls/bignum.h"
26*62c56f98SSadaf Ebrahimi #include "mbedtls/ecp.h"
27*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
28*62c56f98SSadaf Ebrahimi #endif
29*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
30*62c56f98SSadaf Ebrahimi #include "pk_internal.h"
31*62c56f98SSadaf Ebrahimi #endif
32*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
33*62c56f98SSadaf Ebrahimi #include "pkwrite.h"
34*62c56f98SSadaf Ebrahimi #endif
35*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C)
36*62c56f98SSadaf Ebrahimi #include "mbedtls/ecdsa.h"
37*62c56f98SSadaf Ebrahimi #endif
38*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PEM_WRITE_C)
39*62c56f98SSadaf Ebrahimi #include "mbedtls/pem.h"
40*62c56f98SSadaf Ebrahimi #endif
41*62c56f98SSadaf Ebrahimi
42*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
43*62c56f98SSadaf Ebrahimi #include "psa/crypto.h"
44*62c56f98SSadaf Ebrahimi #include "psa_util_internal.h"
45*62c56f98SSadaf Ebrahimi #endif
46*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
47*62c56f98SSadaf Ebrahimi
48*62c56f98SSadaf Ebrahimi /* Helper for Montgomery curves */
49*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
50*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
mbedtls_pk_is_rfc8410(const mbedtls_pk_context * pk)51*62c56f98SSadaf Ebrahimi static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk)
52*62c56f98SSadaf Ebrahimi {
53*62c56f98SSadaf Ebrahimi mbedtls_ecp_group_id id = mbedtls_pk_get_group_id(pk);
54*62c56f98SSadaf Ebrahimi
55*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_HAVE_CURVE25519)
56*62c56f98SSadaf Ebrahimi if (id == MBEDTLS_ECP_DP_CURVE25519) {
57*62c56f98SSadaf Ebrahimi return 1;
58*62c56f98SSadaf Ebrahimi }
59*62c56f98SSadaf Ebrahimi #endif
60*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_HAVE_CURVE448)
61*62c56f98SSadaf Ebrahimi if (id == MBEDTLS_ECP_DP_CURVE448) {
62*62c56f98SSadaf Ebrahimi return 1;
63*62c56f98SSadaf Ebrahimi }
64*62c56f98SSadaf Ebrahimi #endif
65*62c56f98SSadaf Ebrahimi return 0;
66*62c56f98SSadaf Ebrahimi }
67*62c56f98SSadaf Ebrahimi
68*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PEM_WRITE_C)
69*62c56f98SSadaf Ebrahimi /* It is assumed that the input key is opaque */
pk_get_opaque_ec_family(const mbedtls_pk_context * pk)70*62c56f98SSadaf Ebrahimi static psa_ecc_family_t pk_get_opaque_ec_family(const mbedtls_pk_context *pk)
71*62c56f98SSadaf Ebrahimi {
72*62c56f98SSadaf Ebrahimi psa_ecc_family_t ec_family = 0;
73*62c56f98SSadaf Ebrahimi psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
74*62c56f98SSadaf Ebrahimi
75*62c56f98SSadaf Ebrahimi if (psa_get_key_attributes(pk->priv_id, &key_attrs) != PSA_SUCCESS) {
76*62c56f98SSadaf Ebrahimi return 0;
77*62c56f98SSadaf Ebrahimi }
78*62c56f98SSadaf Ebrahimi ec_family = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attrs));
79*62c56f98SSadaf Ebrahimi psa_reset_key_attributes(&key_attrs);
80*62c56f98SSadaf Ebrahimi
81*62c56f98SSadaf Ebrahimi return ec_family;
82*62c56f98SSadaf Ebrahimi }
83*62c56f98SSadaf Ebrahimi #endif /* MBETLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C */
84*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
85*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
86*62c56f98SSadaf Ebrahimi
87*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
88*62c56f98SSadaf Ebrahimi /* It is assumed that the input key is opaque */
pk_get_opaque_key_type(const mbedtls_pk_context * pk)89*62c56f98SSadaf Ebrahimi static psa_key_type_t pk_get_opaque_key_type(const mbedtls_pk_context *pk)
90*62c56f98SSadaf Ebrahimi {
91*62c56f98SSadaf Ebrahimi psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
92*62c56f98SSadaf Ebrahimi psa_key_type_t opaque_key_type;
93*62c56f98SSadaf Ebrahimi
94*62c56f98SSadaf Ebrahimi if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
95*62c56f98SSadaf Ebrahimi return 0;
96*62c56f98SSadaf Ebrahimi }
97*62c56f98SSadaf Ebrahimi opaque_key_type = psa_get_key_type(&opaque_attrs);
98*62c56f98SSadaf Ebrahimi psa_reset_key_attributes(&opaque_attrs);
99*62c56f98SSadaf Ebrahimi
100*62c56f98SSadaf Ebrahimi return opaque_key_type;
101*62c56f98SSadaf Ebrahimi }
102*62c56f98SSadaf Ebrahimi #endif /* MBETLS_USE_PSA_CRYPTO */
103*62c56f98SSadaf Ebrahimi
104*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
105*62c56f98SSadaf Ebrahimi /*
106*62c56f98SSadaf Ebrahimi * RSAPublicKey ::= SEQUENCE {
107*62c56f98SSadaf Ebrahimi * modulus INTEGER, -- n
108*62c56f98SSadaf Ebrahimi * publicExponent INTEGER -- e
109*62c56f98SSadaf Ebrahimi * }
110*62c56f98SSadaf Ebrahimi */
pk_write_rsa_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)111*62c56f98SSadaf Ebrahimi static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
112*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
113*62c56f98SSadaf Ebrahimi {
114*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
115*62c56f98SSadaf Ebrahimi size_t len = 0;
116*62c56f98SSadaf Ebrahimi mbedtls_mpi T;
117*62c56f98SSadaf Ebrahimi mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
118*62c56f98SSadaf Ebrahimi
119*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&T);
120*62c56f98SSadaf Ebrahimi
121*62c56f98SSadaf Ebrahimi /* Export E */
122*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
123*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
124*62c56f98SSadaf Ebrahimi goto end_of_export;
125*62c56f98SSadaf Ebrahimi }
126*62c56f98SSadaf Ebrahimi len += ret;
127*62c56f98SSadaf Ebrahimi
128*62c56f98SSadaf Ebrahimi /* Export N */
129*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
130*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
131*62c56f98SSadaf Ebrahimi goto end_of_export;
132*62c56f98SSadaf Ebrahimi }
133*62c56f98SSadaf Ebrahimi len += ret;
134*62c56f98SSadaf Ebrahimi
135*62c56f98SSadaf Ebrahimi end_of_export:
136*62c56f98SSadaf Ebrahimi
137*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&T);
138*62c56f98SSadaf Ebrahimi if (ret < 0) {
139*62c56f98SSadaf Ebrahimi return ret;
140*62c56f98SSadaf Ebrahimi }
141*62c56f98SSadaf Ebrahimi
142*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
143*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
144*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_SEQUENCE));
145*62c56f98SSadaf Ebrahimi
146*62c56f98SSadaf Ebrahimi return (int) len;
147*62c56f98SSadaf Ebrahimi }
148*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_RSA_C */
149*62c56f98SSadaf Ebrahimi
150*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
151*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
pk_write_ec_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)152*62c56f98SSadaf Ebrahimi static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
153*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
154*62c56f98SSadaf Ebrahimi {
155*62c56f98SSadaf Ebrahimi size_t len = 0;
156*62c56f98SSadaf Ebrahimi uint8_t buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
157*62c56f98SSadaf Ebrahimi
158*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
159*62c56f98SSadaf Ebrahimi if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
160*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
161*62c56f98SSadaf Ebrahimi }
162*62c56f98SSadaf Ebrahimi } else {
163*62c56f98SSadaf Ebrahimi len = pk->pub_raw_len;
164*62c56f98SSadaf Ebrahimi memcpy(buf, pk->pub_raw, len);
165*62c56f98SSadaf Ebrahimi }
166*62c56f98SSadaf Ebrahimi
167*62c56f98SSadaf Ebrahimi if (*p < start || (size_t) (*p - start) < len) {
168*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
169*62c56f98SSadaf Ebrahimi }
170*62c56f98SSadaf Ebrahimi
171*62c56f98SSadaf Ebrahimi *p -= len;
172*62c56f98SSadaf Ebrahimi memcpy(*p, buf, len);
173*62c56f98SSadaf Ebrahimi
174*62c56f98SSadaf Ebrahimi return (int) len;
175*62c56f98SSadaf Ebrahimi }
176*62c56f98SSadaf Ebrahimi #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
pk_write_ec_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)177*62c56f98SSadaf Ebrahimi static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
178*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
179*62c56f98SSadaf Ebrahimi {
180*62c56f98SSadaf Ebrahimi size_t len = 0;
181*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
182*62c56f98SSadaf Ebrahimi uint8_t buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
183*62c56f98SSadaf Ebrahimi #else
184*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
185*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
186*62c56f98SSadaf Ebrahimi mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
187*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
188*62c56f98SSadaf Ebrahimi
189*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
190*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
191*62c56f98SSadaf Ebrahimi if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
192*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
193*62c56f98SSadaf Ebrahimi }
194*62c56f98SSadaf Ebrahimi *p -= len;
195*62c56f98SSadaf Ebrahimi memcpy(*p, buf, len);
196*62c56f98SSadaf Ebrahimi return (int) len;
197*62c56f98SSadaf Ebrahimi } else
198*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
199*62c56f98SSadaf Ebrahimi {
200*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
201*62c56f98SSadaf Ebrahimi MBEDTLS_ECP_PF_UNCOMPRESSED,
202*62c56f98SSadaf Ebrahimi &len, buf, sizeof(buf))) != 0) {
203*62c56f98SSadaf Ebrahimi return ret;
204*62c56f98SSadaf Ebrahimi }
205*62c56f98SSadaf Ebrahimi }
206*62c56f98SSadaf Ebrahimi
207*62c56f98SSadaf Ebrahimi if (*p < start || (size_t) (*p - start) < len) {
208*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
209*62c56f98SSadaf Ebrahimi }
210*62c56f98SSadaf Ebrahimi
211*62c56f98SSadaf Ebrahimi *p -= len;
212*62c56f98SSadaf Ebrahimi memcpy(*p, buf, len);
213*62c56f98SSadaf Ebrahimi
214*62c56f98SSadaf Ebrahimi return (int) len;
215*62c56f98SSadaf Ebrahimi }
216*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
217*62c56f98SSadaf Ebrahimi
218*62c56f98SSadaf Ebrahimi /*
219*62c56f98SSadaf Ebrahimi * ECParameters ::= CHOICE {
220*62c56f98SSadaf Ebrahimi * namedCurve OBJECT IDENTIFIER
221*62c56f98SSadaf Ebrahimi * }
222*62c56f98SSadaf Ebrahimi */
pk_write_ec_param(unsigned char ** p,unsigned char * start,mbedtls_ecp_group_id grp_id)223*62c56f98SSadaf Ebrahimi static int pk_write_ec_param(unsigned char **p, unsigned char *start,
224*62c56f98SSadaf Ebrahimi mbedtls_ecp_group_id grp_id)
225*62c56f98SSadaf Ebrahimi {
226*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
227*62c56f98SSadaf Ebrahimi size_t len = 0;
228*62c56f98SSadaf Ebrahimi const char *oid;
229*62c56f98SSadaf Ebrahimi size_t oid_len;
230*62c56f98SSadaf Ebrahimi
231*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
232*62c56f98SSadaf Ebrahimi return ret;
233*62c56f98SSadaf Ebrahimi }
234*62c56f98SSadaf Ebrahimi
235*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
236*62c56f98SSadaf Ebrahimi
237*62c56f98SSadaf Ebrahimi return (int) len;
238*62c56f98SSadaf Ebrahimi }
239*62c56f98SSadaf Ebrahimi
240*62c56f98SSadaf Ebrahimi /*
241*62c56f98SSadaf Ebrahimi * privateKey OCTET STRING -- always of length ceil(log2(n)/8)
242*62c56f98SSadaf Ebrahimi */
243*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
pk_write_ec_private(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)244*62c56f98SSadaf Ebrahimi static int pk_write_ec_private(unsigned char **p, unsigned char *start,
245*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
246*62c56f98SSadaf Ebrahimi {
247*62c56f98SSadaf Ebrahimi size_t byte_length;
248*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
249*62c56f98SSadaf Ebrahimi unsigned char tmp[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
250*62c56f98SSadaf Ebrahimi psa_status_t status;
251*62c56f98SSadaf Ebrahimi
252*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
253*62c56f98SSadaf Ebrahimi status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
254*62c56f98SSadaf Ebrahimi if (status != PSA_SUCCESS) {
255*62c56f98SSadaf Ebrahimi ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
256*62c56f98SSadaf Ebrahimi return ret;
257*62c56f98SSadaf Ebrahimi }
258*62c56f98SSadaf Ebrahimi } else {
259*62c56f98SSadaf Ebrahimi status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
260*62c56f98SSadaf Ebrahimi if (status != PSA_SUCCESS) {
261*62c56f98SSadaf Ebrahimi ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
262*62c56f98SSadaf Ebrahimi goto exit;
263*62c56f98SSadaf Ebrahimi }
264*62c56f98SSadaf Ebrahimi }
265*62c56f98SSadaf Ebrahimi
266*62c56f98SSadaf Ebrahimi ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
267*62c56f98SSadaf Ebrahimi exit:
268*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(tmp, sizeof(tmp));
269*62c56f98SSadaf Ebrahimi return ret;
270*62c56f98SSadaf Ebrahimi }
271*62c56f98SSadaf Ebrahimi #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
pk_write_ec_private(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)272*62c56f98SSadaf Ebrahimi static int pk_write_ec_private(unsigned char **p, unsigned char *start,
273*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
274*62c56f98SSadaf Ebrahimi {
275*62c56f98SSadaf Ebrahimi size_t byte_length;
276*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
277*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
278*62c56f98SSadaf Ebrahimi unsigned char tmp[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
279*62c56f98SSadaf Ebrahimi psa_status_t status;
280*62c56f98SSadaf Ebrahimi #else
281*62c56f98SSadaf Ebrahimi unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
282*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
283*62c56f98SSadaf Ebrahimi
284*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
285*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
286*62c56f98SSadaf Ebrahimi status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
287*62c56f98SSadaf Ebrahimi if (status != PSA_SUCCESS) {
288*62c56f98SSadaf Ebrahimi ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
289*62c56f98SSadaf Ebrahimi return ret;
290*62c56f98SSadaf Ebrahimi }
291*62c56f98SSadaf Ebrahimi } else
292*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
293*62c56f98SSadaf Ebrahimi {
294*62c56f98SSadaf Ebrahimi mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
295*62c56f98SSadaf Ebrahimi byte_length = (ec->grp.pbits + 7) / 8;
296*62c56f98SSadaf Ebrahimi
297*62c56f98SSadaf Ebrahimi ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
298*62c56f98SSadaf Ebrahimi if (ret != 0) {
299*62c56f98SSadaf Ebrahimi goto exit;
300*62c56f98SSadaf Ebrahimi }
301*62c56f98SSadaf Ebrahimi }
302*62c56f98SSadaf Ebrahimi ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
303*62c56f98SSadaf Ebrahimi exit:
304*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(tmp, sizeof(tmp));
305*62c56f98SSadaf Ebrahimi return ret;
306*62c56f98SSadaf Ebrahimi }
307*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
308*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
309*62c56f98SSadaf Ebrahimi
310*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
pk_write_opaque_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * pk)311*62c56f98SSadaf Ebrahimi static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
312*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
313*62c56f98SSadaf Ebrahimi {
314*62c56f98SSadaf Ebrahimi size_t buffer_size;
315*62c56f98SSadaf Ebrahimi size_t len = 0;
316*62c56f98SSadaf Ebrahimi
317*62c56f98SSadaf Ebrahimi if (*p < start) {
318*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
319*62c56f98SSadaf Ebrahimi }
320*62c56f98SSadaf Ebrahimi
321*62c56f98SSadaf Ebrahimi buffer_size = (size_t) (*p - start);
322*62c56f98SSadaf Ebrahimi if (psa_export_public_key(pk->priv_id, start, buffer_size,
323*62c56f98SSadaf Ebrahimi &len) != PSA_SUCCESS) {
324*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
325*62c56f98SSadaf Ebrahimi }
326*62c56f98SSadaf Ebrahimi
327*62c56f98SSadaf Ebrahimi *p -= len;
328*62c56f98SSadaf Ebrahimi memmove(*p, start, len);
329*62c56f98SSadaf Ebrahimi
330*62c56f98SSadaf Ebrahimi return (int) len;
331*62c56f98SSadaf Ebrahimi }
332*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
333*62c56f98SSadaf Ebrahimi
mbedtls_pk_write_pubkey(unsigned char ** p,unsigned char * start,const mbedtls_pk_context * key)334*62c56f98SSadaf Ebrahimi int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
335*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *key)
336*62c56f98SSadaf Ebrahimi {
337*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
338*62c56f98SSadaf Ebrahimi size_t len = 0;
339*62c56f98SSadaf Ebrahimi
340*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
341*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
342*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, key));
343*62c56f98SSadaf Ebrahimi } else
344*62c56f98SSadaf Ebrahimi #endif
345*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
346*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
347*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
348*62c56f98SSadaf Ebrahimi } else
349*62c56f98SSadaf Ebrahimi #endif
350*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
351*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
352*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
353*62c56f98SSadaf Ebrahimi } else
354*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
355*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
356*62c56f98SSadaf Ebrahimi
357*62c56f98SSadaf Ebrahimi return (int) len;
358*62c56f98SSadaf Ebrahimi }
359*62c56f98SSadaf Ebrahimi
mbedtls_pk_write_pubkey_der(const mbedtls_pk_context * key,unsigned char * buf,size_t size)360*62c56f98SSadaf Ebrahimi int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
361*62c56f98SSadaf Ebrahimi {
362*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
363*62c56f98SSadaf Ebrahimi unsigned char *c;
364*62c56f98SSadaf Ebrahimi int has_par = 1;
365*62c56f98SSadaf Ebrahimi size_t len = 0, par_len = 0, oid_len = 0;
366*62c56f98SSadaf Ebrahimi mbedtls_pk_type_t pk_type;
367*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
368*62c56f98SSadaf Ebrahimi mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
369*62c56f98SSadaf Ebrahimi #endif
370*62c56f98SSadaf Ebrahimi const char *oid = NULL;
371*62c56f98SSadaf Ebrahimi
372*62c56f98SSadaf Ebrahimi if (size == 0) {
373*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
374*62c56f98SSadaf Ebrahimi }
375*62c56f98SSadaf Ebrahimi
376*62c56f98SSadaf Ebrahimi c = buf + size;
377*62c56f98SSadaf Ebrahimi
378*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
379*62c56f98SSadaf Ebrahimi
380*62c56f98SSadaf Ebrahimi if (c - buf < 1) {
381*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
382*62c56f98SSadaf Ebrahimi }
383*62c56f98SSadaf Ebrahimi
384*62c56f98SSadaf Ebrahimi /*
385*62c56f98SSadaf Ebrahimi * SubjectPublicKeyInfo ::= SEQUENCE {
386*62c56f98SSadaf Ebrahimi * algorithm AlgorithmIdentifier,
387*62c56f98SSadaf Ebrahimi * subjectPublicKey BIT STRING }
388*62c56f98SSadaf Ebrahimi */
389*62c56f98SSadaf Ebrahimi *--c = 0;
390*62c56f98SSadaf Ebrahimi len += 1;
391*62c56f98SSadaf Ebrahimi
392*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
393*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
394*62c56f98SSadaf Ebrahimi
395*62c56f98SSadaf Ebrahimi pk_type = mbedtls_pk_get_type(key);
396*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
397*62c56f98SSadaf Ebrahimi if (pk_type == MBEDTLS_PK_ECKEY) {
398*62c56f98SSadaf Ebrahimi ec_grp_id = mbedtls_pk_get_group_id(key);
399*62c56f98SSadaf Ebrahimi }
400*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
401*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
402*62c56f98SSadaf Ebrahimi if (pk_type == MBEDTLS_PK_OPAQUE) {
403*62c56f98SSadaf Ebrahimi psa_key_type_t opaque_key_type = pk_get_opaque_key_type(key);
404*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
405*62c56f98SSadaf Ebrahimi if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
406*62c56f98SSadaf Ebrahimi pk_type = MBEDTLS_PK_ECKEY;
407*62c56f98SSadaf Ebrahimi ec_grp_id = mbedtls_pk_get_group_id(key);
408*62c56f98SSadaf Ebrahimi } else
409*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
410*62c56f98SSadaf Ebrahimi if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
411*62c56f98SSadaf Ebrahimi /* The rest of the function works as for legacy RSA contexts. */
412*62c56f98SSadaf Ebrahimi pk_type = MBEDTLS_PK_RSA;
413*62c56f98SSadaf Ebrahimi }
414*62c56f98SSadaf Ebrahimi }
415*62c56f98SSadaf Ebrahimi /* `pk_type` will have been changed to non-opaque by here if this function can handle it */
416*62c56f98SSadaf Ebrahimi if (pk_type == MBEDTLS_PK_OPAQUE) {
417*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
418*62c56f98SSadaf Ebrahimi }
419*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
420*62c56f98SSadaf Ebrahimi
421*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
422*62c56f98SSadaf Ebrahimi if (pk_type == MBEDTLS_PK_ECKEY) {
423*62c56f98SSadaf Ebrahimi /* Some groups have their own AlgorithmIdentifier OID, others are handled
424*62c56f98SSadaf Ebrahimi * by mbedtls_oid_get_oid_by_pk_alg() below */
425*62c56f98SSadaf Ebrahimi ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
426*62c56f98SSadaf Ebrahimi
427*62c56f98SSadaf Ebrahimi if (ret == 0) {
428*62c56f98SSadaf Ebrahimi /* Currently, none of the supported algorithms that have their own
429*62c56f98SSadaf Ebrahimi * AlgorithmIdentifier OID have any parameters */
430*62c56f98SSadaf Ebrahimi has_par = 0;
431*62c56f98SSadaf Ebrahimi } else if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
432*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
433*62c56f98SSadaf Ebrahimi } else {
434*62c56f98SSadaf Ebrahimi return ret;
435*62c56f98SSadaf Ebrahimi }
436*62c56f98SSadaf Ebrahimi }
437*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
438*62c56f98SSadaf Ebrahimi
439*62c56f98SSadaf Ebrahimi if (oid_len == 0) {
440*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
441*62c56f98SSadaf Ebrahimi &oid_len)) != 0) {
442*62c56f98SSadaf Ebrahimi return ret;
443*62c56f98SSadaf Ebrahimi }
444*62c56f98SSadaf Ebrahimi }
445*62c56f98SSadaf Ebrahimi
446*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
447*62c56f98SSadaf Ebrahimi par_len, has_par));
448*62c56f98SSadaf Ebrahimi
449*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
450*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
451*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_SEQUENCE));
452*62c56f98SSadaf Ebrahimi
453*62c56f98SSadaf Ebrahimi return (int) len;
454*62c56f98SSadaf Ebrahimi }
455*62c56f98SSadaf Ebrahimi
456*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
457*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
458*62c56f98SSadaf Ebrahimi /*
459*62c56f98SSadaf Ebrahimi * RFC8410 section 7
460*62c56f98SSadaf Ebrahimi *
461*62c56f98SSadaf Ebrahimi * OneAsymmetricKey ::= SEQUENCE {
462*62c56f98SSadaf Ebrahimi * version Version,
463*62c56f98SSadaf Ebrahimi * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
464*62c56f98SSadaf Ebrahimi * privateKey PrivateKey,
465*62c56f98SSadaf Ebrahimi * attributes [0] IMPLICIT Attributes OPTIONAL,
466*62c56f98SSadaf Ebrahimi * ...,
467*62c56f98SSadaf Ebrahimi * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
468*62c56f98SSadaf Ebrahimi * ...
469*62c56f98SSadaf Ebrahimi * }
470*62c56f98SSadaf Ebrahimi * ...
471*62c56f98SSadaf Ebrahimi * CurvePrivateKey ::= OCTET STRING
472*62c56f98SSadaf Ebrahimi */
pk_write_ec_rfc8410_der(unsigned char ** p,unsigned char * buf,const mbedtls_pk_context * pk)473*62c56f98SSadaf Ebrahimi static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
474*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
475*62c56f98SSadaf Ebrahimi {
476*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
477*62c56f98SSadaf Ebrahimi size_t len = 0;
478*62c56f98SSadaf Ebrahimi size_t oid_len = 0;
479*62c56f98SSadaf Ebrahimi const char *oid;
480*62c56f98SSadaf Ebrahimi mbedtls_ecp_group_id grp_id;
481*62c56f98SSadaf Ebrahimi
482*62c56f98SSadaf Ebrahimi /* privateKey */
483*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
484*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
485*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
486*62c56f98SSadaf Ebrahimi
487*62c56f98SSadaf Ebrahimi grp_id = mbedtls_pk_get_group_id(pk);
488*62c56f98SSadaf Ebrahimi /* privateKeyAlgorithm */
489*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
490*62c56f98SSadaf Ebrahimi return ret;
491*62c56f98SSadaf Ebrahimi }
492*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len,
493*62c56f98SSadaf Ebrahimi mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
494*62c56f98SSadaf Ebrahimi
495*62c56f98SSadaf Ebrahimi /* version */
496*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
497*62c56f98SSadaf Ebrahimi
498*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
499*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
500*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_SEQUENCE));
501*62c56f98SSadaf Ebrahimi
502*62c56f98SSadaf Ebrahimi return (int) len;
503*62c56f98SSadaf Ebrahimi }
504*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
505*62c56f98SSadaf Ebrahimi
506*62c56f98SSadaf Ebrahimi /*
507*62c56f98SSadaf Ebrahimi * RFC 5915, or SEC1 Appendix C.4
508*62c56f98SSadaf Ebrahimi *
509*62c56f98SSadaf Ebrahimi * ECPrivateKey ::= SEQUENCE {
510*62c56f98SSadaf Ebrahimi * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
511*62c56f98SSadaf Ebrahimi * privateKey OCTET STRING,
512*62c56f98SSadaf Ebrahimi * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
513*62c56f98SSadaf Ebrahimi * publicKey [1] BIT STRING OPTIONAL
514*62c56f98SSadaf Ebrahimi * }
515*62c56f98SSadaf Ebrahimi */
pk_write_ec_der(unsigned char ** p,unsigned char * buf,const mbedtls_pk_context * pk)516*62c56f98SSadaf Ebrahimi static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
517*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
518*62c56f98SSadaf Ebrahimi {
519*62c56f98SSadaf Ebrahimi size_t len = 0;
520*62c56f98SSadaf Ebrahimi int ret;
521*62c56f98SSadaf Ebrahimi size_t pub_len = 0, par_len = 0;
522*62c56f98SSadaf Ebrahimi mbedtls_ecp_group_id grp_id;
523*62c56f98SSadaf Ebrahimi
524*62c56f98SSadaf Ebrahimi /* publicKey */
525*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
526*62c56f98SSadaf Ebrahimi
527*62c56f98SSadaf Ebrahimi if (*p - buf < 1) {
528*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
529*62c56f98SSadaf Ebrahimi }
530*62c56f98SSadaf Ebrahimi (*p)--;
531*62c56f98SSadaf Ebrahimi **p = 0;
532*62c56f98SSadaf Ebrahimi pub_len += 1;
533*62c56f98SSadaf Ebrahimi
534*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
535*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
536*62c56f98SSadaf Ebrahimi
537*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
538*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
539*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONTEXT_SPECIFIC |
540*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | 1));
541*62c56f98SSadaf Ebrahimi len += pub_len;
542*62c56f98SSadaf Ebrahimi
543*62c56f98SSadaf Ebrahimi /* parameters */
544*62c56f98SSadaf Ebrahimi grp_id = mbedtls_pk_get_group_id(pk);
545*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
546*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
547*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
548*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONTEXT_SPECIFIC |
549*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | 0));
550*62c56f98SSadaf Ebrahimi len += par_len;
551*62c56f98SSadaf Ebrahimi
552*62c56f98SSadaf Ebrahimi /* privateKey */
553*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
554*62c56f98SSadaf Ebrahimi
555*62c56f98SSadaf Ebrahimi /* version */
556*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
557*62c56f98SSadaf Ebrahimi
558*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
559*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
560*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_SEQUENCE));
561*62c56f98SSadaf Ebrahimi
562*62c56f98SSadaf Ebrahimi return (int) len;
563*62c56f98SSadaf Ebrahimi }
564*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
565*62c56f98SSadaf Ebrahimi
566*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
pk_write_rsa_der(unsigned char ** p,unsigned char * buf,const mbedtls_pk_context * pk)567*62c56f98SSadaf Ebrahimi static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
568*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
569*62c56f98SSadaf Ebrahimi {
570*62c56f98SSadaf Ebrahimi size_t len = 0;
571*62c56f98SSadaf Ebrahimi int ret;
572*62c56f98SSadaf Ebrahimi
573*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
574*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
575*62c56f98SSadaf Ebrahimi uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
576*62c56f98SSadaf Ebrahimi size_t tmp_len = 0;
577*62c56f98SSadaf Ebrahimi
578*62c56f98SSadaf Ebrahimi if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
579*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
580*62c56f98SSadaf Ebrahimi }
581*62c56f98SSadaf Ebrahimi *p -= tmp_len;
582*62c56f98SSadaf Ebrahimi memcpy(*p, tmp, tmp_len);
583*62c56f98SSadaf Ebrahimi len += tmp_len;
584*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(tmp, sizeof(tmp));
585*62c56f98SSadaf Ebrahimi } else
586*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
587*62c56f98SSadaf Ebrahimi {
588*62c56f98SSadaf Ebrahimi mbedtls_mpi T; /* Temporary holding the exported parameters */
589*62c56f98SSadaf Ebrahimi mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
590*62c56f98SSadaf Ebrahimi
591*62c56f98SSadaf Ebrahimi /*
592*62c56f98SSadaf Ebrahimi * Export the parameters one after another to avoid simultaneous copies.
593*62c56f98SSadaf Ebrahimi */
594*62c56f98SSadaf Ebrahimi
595*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&T);
596*62c56f98SSadaf Ebrahimi
597*62c56f98SSadaf Ebrahimi /* Export QP */
598*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
599*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
600*62c56f98SSadaf Ebrahimi goto end_of_export;
601*62c56f98SSadaf Ebrahimi }
602*62c56f98SSadaf Ebrahimi len += ret;
603*62c56f98SSadaf Ebrahimi
604*62c56f98SSadaf Ebrahimi /* Export DQ */
605*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
606*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
607*62c56f98SSadaf Ebrahimi goto end_of_export;
608*62c56f98SSadaf Ebrahimi }
609*62c56f98SSadaf Ebrahimi len += ret;
610*62c56f98SSadaf Ebrahimi
611*62c56f98SSadaf Ebrahimi /* Export DP */
612*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
613*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
614*62c56f98SSadaf Ebrahimi goto end_of_export;
615*62c56f98SSadaf Ebrahimi }
616*62c56f98SSadaf Ebrahimi len += ret;
617*62c56f98SSadaf Ebrahimi
618*62c56f98SSadaf Ebrahimi /* Export Q */
619*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
620*62c56f98SSadaf Ebrahimi &T, NULL, NULL)) != 0 ||
621*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
622*62c56f98SSadaf Ebrahimi goto end_of_export;
623*62c56f98SSadaf Ebrahimi }
624*62c56f98SSadaf Ebrahimi len += ret;
625*62c56f98SSadaf Ebrahimi
626*62c56f98SSadaf Ebrahimi /* Export P */
627*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
628*62c56f98SSadaf Ebrahimi NULL, NULL, NULL)) != 0 ||
629*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
630*62c56f98SSadaf Ebrahimi goto end_of_export;
631*62c56f98SSadaf Ebrahimi }
632*62c56f98SSadaf Ebrahimi len += ret;
633*62c56f98SSadaf Ebrahimi
634*62c56f98SSadaf Ebrahimi /* Export D */
635*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
636*62c56f98SSadaf Ebrahimi NULL, &T, NULL)) != 0 ||
637*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
638*62c56f98SSadaf Ebrahimi goto end_of_export;
639*62c56f98SSadaf Ebrahimi }
640*62c56f98SSadaf Ebrahimi len += ret;
641*62c56f98SSadaf Ebrahimi
642*62c56f98SSadaf Ebrahimi /* Export E */
643*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
644*62c56f98SSadaf Ebrahimi NULL, NULL, &T)) != 0 ||
645*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
646*62c56f98SSadaf Ebrahimi goto end_of_export;
647*62c56f98SSadaf Ebrahimi }
648*62c56f98SSadaf Ebrahimi len += ret;
649*62c56f98SSadaf Ebrahimi
650*62c56f98SSadaf Ebrahimi /* Export N */
651*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
652*62c56f98SSadaf Ebrahimi NULL, NULL, NULL)) != 0 ||
653*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
654*62c56f98SSadaf Ebrahimi goto end_of_export;
655*62c56f98SSadaf Ebrahimi }
656*62c56f98SSadaf Ebrahimi len += ret;
657*62c56f98SSadaf Ebrahimi
658*62c56f98SSadaf Ebrahimi end_of_export:
659*62c56f98SSadaf Ebrahimi
660*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&T);
661*62c56f98SSadaf Ebrahimi if (ret < 0) {
662*62c56f98SSadaf Ebrahimi return ret;
663*62c56f98SSadaf Ebrahimi }
664*62c56f98SSadaf Ebrahimi
665*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
666*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
667*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p,
668*62c56f98SSadaf Ebrahimi buf, MBEDTLS_ASN1_CONSTRUCTED |
669*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_SEQUENCE));
670*62c56f98SSadaf Ebrahimi }
671*62c56f98SSadaf Ebrahimi
672*62c56f98SSadaf Ebrahimi return (int) len;
673*62c56f98SSadaf Ebrahimi }
674*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_RSA_C */
675*62c56f98SSadaf Ebrahimi
mbedtls_pk_write_key_der(const mbedtls_pk_context * key,unsigned char * buf,size_t size)676*62c56f98SSadaf Ebrahimi int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
677*62c56f98SSadaf Ebrahimi {
678*62c56f98SSadaf Ebrahimi unsigned char *c;
679*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
680*62c56f98SSadaf Ebrahimi int is_rsa_opaque = 0;
681*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_RSA_C */
682*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
683*62c56f98SSadaf Ebrahimi int is_ec_opaque = 0;
684*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
685*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
686*62c56f98SSadaf Ebrahimi psa_key_type_t opaque_key_type;
687*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
688*62c56f98SSadaf Ebrahimi
689*62c56f98SSadaf Ebrahimi if (size == 0) {
690*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
691*62c56f98SSadaf Ebrahimi }
692*62c56f98SSadaf Ebrahimi
693*62c56f98SSadaf Ebrahimi c = buf + size;
694*62c56f98SSadaf Ebrahimi
695*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
696*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
697*62c56f98SSadaf Ebrahimi opaque_key_type = pk_get_opaque_key_type(key);
698*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
699*62c56f98SSadaf Ebrahimi is_rsa_opaque = PSA_KEY_TYPE_IS_RSA(opaque_key_type);
700*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_RSA_C */
701*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
702*62c56f98SSadaf Ebrahimi is_ec_opaque = PSA_KEY_TYPE_IS_ECC(opaque_key_type);
703*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
704*62c56f98SSadaf Ebrahimi }
705*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
706*62c56f98SSadaf Ebrahimi
707*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
708*62c56f98SSadaf Ebrahimi if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) || is_rsa_opaque) {
709*62c56f98SSadaf Ebrahimi return pk_write_rsa_der(&c, buf, key);
710*62c56f98SSadaf Ebrahimi } else
711*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_RSA_C */
712*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
713*62c56f98SSadaf Ebrahimi if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) || is_ec_opaque) {
714*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
715*62c56f98SSadaf Ebrahimi if (mbedtls_pk_is_rfc8410(key)) {
716*62c56f98SSadaf Ebrahimi return pk_write_ec_rfc8410_der(&c, buf, key);
717*62c56f98SSadaf Ebrahimi }
718*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
719*62c56f98SSadaf Ebrahimi return pk_write_ec_der(&c, buf, key);
720*62c56f98SSadaf Ebrahimi } else
721*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
722*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
723*62c56f98SSadaf Ebrahimi }
724*62c56f98SSadaf Ebrahimi
725*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PEM_WRITE_C)
726*62c56f98SSadaf Ebrahimi
727*62c56f98SSadaf Ebrahimi #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
728*62c56f98SSadaf Ebrahimi #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
729*62c56f98SSadaf Ebrahimi
730*62c56f98SSadaf Ebrahimi #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n"
731*62c56f98SSadaf Ebrahimi #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n"
732*62c56f98SSadaf Ebrahimi #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n"
733*62c56f98SSadaf Ebrahimi #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n"
734*62c56f98SSadaf Ebrahimi #define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----\n"
735*62c56f98SSadaf Ebrahimi #define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----\n"
736*62c56f98SSadaf Ebrahimi
737*62c56f98SSadaf Ebrahimi #define PUB_DER_MAX_BYTES \
738*62c56f98SSadaf Ebrahimi (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
739*62c56f98SSadaf Ebrahimi MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
740*62c56f98SSadaf Ebrahimi #define PRV_DER_MAX_BYTES \
741*62c56f98SSadaf Ebrahimi (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
742*62c56f98SSadaf Ebrahimi MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
743*62c56f98SSadaf Ebrahimi
mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context * key,unsigned char * buf,size_t size)744*62c56f98SSadaf Ebrahimi int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
745*62c56f98SSadaf Ebrahimi {
746*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
747*62c56f98SSadaf Ebrahimi unsigned char output_buf[PUB_DER_MAX_BYTES];
748*62c56f98SSadaf Ebrahimi size_t olen = 0;
749*62c56f98SSadaf Ebrahimi
750*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
751*62c56f98SSadaf Ebrahimi sizeof(output_buf))) < 0) {
752*62c56f98SSadaf Ebrahimi return ret;
753*62c56f98SSadaf Ebrahimi }
754*62c56f98SSadaf Ebrahimi
755*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
756*62c56f98SSadaf Ebrahimi output_buf + sizeof(output_buf) - ret,
757*62c56f98SSadaf Ebrahimi ret, buf, size, &olen)) != 0) {
758*62c56f98SSadaf Ebrahimi return ret;
759*62c56f98SSadaf Ebrahimi }
760*62c56f98SSadaf Ebrahimi
761*62c56f98SSadaf Ebrahimi return 0;
762*62c56f98SSadaf Ebrahimi }
763*62c56f98SSadaf Ebrahimi
mbedtls_pk_write_key_pem(const mbedtls_pk_context * key,unsigned char * buf,size_t size)764*62c56f98SSadaf Ebrahimi int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
765*62c56f98SSadaf Ebrahimi {
766*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
767*62c56f98SSadaf Ebrahimi unsigned char output_buf[PRV_DER_MAX_BYTES];
768*62c56f98SSadaf Ebrahimi const char *begin, *end;
769*62c56f98SSadaf Ebrahimi size_t olen = 0;
770*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
771*62c56f98SSadaf Ebrahimi int is_ec_opaque = 0;
772*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
773*62c56f98SSadaf Ebrahimi int is_montgomery_opaque = 0;
774*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
775*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
776*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
777*62c56f98SSadaf Ebrahimi int is_rsa_opaque = 0;
778*62c56f98SSadaf Ebrahimi #endif
779*62c56f98SSadaf Ebrahimi
780*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) {
781*62c56f98SSadaf Ebrahimi return ret;
782*62c56f98SSadaf Ebrahimi }
783*62c56f98SSadaf Ebrahimi
784*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
785*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
786*62c56f98SSadaf Ebrahimi psa_key_type_t opaque_key_type = pk_get_opaque_key_type(key);
787*62c56f98SSadaf Ebrahimi
788*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
789*62c56f98SSadaf Ebrahimi is_rsa_opaque = PSA_KEY_TYPE_IS_RSA(opaque_key_type);
790*62c56f98SSadaf Ebrahimi #endif
791*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
792*62c56f98SSadaf Ebrahimi is_ec_opaque = PSA_KEY_TYPE_IS_ECC(opaque_key_type);
793*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
794*62c56f98SSadaf Ebrahimi if (pk_get_opaque_ec_family(key) == PSA_ECC_FAMILY_MONTGOMERY) {
795*62c56f98SSadaf Ebrahimi is_montgomery_opaque = 1;
796*62c56f98SSadaf Ebrahimi }
797*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
798*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
799*62c56f98SSadaf Ebrahimi }
800*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
801*62c56f98SSadaf Ebrahimi
802*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
803*62c56f98SSadaf Ebrahimi if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) || is_rsa_opaque) {
804*62c56f98SSadaf Ebrahimi begin = PEM_BEGIN_PRIVATE_KEY_RSA;
805*62c56f98SSadaf Ebrahimi end = PEM_END_PRIVATE_KEY_RSA;
806*62c56f98SSadaf Ebrahimi } else
807*62c56f98SSadaf Ebrahimi #endif
808*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
809*62c56f98SSadaf Ebrahimi if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) || is_ec_opaque) {
810*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
811*62c56f98SSadaf Ebrahimi if (is_montgomery_opaque ||
812*62c56f98SSadaf Ebrahimi ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) &&
813*62c56f98SSadaf Ebrahimi (mbedtls_pk_is_rfc8410(key)))) {
814*62c56f98SSadaf Ebrahimi begin = PEM_BEGIN_PRIVATE_KEY_PKCS8;
815*62c56f98SSadaf Ebrahimi end = PEM_END_PRIVATE_KEY_PKCS8;
816*62c56f98SSadaf Ebrahimi } else
817*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
818*62c56f98SSadaf Ebrahimi {
819*62c56f98SSadaf Ebrahimi begin = PEM_BEGIN_PRIVATE_KEY_EC;
820*62c56f98SSadaf Ebrahimi end = PEM_END_PRIVATE_KEY_EC;
821*62c56f98SSadaf Ebrahimi }
822*62c56f98SSadaf Ebrahimi } else
823*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
824*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
825*62c56f98SSadaf Ebrahimi
826*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_pem_write_buffer(begin, end,
827*62c56f98SSadaf Ebrahimi output_buf + sizeof(output_buf) - ret,
828*62c56f98SSadaf Ebrahimi ret, buf, size, &olen)) != 0) {
829*62c56f98SSadaf Ebrahimi return ret;
830*62c56f98SSadaf Ebrahimi }
831*62c56f98SSadaf Ebrahimi
832*62c56f98SSadaf Ebrahimi return 0;
833*62c56f98SSadaf Ebrahimi }
834*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PEM_WRITE_C */
835*62c56f98SSadaf Ebrahimi
836*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_WRITE_C */
837