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 /*
57  * global options
58  */
59 struct options {
60     int mode;                   /* the mode to run the application in   */
61     const char *filename;       /* filename of the key file             */
62     const char *password;       /* password for the private key         */
63     const char *password_file;  /* password_file for the private key    */
64 } opt;
65 
main(int argc,char * argv[])66 int main(int argc, char *argv[])
67 {
68     int ret = 1;
69     int exit_code = MBEDTLS_EXIT_FAILURE;
70     char buf[1024];
71     int i;
72     char *p, *q;
73 
74     const char *pers = "pkey/key_app";
75     mbedtls_entropy_context entropy;
76     mbedtls_ctr_drbg_context ctr_drbg;
77 
78     mbedtls_pk_context pk;
79     mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
80 
81     /*
82      * Set to sane values
83      */
84     mbedtls_entropy_init(&entropy);
85     mbedtls_ctr_drbg_init(&ctr_drbg);
86 
87     mbedtls_pk_init(&pk);
88     memset(buf, 0, sizeof(buf));
89 
90 #if defined(MBEDTLS_USE_PSA_CRYPTO)
91     psa_status_t status = psa_crypto_init();
92     if (status != PSA_SUCCESS) {
93         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
94                         (int) status);
95         goto cleanup;
96     }
97 #endif /* MBEDTLS_USE_PSA_CRYPTO */
98 
99     mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
100     mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP);
101     mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP);
102 
103     if (argc < 2) {
104 usage:
105         mbedtls_printf(USAGE);
106         goto cleanup;
107     }
108 
109     opt.mode                = DFL_MODE;
110     opt.filename            = DFL_FILENAME;
111     opt.password            = DFL_PASSWORD;
112     opt.password_file       = DFL_PASSWORD_FILE;
113 
114     for (i = 1; i < argc; i++) {
115         p = argv[i];
116         if ((q = strchr(p, '=')) == NULL) {
117             goto usage;
118         }
119         *q++ = '\0';
120 
121         if (strcmp(p, "mode") == 0) {
122             if (strcmp(q, "private") == 0) {
123                 opt.mode = MODE_PRIVATE;
124             } else if (strcmp(q, "public") == 0) {
125                 opt.mode = MODE_PUBLIC;
126             } else {
127                 goto usage;
128             }
129         } else if (strcmp(p, "filename") == 0) {
130             opt.filename = q;
131         } else if (strcmp(p, "password") == 0) {
132             opt.password = q;
133         } else if (strcmp(p, "password_file") == 0) {
134             opt.password_file = q;
135         } else {
136             goto usage;
137         }
138     }
139 
140     if (opt.mode == MODE_PRIVATE) {
141         if (strlen(opt.password) && strlen(opt.password_file)) {
142             mbedtls_printf("Error: cannot have both password and password_file\n");
143             goto usage;
144         }
145 
146         if (strlen(opt.password_file)) {
147             FILE *f;
148 
149             mbedtls_printf("\n  . Loading the password file ...");
150             if ((f = fopen(opt.password_file, "rb")) == NULL) {
151                 mbedtls_printf(" failed\n  !  fopen returned NULL\n");
152                 goto cleanup;
153             }
154             if (fgets(buf, sizeof(buf), f) == NULL) {
155                 fclose(f);
156                 mbedtls_printf("Error: fgets() failed to retrieve password\n");
157                 goto cleanup;
158             }
159             fclose(f);
160 
161             i = (int) strlen(buf);
162             if (buf[i - 1] == '\n') {
163                 buf[i - 1] = '\0';
164             }
165             if (buf[i - 2] == '\r') {
166                 buf[i - 2] = '\0';
167             }
168             opt.password = buf;
169         }
170 
171         /*
172          * 1.1. Load the key
173          */
174         mbedtls_printf("\n  . Loading the private key ...");
175         fflush(stdout);
176 
177         if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
178                                          (const unsigned char *) pers,
179                                          strlen(pers))) != 0) {
180             mbedtls_printf(" failed\n  !  mbedtls_ctr_drbg_seed returned -0x%04x\n",
181                            (unsigned int) -ret);
182             goto cleanup;
183         }
184 
185         ret = mbedtls_pk_parse_keyfile(&pk, opt.filename, opt.password,
186                                        mbedtls_ctr_drbg_random, &ctr_drbg);
187 
188         if (ret != 0) {
189             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x\n",
190                            (unsigned int) -ret);
191             goto cleanup;
192         }
193 
194         mbedtls_printf(" ok\n");
195 
196         /*
197          * 1.2 Print the key
198          */
199         mbedtls_printf("  . Key information    ...\n");
200 #if defined(MBEDTLS_RSA_C)
201         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) {
202             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
203 
204             if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 ||
205                 (ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP))      != 0) {
206                 mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
207                 goto cleanup;
208             }
209 
210             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("N:  ", &N, 16, NULL));
211             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("E:  ", &E, 16, NULL));
212             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("D:  ", &D, 16, NULL));
213             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("P:  ", &P, 16, NULL));
214             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q:  ", &Q, 16, NULL));
215             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("DP: ", &DP, 16, NULL));
216             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("DQ:  ", &DQ, 16, NULL));
217             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("QP:  ", &QP, 16, NULL));
218         } else
219 #endif
220 #if defined(MBEDTLS_ECP_C)
221         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY) {
222             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(pk);
223             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(X): ",
224                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16,
225                                                    NULL));
226             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(Y): ",
227                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16,
228                                                    NULL));
229             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(Z): ",
230                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 16,
231                                                    NULL));
232             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("D   : ", &ecp->MBEDTLS_PRIVATE(d), 16, NULL));
233         } else
234 #endif
235         {
236             mbedtls_printf("Do not know how to print key information for this type\n");
237             goto cleanup;
238         }
239     } else if (opt.mode == MODE_PUBLIC) {
240         /*
241          * 1.1. Load the key
242          */
243         mbedtls_printf("\n  . Loading the public key ...");
244         fflush(stdout);
245 
246         ret = mbedtls_pk_parse_public_keyfile(&pk, opt.filename);
247 
248         if (ret != 0) {
249             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_public_keyfile returned -0x%04x\n",
250                            (unsigned int) -ret);
251             goto cleanup;
252         }
253 
254         mbedtls_printf(" ok\n");
255 
256         mbedtls_printf("  . Key information    ...\n");
257 #if defined(MBEDTLS_RSA_C)
258         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) {
259             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
260 
261             if ((ret = mbedtls_rsa_export(rsa, &N, NULL, NULL,
262                                           NULL, &E)) != 0) {
263                 mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
264                 goto cleanup;
265             }
266             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("N:  ", &N, 16, NULL));
267             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("E:  ", &E, 16, NULL));
268         } else
269 #endif
270 #if defined(MBEDTLS_ECP_C)
271         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY) {
272             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(pk);
273             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(X): ",
274                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16,
275                                                    NULL));
276             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(Y): ",
277                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16,
278                                                    NULL));
279             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(Z): ",
280                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 16,
281                                                    NULL));
282         } else
283 #endif
284         {
285             mbedtls_printf("Do not know how to print key information for this type\n");
286             goto cleanup;
287         }
288     } else {
289         goto usage;
290     }
291 
292     exit_code = MBEDTLS_EXIT_SUCCESS;
293 
294 cleanup:
295 
296 #if defined(MBEDTLS_ERROR_C)
297     if (exit_code != MBEDTLS_EXIT_SUCCESS) {
298         mbedtls_strerror(ret, buf, sizeof(buf));
299         mbedtls_printf("  !  Last error was: %s\n", buf);
300     }
301 #endif
302 
303     mbedtls_ctr_drbg_free(&ctr_drbg);
304     mbedtls_entropy_free(&entropy);
305     mbedtls_pk_free(&pk);
306 #if defined(MBEDTLS_USE_PSA_CRYPTO)
307     mbedtls_psa_crypto_free();
308 #endif /* MBEDTLS_USE_PSA_CRYPTO */
309     mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
310     mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP);
311     mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP);
312 
313     mbedtls_exit(exit_code);
314 }
315 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
316           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
317