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