Coverage Report

Created: 2025-07-01 06:54

/work/mbedtls-2.28.8/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 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
18
#include <string.h>
19
20
#if defined(MBEDTLS_RSA_C)
21
#include "mbedtls/rsa.h"
22
#endif
23
#if defined(MBEDTLS_ECP_C)
24
#include "mbedtls/bignum.h"
25
#include "mbedtls/ecp.h"
26
#include "mbedtls/platform_util.h"
27
#endif
28
#if defined(MBEDTLS_ECDSA_C)
29
#include "mbedtls/ecdsa.h"
30
#endif
31
#if defined(MBEDTLS_PEM_WRITE_C)
32
#include "mbedtls/pem.h"
33
#endif
34
35
#if defined(MBEDTLS_USE_PSA_CRYPTO)
36
#include "psa/crypto.h"
37
#include "mbedtls/psa_util.h"
38
#endif
39
#include "mbedtls/platform.h"
40
41
/* Parameter validation macros based on platform_util.h */
42
#define PK_VALIDATE_RET(cond)    \
43
0
    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA)
44
#define PK_VALIDATE(cond)        \
45
    MBEDTLS_INTERNAL_VALIDATE(cond)
46
47
#if defined(MBEDTLS_RSA_C)
48
/*
49
 *  RSAPublicKey ::= SEQUENCE {
50
 *      modulus           INTEGER,  -- n
51
 *      publicExponent    INTEGER   -- e
52
 *  }
53
 */
54
static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
55
                               mbedtls_rsa_context *rsa)
56
0
{
57
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
58
0
    size_t len = 0;
59
0
    mbedtls_mpi T;
60
61
0
    mbedtls_mpi_init(&T);
62
63
    /* Export E */
64
0
    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
65
0
        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
66
0
        goto end_of_export;
67
0
    }
68
0
    len += ret;
69
70
    /* Export N */
71
0
    if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
72
0
        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
73
0
        goto end_of_export;
74
0
    }
75
0
    len += ret;
76
77
0
end_of_export:
78
79
0
    mbedtls_mpi_free(&T);
80
0
    if (ret < 0) {
81
0
        return ret;
82
0
    }
83
84
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
85
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
86
0
                                                     MBEDTLS_ASN1_SEQUENCE));
87
88
0
    return (int) len;
89
0
}
90
#endif /* MBEDTLS_RSA_C */
91
92
#if defined(MBEDTLS_ECP_C)
93
/*
94
 * EC public key is an EC point
95
 */
96
static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
97
                              mbedtls_ecp_keypair *ec)
98
0
{
99
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
100
0
    size_t len = 0;
101
0
    unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
102
103
0
    if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
104
0
                                              MBEDTLS_ECP_PF_UNCOMPRESSED,
105
0
                                              &len, buf, sizeof(buf))) != 0) {
106
0
        return ret;
107
0
    }
108
109
0
    if (*p < start || (size_t) (*p - start) < len) {
110
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
111
0
    }
112
113
0
    *p -= len;
114
0
    memcpy(*p, buf, len);
115
116
0
    return (int) len;
117
0
}
118
119
/*
120
 * ECParameters ::= CHOICE {
121
 *   namedCurve         OBJECT IDENTIFIER
122
 * }
123
 */
124
static int pk_write_ec_param(unsigned char **p, unsigned char *start,
125
                             mbedtls_ecp_keypair *ec)
126
0
{
127
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
128
0
    size_t len = 0;
129
0
    const char *oid;
130
0
    size_t oid_len;
131
132
0
    if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) {
133
0
        return ret;
134
0
    }
135
136
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
137
138
0
    return (int) len;
139
0
}
140
141
/*
142
 * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
143
 */
144
static int pk_write_ec_private(unsigned char **p, unsigned char *start,
145
                               mbedtls_ecp_keypair *ec)
146
0
{
147
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
148
0
    size_t byte_length = (ec->grp.pbits + 7) / 8;
149
0
    unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
150
151
0
    ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
152
0
    if (ret != 0) {
153
0
        goto exit;
154
0
    }
155
0
    ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
156
157
0
exit:
158
0
    mbedtls_platform_zeroize(tmp, byte_length);
159
0
    return ret;
160
0
}
161
#endif /* MBEDTLS_ECP_C */
162
163
int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
164
                            const mbedtls_pk_context *key)
165
0
{
166
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
167
0
    size_t len = 0;
168
169
0
    (void) p;
170
0
    (void) start;
171
0
    (void) key;
172
0
    (void) ret;
173
174
0
    PK_VALIDATE_RET(p != NULL);
175
0
    PK_VALIDATE_RET(*p != NULL);
176
0
    PK_VALIDATE_RET(start != NULL);
177
0
    PK_VALIDATE_RET(key != NULL);
178
179
0
#if defined(MBEDTLS_RSA_C)
180
0
    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
181
0
        MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key)));
182
0
    } else
