1 /*
2  *  Key reading application
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  */
7 
8 #include "mbedtls/build_info.h"
9 
10 #include "mbedtls/platform.h"
11 
12 #if defined(MBEDTLS_BIGNUM_C) && \
13     defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \
14     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
15 #include "mbedtls/error.h"
16 #include "mbedtls/rsa.h"
17 #include "mbedtls/pk.h"
18 #include "mbedtls/entropy.h"
19 #include "mbedtls/ctr_drbg.h"
20 
21 #include <string.h>
22 #endif
23 
24 #define MODE_NONE               0
25 #define MODE_PRIVATE            1
26 #define MODE_PUBLIC             2
27 
28 #define DFL_MODE                MODE_NONE
29 #define DFL_FILENAME            "keyfile.key"
30 #define DFL_PASSWORD            ""
31 #define DFL_PASSWORD_FILE       ""
32 #define DFL_DEBUG_LEVEL         0
33 
34 #define USAGE \
35     "\n usage: key_app param=<>...\n"                   \
36     "\n acceptable parameters:\n"                       \
37     "    mode=private|public default: none\n"           \
38     "    filename=%%s         default: keyfile.key\n"   \
39     "    password=%%s         default: \"\"\n"          \
40     "    password_file=%%s    default: \"\"\n"          \
41     "\n"
42 
43 #if !defined(MBEDTLS_BIGNUM_C) ||                                  \
44     !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
45     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
main(void)46 int main(void)
47 {
48     mbedtls_printf("MBEDTLS_BIGNUM_C and/or "
49                    "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or "
50                    "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C not defined.\n");
51     mbedtls_exit(0);
52 }
53 #else
54 
55 
56 #if defined(MBEDTLS_ECP_C)
show_ecp_key(const mbedtls_ecp_keypair *ecp, int has_private)57 static int show_ecp_key(const mbedtls_ecp_keypair *ecp, int has_private)
58 {
59     int ret = 0;
60 
61     const mbedtls_ecp_curve_info *curve_info =
62         mbedtls_ecp_curve_info_from_grp_id(
63             mbedtls_ecp_keypair_get_group_id(ecp));
64     mbedtls_printf("curve: %s\n", curve_info->name);
65 
66     mbedtls_ecp_group grp;
67     mbedtls_ecp_group_init(&grp);
68     mbedtls_mpi D;
69     mbedtls_mpi_init(&D);
70     mbedtls_ecp_point pt;
71     mbedtls_ecp_point_init(&pt);
72     mbedtls_mpi X, Y;
73     mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y);
74 
75     MBEDTLS_MPI_CHK(mbedtls_ecp_export(ecp, &grp,
76                                        (has_private ? &D : NULL),
77                                        &pt));
78 
79     unsigned char point_bin[MBEDTLS_ECP_MAX_PT_LEN];
80     size_t len = 0;
81     MBEDTLS_MPI_CHK(mbedtls_ecp_point_write_binary(
82                         &grp, &pt, MBEDTLS_ECP_PF_UNCOMPRESSED,
83                         &len, point_bin, sizeof(point_bin)));
84     switch (mbedtls_ecp_get_type(&grp)) {
85         case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS:
86             if ((len & 1) == 0 || point_bin[0] != 0x04) {
87                 /* Point in an unxepected format. This shouldn't happen. */
88                 ret = -1;
89                 goto cleanup;
90             }
91             MBEDTLS_MPI_CHK(
92                 mbedtls_mpi_read_binary(&X, point_bin + 1, len / 2));
93             MBEDTLS_MPI_CHK(
94                 mbedtls_mpi_read_binary(&Y, point_bin + 1 + len / 2, len / 2));
95             mbedtls_mpi_write_file("X_Q:   ", &X, 16, NULL);
96             mbedtls_mpi_write_file("Y_Q:   ", &Y, 16, NULL);
97             break;
98         case MBEDTLS_ECP_TYPE_MONTGOMERY:
99             MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, point_bin, len));
100             mbedtls_mpi_write_file("X_Q:   ", &X, 16, NULL);
101             break;
102         default:
103             mbedtls_printf(
104                 "This program does not yet support listing coordinates for this curve type.\n");
105             break;
106     }
107 
108     if (has_private) {
109         mbedtls_mpi_write_file("D:     ", &D, 16, NULL);
110     }
111 
112 cleanup:
113     mbedtls_ecp_group_free(&grp);
114     mbedtls_mpi_free(&D);
115     mbedtls_ecp_point_free(&pt);
116     mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y);
117     return ret;
118 }
119 #endif
120 
121 /*
122  * global options
123  */
124 struct options {
125     int mode;                   /* the mode to run the application in   */
126     const char *filename;       /* filename of the key file             */
127     const char *password;       /* password for the private key         */
128     const char *password_file;  /* password_file for the private key    */
129 } opt;
130 
main(int argc, char *argv[])131 int main(int argc, char *argv[])
132 {
133     int ret = 1;
134     int exit_code = MBEDTLS_EXIT_FAILURE;
135     char buf[1024];
136     int i;
137     char *p, *q;
138 
139     const char *pers = "pkey/key_app";
140     mbedtls_entropy_context entropy;
141     mbedtls_ctr_drbg_context ctr_drbg;
142 
143     mbedtls_pk_context pk;
144     mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
145 
146     /*
147      * Set to sane values
148      */
149     mbedtls_entropy_init(&entropy);
150     mbedtls_ctr_drbg_init(&ctr_drbg);
151 
152     mbedtls_pk_init(&pk);
153     memset(buf, 0, sizeof(buf));
154 
155 #if defined(MBEDTLS_USE_PSA_CRYPTO)
156     psa_status_t status = psa_crypto_init();
157     if (status != PSA_SUCCESS) {
158         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
159                         (int) status);
160         goto cleanup;
161     }
162 #endif /* MBEDTLS_USE_PSA_CRYPTO */
163 
164     mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
165     mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP);
166     mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP);
167 
168     if (argc < 2) {
169 usage:
170         mbedtls_printf(USAGE);
171         goto cleanup;
172     }
173 
174     opt.mode                = DFL_MODE;
175     opt.filename            = DFL_FILENAME;
176     opt.password            = DFL_PASSWORD;
177     opt.password_file       = DFL_PASSWORD_FILE;
178 
179     for (i = 1; i < argc; i++) {
180         p = argv[i];
181         if ((q = strchr(p, '=')) == NULL) {
182             goto usage;
183         }
184         *q++ = '\0';
185 
186         if (strcmp(p, "mode") == 0) {
187             if (strcmp(q, "private") == 0) {
188                 opt.mode = MODE_PRIVATE;
189             } else if (strcmp(q, "public") == 0) {
190                 opt.mode = MODE_PUBLIC;
191             } else {
192                 goto usage;
193             }
194         } else if (strcmp(p, "filename") == 0) {
195             opt.filename = q;
196         } else if (strcmp(p, "password") == 0) {
197             opt.password = q;
198         } else if (strcmp(p, "password_file") == 0) {
199             opt.password_file = q;
200         } else {
201             goto usage;
202         }
203     }
204 
205     if (opt.mode == MODE_PRIVATE) {
206         if (strlen(opt.password) && strlen(opt.password_file)) {
207             mbedtls_printf("Error: cannot have both password and password_file\n");
208             goto usage;
209         }
210 
211         if (strlen(opt.password_file)) {
212             FILE *f;
213 
214             mbedtls_printf("\n  . Loading the password file ...");
215             if ((f = fopen(opt.password_file, "rb")) == NULL) {
216                 mbedtls_printf(" failed\n  !  fopen returned NULL\n");
217                 goto cleanup;
218             }
219             if (fgets(buf, sizeof(buf), f) == NULL) {
220                 fclose(f);
221                 mbedtls_printf("Error: fgets() failed to retrieve password\n");
222                 goto cleanup;
223             }
224             fclose(f);
225 
226             i = (int) strlen(buf);
227             if (buf[i - 1] == '\n') {
228                 buf[i - 1] = '\0';
229             }
230             if (buf[i - 2] == '\r') {
231                 buf[i - 2] = '\0';
232             }
233             opt.password = buf;
234         }
235 
236         /*
237          * 1.1. Load the key
238          */
239         mbedtls_printf("\n  . Loading the private key ...");
240         fflush(stdout);
241 
242         if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
243                                          (const unsigned char *) pers,
244                                          strlen(pers))) != 0) {
245             mbedtls_printf(" failed\n  !  mbedtls_ctr_drbg_seed returned -0x%04x\n",
246                            (unsigned int) -ret);
247             goto cleanup;
248         }
249 
250         ret = mbedtls_pk_parse_keyfile(&pk, opt.filename, opt.password,
251                                        mbedtls_ctr_drbg_random, &ctr_drbg);
252 
253         if (ret != 0) {
254             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x\n",
255                            (unsigned int) -ret);
256             goto cleanup;
257         }
258 
259         mbedtls_printf(" ok\n");
260 
261         /*
262          * 1.2 Print the key
263          */
264         mbedtls_printf("  . Key information    ...\n");
265 #if defined(MBEDTLS_RSA_C)
266         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) {
267             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
268 
269             if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 ||
270                 (ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP))      != 0) {
271                 mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
272                 goto cleanup;
273             }
274 
275             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("N:  ", &N, 16, NULL));
276             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("E:  ", &E, 16, NULL));
277             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("D:  ", &D, 16, NULL));
278             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("P:  ", &P, 16, NULL));
279             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q:  ", &Q, 16, NULL));
280             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("DP: ", &DP, 16, NULL));
281             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("DQ:  ", &DQ, 16, NULL));
282             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("QP:  ", &QP, 16, NULL));
283         } else
284 #endif
285 #if defined(MBEDTLS_ECP_C)
286         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY) {
287             if (show_ecp_key(mbedtls_pk_ec(pk), 1) != 0) {
288                 mbedtls_printf(" failed\n  ! could not export ECC parameters\n\n");
289                 goto cleanup;
290             }
291         } else
292 #endif
293         {
294             mbedtls_printf("Do not know how to print key information for this type\n");
295             goto cleanup;
296         }
297     } else if (opt.mode == MODE_PUBLIC) {
298         /*
299          * 1.1. Load the key
300          */
301         mbedtls_printf("\n  . Loading the public key ...");
302         fflush(stdout);
303 
304         ret = mbedtls_pk_parse_public_keyfile(&pk, opt.filename);
305 
306         if (ret != 0) {
307             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_public_keyfile returned -0x%04x\n",
308                            (unsigned int) -ret);
309             goto cleanup;
310         }
311 
312         mbedtls_printf(" ok\n");
313 
314         mbedtls_printf("  . Key information    ...\n");
315 #if defined(MBEDTLS_RSA_C)
316         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) {
317             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
318 
319             if ((ret = mbedtls_rsa_export(rsa, &N, NULL, NULL,
320                                           NULL, &E)) != 0) {
321                 mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
322                 goto cleanup;
323             }
324             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("N:  ", &N, 16, NULL));
325             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("E:  ", &E, 16, NULL));
326         } else
327 #endif
328 #if defined(MBEDTLS_ECP_C)
329         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY) {
330             if (show_ecp_key(mbedtls_pk_ec(pk), 0) != 0) {
331                 mbedtls_printf(" failed\n  ! could not export ECC parameters\n\n");
332                 goto cleanup;
333             }
334         } else
335 #endif
336         {
337             mbedtls_printf("Do not know how to print key information for this type\n");
338             goto cleanup;
339         }
340     } else {
341         goto usage;
342     }
343 
344     exit_code = MBEDTLS_EXIT_SUCCESS;
345 
346 cleanup:
347 
348 #if defined(MBEDTLS_ERROR_C)
349     if (exit_code != MBEDTLS_EXIT_SUCCESS) {
350         mbedtls_strerror(ret, buf, sizeof(buf));
351         mbedtls_printf("  !  Last error was: %s\n", buf);
352     }
353 #endif
354 
355     mbedtls_ctr_drbg_free(&ctr_drbg);
356     mbedtls_entropy_free(&entropy);
357     mbedtls_pk_free(&pk);
358 #if defined(MBEDTLS_USE_PSA_CRYPTO)
359     mbedtls_psa_crypto_free();
360 #endif /* MBEDTLS_USE_PSA_CRYPTO */
361     mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
362     mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP);
363     mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP);
364 
365     mbedtls_exit(exit_code);
366 }
367 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
368           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
369