Coverage Report

Created: 2024-08-27 12:19

/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 */