1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  Key writing application
3a8e1175bSopenharmony_ci *
4a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
5a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6a8e1175bSopenharmony_ci */
7a8e1175bSopenharmony_ci
8a8e1175bSopenharmony_ci#include "mbedtls/build_info.h"
9a8e1175bSopenharmony_ci
10a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
11a8e1175bSopenharmony_ci
12a8e1175bSopenharmony_ci#if !defined(MBEDTLS_PK_PARSE_C) || \
13a8e1175bSopenharmony_ci    !defined(MBEDTLS_PK_WRITE_C) || \
14a8e1175bSopenharmony_ci    !defined(MBEDTLS_FS_IO)      || \
15a8e1175bSopenharmony_ci    !defined(MBEDTLS_ENTROPY_C)  || \
16a8e1175bSopenharmony_ci    !defined(MBEDTLS_CTR_DRBG_C) || \
17a8e1175bSopenharmony_ci    !defined(MBEDTLS_BIGNUM_C)
18a8e1175bSopenharmony_ciint main(void)
19a8e1175bSopenharmony_ci{
20a8e1175bSopenharmony_ci    mbedtls_printf("MBEDTLS_PK_PARSE_C and/or MBEDTLS_PK_WRITE_C and/or "
21a8e1175bSopenharmony_ci                   "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
22a8e1175bSopenharmony_ci                   "MBEDTLS_FS_IO and/or MBEDTLS_BIGNUM_C not defined.\n");
23a8e1175bSopenharmony_ci    mbedtls_exit(0);
24a8e1175bSopenharmony_ci}
25a8e1175bSopenharmony_ci#else
26a8e1175bSopenharmony_ci
27a8e1175bSopenharmony_ci#include "mbedtls/error.h"
28a8e1175bSopenharmony_ci#include "mbedtls/pk.h"
29a8e1175bSopenharmony_ci#include "mbedtls/error.h"
30a8e1175bSopenharmony_ci
31a8e1175bSopenharmony_ci#include "mbedtls/entropy.h"
32a8e1175bSopenharmony_ci#include "mbedtls/ctr_drbg.h"
33a8e1175bSopenharmony_ci
34a8e1175bSopenharmony_ci#include <stdio.h>
35a8e1175bSopenharmony_ci#include <string.h>
36a8e1175bSopenharmony_ci
37a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C)
38a8e1175bSopenharmony_ci#define USAGE_OUT \
39a8e1175bSopenharmony_ci    "    output_file=%%s      default: keyfile.pem\n"   \
40a8e1175bSopenharmony_ci    "    output_format=pem|der default: pem\n"
41a8e1175bSopenharmony_ci#else
42a8e1175bSopenharmony_ci#define USAGE_OUT \
43a8e1175bSopenharmony_ci    "    output_file=%%s      default: keyfile.der\n"   \
44a8e1175bSopenharmony_ci    "    output_format=der     default: der\n"
45a8e1175bSopenharmony_ci#endif
46a8e1175bSopenharmony_ci
47a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C)
48a8e1175bSopenharmony_ci#define DFL_OUTPUT_FILENAME     "keyfile.pem"
49a8e1175bSopenharmony_ci#define DFL_OUTPUT_FORMAT       OUTPUT_FORMAT_PEM
50a8e1175bSopenharmony_ci#else
51a8e1175bSopenharmony_ci#define DFL_OUTPUT_FILENAME     "keyfile.der"
52a8e1175bSopenharmony_ci#define DFL_OUTPUT_FORMAT       OUTPUT_FORMAT_DER
53a8e1175bSopenharmony_ci#endif
54a8e1175bSopenharmony_ci
55a8e1175bSopenharmony_ci#define DFL_MODE                MODE_NONE
56a8e1175bSopenharmony_ci#define DFL_FILENAME            "keyfile.key"
57a8e1175bSopenharmony_ci#define DFL_DEBUG_LEVEL         0
58a8e1175bSopenharmony_ci#define DFL_OUTPUT_MODE         OUTPUT_MODE_NONE
59a8e1175bSopenharmony_ci
60a8e1175bSopenharmony_ci#define MODE_NONE               0
61a8e1175bSopenharmony_ci#define MODE_PRIVATE            1
62a8e1175bSopenharmony_ci#define MODE_PUBLIC             2
63a8e1175bSopenharmony_ci
64a8e1175bSopenharmony_ci#define OUTPUT_MODE_NONE               0
65a8e1175bSopenharmony_ci#define OUTPUT_MODE_PRIVATE            1
66a8e1175bSopenharmony_ci#define OUTPUT_MODE_PUBLIC             2
67a8e1175bSopenharmony_ci
68a8e1175bSopenharmony_ci#define OUTPUT_FORMAT_PEM              0
69a8e1175bSopenharmony_ci#define OUTPUT_FORMAT_DER              1
70a8e1175bSopenharmony_ci
71a8e1175bSopenharmony_ci#define USAGE \
72a8e1175bSopenharmony_ci    "\n usage: key_app_writer param=<>...\n"            \
73a8e1175bSopenharmony_ci    "\n acceptable parameters:\n"                       \
74a8e1175bSopenharmony_ci    "    mode=private|public default: none\n"           \
75a8e1175bSopenharmony_ci    "    filename=%%s         default: keyfile.key\n"   \
76a8e1175bSopenharmony_ci    "    output_mode=private|public default: none\n"    \
77a8e1175bSopenharmony_ci    USAGE_OUT                                           \
78a8e1175bSopenharmony_ci    "\n"
79a8e1175bSopenharmony_ci
80a8e1175bSopenharmony_ci
81a8e1175bSopenharmony_ci/*
82a8e1175bSopenharmony_ci * global options
83a8e1175bSopenharmony_ci */
84a8e1175bSopenharmony_cistruct options {
85a8e1175bSopenharmony_ci    int mode;                   /* the mode to run the application in   */
86a8e1175bSopenharmony_ci    const char *filename;       /* filename of the key file             */
87a8e1175bSopenharmony_ci    int output_mode;            /* the output mode to use               */
88a8e1175bSopenharmony_ci    const char *output_file;    /* where to store the constructed key file  */
89a8e1175bSopenharmony_ci    int output_format;          /* the output format to use             */
90a8e1175bSopenharmony_ci} opt;
91a8e1175bSopenharmony_ci
92a8e1175bSopenharmony_cistatic int write_public_key(mbedtls_pk_context *key, const char *output_file)
93a8e1175bSopenharmony_ci{
94a8e1175bSopenharmony_ci    int ret;
95a8e1175bSopenharmony_ci    FILE *f;
96a8e1175bSopenharmony_ci    unsigned char output_buf[16000];
97a8e1175bSopenharmony_ci    unsigned char *c = output_buf;
98a8e1175bSopenharmony_ci    size_t len = 0;
99a8e1175bSopenharmony_ci
100a8e1175bSopenharmony_ci    memset(output_buf, 0, 16000);
101a8e1175bSopenharmony_ci
102a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C)
103a8e1175bSopenharmony_ci    if (opt.output_format == OUTPUT_FORMAT_PEM) {
104a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_write_pubkey_pem(key, output_buf, 16000)) != 0) {
105a8e1175bSopenharmony_ci            return ret;
106a8e1175bSopenharmony_ci        }
107a8e1175bSopenharmony_ci
108a8e1175bSopenharmony_ci        len = strlen((char *) output_buf);
109a8e1175bSopenharmony_ci    } else
110a8e1175bSopenharmony_ci#endif
111a8e1175bSopenharmony_ci    {
112a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, 16000)) < 0) {
113a8e1175bSopenharmony_ci            return ret;
114a8e1175bSopenharmony_ci        }
115a8e1175bSopenharmony_ci
116a8e1175bSopenharmony_ci        len = ret;
117a8e1175bSopenharmony_ci        c = output_buf + sizeof(output_buf) - len;
118a8e1175bSopenharmony_ci    }
119a8e1175bSopenharmony_ci
120a8e1175bSopenharmony_ci    if ((f = fopen(output_file, "w")) == NULL) {
121a8e1175bSopenharmony_ci        return -1;
122a8e1175bSopenharmony_ci    }
123a8e1175bSopenharmony_ci
124a8e1175bSopenharmony_ci    if (fwrite(c, 1, len, f) != len) {
125a8e1175bSopenharmony_ci        fclose(f);
126a8e1175bSopenharmony_ci        return -1;
127a8e1175bSopenharmony_ci    }
128a8e1175bSopenharmony_ci
129a8e1175bSopenharmony_ci    fclose(f);
130a8e1175bSopenharmony_ci
131a8e1175bSopenharmony_ci    return 0;
132a8e1175bSopenharmony_ci}
133a8e1175bSopenharmony_ci
134a8e1175bSopenharmony_cistatic int write_private_key(mbedtls_pk_context *key, const char *output_file)
135a8e1175bSopenharmony_ci{
136a8e1175bSopenharmony_ci    int ret;
137a8e1175bSopenharmony_ci    FILE *f;
138a8e1175bSopenharmony_ci    unsigned char output_buf[16000];
139a8e1175bSopenharmony_ci    unsigned char *c = output_buf;
140a8e1175bSopenharmony_ci    size_t len = 0;
141a8e1175bSopenharmony_ci
142a8e1175bSopenharmony_ci    memset(output_buf, 0, 16000);
143a8e1175bSopenharmony_ci
144a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C)
145a8e1175bSopenharmony_ci    if (opt.output_format == OUTPUT_FORMAT_PEM) {
146a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_write_key_pem(key, output_buf, 16000)) != 0) {
147a8e1175bSopenharmony_ci            return ret;
148a8e1175bSopenharmony_ci        }
149a8e1175bSopenharmony_ci
150a8e1175bSopenharmony_ci        len = strlen((char *) output_buf);
151a8e1175bSopenharmony_ci    } else
152a8e1175bSopenharmony_ci#endif
153a8e1175bSopenharmony_ci    {
154a8e1175bSopenharmony_ci        if ((ret = mbedtls_pk_write_key_der(key, output_buf, 16000)) < 0) {
155a8e1175bSopenharmony_ci            return ret;
156a8e1175bSopenharmony_ci        }
157a8e1175bSopenharmony_ci
158a8e1175bSopenharmony_ci        len = ret;
159a8e1175bSopenharmony_ci        c = output_buf + sizeof(output_buf) - len;
160a8e1175bSopenharmony_ci    }
161a8e1175bSopenharmony_ci
162a8e1175bSopenharmony_ci    if ((f = fopen(output_file, "w")) == NULL) {
163a8e1175bSopenharmony_ci        return -1;
164a8e1175bSopenharmony_ci    }
165a8e1175bSopenharmony_ci
166a8e1175bSopenharmony_ci    if (fwrite(c, 1, len, f) != len) {
167a8e1175bSopenharmony_ci        fclose(f);
168a8e1175bSopenharmony_ci        return -1;
169a8e1175bSopenharmony_ci    }
170a8e1175bSopenharmony_ci
171a8e1175bSopenharmony_ci    fclose(f);
172a8e1175bSopenharmony_ci
173a8e1175bSopenharmony_ci    return 0;
174a8e1175bSopenharmony_ci}
175a8e1175bSopenharmony_ci
176a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_C)
177a8e1175bSopenharmony_cistatic int show_ecp_key(const mbedtls_ecp_keypair *ecp, int has_private)
178a8e1175bSopenharmony_ci{
179a8e1175bSopenharmony_ci    int ret = 0;
180a8e1175bSopenharmony_ci
181a8e1175bSopenharmony_ci    const mbedtls_ecp_curve_info *curve_info =
182a8e1175bSopenharmony_ci        mbedtls_ecp_curve_info_from_grp_id(
183a8e1175bSopenharmony_ci            mbedtls_ecp_keypair_get_group_id(ecp));
184a8e1175bSopenharmony_ci    mbedtls_printf("curve: %s\n", curve_info->name);
185a8e1175bSopenharmony_ci
186a8e1175bSopenharmony_ci    mbedtls_ecp_group grp;
187a8e1175bSopenharmony_ci    mbedtls_ecp_group_init(&grp);
188a8e1175bSopenharmony_ci    mbedtls_mpi D;
189a8e1175bSopenharmony_ci    mbedtls_mpi_init(&D);
190a8e1175bSopenharmony_ci    mbedtls_ecp_point pt;
191a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&pt);
192a8e1175bSopenharmony_ci    mbedtls_mpi X, Y;
193a8e1175bSopenharmony_ci    mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y);
194a8e1175bSopenharmony_ci
195a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_export(ecp, &grp,
196a8e1175bSopenharmony_ci                                       (has_private ? &D : NULL),
197a8e1175bSopenharmony_ci                                       &pt));
198a8e1175bSopenharmony_ci
199a8e1175bSopenharmony_ci    unsigned char point_bin[MBEDTLS_ECP_MAX_PT_LEN];
200a8e1175bSopenharmony_ci    size_t len = 0;
201a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_point_write_binary(
202a8e1175bSopenharmony_ci                        &grp, &pt, MBEDTLS_ECP_PF_UNCOMPRESSED,
203a8e1175bSopenharmony_ci                        &len, point_bin, sizeof(point_bin)));
204a8e1175bSopenharmony_ci    switch (mbedtls_ecp_get_type(&grp)) {
205a8e1175bSopenharmony_ci        case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS:
206a8e1175bSopenharmony_ci            if ((len & 1) == 0 || point_bin[0] != 0x04) {
207a8e1175bSopenharmony_ci                /* Point in an unxepected format. This shouldn't happen. */
208a8e1175bSopenharmony_ci                ret = -1;
209a8e1175bSopenharmony_ci                goto cleanup;
210a8e1175bSopenharmony_ci            }
211a8e1175bSopenharmony_ci            MBEDTLS_MPI_CHK(
212a8e1175bSopenharmony_ci                mbedtls_mpi_read_binary(&X, point_bin + 1, len / 2));
213a8e1175bSopenharmony_ci            MBEDTLS_MPI_CHK(
214a8e1175bSopenharmony_ci                mbedtls_mpi_read_binary(&Y, point_bin + 1 + len / 2, len / 2));
215a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("X_Q:   ", &X, 16, NULL);
216a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("Y_Q:   ", &Y, 16, NULL);
217a8e1175bSopenharmony_ci            break;
218a8e1175bSopenharmony_ci        case MBEDTLS_ECP_TYPE_MONTGOMERY:
219a8e1175bSopenharmony_ci            MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, point_bin, len));
220a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("X_Q:   ", &X, 16, NULL);
221a8e1175bSopenharmony_ci            break;
222a8e1175bSopenharmony_ci        default:
223a8e1175bSopenharmony_ci            mbedtls_printf(
224a8e1175bSopenharmony_ci                "This program does not yet support listing coordinates for this curve type.\n");
225a8e1175bSopenharmony_ci            break;
226a8e1175bSopenharmony_ci    }
227a8e1175bSopenharmony_ci
228a8e1175bSopenharmony_ci    if (has_private) {
229a8e1175bSopenharmony_ci        mbedtls_mpi_write_file("D:     ", &D, 16, NULL);
230a8e1175bSopenharmony_ci    }
231a8e1175bSopenharmony_ci
232a8e1175bSopenharmony_cicleanup:
233a8e1175bSopenharmony_ci    mbedtls_ecp_group_free(&grp);
234a8e1175bSopenharmony_ci    mbedtls_mpi_free(&D);
235a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&pt);
236a8e1175bSopenharmony_ci    mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y);
237a8e1175bSopenharmony_ci    return ret;
238a8e1175bSopenharmony_ci}
239a8e1175bSopenharmony_ci#endif
240a8e1175bSopenharmony_ci
241a8e1175bSopenharmony_ciint main(int argc, char *argv[])
242a8e1175bSopenharmony_ci{
243a8e1175bSopenharmony_ci    int ret = 1;
244a8e1175bSopenharmony_ci    int exit_code = MBEDTLS_EXIT_FAILURE;
245a8e1175bSopenharmony_ci#if defined(MBEDTLS_ERROR_C)
246a8e1175bSopenharmony_ci    char buf[200];
247a8e1175bSopenharmony_ci#endif
248a8e1175bSopenharmony_ci    int i;
249a8e1175bSopenharmony_ci    char *p, *q;
250a8e1175bSopenharmony_ci
251a8e1175bSopenharmony_ci    const char *pers = "pkey/key_app";
252a8e1175bSopenharmony_ci    mbedtls_entropy_context entropy;
253a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_context ctr_drbg;
254a8e1175bSopenharmony_ci
255a8e1175bSopenharmony_ci    mbedtls_pk_context key;
256a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
257a8e1175bSopenharmony_ci    mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
258a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
259a8e1175bSopenharmony_ci
260a8e1175bSopenharmony_ci    /*
261a8e1175bSopenharmony_ci     * Set to sane values
262a8e1175bSopenharmony_ci     */
263a8e1175bSopenharmony_ci    mbedtls_entropy_init(&entropy);
264a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_init(&ctr_drbg);
265a8e1175bSopenharmony_ci
266a8e1175bSopenharmony_ci    mbedtls_pk_init(&key);
267a8e1175bSopenharmony_ci#if defined(MBEDTLS_ERROR_C)
268a8e1175bSopenharmony_ci    memset(buf, 0, sizeof(buf));
269a8e1175bSopenharmony_ci#endif
270a8e1175bSopenharmony_ci
271a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
272a8e1175bSopenharmony_ci    psa_status_t status = psa_crypto_init();
273a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
274a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
275a8e1175bSopenharmony_ci                        (int) status);
276a8e1175bSopenharmony_ci        goto exit;
277a8e1175bSopenharmony_ci    }
278a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
279a8e1175bSopenharmony_ci
280a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
281a8e1175bSopenharmony_ci    mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
282a8e1175bSopenharmony_ci    mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP);
283a8e1175bSopenharmony_ci    mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP);
284a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
285a8e1175bSopenharmony_ci
286a8e1175bSopenharmony_ci    if (argc < 2) {
287a8e1175bSopenharmony_ciusage:
288a8e1175bSopenharmony_ci        mbedtls_printf(USAGE);
289a8e1175bSopenharmony_ci        goto exit;
290a8e1175bSopenharmony_ci    }
291a8e1175bSopenharmony_ci
292a8e1175bSopenharmony_ci    opt.mode                = DFL_MODE;
293a8e1175bSopenharmony_ci    opt.filename            = DFL_FILENAME;
294a8e1175bSopenharmony_ci    opt.output_mode         = DFL_OUTPUT_MODE;
295a8e1175bSopenharmony_ci    opt.output_file         = DFL_OUTPUT_FILENAME;
296a8e1175bSopenharmony_ci    opt.output_format       = DFL_OUTPUT_FORMAT;
297a8e1175bSopenharmony_ci
298a8e1175bSopenharmony_ci    for (i = 1; i < argc; i++) {
299a8e1175bSopenharmony_ci        p = argv[i];
300a8e1175bSopenharmony_ci        if ((q = strchr(p, '=')) == NULL) {
301a8e1175bSopenharmony_ci            goto usage;
302a8e1175bSopenharmony_ci        }
303a8e1175bSopenharmony_ci        *q++ = '\0';
304a8e1175bSopenharmony_ci
305a8e1175bSopenharmony_ci        if (strcmp(p, "mode") == 0) {
306a8e1175bSopenharmony_ci            if (strcmp(q, "private") == 0) {
307a8e1175bSopenharmony_ci                opt.mode = MODE_PRIVATE;
308a8e1175bSopenharmony_ci            } else if (strcmp(q, "public") == 0) {
309a8e1175bSopenharmony_ci                opt.mode = MODE_PUBLIC;
310a8e1175bSopenharmony_ci            } else {
311a8e1175bSopenharmony_ci                goto usage;
312a8e1175bSopenharmony_ci            }
313a8e1175bSopenharmony_ci        } else if (strcmp(p, "output_mode") == 0) {
314a8e1175bSopenharmony_ci            if (strcmp(q, "private") == 0) {
315a8e1175bSopenharmony_ci                opt.output_mode = OUTPUT_MODE_PRIVATE;
316a8e1175bSopenharmony_ci            } else if (strcmp(q, "public") == 0) {
317a8e1175bSopenharmony_ci                opt.output_mode = OUTPUT_MODE_PUBLIC;
318a8e1175bSopenharmony_ci            } else {
319a8e1175bSopenharmony_ci                goto usage;
320a8e1175bSopenharmony_ci            }
321a8e1175bSopenharmony_ci        } else if (strcmp(p, "output_format") == 0) {
322a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C)
323a8e1175bSopenharmony_ci            if (strcmp(q, "pem") == 0) {
324a8e1175bSopenharmony_ci                opt.output_format = OUTPUT_FORMAT_PEM;
325a8e1175bSopenharmony_ci            } else
326a8e1175bSopenharmony_ci#endif
327a8e1175bSopenharmony_ci            if (strcmp(q, "der") == 0) {
328a8e1175bSopenharmony_ci                opt.output_format = OUTPUT_FORMAT_DER;
329a8e1175bSopenharmony_ci            } else {
330a8e1175bSopenharmony_ci                goto usage;
331a8e1175bSopenharmony_ci            }
332a8e1175bSopenharmony_ci        } else if (strcmp(p, "filename") == 0) {
333a8e1175bSopenharmony_ci            opt.filename = q;
334a8e1175bSopenharmony_ci        } else if (strcmp(p, "output_file") == 0) {
335a8e1175bSopenharmony_ci            opt.output_file = q;
336a8e1175bSopenharmony_ci        } else {
337a8e1175bSopenharmony_ci            goto usage;
338a8e1175bSopenharmony_ci        }
339a8e1175bSopenharmony_ci    }
340a8e1175bSopenharmony_ci
341a8e1175bSopenharmony_ci    if (opt.mode == MODE_NONE && opt.output_mode != OUTPUT_MODE_NONE) {
342a8e1175bSopenharmony_ci        mbedtls_printf("\nCannot output a key without reading one.\n");
343a8e1175bSopenharmony_ci        goto exit;
344a8e1175bSopenharmony_ci    }
345a8e1175bSopenharmony_ci
346a8e1175bSopenharmony_ci    if (opt.mode == MODE_PUBLIC && opt.output_mode == OUTPUT_MODE_PRIVATE) {
347a8e1175bSopenharmony_ci        mbedtls_printf("\nCannot output a private key from a public key.\n");
348a8e1175bSopenharmony_ci        goto exit;
349a8e1175bSopenharmony_ci    }
350a8e1175bSopenharmony_ci
351a8e1175bSopenharmony_ci    if (opt.mode == MODE_PRIVATE) {
352a8e1175bSopenharmony_ci        /*
353a8e1175bSopenharmony_ci         * 1.1. Load the key
354a8e1175bSopenharmony_ci         */
355a8e1175bSopenharmony_ci        mbedtls_printf("\n  . Loading the private key ...");
356a8e1175bSopenharmony_ci        fflush(stdout);
357a8e1175bSopenharmony_ci
358a8e1175bSopenharmony_ci        if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
359a8e1175bSopenharmony_ci                                         (const unsigned char *) pers,
360a8e1175bSopenharmony_ci                                         strlen(pers))) != 0) {
361a8e1175bSopenharmony_ci            mbedtls_printf(" failed\n  !  mbedtls_ctr_drbg_seed returned -0x%04x\n",
362a8e1175bSopenharmony_ci                           (unsigned int) -ret);
363a8e1175bSopenharmony_ci            goto exit;
364a8e1175bSopenharmony_ci        }
365a8e1175bSopenharmony_ci
366a8e1175bSopenharmony_ci        ret = mbedtls_pk_parse_keyfile(&key, opt.filename, NULL,
367a8e1175bSopenharmony_ci                                       mbedtls_ctr_drbg_random, &ctr_drbg);
368a8e1175bSopenharmony_ci        if (ret != 0) {
369a8e1175bSopenharmony_ci            mbedtls_printf(" failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x",
370a8e1175bSopenharmony_ci                           (unsigned int) -ret);
371a8e1175bSopenharmony_ci            goto exit;
372a8e1175bSopenharmony_ci        }
373a8e1175bSopenharmony_ci
374a8e1175bSopenharmony_ci        mbedtls_printf(" ok\n");
375a8e1175bSopenharmony_ci
376a8e1175bSopenharmony_ci        /*
377a8e1175bSopenharmony_ci         * 1.2 Print the key
378a8e1175bSopenharmony_ci         */
379a8e1175bSopenharmony_ci        mbedtls_printf("  . Key information    ...\n");
380a8e1175bSopenharmony_ci
381a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
382a8e1175bSopenharmony_ci        if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_RSA) {
383a8e1175bSopenharmony_ci            mbedtls_rsa_context *rsa = mbedtls_pk_rsa(key);
384a8e1175bSopenharmony_ci
385a8e1175bSopenharmony_ci            if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 ||
386a8e1175bSopenharmony_ci                (ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP))      != 0) {
387a8e1175bSopenharmony_ci                mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
388a8e1175bSopenharmony_ci                goto exit;
389a8e1175bSopenharmony_ci            }
390a8e1175bSopenharmony_ci
391a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("N:  ",  &N,  16, NULL);
392a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("E:  ",  &E,  16, NULL);
393a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("D:  ",  &D,  16, NULL);
394a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("P:  ",  &P,  16, NULL);
395a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("Q:  ",  &Q,  16, NULL);
396a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("DP: ",  &DP, 16, NULL);
397a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("DQ:  ", &DQ, 16, NULL);
398a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("QP:  ", &QP, 16, NULL);
399a8e1175bSopenharmony_ci        } else
400a8e1175bSopenharmony_ci#endif
401a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_C)
402a8e1175bSopenharmony_ci        if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_ECKEY) {
403a8e1175bSopenharmony_ci            if (show_ecp_key(mbedtls_pk_ec(key), 1) != 0) {
404a8e1175bSopenharmony_ci                mbedtls_printf(" failed\n  ! could not export ECC parameters\n\n");
405a8e1175bSopenharmony_ci                goto exit;
406a8e1175bSopenharmony_ci            }
407a8e1175bSopenharmony_ci        } else
408a8e1175bSopenharmony_ci#endif
409a8e1175bSopenharmony_ci        mbedtls_printf("key type not supported yet\n");
410a8e1175bSopenharmony_ci
411a8e1175bSopenharmony_ci    } else if (opt.mode == MODE_PUBLIC) {
412a8e1175bSopenharmony_ci        /*
413a8e1175bSopenharmony_ci         * 1.1. Load the key
414a8e1175bSopenharmony_ci         */
415a8e1175bSopenharmony_ci        mbedtls_printf("\n  . Loading the public key ...");
416a8e1175bSopenharmony_ci        fflush(stdout);
417a8e1175bSopenharmony_ci
418a8e1175bSopenharmony_ci        ret = mbedtls_pk_parse_public_keyfile(&key, opt.filename);
419a8e1175bSopenharmony_ci
420a8e1175bSopenharmony_ci        if (ret != 0) {
421a8e1175bSopenharmony_ci            mbedtls_printf(" failed\n  !  mbedtls_pk_parse_public_key returned -0x%04x",
422a8e1175bSopenharmony_ci                           (unsigned int) -ret);
423a8e1175bSopenharmony_ci            goto exit;
424a8e1175bSopenharmony_ci        }
425a8e1175bSopenharmony_ci
426a8e1175bSopenharmony_ci        mbedtls_printf(" ok\n");
427a8e1175bSopenharmony_ci
428a8e1175bSopenharmony_ci        /*
429a8e1175bSopenharmony_ci         * 1.2 Print the key
430a8e1175bSopenharmony_ci         */
431a8e1175bSopenharmony_ci        mbedtls_printf("  . Key information    ...\n");
432a8e1175bSopenharmony_ci
433a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
434a8e1175bSopenharmony_ci        if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_RSA) {
435a8e1175bSopenharmony_ci            mbedtls_rsa_context *rsa = mbedtls_pk_rsa(key);
436a8e1175bSopenharmony_ci
437a8e1175bSopenharmony_ci            if ((ret = mbedtls_rsa_export(rsa, &N, NULL, NULL,
438a8e1175bSopenharmony_ci                                          NULL, &E)) != 0) {
439a8e1175bSopenharmony_ci                mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
440a8e1175bSopenharmony_ci                goto exit;
441a8e1175bSopenharmony_ci            }
442a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("N: ", &N, 16, NULL);
443a8e1175bSopenharmony_ci            mbedtls_mpi_write_file("E: ", &E, 16, NULL);
444a8e1175bSopenharmony_ci        } else
445a8e1175bSopenharmony_ci#endif
446a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_C)
447a8e1175bSopenharmony_ci        if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_ECKEY) {
448a8e1175bSopenharmony_ci            if (show_ecp_key(mbedtls_pk_ec(key), 0) != 0) {
449a8e1175bSopenharmony_ci                mbedtls_printf(" failed\n  ! could not export ECC parameters\n\n");
450a8e1175bSopenharmony_ci                goto exit;
451a8e1175bSopenharmony_ci            }
452a8e1175bSopenharmony_ci        } else
453a8e1175bSopenharmony_ci#endif
454a8e1175bSopenharmony_ci        mbedtls_printf("key type not supported yet\n");
455a8e1175bSopenharmony_ci    } else {
456a8e1175bSopenharmony_ci        goto usage;
457a8e1175bSopenharmony_ci    }
458a8e1175bSopenharmony_ci
459a8e1175bSopenharmony_ci    if (opt.output_mode == OUTPUT_MODE_PUBLIC) {
460a8e1175bSopenharmony_ci        write_public_key(&key, opt.output_file);
461a8e1175bSopenharmony_ci    }
462a8e1175bSopenharmony_ci    if (opt.output_mode == OUTPUT_MODE_PRIVATE) {
463a8e1175bSopenharmony_ci        write_private_key(&key, opt.output_file);
464a8e1175bSopenharmony_ci    }
465a8e1175bSopenharmony_ci
466a8e1175bSopenharmony_ci    exit_code = MBEDTLS_EXIT_SUCCESS;
467a8e1175bSopenharmony_ci
468a8e1175bSopenharmony_ciexit:
469a8e1175bSopenharmony_ci
470a8e1175bSopenharmony_ci    if (exit_code != MBEDTLS_EXIT_SUCCESS) {
471a8e1175bSopenharmony_ci#ifdef MBEDTLS_ERROR_C
472a8e1175bSopenharmony_ci        mbedtls_strerror(ret, buf, sizeof(buf));
473a8e1175bSopenharmony_ci        mbedtls_printf(" - %s\n", buf);
474a8e1175bSopenharmony_ci#else
475a8e1175bSopenharmony_ci        mbedtls_printf("\n");
476a8e1175bSopenharmony_ci#endif
477a8e1175bSopenharmony_ci    }
478a8e1175bSopenharmony_ci
479a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C)
480a8e1175bSopenharmony_ci    mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
481a8e1175bSopenharmony_ci    mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP);
482a8e1175bSopenharmony_ci    mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP);
483a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */
484a8e1175bSopenharmony_ci
485a8e1175bSopenharmony_ci    mbedtls_pk_free(&key);
486a8e1175bSopenharmony_ci
487a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_free(&ctr_drbg);
488a8e1175bSopenharmony_ci    mbedtls_entropy_free(&entropy);
489a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
490a8e1175bSopenharmony_ci    mbedtls_psa_crypto_free();
491a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
492a8e1175bSopenharmony_ci
493a8e1175bSopenharmony_ci    mbedtls_exit(exit_code);
494a8e1175bSopenharmony_ci}
495a8e1175bSopenharmony_ci#endif /* program viability conditions */
496