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