xref: /aosp_15_r20/external/mbedtls/library/pkwrite.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
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