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