• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Key writing application
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  */
7 
8 #if !defined(MBEDTLS_CONFIG_FILE)
9 #include "mbedtls/config.h"
10 #else
11 #include MBEDTLS_CONFIG_FILE
12 #endif
13 
14 #include "mbedtls/platform.h"
15 
16 #if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO)
17 #include "mbedtls/error.h"
18 #include "mbedtls/pk.h"
19 #include "mbedtls/error.h"
20 
21 #include <stdio.h>
22 #include <string.h>
23 #endif
24 
25 #if defined(MBEDTLS_PEM_WRITE_C)
26 #define USAGE_OUT \
27     "    output_file=%%s      default: keyfile.pem\n"   \
28     "    output_format=pem|der default: pem\n"
29 #else
30 #define USAGE_OUT \
31     "    output_file=%%s      default: keyfile.der\n"   \
32     "    output_format=der     default: der\n"
33 #endif
34 
35 #if defined(MBEDTLS_PEM_WRITE_C)
36 #define DFL_OUTPUT_FILENAME     "keyfile.pem"
37 #define DFL_OUTPUT_FORMAT       OUTPUT_FORMAT_PEM
38 #else
39 #define DFL_OUTPUT_FILENAME     "keyfile.der"
40 #define DFL_OUTPUT_FORMAT       OUTPUT_FORMAT_DER
41 #endif
42 
43 #define DFL_MODE                MODE_NONE
44 #define DFL_FILENAME            "keyfile.key"
45 #define DFL_DEBUG_LEVEL         0
46 #define DFL_OUTPUT_MODE         OUTPUT_MODE_NONE
47 
48 #define MODE_NONE               0
49 #define MODE_PRIVATE            1
50 #define MODE_PUBLIC             2
51 
52 #define OUTPUT_MODE_NONE               0
53 #define OUTPUT_MODE_PRIVATE            1
54 #define OUTPUT_MODE_PUBLIC             2
55 
56 #define OUTPUT_FORMAT_PEM              0
57 #define OUTPUT_FORMAT_DER              1
58 
59 #define USAGE \
60     "\n usage: key_app_writer param=<>...\n"            \
61     "\n acceptable parameters:\n"                       \
62     "    mode=private|public default: none\n"           \
63     "    filename=%%s         default: keyfile.key\n"   \
64     "    output_mode=private|public default: none\n"    \
65     USAGE_OUT                                           \
66     "\n"
67 
68 #if !defined(MBEDTLS_PK_PARSE_C) || \
69     !defined(MBEDTLS_PK_WRITE_C) || \
70     !defined(MBEDTLS_FS_IO)
main(void)71 int main(void)
72 {
73     mbedtls_printf(
74         "MBEDTLS_PK_PARSE_C and/or MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO not defined.\n");
75     mbedtls_exit(0);
76 }
77 #else
78 
79 
80 /*
81  * global options
82  */
83 struct options {
84     int mode;                   /* the mode to run the application in   */
85     const char *filename;       /* filename of the key file             */
86     int output_mode;            /* the output mode to use               */
87     const char *output_file;    /* where to store the constructed key file  */
88     int output_format;          /* the output format to use             */
89 } opt;
90 
write_public_key(mbedtls_pk_context * key,const char * output_file)91 static int write_public_key(mbedtls_pk_context *key, const char *output_file)
92 {
93     int ret;
94     FILE *f;
95     unsigned char output_buf[16000];
96     unsigned char *c = output_buf;
97     size_t len = 0;
98 
99     memset(output_buf, 0, 16000);
100 
101 #if defined(MBEDTLS_PEM_WRITE_C)
102     if (opt.output_format == OUTPUT_FORMAT_PEM) {
103         if ((ret = mbedtls_pk_write_pubkey_pem(key, output_buf, 16000)) != 0) {
104             return ret;
105         }
106 
107         len = strlen((char *) output_buf);
108     } else
109 #endif
110     {
111         if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, 16000)) < 0) {
112             return ret;
113         }
114 
115         len = ret;
116         c = output_buf + sizeof(output_buf) - len;
117     }
118 
119     if ((f = fopen(output_file, "w")) == NULL) {
120         return -1;
121     }
122 
123     if (fwrite(c, 1, len, f) != len) {
124         fclose(f);
125         return -1;
126     }
127 
128     fclose(f);
129 
130     return 0;
131 }
132 
write_private_key(mbedtls_pk_context * key,const char * output_file)133 static int write_private_key(mbedtls_pk_context *key, const char *output_file)
134 {
135     int ret;
136     FILE *f;
137     unsigned char output_buf[16000];
138     unsigned char *c = output_buf;
139     size_t len = 0;
140 
141     memset(output_buf, 0, 16000);
142 
143 #if defined(MBEDTLS_PEM_WRITE_C)
144     if (opt.output_format == OUTPUT_FORMAT_PEM) {
145         if ((ret = mbedtls_pk_write_key_pem(key, output_buf, 16000)) != 0) {
146             return ret;
147         }
148 
149         len = strlen((char *) output_buf);
150     } else
151 #endif
152     {
153         if ((ret = mbedtls_pk_write_key_der(key, output_buf, 16000)) < 0) {
154             return ret;
155         }
156 
157         len = ret;
158         c = output_buf + sizeof(output_buf) - len;
159     }
160 
161     if ((f = fopen(output_file, "w")) == NULL) {
162         return -1;
163     }
164 
165     if (fwrite(c, 1, len, f) != len) {
166         fclose(f);
167         return -1;
168     }
169 
170     fclose(f);
171 
172     return 0;
173 }
174 
main(int argc,char * argv[])175 int main(int argc, char *argv[])
176 {
177     int ret = 1;
178     int exit_code = MBEDTLS_EXIT_FAILURE;
179 #if defined(MBEDTLS_ERROR_C)
180     char buf[200];
181 #endif
182     int i;
183     char *p, *q;
184 
185     mbedtls_pk_context key;
186     mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
187 
188     /*
189      * Set to sane values
190      */
191     mbedtls_pk_init(&key);
192 #if defined(MBEDTLS_ERROR_C)
193     memset(buf, 0, sizeof(buf));
194 #endif
195 
196 #if defined(MBEDTLS_USE_PSA_CRYPTO)
197     psa_status_t status = psa_crypto_init();
198     if (status != PSA_SUCCESS) {
199         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
200                         (int) status);
201         goto exit;
202     }
203 #endif /* MBEDTLS_USE_PSA_CRYPTO */
204 
205     mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
206     mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP);
207     mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP);
208 
209     if (argc < 2) {
210 usage:
211         mbedtls_printf(USAGE);
212         goto exit;
213     }
214 
215     opt.mode                = DFL_MODE;
216     opt.filename            = DFL_FILENAME;
217     opt.output_mode         = DFL_OUTPUT_MODE;
218     opt.output_file         = DFL_OUTPUT_FILENAME;
219     opt.output_format       = DFL_OUTPUT_FORMAT;
220 
221     for (i = 1; i < argc; i++) {
222         p = argv[i];
223         if ((q = strchr(p, '=')) == NULL) {
224             goto usage;
225         }
226         *q++ = '\0';
227 
228         if (strcmp(p, "mode") == 0) {
229             if (strcmp(q, "private") == 0) {
230                 opt.mode = MODE_PRIVATE;
231             } else if (strcmp(q, "public") == 0) {
232                 opt.mode = MODE_PUBLIC;
233             } else {
234                 goto usage;
235             }
236         } else if (strcmp(p, "output_mode") == 0) {
237             if (strcmp(q, "private") == 0) {
238                 opt.output_mode = OUTPUT_MODE_PRIVATE;
239             } else if (strcmp(q, "public") == 0) {
240                 opt.output_mode = OUTPUT_MODE_PUBLIC;
241             } else {
242                 goto usage;
243             }
244         } else if (strcmp(p, "output_format") == 0) {
245 #if defined(MBEDTLS_PEM_WRITE_C)
246             if (strcmp(q, "pem") == 0) {
247                 opt.output_format = OUTPUT_FORMAT_PEM;
248             } else
249 #endif
250             if (strcmp(q, "der") == 0) {
251                 opt.output_format = OUTPUT_FORMAT_DER;
252             } else {
253                 goto usage;
254             }
255         } else if (strcmp(p, "filename") == 0) {
256             opt.filename = q;
257         } else if (strcmp(p, "output_file") == 0) {
258             opt.output_file = q;
259         } else {
260             goto usage;
261         }
262     }
263 
264     if (opt.mode == MODE_NONE && opt.output_mode != OUTPUT_MODE_NONE) {
265         mbedtls_printf("\nCannot output a key without reading one.\n");
266         goto exit;
267     }
268 
269     if (opt.mode == MODE_PUBLIC && opt.output_mode == OUTPUT_MODE_PRIVATE) {
270         mbedtls_printf("\nCannot output a private key from a public key.\n");
271         goto exit;
272     }
273 
274     if (opt.mode == MODE_PRIVATE) {
275         /*
276          * 1.1. Load the key
277          */
278         mbedtls_printf("\n  . Loading the private key ...");
279         fflush(stdout);
280 
281         ret = mbedtls_pk_parse_keyfile(&key, opt.filename, NULL);
282 
283         if (ret != 0) {
284             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x",
285                            (unsigned int) -ret);
286             goto exit;
287         }
288 
289         mbedtls_printf(" ok\n");
290 
291         /*
292          * 1.2 Print the key
293          */
294         mbedtls_printf("  . Key information    ...\n");
295 
296 #if defined(MBEDTLS_RSA_C)
297         if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_RSA) {
298             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(key);
299 
300             if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 ||
301                 (ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP))      != 0) {
302                 mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
303                 goto exit;
304             }
305 
306             mbedtls_mpi_write_file("N:  ",  &N,  16, NULL);
307             mbedtls_mpi_write_file("E:  ",  &E,  16, NULL);
308             mbedtls_mpi_write_file("D:  ",  &D,  16, NULL);
309             mbedtls_mpi_write_file("P:  ",  &P,  16, NULL);
310             mbedtls_mpi_write_file("Q:  ",  &Q,  16, NULL);
311             mbedtls_mpi_write_file("DP: ",  &DP, 16, NULL);
312             mbedtls_mpi_write_file("DQ:  ", &DQ, 16, NULL);
313             mbedtls_mpi_write_file("QP:  ", &QP, 16, NULL);
314         } else
315 #endif
316 #if defined(MBEDTLS_ECP_C)
317         if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_ECKEY) {
318             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(key);
319             mbedtls_mpi_write_file("Q(X): ", &ecp->Q.X, 16, NULL);
320             mbedtls_mpi_write_file("Q(Y): ", &ecp->Q.Y, 16, NULL);
321             mbedtls_mpi_write_file("Q(Z): ", &ecp->Q.Z, 16, NULL);
322             mbedtls_mpi_write_file("D   : ", &ecp->d, 16, NULL);
323         } else
324 #endif
325         mbedtls_printf("key type not supported yet\n");
326 
327     } else if (opt.mode == MODE_PUBLIC) {
328         /*
329          * 1.1. Load the key
330          */
331         mbedtls_printf("\n  . Loading the public key ...");
332         fflush(stdout);
333 
334         ret = mbedtls_pk_parse_public_keyfile(&key, opt.filename);
335 
336         if (ret != 0) {
337             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_public_key returned -0x%04x",
338                            (unsigned int) -ret);
339             goto exit;
340         }
341 
342         mbedtls_printf(" ok\n");
343 
344         /*
345          * 1.2 Print the key
346          */
347         mbedtls_printf("  . Key information    ...\n");
348 
349 #if defined(MBEDTLS_RSA_C)
350         if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_RSA) {
351             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(key);
352 
353             if ((ret = mbedtls_rsa_export(rsa, &N, NULL, NULL,
354                                           NULL, &E)) != 0) {
355                 mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
356                 goto exit;
357             }
358             mbedtls_mpi_write_file("N: ", &N, 16, NULL);
359             mbedtls_mpi_write_file("E: ", &E, 16, NULL);
360         } else
361 #endif
362 #if defined(MBEDTLS_ECP_C)
363         if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_ECKEY) {
364             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(key);
365             mbedtls_mpi_write_file("Q(X): ", &ecp->Q.X, 16, NULL);
366             mbedtls_mpi_write_file("Q(Y): ", &ecp->Q.Y, 16, NULL);
367             mbedtls_mpi_write_file("Q(Z): ", &ecp->Q.Z, 16, NULL);
368         } else
369 #endif
370         mbedtls_printf("key type not supported yet\n");
371     } else {
372         goto usage;
373     }
374 
375     if (opt.output_mode == OUTPUT_MODE_PUBLIC) {
376         write_public_key(&key, opt.output_file);
377     }
378     if (opt.output_mode == OUTPUT_MODE_PRIVATE) {
379         write_private_key(&key, opt.output_file);
380     }
381 
382     exit_code = MBEDTLS_EXIT_SUCCESS;
383 
384 exit:
385 
386     if (exit_code != MBEDTLS_EXIT_SUCCESS) {
387 #ifdef MBEDTLS_ERROR_C
388         mbedtls_strerror(ret, buf, sizeof(buf));
389         mbedtls_printf(" - %s\n", buf);
390 #else
391         mbedtls_printf("\n");
392 #endif
393     }
394 
395     mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
396     mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP);
397     mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP);
398 
399     mbedtls_pk_free(&key);
400 #if defined(MBEDTLS_USE_PSA_CRYPTO)
401     mbedtls_psa_crypto_free();
402 #endif /* MBEDTLS_USE_PSA_CRYPTO */
403 
404 #if defined(_WIN32)
405     mbedtls_printf("  + Press Enter to exit this program.\n");
406     fflush(stdout); getchar();
407 #endif
408 
409     mbedtls_exit(exit_code);
410 }
411 #endif /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C && MBEDTLS_FS_IO */
412