183
0
#endif
184
0
#if defined(MBEDTLS_ECP_C)
185
0
    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
186
0
        MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key)));
187
0
    } else
188
0
#endif
189
#if defined(MBEDTLS_USE_PSA_CRYPTO)
190
    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
191
        size_t buffer_size;
192
        psa_key_id_t *key_id = (psa_key_id_t *) key->pk_ctx;
193
194
        if (*p < start) {
195
            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
196
        }
197
198
        buffer_size = (size_t) (*p - start);
199
        if (psa_export_public_key(*key_id, start, buffer_size, &len)
200
            != PSA_SUCCESS) {
201
            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
202
        } else {
203
            *p -= len;
204
            memmove(*p, start, len);
205
        }
206
    } else
207
#endif /* MBEDTLS_USE_PSA_CRYPTO */
208
0
    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
209
210
0
    return (int) len;
211
0
}
212
213
int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *key, unsigned char *buf, size_t size)
214
0
{
215
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
216
0
    unsigned char *c;
217
0
    size_t len = 0, par_len = 0, oid_len;
218
0
    mbedtls_pk_type_t pk_type;
219
0
    const char *oid;
220
221
0
    PK_VALIDATE_RET(key != NULL);
222
0
    if (size == 0) {
223
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
224
0
    }
225
0
    PK_VALIDATE_RET(buf != NULL);
226
227
0
    c = buf + size;
228
229
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
230
231
0
    if (c - buf < 1) {
232
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
233
0
    }
234
235
    /*
236
     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
237
     *       algorithm            AlgorithmIdentifier,
238
     *       subjectPublicKey     BIT STRING }
239
     */
240
0
    *--c = 0;
241
0
    len += 1;
242
243
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
244
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
245
246
0
    pk_type = mbedtls_pk_get_type(key);
247
0
#if defined(MBEDTLS_ECP_C)
248
0
    if (pk_type == MBEDTLS_PK_ECKEY) {
249
0
        MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key)));
250
0
    }
251
0
#endif
252
#if defined(MBEDTLS_USE_PSA_CRYPTO)
253
    if (pk_type == MBEDTLS_PK_OPAQUE) {
254
        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
255
        psa_key_type_t key_type;
256
        psa_key_id_t key_id;
257
        psa_ecc_family_t curve;
258
        size_t bits;
259
260
        key_id = *((psa_key_id_t *) key->pk_ctx);
261
        if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) {
262
            return MBEDTLS_ERR_PK_HW_ACCEL_FAILED;
263
        }
264
        key_type = psa_get_key_type(&attributes);
265
        bits = psa_get_key_bits(&attributes);
266
        psa_reset_key_attributes(&attributes);
267
268
        curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type);
269
        if (curve == 0) {
270
            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
271
        }
272
273
        ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits, &oid, &oid_len);
274
        if (ret != 0) {
275
            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
276
        }
277
278
        /* Write EC algorithm parameters; that's akin
279
         * to pk_write_ec_param() above. */
280
        MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_oid(&c, buf,
281
                                                             oid, oid_len));
282
283
        /* The rest of the function works as for legacy EC contexts. */
284
        pk_type = MBEDTLS_PK_ECKEY;
285
    }
286
#endif /* MBEDTLS_USE_PSA_CRYPTO */
287
288
0
    if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
289
0
                                             &oid_len)) != 0) {
290
0
        return ret;
291
0
    }
292
293
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len,
294
0
                                                                      par_len));
295
296
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
297
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
298
0
                                                     MBEDTLS_ASN1_SEQUENCE));
299
300
0
    return (int) len;
301
0
}
302
303
int mbedtls_pk_write_key_der(mbedtls_pk_context *key, unsigned char *buf, size_t size)
304
0
{
305
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
306
0
    unsigned char *c;
307
0
    size_t len = 0;
308
309
0
    (void) ret;
310
0
    (void) c;
311
0
    (void) key;
312
313
0
    PK_VALIDATE_RET(key != NULL);
314
0
    if (size == 0) {
315
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
316
0
    }
317
0
    PK_VALIDATE_RET(buf != NULL);
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
/*
477
 * Max sizes of key per types. Shown as tag + len (+ content).
478
 */
479
480
#if defined(MBEDTLS_RSA_C)
481
/*
482
 * RSA public keys:
483
 *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
484
 *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
485
 *                                                + 1 + 1 + 9 (rsa oid)
486
 *                                                + 1 + 1 (params null)
487
 *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
488
 *  RSAPublicKey ::= SEQUENCE {                     1 + 3
489
 *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
490
 *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
491
 *  }
492
 */
493
0
#define RSA_PUB_DER_MAX_BYTES   (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
494
495
/*
496
 * RSA private keys:
497
 *  RSAPrivateKey ::= SEQUENCE {                    1 + 3
498
 *      version           Version,                  1 + 1 + 1
499
 *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1
500
 *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1
501
 *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1
502
 *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
503
 *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
504
 *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
505
 *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
506
 *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
507
 *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
508
 *  }
509
 */
510
0
#define MPI_MAX_SIZE_2          (MBEDTLS_MPI_MAX_SIZE / 2 + \
511
0
                                 MBEDTLS_MPI_MAX_SIZE % 2)
