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