blob: 00553194d34df0563c935ee3062aeb64cedfd493 [file] [log] [blame]
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001/*
2 * Key reading application
3 *
4 * Copyright (C) 2006-2011, Brainspark B.V.
5 *
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
36#include "polarssl/error.h"
37#include "polarssl/rsa.h"
38#include "polarssl/x509.h"
39#include "polarssl/base64.h"
40#include "polarssl/x509write.h"
41
42#define MODE_NONE 0
43#define MODE_PRIVATE 1
44#define MODE_PUBLIC 2
45
46#define OUTPUT_MODE_NONE 0
47#define OUTPUT_MODE_PRIVATE 1
48#define OUTPUT_MODE_PUBLIC 2
49
50#define DFL_MODE MODE_NONE
51#define DFL_FILENAME "keyfile.key"
52#define DFL_DEBUG_LEVEL 0
53#define DFL_OUTPUT_MODE OUTPUT_MODE_NONE
54#define DFL_OUTPUT_FILENAME "keyfile.pem"
55
56/*
57 * global options
58 */
59struct options
60{
61 int mode; /* the mode to run the application in */
Paul Bakkere0225e42013-06-06 12:52:24 +020062 const char *filename; /* filename of the key file */
Paul Bakkerbdb912d2012-02-13 23:11:30 +000063 int debug_level; /* level of debugging */
64 int output_mode; /* the output mode to use */
Paul Bakkere0225e42013-06-06 12:52:24 +020065 const char *output_file; /* where to store the constructed key file */
Paul Bakkerbdb912d2012-02-13 23:11:30 +000066} opt;
67
68void my_debug( void *ctx, int level, const char *str )
69{
70 if( level < opt.debug_level )
71 {
72 fprintf( (FILE *) ctx, "%s", str );
73 fflush( (FILE *) ctx );
74 }
75}
76
Paul Bakkere0225e42013-06-06 12:52:24 +020077void write_public_key( rsa_context *rsa, const char *output_file )
Paul Bakkerbdb912d2012-02-13 23:11:30 +000078{
79 FILE *f;
Paul Bakker1d569582012-10-03 20:35:44 +000080 unsigned char output_buf[16000];
81 unsigned char base_buf[16000];
Paul Bakkerbdb912d2012-02-13 23:11:30 +000082 unsigned char *c;
83 int ret;
Paul Bakker1d569582012-10-03 20:35:44 +000084 size_t len = 0, olen = 16000;
Paul Bakkerbdb912d2012-02-13 23:11:30 +000085
Paul Bakker1d569582012-10-03 20:35:44 +000086 memset(output_buf, 0, 16000);
87 ret = x509_write_pubkey_der( output_buf, 16000, rsa );
Paul Bakkerbdb912d2012-02-13 23:11:30 +000088
89 if( ret < 0 )
90 return;
91
92 len = ret;
Paul Bakker1d569582012-10-03 20:35:44 +000093 c = output_buf + 15999 - len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +000094
95 base64_encode( base_buf, &olen, c, len );
96
97 c = base_buf;
98
99 f = fopen( output_file, "w" );
Paul Bakkera16e7f22014-07-09 14:58:11 +0200100 if( f == NULL )
101 return;
102
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000103 fprintf(f, "-----BEGIN PUBLIC KEY-----\n");
104 while (olen)
105 {
106 int use_len = olen;
107 if (use_len > 64) use_len = 64;
108 fwrite( c, 1, use_len, f );
109 olen -= use_len;
110 c += use_len;
111 fprintf(f, "\n");
112 }
113 fprintf(f, "-----END PUBLIC KEY-----\n");
114 fclose(f);
115}
116
Paul Bakkere0225e42013-06-06 12:52:24 +0200117void write_private_key( rsa_context *rsa, const char *output_file )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000118{
119 FILE *f;
Paul Bakker1d569582012-10-03 20:35:44 +0000120 unsigned char output_buf[16000];
121 unsigned char base_buf[16000];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000122 unsigned char *c;
123 int ret;
Paul Bakker1d569582012-10-03 20:35:44 +0000124 size_t len = 0, olen = 16000;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000125
Paul Bakker1d569582012-10-03 20:35:44 +0000126 memset(output_buf, 0, 16000);
127 ret = x509_write_key_der( output_buf, 16000, rsa );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000128 if( ret < 0 )
129 return;
130
131 len = ret;
Paul Bakker1d569582012-10-03 20:35:44 +0000132 c = output_buf + 15999 - len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000133
134 base64_encode( base_buf, &olen, c, len );
135
136 c = base_buf;
137
138 f = fopen( output_file, "w" );
139 fprintf(f, "-----BEGIN RSA PRIVATE KEY-----\n");
140 while (olen)
141 {
142 int use_len = olen;
143 if (use_len > 64) use_len = 64;
144 fwrite( c, 1, use_len, f );
145 olen -= use_len;
146 c += use_len;
147 fprintf(f, "\n");
148 }
149 fprintf(f, "-----END RSA PRIVATE KEY-----\n");
150 fclose(f);
151}
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" \
158 " debug_level=%%d default: 0 (disabled)\n" \
159 " output_mode=private|public default: none\n" \
160 " output_file=%%s defeult: keyfile.pem\n" \
161 "\n"
162
163#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \
164 !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO)
165int main( int argc, char *argv[] )
166{
167 ((void) argc);
168 ((void) argv);
169
170 printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or "
171 "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n");
172 return( 0 );
173}
174#else
175int main( int argc, char *argv[] )
176{
177 int ret = 0;
178 rsa_context rsa;
179 char buf[1024];
Paul Bakker1d569582012-10-03 20:35:44 +0000180 int i;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000181 char *p, *q;
182
183 /*
184 * Set to sane values
185 */
186 memset( &rsa, 0, sizeof( rsa_context ) );
187 memset( buf, 0, 1024 );
188
189 if( argc == 0 )
190 {
191 usage:
192 printf( USAGE );
193 goto exit;
194 }
195
196 opt.mode = DFL_MODE;
197 opt.filename = DFL_FILENAME;
198 opt.debug_level = DFL_DEBUG_LEVEL;
199 opt.output_mode = DFL_OUTPUT_MODE;
200 opt.output_file = DFL_OUTPUT_FILENAME;
201
202 for( i = 1; i < argc; i++ )
203 {
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000204 p = argv[i];
205 if( ( q = strchr( p, '=' ) ) == NULL )
206 goto usage;
207 *q++ = '\0';
208
209 if( strcmp( p, "mode" ) == 0 )
210 {
211 if( strcmp( q, "private" ) == 0 )
212 opt.mode = MODE_PRIVATE;
213 else if( strcmp( q, "public" ) == 0 )
214 opt.mode = MODE_PUBLIC;
215 else
216 goto usage;
217 }
218 else if( strcmp( p, "output_mode" ) == 0 )
219 {
220 if( strcmp( q, "private" ) == 0 )
221 opt.output_mode = OUTPUT_MODE_PRIVATE;
222 else if( strcmp( q, "public" ) == 0 )
223 opt.output_mode = OUTPUT_MODE_PUBLIC;
224 else
225 goto usage;
226 }
227 else if( strcmp( p, "filename" ) == 0 )
228 opt.filename = q;
229 else if( strcmp( p, "output_file" ) == 0 )
230 opt.output_file = q;
231 else if( strcmp( p, "debug_level" ) == 0 )
232 {
233 opt.debug_level = atoi( q );
234 if( opt.debug_level < 0 || opt.debug_level > 65535 )
235 goto usage;
236 }
237 else
238 goto usage;
239 }
240
241 if( opt.mode == MODE_NONE && opt.output_mode != OUTPUT_MODE_NONE )
242 {
243 printf( "\nCannot output a key without reading one.\n");
244 goto exit;
245 }
246
247 if( opt.mode == MODE_PUBLIC && opt.output_mode == OUTPUT_MODE_PRIVATE )
248 {
249 printf( "\nCannot output a private key from a public key.\n");
250 goto exit;
251 }
252
253 if( opt.mode == MODE_PRIVATE )
254 {
255 /*
256 * 1.1. Load the key
257 */
258 printf( "\n . Loading the private key ..." );
259 fflush( stdout );
260
261 ret = x509parse_keyfile( &rsa, opt.filename, NULL );
262
263 if( ret != 0 )
264 {
265#ifdef POLARSSL_ERROR_C
266 error_strerror( ret, buf, 1024 );
267#endif
268 printf( " failed\n ! x509parse_key returned %d - %s\n\n", ret, buf );
269 rsa_free( &rsa );
270 goto exit;
271 }
272
273 printf( " ok\n" );
274
275 /*
276 * 1.2 Print the key
277 */
278 printf( " . Key information ...\n" );
279 mpi_write_file( "N: ", &rsa.N, 16, NULL );
280 mpi_write_file( "E: ", &rsa.E, 16, NULL );
281 mpi_write_file( "D: ", &rsa.D, 16, NULL );
282 mpi_write_file( "P: ", &rsa.P, 16, NULL );
283 mpi_write_file( "Q: ", &rsa.Q, 16, NULL );
284 mpi_write_file( "DP: ", &rsa.DP, 16, NULL );
285 mpi_write_file( "DQ: ", &rsa.DQ, 16, NULL );
286 mpi_write_file( "QP: ", &rsa.QP, 16, NULL );
287
288 }
289 else if( opt.mode == MODE_PUBLIC )
290 {
291 /*
292 * 1.1. Load the key
293 */
294 printf( "\n . Loading the public key ..." );
295 fflush( stdout );
296
297 ret = x509parse_public_keyfile( &rsa, opt.filename );
298
299 if( ret != 0 )
300 {
301#ifdef POLARSSL_ERROR_C
302 error_strerror( ret, buf, 1024 );
303#endif
304 printf( " failed\n ! x509parse_public_key returned %d - %s\n\n", ret, buf );
305 rsa_free( &rsa );
306 goto exit;
307 }
308
309 printf( " ok\n" );
310
311 /*
312 * 1.2 Print the key
313 */
314 printf( " . Key information ...\n" );
315 mpi_write_file( "N: ", &rsa.N, 16, NULL );
316 mpi_write_file( "E: ", &rsa.E, 16, NULL );
317 }
318 else
319 goto usage;
320
321 if( opt.output_mode == OUTPUT_MODE_PUBLIC )
322 {
323 write_public_key( &rsa, opt.output_file );
324 }
325 if( opt.output_mode == OUTPUT_MODE_PRIVATE )
326 {
327 write_private_key( &rsa, opt.output_file );
328 }
329
330exit:
331
332 rsa_free( &rsa );
333
334#if defined(_WIN32)
335 printf( " + Press Enter to exit this program.\n" );
336 fflush( stdout ); getchar();
337#endif
338
339 return( ret );
340}
341#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C &&
342 POLARSSL_X509_PARSE_C && POLARSSL_FS_IO */