• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Key generation application
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  *
7  *  This file is provided under the Apache License 2.0, or the
8  *  GNU General Public License v2.0 or later.
9  *
10  *  **********
11  *  Apache License 2.0:
12  *
13  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
14  *  not use this file except in compliance with the License.
15  *  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  *  Unless required by applicable law or agreed to in writing, software
20  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the License for the specific language governing permissions and
23  *  limitations under the License.
24  *
25  *  **********
26  *
27  *  **********
28  *  GNU General Public License v2.0 or later:
29  *
30  *  This program is free software; you can redistribute it and/or modify
31  *  it under the terms of the GNU General Public License as published by
32  *  the Free Software Foundation; either version 2 of the License, or
33  *  (at your option) any later version.
34  *
35  *  This program is distributed in the hope that it will be useful,
36  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  *  GNU General Public License for more details.
39  *
40  *  You should have received a copy of the GNU General Public License along
41  *  with this program; if not, write to the Free Software Foundation, Inc.,
42  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43  *
44  *  **********
45  */
46 
47 #if !defined(MBEDTLS_CONFIG_FILE)
48 #include "mbedtls/config.h"
49 #else
50 #include MBEDTLS_CONFIG_FILE
51 #endif
52 
53 #if defined(MBEDTLS_PLATFORM_C)
54 #include "mbedtls/platform.h"
55 #else
56 #include <stdio.h>
57 #include <stdlib.h>
58 #define mbedtls_printf          printf
59 #define mbedtls_exit            exit
60 #define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
61 #define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
62 #endif /* MBEDTLS_PLATFORM_C */
63 
64 #if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO) && \
65     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
66 #include "mbedtls/error.h"
67 #include "mbedtls/pk.h"
68 #include "mbedtls/ecdsa.h"
69 #include "mbedtls/rsa.h"
70 #include "mbedtls/error.h"
71 #include "mbedtls/entropy.h"
72 #include "mbedtls/ctr_drbg.h"
73 
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77 
78 #if !defined(_WIN32)
79 #include <unistd.h>
80 
81 #define DEV_RANDOM_THRESHOLD        32
82 
dev_random_entropy_poll(void * data,unsigned char * output,size_t len,size_t * olen)83 int dev_random_entropy_poll( void *data, unsigned char *output,
84                              size_t len, size_t *olen )
85 {
86     FILE *file;
87     size_t ret, left = len;
88     unsigned char *p = output;
89     ((void) data);
90 
91     *olen = 0;
92 
93     file = fopen( "/dev/random", "rb" );
94     if( file == NULL )
95         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
96 
97     while( left > 0 )
98     {
99         /* /dev/random can return much less than requested. If so, try again */
100         ret = fread( p, 1, left, file );
101         if( ret == 0 && ferror( file ) )
102         {
103             fclose( file );
104             return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
105         }
106 
107         p += ret;
108         left -= ret;
109         sleep( 1 );
110     }
111     fclose( file );
112     *olen = len;
113 
114     return( 0 );
115 }
116 #endif /* !_WIN32 */
117 #endif
118 
119 #if defined(MBEDTLS_ECP_C)
120 #define DFL_EC_CURVE            mbedtls_ecp_curve_list()->grp_id
121 #else
122 #define DFL_EC_CURVE            0
123 #endif
124 
125 #if !defined(_WIN32) && defined(MBEDTLS_FS_IO)
126 #define USAGE_DEV_RANDOM \
127     "    use_dev_random=0|1    default: 0\n"
128 #else
129 #define USAGE_DEV_RANDOM ""
130 #endif /* !_WIN32 && MBEDTLS_FS_IO */
131 
132 #define FORMAT_PEM              0
133 #define FORMAT_DER              1
134 
135 #define DFL_TYPE                MBEDTLS_PK_RSA
136 #define DFL_RSA_KEYSIZE         4096
137 #define DFL_FILENAME            "keyfile.key"
138 #define DFL_FORMAT              FORMAT_PEM
139 #define DFL_USE_DEV_RANDOM      0
140 
141 #define USAGE \
142     "\n usage: gen_key param=<>...\n"                   \
143     "\n acceptable parameters:\n"                       \
144     "    type=rsa|ec           default: rsa\n"          \
145     "    rsa_keysize=%%d        default: 4096\n"        \
146     "    ec_curve=%%s           see below\n"            \
147     "    filename=%%s           default: keyfile.key\n" \
148     "    format=pem|der        default: pem\n"          \
149     USAGE_DEV_RANDOM                                    \
150     "\n"
151 
152 #if !defined(MBEDTLS_PK_WRITE_C) || !defined(MBEDTLS_PEM_WRITE_C) || \
153     !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_ENTROPY_C) || \
154     !defined(MBEDTLS_CTR_DRBG_C)
main(void)155 int main( void )
156 {
157     mbedtls_printf( "MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO and/or "
158             "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
159             "MBEDTLS_PEM_WRITE_C"
160             "not defined.\n" );
161     mbedtls_exit( 0 );
162 }
163 #else
164 
165 
166 /*
167  * global options
168  */
169 struct options
170 {
171     int type;                   /* the type of key to generate          */
172     int rsa_keysize;            /* length of key in bits                */
173     int ec_curve;               /* curve identifier for EC keys         */
174     const char *filename;       /* filename of the key file             */
175     int format;                 /* the output format to use             */
176     int use_dev_random;         /* use /dev/random as entropy source    */
177 } opt;
178 
write_private_key(mbedtls_pk_context * key,const char * output_file)179 static int write_private_key( mbedtls_pk_context *key, const char *output_file )
180 {
181     int ret;
182     FILE *f;
183     unsigned char output_buf[16000];
184     unsigned char *c = output_buf;
185     size_t len = 0;
186 
187     memset(output_buf, 0, 16000);
188     if( opt.format == FORMAT_PEM )
189     {
190         if( ( ret = mbedtls_pk_write_key_pem( key, output_buf, 16000 ) ) != 0 )
191             return( ret );
192 
193         len = strlen( (char *) output_buf );
194     }
195     else
196     {
197         if( ( ret = mbedtls_pk_write_key_der( key, output_buf, 16000 ) ) < 0 )
198             return( ret );
199 
200         len = ret;
201         c = output_buf + sizeof(output_buf) - len;
202     }
203 
204     if( ( f = fopen( output_file, "wb" ) ) == NULL )
205         return( -1 );
206 
207     if( fwrite( c, 1, len, f ) != len )
208     {
209         fclose( f );
210         return( -1 );
211     }
212 
213     fclose( f );
214 
215     return( 0 );
216 }
217 
main(int argc,char * argv[])218 int main( int argc, char *argv[] )
219 {
220     int ret = 1;
221     int exit_code = MBEDTLS_EXIT_FAILURE;
222     mbedtls_pk_context key;
223     char buf[1024];
224     int i;
225     char *p, *q;
226     mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
227     mbedtls_entropy_context entropy;
228     mbedtls_ctr_drbg_context ctr_drbg;
229     const char *pers = "gen_key";
230 #if defined(MBEDTLS_ECP_C)
231     const mbedtls_ecp_curve_info *curve_info;
232 #endif
233 
234     /*
235      * Set to sane values
236      */
237 
238     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q );
239     mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP );
240     mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP );
241 
242     mbedtls_pk_init( &key );
243     mbedtls_ctr_drbg_init( &ctr_drbg );
244     memset( buf, 0, sizeof( buf ) );
245 
246     if( argc == 0 )
247     {
248     usage:
249         mbedtls_printf( USAGE );
250 #if defined(MBEDTLS_ECP_C)
251         mbedtls_printf( " available ec_curve values:\n" );
252         curve_info = mbedtls_ecp_curve_list();
253         mbedtls_printf( "    %s (default)\n", curve_info->name );
254         while( ( ++curve_info )->name != NULL )
255             mbedtls_printf( "    %s\n", curve_info->name );
256 #endif /* MBEDTLS_ECP_C */
257         goto exit;
258     }
259 
260     opt.type                = DFL_TYPE;
261     opt.rsa_keysize         = DFL_RSA_KEYSIZE;
262     opt.ec_curve            = DFL_EC_CURVE;
263     opt.filename            = DFL_FILENAME;
264     opt.format              = DFL_FORMAT;
265     opt.use_dev_random      = DFL_USE_DEV_RANDOM;
266 
267     for( i = 1; i < argc; i++ )
268     {
269         p = argv[i];
270         if( ( q = strchr( p, '=' ) ) == NULL )
271             goto usage;
272         *q++ = '\0';
273 
274         if( strcmp( p, "type" ) == 0 )
275         {
276             if( strcmp( q, "rsa" ) == 0 )
277                 opt.type = MBEDTLS_PK_RSA;
278             else if( strcmp( q, "ec" ) == 0 )
279                 opt.type = MBEDTLS_PK_ECKEY;
280             else
281                 goto usage;
282         }
283         else if( strcmp( p, "format" ) == 0 )
284         {
285             if( strcmp( q, "pem" ) == 0 )
286                 opt.format = FORMAT_PEM;
287             else if( strcmp( q, "der" ) == 0 )
288                 opt.format = FORMAT_DER;
289             else
290                 goto usage;
291         }
292         else if( strcmp( p, "rsa_keysize" ) == 0 )
293         {
294             opt.rsa_keysize = atoi( q );
295             if( opt.rsa_keysize < 1024 ||
296                 opt.rsa_keysize > MBEDTLS_MPI_MAX_BITS )
297                 goto usage;
298         }
299 #if defined(MBEDTLS_ECP_C)
300         else if( strcmp( p, "ec_curve" ) == 0 )
301         {
302             if( ( curve_info = mbedtls_ecp_curve_info_from_name( q ) ) == NULL )
303                 goto usage;
304             opt.ec_curve = curve_info->grp_id;
305         }
306 #endif
307         else if( strcmp( p, "filename" ) == 0 )
308             opt.filename = q;
309         else if( strcmp( p, "use_dev_random" ) == 0 )
310         {
311             opt.use_dev_random = atoi( q );
312             if( opt.use_dev_random < 0 || opt.use_dev_random > 1 )
313                 goto usage;
314         }
315         else
316             goto usage;
317     }
318 
319     mbedtls_printf( "\n  . Seeding the random number generator..." );
320     fflush( stdout );
321 
322     mbedtls_entropy_init( &entropy );
323 #if !defined(_WIN32) && defined(MBEDTLS_FS_IO)
324     if( opt.use_dev_random )
325     {
326         if( ( ret = mbedtls_entropy_add_source( &entropy, dev_random_entropy_poll,
327                                         NULL, DEV_RANDOM_THRESHOLD,
328                                         MBEDTLS_ENTROPY_SOURCE_STRONG ) ) != 0 )
329         {
330             mbedtls_printf( " failed\n  ! mbedtls_entropy_add_source returned -0x%04x\n", -ret );
331             goto exit;
332         }
333 
334         mbedtls_printf("\n    Using /dev/random, so can take a long time! " );
335         fflush( stdout );
336     }
337 #endif /* !_WIN32 && MBEDTLS_FS_IO */
338 
339     if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
340                                (const unsigned char *) pers,
341                                strlen( pers ) ) ) != 0 )
342     {
343         mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret );
344         goto exit;
345     }
346 
347     /*
348      * 1.1. Generate the key
349      */
350     mbedtls_printf( "\n  . Generating the private key ..." );
351     fflush( stdout );
352 
353     if( ( ret = mbedtls_pk_setup( &key,
354             mbedtls_pk_info_from_type( (mbedtls_pk_type_t) opt.type ) ) ) != 0 )
355     {
356         mbedtls_printf( " failed\n  !  mbedtls_pk_setup returned -0x%04x", -ret );
357         goto exit;
358     }
359 
360 #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
361     if( opt.type == MBEDTLS_PK_RSA )
362     {
363         ret = mbedtls_rsa_gen_key( mbedtls_pk_rsa( key ), mbedtls_ctr_drbg_random, &ctr_drbg,
364                                    opt.rsa_keysize, 65537 );
365         if( ret != 0 )
366         {
367             mbedtls_printf( " failed\n  !  mbedtls_rsa_gen_key returned -0x%04x", -ret );
368             goto exit;
369         }
370     }
371     else
372 #endif /* MBEDTLS_RSA_C */
373 #if defined(MBEDTLS_ECP_C)
374     if( opt.type == MBEDTLS_PK_ECKEY )
375     {
376         ret = mbedtls_ecp_gen_key( (mbedtls_ecp_group_id) opt.ec_curve,
377                                    mbedtls_pk_ec( key ),
378                                    mbedtls_ctr_drbg_random, &ctr_drbg );
379         if( ret != 0 )
380         {
381             mbedtls_printf( " failed\n  !  mbedtls_ecp_gen_key returned -0x%04x", -ret );
382             goto exit;
383         }
384     }
385     else
386 #endif /* MBEDTLS_ECP_C */
387     {
388         mbedtls_printf( " failed\n  !  key type not supported\n" );
389         goto exit;
390     }
391 
392     /*
393      * 1.2 Print the key
394      */
395     mbedtls_printf( " ok\n  . Key information:\n" );
396 
397 #if defined(MBEDTLS_RSA_C)
398     if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_RSA )
399     {
400         mbedtls_rsa_context *rsa = mbedtls_pk_rsa( key );
401 
402         if( ( ret = mbedtls_rsa_export    ( rsa, &N, &P, &Q, &D, &E ) ) != 0 ||
403             ( ret = mbedtls_rsa_export_crt( rsa, &DP, &DQ, &QP ) )      != 0 )
404         {
405             mbedtls_printf( " failed\n  ! could not export RSA parameters\n\n" );
406             goto exit;
407         }
408 
409         mbedtls_mpi_write_file( "N:  ",  &N,  16, NULL );
410         mbedtls_mpi_write_file( "E:  ",  &E,  16, NULL );
411         mbedtls_mpi_write_file( "D:  ",  &D,  16, NULL );
412         mbedtls_mpi_write_file( "P:  ",  &P,  16, NULL );
413         mbedtls_mpi_write_file( "Q:  ",  &Q,  16, NULL );
414         mbedtls_mpi_write_file( "DP: ",  &DP, 16, NULL );
415         mbedtls_mpi_write_file( "DQ:  ", &DQ, 16, NULL );
416         mbedtls_mpi_write_file( "QP:  ", &QP, 16, NULL );
417     }
418     else
419 #endif
420 #if defined(MBEDTLS_ECP_C)
421     if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_ECKEY )
422     {
423         mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( key );
424         mbedtls_printf( "curve: %s\n",
425                 mbedtls_ecp_curve_info_from_grp_id( ecp->grp.id )->name );
426         mbedtls_mpi_write_file( "X_Q:   ", &ecp->Q.X, 16, NULL );
427         mbedtls_mpi_write_file( "Y_Q:   ", &ecp->Q.Y, 16, NULL );
428         mbedtls_mpi_write_file( "D:     ", &ecp->d  , 16, NULL );
429     }
430     else
431 #endif
432         mbedtls_printf("  ! key type not supported\n");
433 
434     /*
435      * 1.3 Export key
436      */
437     mbedtls_printf( "  . Writing key to file..." );
438 
439     if( ( ret = write_private_key( &key, opt.filename ) ) != 0 )
440     {
441         mbedtls_printf( " failed\n" );
442         goto exit;
443     }
444 
445     mbedtls_printf( " ok\n" );
446 
447     exit_code = MBEDTLS_EXIT_SUCCESS;
448 
449 exit:
450 
451     if( exit_code != MBEDTLS_EXIT_SUCCESS )
452     {
453 #ifdef MBEDTLS_ERROR_C
454         mbedtls_strerror( ret, buf, sizeof( buf ) );
455         mbedtls_printf( " - %s\n", buf );
456 #else
457         mbedtls_printf("\n");
458 #endif
459     }
460 
461     mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
462     mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &DP );
463     mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP );
464 
465     mbedtls_pk_free( &key );
466     mbedtls_ctr_drbg_free( &ctr_drbg );
467     mbedtls_entropy_free( &entropy );
468 
469 #if defined(_WIN32)
470     mbedtls_printf( "  + Press Enter to exit this program.\n" );
471     fflush( stdout ); getchar();
472 #endif
473 
474     mbedtls_exit( exit_code );
475 }
476 #endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_PEM_WRITE_C && MBEDTLS_FS_IO &&
477         * MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
478