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