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