512
0
#define RSA_PRV_DER_MAX_BYTES   (47 + 3 * MBEDTLS_MPI_MAX_SIZE \
513
0
                                 + 5 * MPI_MAX_SIZE_2)
514
515
#else /* MBEDTLS_RSA_C */
516
517
#define RSA_PUB_DER_MAX_BYTES   0
518
#define RSA_PRV_DER_MAX_BYTES   0
519
520
#endif /* MBEDTLS_RSA_C */
521
522
#if defined(MBEDTLS_ECP_C)
523
/*
524
 * EC public keys:
525
 *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
526
 *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)
527
 *                                            + 1 + 1 + 7 (ec oid)
528
 *                                            + 1 + 1 + 9 (namedCurve oid)
529
 *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]
530
 *                                            + 1 (point format)        [1]
531
 *                                            + 2 * ECP_MAX (coords)    [1]
532
 *  }
533
 */
534
0
#define ECP_PUB_DER_MAX_BYTES   (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
535
536
/*
537
 * EC private keys:
538
 * ECPrivateKey ::= SEQUENCE {                  1 + 2
539
 *      version        INTEGER ,                1 + 1 + 1
540
 *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX
541
 *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)
542
 *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
543
 *    }
544
 */
545
0
#define ECP_PRV_DER_MAX_BYTES   (29 + 3 * MBEDTLS_ECP_MAX_BYTES)
546
547
#else /* MBEDTLS_ECP_C */
548
549
#define ECP_PUB_DER_MAX_BYTES   0
550
#define ECP_PRV_DER_MAX_BYTES   0
551
552
#endif /* MBEDTLS_ECP_C */
553
554
0
#define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
555
0
                             RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
556
0
#define PRV_DER_MAX_BYTES   (RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
557
0
                             RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES)
558
559
int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size)
560
0
{
561
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
562
0
    unsigned char *output_buf = NULL;
563
0
    output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);
564
0
    if (output_buf == NULL) {
565
0
        return MBEDTLS_ERR_PK_ALLOC_FAILED;
566
0
    }
567
0
    size_t olen = 0;
568
569
0
    PK_VALIDATE_RET(key != NULL);
570
0
    PK_VALIDATE_RET(buf != NULL || size == 0);
571
572
0
    if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
573
0
                                           PUB_DER_MAX_BYTES)) < 0) {
574
0
        goto cleanup;
575
0
    }
576
577
0
    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
578
0
                                        output_buf + PUB_DER_MAX_BYTES - ret,
579
0
                                        ret, buf, size, &olen)) != 0) {
580
0
        goto cleanup;
581
0
    }
582
583
0
    ret = 0;
584
0
cleanup:
585
0
    mbedtls_free(output_buf);
586
0
    return ret;
587
0
}
588
589
int mbedtls_pk_write_key_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size)
590
0
{
591
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
592
0
    unsigned char *output_buf = NULL;
593
0
    output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);
594
0
    if (output_buf == NULL) {
595
0
        return MBEDTLS_ERR_PK_ALLOC_FAILED;
596
0
    }
597
0
    const char *begin, *end;
598
0
    size_t olen = 0;
599
600
0
    PK_VALIDATE_RET(key != NULL);
601
0
    PK_VALIDATE_RET(buf != NULL || size == 0);
602
603
0
    if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {
604
0
        goto cleanup;
605
0
    }
606
607
0
#if defined(MBEDTLS_RSA_C)
608
0
    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
609
0
        begin = PEM_BEGIN_PRIVATE_KEY_RSA;
610
0
        end = PEM_END_PRIVATE_KEY_RSA;
611
0
    } else
612
0
#endif
613
0
#if defined(MBEDTLS_ECP_C)
614
0
    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
615
0
        begin = PEM_BEGIN_PRIVATE_KEY_EC;
616
0
        end = PEM_END_PRIVATE_KEY_EC;
617
0
    } else
618
0
#endif
619
0
    {
620
0
        ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
621
0
        goto cleanup;
622
0
    }
623
624
0
    if ((ret = mbedtls_pem_write_buffer(begin, end,
625
0
                                        output_buf + PRV_DER_MAX_BYTES - ret,
626
0
                                        ret, buf, size, &olen)) != 0) {
627
0
        goto cleanup;
628
0
    }
629
630
0
    ret = 0;
631
0
cleanup:
632
0
    mbedtls_platform_zeroize(output_buf, PRV_DER_MAX_BYTES);
633
0
    mbedtls_free(output_buf);
634
0
    return ret;
635
0
}
636
#endif /* MBEDTLS_PEM_WRITE_C */
637
638
#endif /* MBEDTLS_PK_WRITE_C */