blob: 371b03a53a7b09db15ba21c5637197975f9130d2 [file] [log] [blame]
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001/*
Paul Bakkerf3df61a2013-08-26 17:22:23 +02002 * Key writing application
Paul Bakkerbdb912d2012-02-13 23:11:30 +00003 *
Paul Bakker3c5ef712013-06-25 16:37:45 +02004 * Copyright (C) 2006-2013, Brainspark B.V.
Paul Bakkerbdb912d2012-02-13 23:11:30 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#ifndef _CRT_SECURE_NO_DEPRECATE
27#define _CRT_SECURE_NO_DEPRECATE 1
28#endif
29
30#include <string.h>
31#include <stdlib.h>
32#include <stdio.h>
33
34#include "polarssl/config.h"
35
Paul Bakkerbdb912d2012-02-13 23:11:30 +000036#include "polarssl/x509write.h"
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +020037#include "polarssl/error.h"
Paul Bakkerbdb912d2012-02-13 23:11:30 +000038
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +020039#if !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_FS_IO)
Paul Bakkered27a042013-04-18 22:46:23 +020040int main( int argc, char *argv[] )
41{
42 ((void) argc);
43 ((void) argv);
44
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +020045 printf( "POLARSSL_X509_WRITE_C and/or POLARSSL_FS_IO not defined.\n" );
Paul Bakkered27a042013-04-18 22:46:23 +020046 return( 0 );
47}
48#else
49
Paul Bakkerbdb912d2012-02-13 23:11:30 +000050#define MODE_NONE 0
51#define MODE_PRIVATE 1
52#define MODE_PUBLIC 2
53
54#define OUTPUT_MODE_NONE 0
55#define OUTPUT_MODE_PRIVATE 1
56#define OUTPUT_MODE_PUBLIC 2
57
Paul Bakkerf3df61a2013-08-26 17:22:23 +020058#define OUTPUT_FORMAT_PEM 0
59#define OUTPUT_FORMAT_DER 1
60
Paul Bakkerbdb912d2012-02-13 23:11:30 +000061#define DFL_MODE MODE_NONE
62#define DFL_FILENAME "keyfile.key"
63#define DFL_DEBUG_LEVEL 0
Paul Bakkerf3df61a2013-08-26 17:22:23 +020064#define DFL_OUTPUT_MODE OUTPUT_MODE_NONE
Paul Bakkerbdb912d2012-02-13 23:11:30 +000065#define DFL_OUTPUT_FILENAME "keyfile.pem"
Paul Bakkerf3df61a2013-08-26 17:22:23 +020066#define DFL_OUTPUT_FORMAT OUTPUT_FORMAT_PEM
Paul Bakkerbdb912d2012-02-13 23:11:30 +000067
68/*
69 * global options
70 */
71struct options
72{
73 int mode; /* the mode to run the application in */
Paul Bakkeref3f8c72013-06-24 13:01:08 +020074 const char *filename; /* filename of the key file */
Paul Bakkerbdb912d2012-02-13 23:11:30 +000075 int output_mode; /* the output mode to use */
Paul Bakkeref3f8c72013-06-24 13:01:08 +020076 const char *output_file; /* where to store the constructed key file */
Paul Bakkerf3df61a2013-08-26 17:22:23 +020077 int output_format; /* the output format to use */
Paul Bakkerbdb912d2012-02-13 23:11:30 +000078} opt;
79
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +020080static int write_public_key( pk_context *key, const char *output_file )
Paul Bakkerbdb912d2012-02-13 23:11:30 +000081{
Paul Bakkerf3df61a2013-08-26 17:22:23 +020082 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +000083 FILE *f;
Paul Bakker1d569582012-10-03 20:35:44 +000084 unsigned char output_buf[16000];
Paul Bakkerf3df61a2013-08-26 17:22:23 +020085 unsigned char *c = output_buf;
86 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +000087
Paul Bakker1d569582012-10-03 20:35:44 +000088 memset(output_buf, 0, 16000);
Paul Bakkerbdb912d2012-02-13 23:11:30 +000089
Paul Bakkerf3df61a2013-08-26 17:22:23 +020090 if( opt.output_format == OUTPUT_FORMAT_PEM )
Paul Bakkerbdb912d2012-02-13 23:11:30 +000091 {
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +020092 if( ( ret = x509write_pubkey_pem( key, output_buf, 16000 ) ) != 0 )
Paul Bakkerf3df61a2013-08-26 17:22:23 +020093 return( ret );
94
95 len = strlen( (char *) output_buf );
Paul Bakkerbdb912d2012-02-13 23:11:30 +000096 }
Paul Bakkerf3df61a2013-08-26 17:22:23 +020097 else
98 {
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +020099 if( ( ret = x509write_pubkey_der( key, output_buf, 16000 ) ) < 0 )
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200100 return( ret );
101
102 len = ret;
103 c = output_buf + sizeof(output_buf) - len - 1;
104 }
105
106 if( ( f = fopen( output_file, "w" ) ) == NULL )
107 return( -1 );
108
109 if( fwrite( c, 1, len, f ) != len )
110 return( -1 );
111
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000112 fclose(f);
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200113
114 return( 0 );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000115}
116
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200117static int write_private_key( pk_context *key, const char *output_file )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000118{
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200119 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000120 FILE *f;
Paul Bakker1d569582012-10-03 20:35:44 +0000121 unsigned char output_buf[16000];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200122 unsigned char *c = output_buf;
123 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000124
Paul Bakker1d569582012-10-03 20:35:44 +0000125 memset(output_buf, 0, 16000);
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200126 if( opt.output_format == OUTPUT_FORMAT_PEM )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000127 {
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200128 if( ( ret = x509write_key_pem( key, output_buf, 16000 ) ) != 0 )
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200129 return( ret );
130
131 len = strlen( (char *) output_buf );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000132 }
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200133 else
134 {
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200135 if( ( ret = x509write_key_der( key, output_buf, 16000 ) ) < 0 )
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200136 return( ret );
137
138 len = ret;
139 c = output_buf + sizeof(output_buf) - len - 1;
140 }
141
142 if( ( f = fopen( output_file, "w" ) ) == NULL )
143 return( -1 );
144
145 if( fwrite( c, 1, len, f ) != len )
146 return( -1 );
147
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000148 fclose(f);
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200149
150 return( 0 );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000151}
152
153#define USAGE \
154 "\n usage: key_app param=<>...\n" \
155 "\n acceptable parameters:\n" \
156 " mode=private|public default: none\n" \
157 " filename=%%s default: keyfile.key\n" \
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000158 " output_mode=private|public default: none\n" \
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200159 " output_file=%%s default: keyfile.pem\n" \
160 " output_format=pem|der default: pem\n" \
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000161 "\n"
162
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000163int main( int argc, char *argv[] )
164{
165 int ret = 0;
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200166 pk_context key;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000167 char buf[1024];
Paul Bakker1d569582012-10-03 20:35:44 +0000168 int i;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000169 char *p, *q;
170
171 /*
172 * Set to sane values
173 */
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200174 pk_init( &key );
175 memset( buf, 0, sizeof( buf ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000176
177 if( argc == 0 )
178 {
179 usage:
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200180 ret = 1;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000181 printf( USAGE );
182 goto exit;
183 }
184
185 opt.mode = DFL_MODE;
186 opt.filename = DFL_FILENAME;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000187 opt.output_mode = DFL_OUTPUT_MODE;
188 opt.output_file = DFL_OUTPUT_FILENAME;
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200189 opt.output_format = DFL_OUTPUT_FORMAT;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000190
191 for( i = 1; i < argc; i++ )
192 {
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000193 p = argv[i];
194 if( ( q = strchr( p, '=' ) ) == NULL )
195 goto usage;
196 *q++ = '\0';
197
198 if( strcmp( p, "mode" ) == 0 )
199 {
200 if( strcmp( q, "private" ) == 0 )
201 opt.mode = MODE_PRIVATE;
202 else if( strcmp( q, "public" ) == 0 )
203 opt.mode = MODE_PUBLIC;
204 else
205 goto usage;
206 }
207 else if( strcmp( p, "output_mode" ) == 0 )
208 {
209 if( strcmp( q, "private" ) == 0 )
210 opt.output_mode = OUTPUT_MODE_PRIVATE;
211 else if( strcmp( q, "public" ) == 0 )
212 opt.output_mode = OUTPUT_MODE_PUBLIC;
213 else
214 goto usage;
215 }
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200216 else if( strcmp( p, "output_format" ) == 0 )
217 {
218 if( strcmp( q, "pem" ) == 0 )
219 opt.output_format = OUTPUT_FORMAT_PEM;
220 else if( strcmp( q, "der" ) == 0 )
221 opt.output_format = OUTPUT_FORMAT_DER;
222 else
223 goto usage;
224 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000225 else if( strcmp( p, "filename" ) == 0 )
226 opt.filename = q;
227 else if( strcmp( p, "output_file" ) == 0 )
228 opt.output_file = q;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000229 else
230 goto usage;
231 }
232
233 if( opt.mode == MODE_NONE && opt.output_mode != OUTPUT_MODE_NONE )
234 {
235 printf( "\nCannot output a key without reading one.\n");
236 goto exit;
237 }
238
239 if( opt.mode == MODE_PUBLIC && opt.output_mode == OUTPUT_MODE_PRIVATE )
240 {
241 printf( "\nCannot output a private key from a public key.\n");
242 goto exit;
243 }
244
245 if( opt.mode == MODE_PRIVATE )
246 {
247 /*
248 * 1.1. Load the key
249 */
250 printf( "\n . Loading the private key ..." );
251 fflush( stdout );
252
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200253 ret = x509parse_keyfile( &key, opt.filename, NULL );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000254
255 if( ret != 0 )
256 {
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200257 printf( " failed\n ! x509parse_key returned %d", ret );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000258 goto exit;
259 }
260
261 printf( " ok\n" );
262
263 /*
264 * 1.2 Print the key
265 */
266 printf( " . Key information ...\n" );
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200267
268#if defined(POLARSSL_RSA_C)
269 if( pk_get_type( &key ) == POLARSSL_PK_RSA )
270 {
271 rsa_context *rsa = pk_rsa( key );
272 mpi_write_file( "N: ", &rsa->N, 16, NULL );
273 mpi_write_file( "E: ", &rsa->E, 16, NULL );
274 mpi_write_file( "D: ", &rsa->D, 16, NULL );
275 mpi_write_file( "P: ", &rsa->P, 16, NULL );
276 mpi_write_file( "Q: ", &rsa->Q, 16, NULL );
277 mpi_write_file( "DP: ", &rsa->DP, 16, NULL );
278 mpi_write_file( "DQ: ", &rsa->DQ, 16, NULL );
279 mpi_write_file( "QP: ", &rsa->QP, 16, NULL );
280 }
281 else
282#endif
283 printf("key type not supported yet\n");
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000284
285 }
286 else if( opt.mode == MODE_PUBLIC )
287 {
288 /*
289 * 1.1. Load the key
290 */
291 printf( "\n . Loading the public key ..." );
292 fflush( stdout );
293
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200294 ret = x509parse_public_keyfile( &key, opt.filename );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000295
296 if( ret != 0 )
297 {
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200298 printf( " failed\n ! x509parse_public_key returned %d", ret );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000299 goto exit;
300 }
301
302 printf( " ok\n" );
303
304 /*
305 * 1.2 Print the key
306 */
307 printf( " . Key information ...\n" );
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200308
309#if defined(POLARSSL_RSA_C)
310 if( pk_get_type( &key ) == POLARSSL_PK_RSA )
311 {
312 rsa_context *rsa = pk_rsa( key );
313 mpi_write_file( "N: ", &rsa->N, 16, NULL );
314 mpi_write_file( "E: ", &rsa->E, 16, NULL );
315 }
316 else
317#endif
318 printf("key type not supported yet\n");
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000319 }
320 else
321 goto usage;
322
323 if( opt.output_mode == OUTPUT_MODE_PUBLIC )
324 {
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200325 write_public_key( &key, opt.output_file );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000326 }
327 if( opt.output_mode == OUTPUT_MODE_PRIVATE )
328 {
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200329 write_private_key( &key, opt.output_file );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000330 }
331
332exit:
333
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200334 if( ret != 0 && ret != 1)
335 {
336#ifdef POLARSSL_ERROR_C
337 polarssl_strerror( ret, buf, sizeof( buf ) );
338 printf( " - %s\n", buf );
339#else
340 printf("\n");
341#endif
342 }
343
344 pk_free( &key );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000345
346#if defined(_WIN32)
347 printf( " + Press Enter to exit this program.\n" );
348 fflush( stdout ); getchar();
349#endif
350
351 return( ret );
352}
Manuel Pégourié-Gonnard26b4d452013-09-12 06:56:06 +0200353#endif /* POLARSSL_X509_WRITE_C && POLARSSL_FS_IO */