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