/src/mbedtls/library/pkwrite.c
Line | Count | Source (jump to first uncovered line) |
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 |
6 | | * |
7 | | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
8 | | * not use this file except in compliance with the License. |
9 | | * You may obtain a copy of the License at |
10 | | * |
11 | | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | | * |
13 | | * Unless required by applicable law or agreed to in writing, software |
14 | | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
15 | | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | | * See the License for the specific language governing permissions and |
17 | | * limitations under the License. |
18 | | */ |
19 | | |
20 | | #include "common.h" |
21 | | |
22 | | #if defined(MBEDTLS_PK_WRITE_C) |
23 | | |
24 | | #include "mbedtls/pk.h" |
25 | | #include "mbedtls/asn1write.h" |
26 | | #include "mbedtls/oid.h" |
27 | | #include "mbedtls/platform_util.h" |
28 | | #include "mbedtls/error.h" |
29 | | |
30 | | #include <string.h> |
31 | | |
32 | | #if defined(MBEDTLS_RSA_C) |
33 | | #include "mbedtls/rsa.h" |
34 | | #endif |
35 | | #if defined(MBEDTLS_ECP_C) |
36 | | #include "mbedtls/bignum.h" |
37 | | #include "mbedtls/ecp.h" |
38 | | #include "mbedtls/platform_util.h" |
39 | | #endif |
40 | | #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) |
41 | | #include "pkwrite.h" |
42 | | #endif |
43 | | #if defined(MBEDTLS_ECDSA_C) |
44 | | #include "mbedtls/ecdsa.h" |
45 | | #endif |
46 | | #if defined(MBEDTLS_PEM_WRITE_C) |
47 | | #include "mbedtls/pem.h" |
48 | | #endif |
49 | | |
50 | | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
51 | | #include "psa/crypto.h" |
52 | | #include "mbedtls/psa_util.h" |
53 | | #endif |
54 | | #include "mbedtls/platform.h" |
55 | | |
56 | | #if defined(MBEDTLS_RSA_C) |
57 | | /* |
58 | | * RSAPublicKey ::= SEQUENCE { |
59 | | * modulus INTEGER, -- n |
60 | | * publicExponent INTEGER -- e |
61 | | * } |
62 | | */ |
63 | | static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start, |
64 | | mbedtls_rsa_context *rsa) |
65 | 0 | { |
66 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
67 | 0 | size_t len = 0; |
68 | 0 | mbedtls_mpi T; |
69 | |
|
70 | 0 | mbedtls_mpi_init(&T); |
71 | | |
72 | | /* Export E */ |
73 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || |
74 | 0 | (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { |
75 | 0 | goto end_of_export; |
76 | 0 | } |
77 | 0 | len += ret; |
78 | | |
79 | | /* Export N */ |
80 | 0 | if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || |
81 | 0 | (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { |
82 | 0 | goto end_of_export; |
83 | 0 | } |
84 | 0 | len += ret; |
85 | |
|
86 | 0 | end_of_export: |
87 | |
|
88 | 0 | mbedtls_mpi_free(&T); |
89 | 0 | if (ret < 0) { |
90 | 0 | return ret; |
91 | 0 | } |
92 | | |
93 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); |
94 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | |
95 | 0 | MBEDTLS_ASN1_SEQUENCE)); |
96 | | |
97 | 0 | return (int) len; |
98 | 0 | } |
99 | | #endif /* MBEDTLS_RSA_C */ |
100 | | |
101 | | #if defined(MBEDTLS_ECP_C) |
102 | | /* |
103 | | * EC public key is an EC point |
104 | | */ |
105 | | static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, |
106 | | mbedtls_ecp_keypair *ec) |
107 | 0 | { |
108 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
109 | 0 | size_t len = 0; |
110 | 0 | unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; |
111 | |
|
112 | 0 | if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, |
113 | 0 | MBEDTLS_ECP_PF_UNCOMPRESSED, |
114 | 0 | &len, buf, sizeof(buf))) != 0) { |
115 | 0 | return ret; |
116 | 0 | } |
117 | | |
118 | 0 | if (*p < start || (size_t) (*p - start) < len) { |
119 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
120 | 0 | } |
121 | | |
122 | 0 | *p -= len; |
123 | 0 | memcpy(*p, buf, len); |
124 | |
|
125 | 0 | return (int) len; |
126 | 0 | } |
127 | | |
128 | | /* |
129 | | * ECParameters ::= CHOICE { |
130 | | * namedCurve OBJECT IDENTIFIER |
131 | | * } |
132 | | */ |
133 | | static int pk_write_ec_param(unsigned char **p, unsigned char *start, |
134 | | mbedtls_ecp_keypair *ec) |
135 | 0 | { |
136 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
137 | 0 | size_t len = 0; |
138 | 0 | const char *oid; |
139 | 0 | size_t oid_len; |
140 | |
|
141 | 0 | if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) { |
142 | 0 | return ret; |
143 | 0 | } |
144 | | |
145 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); |
146 | | |
147 | 0 | return (int) len; |
148 | 0 | } |
149 | | |
150 | | /* |
151 | | * privateKey OCTET STRING -- always of length ceil(log2(n)/8) |
152 | | */ |
153 | | static int pk_write_ec_private(unsigned char **p, unsigned char *start, |
154 | | mbedtls_ecp_keypair *ec) |
155 | 0 | { |
156 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
157 | 0 | size_t byte_length = (ec->grp.pbits + 7) / 8; |
158 | 0 | unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; |
159 | |
|
160 | 0 | ret = mbedtls_ecp_write_key(ec, tmp, byte_length); |
161 | 0 | if (ret != 0) { |
162 | 0 | goto exit; |
163 | 0 | } |
164 | 0 | ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); |
165 | |
|
166 | 0 | exit: |
167 | 0 | mbedtls_platform_zeroize(tmp, byte_length); |
168 | 0 | return ret; |
169 | 0 | } |
170 | | #endif /* MBEDTLS_ECP_C */ |
171 | | |
172 | | int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, |
173 | | const mbedtls_pk_context *key) |
174 | 0 | { |
175 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
176 | 0 | size_t len = 0; |
177 | |
|
178 | 0 | #if defined(MBEDTLS_RSA_C) |
179 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { |
180 | 0 | MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key))); |
181 | 0 | } else |
182 | 0 | #endif |
183 | 0 | #if defined(MBEDTLS_ECP_C) |
184 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { |
185 | 0 | MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key))); |
186 | 0 | } else |
187 | 0 | #endif |
188 | | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
189 | | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { |
190 | | size_t buffer_size; |
191 | | mbedtls_svc_key_id_t *key_id = (mbedtls_svc_key_id_t *) key->pk_ctx; |
192 | | |
193 | | if (*p < start) { |
194 | | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
195 | | } |
196 | | |
197 | | buffer_size = (size_t) (*p - start); |
198 | | if (psa_export_public_key(*key_id, start, buffer_size, &len) |
199 | | != PSA_SUCCESS) { |
200 | | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
201 | | } else { |
202 | | *p -= len; |
203 | | memmove(*p, start, len); |
204 | | } |
205 | | } else |
206 | | #endif /* MBEDTLS_USE_PSA_CRYPTO */ |
207 | 0 | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
208 | | |
209 | 0 | return (int) len; |
210 | 0 | } |
211 | | |
212 | | int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) |
213 | 0 | { |
214 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
215 | 0 | unsigned char *c; |
216 | 0 | size_t len = 0, par_len = 0, oid_len; |
217 | 0 | mbedtls_pk_type_t pk_type; |
218 | 0 | const char *oid; |
219 | |
|
220 | 0 | if (size == 0) { |
221 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
222 | 0 | } |
223 | | |
224 | 0 | c = buf + size; |
225 | |
|
226 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key)); |
227 | | |
228 | 0 | if (c - buf < 1) { |
229 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
230 | 0 | } |
231 | | |
232 | | /* |
233 | | * SubjectPublicKeyInfo ::= SEQUENCE { |
234 | | * algorithm AlgorithmIdentifier, |
235 | | * subjectPublicKey BIT STRING } |
236 | | */ |
237 | 0 | *--c = 0; |
238 | 0 | len += 1; |
239 | |
|
240 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
241 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); |
242 | | |
243 | 0 | pk_type = mbedtls_pk_get_type(key); |
244 | 0 | #if defined(MBEDTLS_ECP_C) |
245 | 0 | if (pk_type == MBEDTLS_PK_ECKEY) { |
246 | 0 | MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key))); |
247 | 0 | } |
248 | 0 | #endif |
249 | | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
250 | | if (pk_type == MBEDTLS_PK_OPAQUE) { |
251 | | psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
252 | | psa_key_type_t key_type; |
253 | | mbedtls_svc_key_id_t key_id; |
254 | | psa_ecc_family_t curve; |
255 | | size_t bits; |
256 | | |
257 | | key_id = *((mbedtls_svc_key_id_t *) key->pk_ctx); |
258 | | if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) { |
259 | | return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; |
260 | | } |
261 | | key_type = psa_get_key_type(&attributes); |
262 | | bits = psa_get_key_bits(&attributes); |
263 | | psa_reset_key_attributes(&attributes); |
264 | | |
265 | | if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) { |
266 | | curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type); |
267 | | if (curve == 0) { |
268 | | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
269 | | } |
270 | | |
271 | | ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits, |
272 | | &oid, &oid_len); |
273 | | if (ret != 0) { |
274 | | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
275 | | } |
276 | | |
277 | | /* Write EC algorithm parameters; that's akin |
278 | | * to pk_write_ec_param() above. */ |
279 | | MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_oid(&c, buf, |
280 | | oid, |
281 | | oid_len)); |
282 | | |
283 | | /* The rest of the function works as for legacy EC contexts. */ |
284 | | pk_type = MBEDTLS_PK_ECKEY; |
285 | | } else if (PSA_KEY_TYPE_IS_RSA(key_type)) { |
286 | | /* The rest of the function works as for legacy RSA contexts. */ |
287 | | pk_type = MBEDTLS_PK_RSA; |
288 | | } else { |
289 | | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
290 | | } |
291 | | } |
292 | | #endif /* MBEDTLS_USE_PSA_CRYPTO */ |
293 | | |
294 | 0 | if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, |
295 | 0 | &oid_len)) != 0) { |
296 | 0 | return ret; |
297 | 0 | } |
298 | | |
299 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len, |
300 | 0 | par_len)); |
301 | | |
302 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
303 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | |
304 | 0 | MBEDTLS_ASN1_SEQUENCE)); |
305 | | |
306 | 0 | return (int) len; |
307 | 0 | } |
308 | | |
309 | | int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) |
310 | 0 | { |
311 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
312 | 0 | unsigned char *c; |
313 | 0 | size_t len = 0; |
314 | |
|
315 | 0 | if (size == 0) { |
316 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
317 | 0 | } |
318 | | |
319 | 0 | c = buf + size; |
320 | |
|
321 | 0 | #if defined(MBEDTLS_RSA_C) |
322 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { |
323 | 0 | mbedtls_mpi T; /* Temporary holding the exported parameters */ |
324 | 0 | mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key); |
325 | | |
326 | | /* |
327 | | * Export the parameters one after another to avoid simultaneous copies. |
328 | | */ |
329 | |
|
330 | 0 | mbedtls_mpi_init(&T); |
331 | | |
332 | | /* Export QP */ |
333 | 0 | if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || |
334 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
335 | 0 | goto end_of_export; |
336 | 0 | } |
337 | 0 | len += ret; |
338 | | |
339 | | /* Export DQ */ |
340 | 0 | if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || |
341 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
342 | 0 | goto end_of_export; |
343 | 0 | } |
344 | 0 | len += ret; |
345 | | |
346 | | /* Export DP */ |
347 | 0 | if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || |
348 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
349 | 0 | goto end_of_export; |
350 | 0 | } |
351 | 0 | len += ret; |
352 | | |
353 | | /* Export Q */ |
354 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, |
355 | 0 | &T, NULL, NULL)) != 0 || |
356 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
357 | 0 | goto end_of_export; |
358 | 0 | } |
359 | 0 | len += ret; |
360 | | |
361 | | /* Export P */ |
362 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, &T, |
363 | 0 | NULL, NULL, NULL)) != 0 || |
364 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
365 | 0 | goto end_of_export; |
366 | 0 | } |
367 | 0 | len += ret; |
368 | | |
369 | | /* Export D */ |
370 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, |
371 | 0 | NULL, &T, NULL)) != 0 || |
372 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
373 | 0 | goto end_of_export; |
374 | 0 | } |
375 | 0 | len += ret; |
376 | | |
377 | | /* Export E */ |
378 | 0 | if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, |
379 | 0 | NULL, NULL, &T)) != 0 || |
380 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
381 | 0 | goto end_of_export; |
382 | 0 | } |
383 | 0 | len += ret; |
384 | | |
385 | | /* Export N */ |
386 | 0 | if ((ret = mbedtls_rsa_export(rsa, &T, NULL, |
387 | 0 | NULL, NULL, NULL)) != 0 || |
388 | 0 | (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) { |
389 | 0 | goto end_of_export; |
390 | 0 | } |
391 | 0 | len += ret; |
392 | |
|
393 | 0 | end_of_export: |
394 | |
|
395 | 0 | mbedtls_mpi_free(&T); |
396 | 0 | if (ret < 0) { |
397 | 0 | return ret; |
398 | 0 | } |
399 | | |
400 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); |
401 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
402 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, |
403 | 0 | buf, MBEDTLS_ASN1_CONSTRUCTED | |
404 | 0 | MBEDTLS_ASN1_SEQUENCE)); |
405 | 0 | } else |
406 | 0 | #endif /* MBEDTLS_RSA_C */ |
407 | 0 | #if defined(MBEDTLS_ECP_C) |
408 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { |
409 | 0 | mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key); |
410 | 0 | size_t pub_len = 0, par_len = 0; |
411 | | |
412 | | /* |
413 | | * RFC 5915, or SEC1 Appendix C.4 |
414 | | * |
415 | | * ECPrivateKey ::= SEQUENCE { |
416 | | * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), |
417 | | * privateKey OCTET STRING, |
418 | | * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, |
419 | | * publicKey [1] BIT STRING OPTIONAL |
420 | | * } |
421 | | */ |
422 | | |
423 | | /* publicKey */ |
424 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, ec)); |
425 | | |
426 | 0 | if (c - buf < 1) { |
427 | 0 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
428 | 0 | } |
429 | 0 | *--c = 0; |
430 | 0 | pub_len += 1; |
431 | |
|
432 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len)); |
433 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); |
434 | | |
435 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len)); |
436 | 0 | MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, |
437 | 0 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | |
438 | 0 | MBEDTLS_ASN1_CONSTRUCTED | 1)); |
439 | 0 | len += pub_len; |
440 | | |
441 | | /* parameters */ |
442 | 0 | MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec)); |
443 | | |
444 | 0 | MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len)); |
445 | 0 | MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(&c, buf, |
446 | 0 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | |
447 | 0 | MBEDTLS_ASN1_CONSTRUCTED | 0)); |
448 | 0 | len += par_len; |
449 | | |
450 | | /* privateKey */ |
451 | 0 | MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(&c, buf, ec)); |
452 | | |
453 | | /* version */ |
454 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1)); |
455 | | |
456 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
457 | 0 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | |
458 | 0 | MBEDTLS_ASN1_SEQUENCE)); |
459 | 0 | } else |
460 | 0 | #endif /* MBEDTLS_ECP_C */ |
461 | 0 | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
462 | | |
463 | 0 | return (int) len; |
464 | 0 | } |
465 | | |
466 | | #if defined(MBEDTLS_PEM_WRITE_C) |
467 | | |
468 | 0 | #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" |
469 | 0 | #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" |
470 | | |
471 | 0 | #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" |
472 | 0 | #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" |
473 | 0 | #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" |
474 | 0 | #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" |
475 | | |
476 | | #define PUB_DER_MAX_BYTES \ |
477 | | (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \ |
478 | | MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) |
479 | | #define PRV_DER_MAX_BYTES \ |
480 | | (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \ |
481 | | MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES) |
482 | | |
483 | | int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) |
484 | 0 | { |
485 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
486 | 0 | unsigned char output_buf[PUB_DER_MAX_BYTES]; |
487 | 0 | size_t olen = 0; |
488 | |
|
489 | 0 | if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, |
490 | 0 | sizeof(output_buf))) < 0) { |
491 | 0 | return ret; |
492 | 0 | } |
493 | | |
494 | 0 | if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, |
495 | 0 | output_buf + sizeof(output_buf) - ret, |
496 | 0 | ret, buf, size, &olen)) != 0) { |
497 | 0 | return ret; |
498 | 0 | } |
499 | | |
500 | 0 | return 0; |
501 | 0 | } |
502 | | |
503 | | int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) |
504 | 0 | { |
505 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
506 | 0 | unsigned char output_buf[PRV_DER_MAX_BYTES]; |
507 | 0 | const char *begin, *end; |
508 | 0 | size_t olen = 0; |
509 | |
|
510 | 0 | if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) { |
511 | 0 | return ret; |
512 | 0 | } |
513 | | |
514 | 0 | #if defined(MBEDTLS_RSA_C) |
515 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { |
516 | 0 | begin = PEM_BEGIN_PRIVATE_KEY_RSA; |
517 | 0 | end = PEM_END_PRIVATE_KEY_RSA; |
518 | 0 | } else |
519 | 0 | #endif |
520 | 0 | #if defined(MBEDTLS_ECP_C) |
521 | 0 | if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { |
522 | 0 | begin = PEM_BEGIN_PRIVATE_KEY_EC; |
523 | 0 | end = PEM_END_PRIVATE_KEY_EC; |
524 | 0 | } else |
525 | 0 | #endif |
526 | 0 | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
527 | | |
528 | 0 | if ((ret = mbedtls_pem_write_buffer(begin, end, |
529 | 0 | output_buf + sizeof(output_buf) - ret, |
530 | 0 | ret, buf, size, &olen)) != 0) { |
531 | 0 | return ret; |
532 | 0 | } |
533 | | |
534 | 0 | return 0; |
535 | 0 | } |
536 | | #endif /* MBEDTLS_PEM_WRITE_C */ |
537 | | |
538 | | #endif /* MBEDTLS_PK_WRITE_C */ |