Line data Source code
1 : /*
2 : * Public Key layer for writing key files and structures
3 : *
4 : * Copyright The Mbed TLS Contributors
5 : * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 : */
7 :
8 : #include "common.h"
9 :
10 : #if defined(MBEDTLS_PK_WRITE_C)
11 :
12 : #include "mbedtls/pk.h"
13 : #include "mbedtls/asn1write.h"
14 : #include "mbedtls/oid.h"
15 : #include "mbedtls/platform_util.h"
16 : #include "mbedtls/error.h"
17 : #include "pk_internal.h"
18 :
19 : #include <string.h>
20 :
21 : #if defined(MBEDTLS_ECP_C)
22 : #include "mbedtls/bignum.h"
23 : #include "mbedtls/ecp.h"
24 : #include "mbedtls/platform_util.h"
25 : #endif
26 : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
27 : #include "pk_internal.h"
28 : #endif
29 : #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
30 : #include "pkwrite.h"
31 : #endif
32 : #if defined(MBEDTLS_PEM_WRITE_C)
33 : #include "mbedtls/pem.h"
34 : #endif
35 : #if defined(MBEDTLS_RSA_C)
36 : #include "rsa_internal.h"
37 : #endif
38 :
39 : #if defined(MBEDTLS_USE_PSA_CRYPTO)
40 : #include "psa/crypto.h"
41 : #include "psa_util_internal.h"
42 : #endif
43 : #include "mbedtls/platform.h"
44 :
45 : /* Helpers for properly sizing buffers aimed at holding public keys or
46 : * key-pairs based on build symbols. */
47 : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
48 : #define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
49 : #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
50 : #elif defined(MBEDTLS_USE_PSA_CRYPTO)
51 : #define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
52 : #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
53 : #else
54 : #define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN
55 : #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES
56 : #endif
57 :
58 : /******************************************************************************
59 : * Internal functions for RSA keys.
60 : ******************************************************************************/
61 : #if defined(MBEDTLS_RSA_C)
62 0 : static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
63 : const mbedtls_pk_context *pk)
64 : {
65 : #if defined(MBEDTLS_USE_PSA_CRYPTO)
66 : if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
67 : uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
68 : size_t tmp_len = 0;
69 :
70 : if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
71 : return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
72 : }
73 : /* Ensure there's enough space in the provided buffer before copying data into it. */
74 : if (tmp_len > (size_t) (*p - buf)) {
75 : mbedtls_platform_zeroize(tmp, sizeof(tmp));
76 : return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
77 : }
78 : *p -= tmp_len;
79 : memcpy(*p, tmp, tmp_len);
80 : mbedtls_platform_zeroize(tmp, sizeof(tmp));
81 :
82 : return (int) tmp_len;
83 : }
84 : #endif /* MBEDTLS_USE_PSA_CRYPTO */
85 0 : return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
86 : }
87 : #endif /* MBEDTLS_RSA_C */
88 :
89 : /******************************************************************************
90 : * Internal functions for EC keys.
91 : ******************************************************************************/
92 : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
93 : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
94 : static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
95 : const mbedtls_pk_context *pk)
96 : {
97 : size_t len = 0;
98 : uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
99 :
100 : if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
101 : if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
102 : return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
103 : }
104 : } else {
105 : len = pk->pub_raw_len;
106 : memcpy(buf, pk->pub_raw, len);
107 : }
108 :
109 : if (*p < start || (size_t) (*p - start) < len) {
110 : return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
111 : }
112 :
113 : *p -= len;
114 : memcpy(*p, buf, len);
115 :
116 : return (int) len;
117 : }
118 : #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
119 12 : static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
120 : const mbedtls_pk_context *pk)
121 : {
122 12 : size_t len = 0;
123 : unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
124 12 : mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
125 12 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
126 :
127 : #if defined(MBEDTLS_USE_PSA_CRYPTO)
128 : if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
129 : if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
130 : return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
131 : }
132 : /* Ensure there's enough space in the provided buffer before copying data into it. */
133 : if (len > (size_t) (*p - start)) {
134 : return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
135 : }
136 : *p -= len;
137 : memcpy(*p, buf, len);
138 : return (int) len;
139 : } else
140 : #endif /* MBEDTLS_USE_PSA_CRYPTO */
141 : {
142 12 : if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
143 : MBEDTLS_ECP_PF_UNCOMPRESSED,
144 : &len, buf, sizeof(buf))) != 0) {
145 0 : return ret;
146 : }
147 : }
148 :
149 12 : if (*p < start || (size_t) (*p - start) < len) {
150 0 : return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
151 : }
152 :
153 12 : *p -= len;
154 12 : memcpy(*p, buf, len);
155 :
156 12 : return (int) len;
157 : }
158 : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
159 :
160 : /*
161 : * privateKey OCTET STRING -- always of length ceil(log2(n)/8)
162 : */
163 : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
164 : static int pk_write_ec_private(unsigned char **p, unsigned char *start,
165 : const mbedtls_pk_context *pk)
166 : {
167 : size_t byte_length;
168 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
169 : unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
170 : psa_status_t status;
171 :
172 : if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
173 : status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
174 : if (status != PSA_SUCCESS) {
175 : ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
176 : return ret;
177 : }
178 : } else {
179 : status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
180 : if (status != PSA_SUCCESS) {
181 : ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
182 : goto exit;
183 : }
184 : }
185 :
186 : ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
187 : exit:
188 : mbedtls_platform_zeroize(tmp, sizeof(tmp));
189 : return ret;
190 : }
191 : #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
192 0 : static int pk_write_ec_private(unsigned char **p, unsigned char *start,
193 : const mbedtls_pk_context *pk)
194 : {
195 : size_t byte_length;
196 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
197 : unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
198 :
199 : #if defined(MBEDTLS_USE_PSA_CRYPTO)
200 : psa_status_t status;
201 : if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
202 : status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
203 : if (status != PSA_SUCCESS) {
204 : ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
205 : return ret;
206 : }
207 : } else
208 : #endif /* MBEDTLS_USE_PSA_CRYPTO */
209 : {
210 0 : mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
211 0 : byte_length = (ec->grp.pbits + 7) / 8;
212 :
213 0 : ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));
214 0 : if (ret != 0) {
215 0 : goto exit;
216 : }
217 : }
218 0 : ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
219 0 : exit:
220 0 : mbedtls_platform_zeroize(tmp, sizeof(tmp));
221 0 : return ret;
222 : }
223 : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
224 :
225 : /*
226 : * ECParameters ::= CHOICE {
227 : * namedCurve OBJECT IDENTIFIER
228 : * }
229 : */
230 12 : static int pk_write_ec_param(unsigned char **p, unsigned char *start,
231 : mbedtls_ecp_group_id grp_id)
232 : {
233 12 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
234 12 : size_t len = 0;
235 : const char *oid;
236 : size_t oid_len;
237 :
238 12 : if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
239 0 : return ret;
240 : }
241 :
242 12 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
243 :
244 12 : return (int) len;
245 : }
246 :
247 : #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
248 : /*
249 : * RFC8410 section 7
250 : *
251 : * OneAsymmetricKey ::= SEQUENCE {
252 : * version Version,
253 : * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
254 : * privateKey PrivateKey,
255 : * attributes [0] IMPLICIT Attributes OPTIONAL,
256 : * ...,
257 : * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
258 : * ...
259 : * }
260 : * ...
261 : * CurvePrivateKey ::= OCTET STRING
262 : */
263 0 : static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
264 : const mbedtls_pk_context *pk)
265 : {
266 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
267 0 : size_t len = 0;
268 0 : size_t oid_len = 0;
269 : const char *oid;
270 : mbedtls_ecp_group_id grp_id;
271 :
272 : /* privateKey */
273 0 : MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
274 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
275 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
276 :
277 0 : grp_id = mbedtls_pk_get_ec_group_id(pk);
278 : /* privateKeyAlgorithm */
279 0 : if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
280 0 : return ret;
281 : }
282 0 : MBEDTLS_ASN1_CHK_ADD(len,
283 : mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
284 :
285 : /* version */
286 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
287 :
288 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
289 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
290 : MBEDTLS_ASN1_SEQUENCE));
291 :
292 0 : return (int) len;
293 : }
294 : #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
295 :
296 : /*
297 : * RFC 5915, or SEC1 Appendix C.4
298 : *
299 : * ECPrivateKey ::= SEQUENCE {
300 : * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
301 : * privateKey OCTET STRING,
302 : * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
303 : * publicKey [1] BIT STRING OPTIONAL
304 : * }
305 : */
306 0 : static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
307 : const mbedtls_pk_context *pk)
308 : {
309 0 : size_t len = 0;
310 : int ret;
311 0 : size_t pub_len = 0, par_len = 0;
312 : mbedtls_ecp_group_id grp_id;
313 :
314 : /* publicKey */
315 0 : MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
316 :
317 0 : if (*p - buf < 1) {
318 0 : return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
319 : }
320 0 : (*p)--;
321 0 : **p = 0;
322 0 : pub_len += 1;
323 :
324 0 : MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
325 0 : MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
326 :
327 0 : MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
328 0 : MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
329 : MBEDTLS_ASN1_CONTEXT_SPECIFIC |
330 : MBEDTLS_ASN1_CONSTRUCTED | 1));
331 0 : len += pub_len;
332 :
333 : /* parameters */
334 0 : grp_id = mbedtls_pk_get_ec_group_id(pk);
335 0 : MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
336 0 : MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
337 0 : MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
338 : MBEDTLS_ASN1_CONTEXT_SPECIFIC |
339 : MBEDTLS_ASN1_CONSTRUCTED | 0));
340 0 : len += par_len;
341 :
342 : /* privateKey */
343 0 : MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
344 :
345 : /* version */
346 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
347 :
348 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
349 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
350 : MBEDTLS_ASN1_SEQUENCE));
351 :
352 0 : return (int) len;
353 : }
354 : #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
355 :
356 : /******************************************************************************
357 : * Internal functions for Opaque keys.
358 : ******************************************************************************/
359 : #if defined(MBEDTLS_USE_PSA_CRYPTO)
360 : static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
361 : const mbedtls_pk_context *pk)
362 : {
363 : size_t buffer_size;
364 : size_t len = 0;
365 :
366 : if (*p < start) {
367 : return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
368 : }
369 :
370 : buffer_size = (size_t) (*p - start);
371 : if (psa_export_public_key(pk->priv_id, start, buffer_size,
372 : &len) != PSA_SUCCESS) {
373 : return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
374 : }
375 :
376 : *p -= len;
377 : memmove(*p, start, len);
378 :
379 : return (int) len;
380 : }
381 : #endif /* MBEDTLS_USE_PSA_CRYPTO */
382 :
383 : /******************************************************************************
384 : * Generic helpers
385 : ******************************************************************************/
386 :
387 : /* Extend the public mbedtls_pk_get_type() by getting key type also in case of
388 : * opaque keys. */
389 24 : static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk)
390 : {
391 24 : mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
392 :
393 : #if defined(MBEDTLS_USE_PSA_CRYPTO)
394 : if (pk_type == MBEDTLS_PK_OPAQUE) {
395 : psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
396 : psa_key_type_t opaque_key_type;
397 :
398 : if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
399 : return MBEDTLS_PK_NONE;
400 : }
401 : opaque_key_type = psa_get_key_type(&opaque_attrs);
402 : psa_reset_key_attributes(&opaque_attrs);
403 :
404 : if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
405 : return MBEDTLS_PK_ECKEY;
406 : } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
407 : return MBEDTLS_PK_RSA;
408 : } else {
409 : return MBEDTLS_PK_NONE;
410 : }
411 : } else
412 : #endif
413 24 : return pk_type;
414 : }
415 :
416 : /******************************************************************************
417 : * Public functions for writing private/public DER keys.
418 : ******************************************************************************/
419 12 : int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
420 : const mbedtls_pk_context *key)
421 : {
422 12 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423 12 : size_t len = 0;
424 :
425 : #if defined(MBEDTLS_RSA_C)
426 12 : if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
427 0 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
428 : } else
429 : #endif
430 : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
431 12 : if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
432 12 : MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
433 : } else
434 : #endif
435 : #if defined(MBEDTLS_USE_PSA_CRYPTO)
436 : if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
437 : MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
438 : } else
439 : #endif /* MBEDTLS_USE_PSA_CRYPTO */
440 0 : return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
441 :
442 12 : return (int) len;
443 : }
444 :
445 12 : int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
446 : {
447 12 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
448 : unsigned char *c;
449 12 : int has_par = 1;
450 12 : size_t len = 0, par_len = 0, oid_len = 0;
451 : mbedtls_pk_type_t pk_type;
452 12 : const char *oid = NULL;
453 :
454 12 : if (size == 0) {
455 0 : return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
456 : }
457 :
458 12 : c = buf + size;
459 :
460 12 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
461 :
462 12 : if (c - buf < 1) {
463 0 : return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
464 : }
465 :
466 : /*
467 : * SubjectPublicKeyInfo ::= SEQUENCE {
468 : * algorithm AlgorithmIdentifier,
469 : * subjectPublicKey BIT STRING }
470 : */
471 12 : *--c = 0;
472 12 : len += 1;
473 :
474 12 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
475 12 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
476 :
477 12 : pk_type = pk_get_type_ext(key);
478 :
479 : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
480 12 : if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
481 12 : mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key);
482 12 : if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
483 0 : ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
484 0 : if (ret != 0) {
485 0 : return ret;
486 : }
487 0 : has_par = 0;
488 : } else {
489 12 : MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
490 : }
491 : }
492 : #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
493 :
494 : /* At this point oid_len is not null only for EC Montgomery keys. */
495 12 : if (oid_len == 0) {
496 12 : ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len);
497 12 : if (ret != 0) {
498 0 : return ret;
499 : }
500 : }
501 :
502 12 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
503 : par_len, has_par));
504 :
505 12 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
506 12 : MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
507 : MBEDTLS_ASN1_SEQUENCE));
508 :
509 12 : return (int) len;
510 : }
511 :
512 0 : int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
513 : {
514 : unsigned char *c;
515 :
516 0 : if (size == 0) {
517 0 : return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
518 : }
519 :
520 0 : c = buf + size;
521 :
522 : #if defined(MBEDTLS_RSA_C)
523 0 : if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
524 0 : return pk_write_rsa_der(&c, buf, key);
525 : } else
526 : #endif /* MBEDTLS_RSA_C */
527 : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
528 0 : if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
529 : #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
530 0 : if (mbedtls_pk_is_rfc8410(key)) {
531 0 : return pk_write_ec_rfc8410_der(&c, buf, key);
532 : }
533 : #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
534 0 : return pk_write_ec_der(&c, buf, key);
535 : } else
536 : #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
537 0 : return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
538 : }
539 :
540 : /******************************************************************************
541 : * Public functions for wrinting private/public PEM keys.
542 : ******************************************************************************/
543 : #if defined(MBEDTLS_PEM_WRITE_C)
544 :
545 : #define PUB_DER_MAX_BYTES \
546 : (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
547 : MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
548 : #define PRV_DER_MAX_BYTES \
549 : (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
550 : MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
551 :
552 0 : int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
553 : {
554 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
555 0 : unsigned char *output_buf = NULL;
556 0 : output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);
557 0 : if (output_buf == NULL) {
558 0 : return MBEDTLS_ERR_PK_ALLOC_FAILED;
559 : }
560 0 : size_t olen = 0;
561 :
562 0 : if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
563 : PUB_DER_MAX_BYTES)) < 0) {
564 0 : goto cleanup;
565 : }
566 :
567 0 : if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n",
568 0 : output_buf + PUB_DER_MAX_BYTES - ret,
569 : ret, buf, size, &olen)) != 0) {
570 0 : goto cleanup;
571 : }
572 :
573 0 : ret = 0;
574 0 : cleanup:
575 0 : mbedtls_free(output_buf);
576 0 : return ret;
577 : }
578 :
579 0 : int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
580 : {
581 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
582 0 : unsigned char *output_buf = NULL;
583 0 : output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);
584 0 : if (output_buf == NULL) {
585 0 : return MBEDTLS_ERR_PK_ALLOC_FAILED;
586 : }
587 : const char *begin, *end;
588 0 : size_t olen = 0;
589 :
590 0 : if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {
591 0 : goto cleanup;
592 : }
593 :
594 : #if defined(MBEDTLS_RSA_C)
595 0 : if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
596 0 : begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n";
597 0 : end = PEM_END_PRIVATE_KEY_RSA "\n";
598 : } else
599 : #endif
600 : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
601 0 : if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
602 0 : if (mbedtls_pk_is_rfc8410(key)) {
603 0 : begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n";
604 0 : end = PEM_END_PRIVATE_KEY_PKCS8 "\n";
605 : } else {
606 0 : begin = PEM_BEGIN_PRIVATE_KEY_EC "\n";
607 0 : end = PEM_END_PRIVATE_KEY_EC "\n";
608 : }
609 : } else
610 : #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
611 : {
612 0 : ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
613 0 : goto cleanup;
614 : }
615 :
616 0 : if ((ret = mbedtls_pem_write_buffer(begin, end,
617 0 : output_buf + PRV_DER_MAX_BYTES - ret,
618 : ret, buf, size, &olen)) != 0) {
619 0 : goto cleanup;
620 : }
621 :
622 0 : ret = 0;
623 0 : cleanup:
624 0 : mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES);
625 0 : return ret;
626 : }
627 : #endif /* MBEDTLS_PEM_WRITE_C */
628 :
629 : #endif /* MBEDTLS_PK_WRITE_C */
|