blob: ab05952d37a2df034d7817493029a9c388c4e5fb [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 */
62 char *filename; /* filename of the key file */
63 int debug_level; /* level of debugging */
64 int output_mode; /* the output mode to use */
65 char *output_file; /* where to store the constructed key file */
66} 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
77void write_public_key( rsa_context *rsa, char *output_file )
78{
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" );
100 fprintf(f, "-----BEGIN PUBLIC KEY-----\n");
101 while (olen)
102 {
103 int use_len = olen;
104 if (use_len > 64) use_len = 64;
105 fwrite( c, 1, use_len, f );
106 olen -= use_len;
107 c += use_len;
108 fprintf(f, "\n");
109 }
110 fprintf(f, "-----END PUBLIC KEY-----\n");
111 fclose(f);
112}
113
114void write_private_key( rsa_context *rsa, char *output_file )
115{
116 FILE *f;
Paul Bakker1d569582012-10-03 20:35:44 +0000117 unsigned char output_buf[16000];
118 unsigned char base_buf[16000];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000119 unsigned char *c;
120 int ret;
Paul Bakker1d569582012-10-03 20:35:44 +0000121 size_t len = 0, olen = 16000;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000122
Paul Bakker1d569582012-10-03 20:35:44 +0000123 memset(output_buf, 0, 16000);
124 ret = x509_write_key_der( output_buf, 16000, rsa );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000125 if( ret < 0 )
126 return;
127
128 len = ret;
Paul Bakker1d569582012-10-03 20:35:44 +0000129 c = output_buf + 15999 - len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000130
131 base64_encode( base_buf, &olen, c, len );
132
133 c = base_buf;
134
135 f = fopen( output_file, "w" );
136 fprintf(f, "-----BEGIN RSA PRIVATE KEY-----\n");
137 while (olen)
138 {
139 int use_len = olen;
140 if (use_len > 64) use_len = 64;
141 fwrite( c, 1, use_len, f );
142 olen -= use_len;
143 c += use_len;
144 fprintf(f, "\n");
145 }
146 fprintf(f, "-----END RSA PRIVATE KEY-----\n");
147 fclose(f);
148}
149
150#define USAGE \
151 "\n usage: key_app param=<>...\n" \
152 "\n acceptable parameters:\n" \
153 " mode=private|public default: none\n" \
154 " filename=%%s default: keyfile.key\n" \
155 " debug_level=%%d default: 0 (disabled)\n" \
156 " output_mode=private|public default: none\n" \
157 " output_file=%%s defeult: keyfile.pem\n" \
158 "\n"
159
160#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \
161 !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO)
162int main( int argc, char *argv[] )
163{
164 ((void) argc);
165 ((void) argv);
166
167 printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or "
168 "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n");
169 return( 0 );
170}
171#else
172int main( int argc, char *argv[] )
173{
174 int ret = 0;
175 rsa_context rsa;
176 char buf[1024];
Paul Bakker1d569582012-10-03 20:35:44 +0000177 int i;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000178 char *p, *q;
179
180 /*
181 * Set to sane values
182 */
183 memset( &rsa, 0, sizeof( rsa_context ) );
184 memset( buf, 0, 1024 );
185
186 if( argc == 0 )
187 {
188 usage:
189 printf( USAGE );
190 goto exit;
191 }
192
193 opt.mode = DFL_MODE;
194 opt.filename = DFL_FILENAME;
195 opt.debug_level = DFL_DEBUG_LEVEL;
196 opt.output_mode = DFL_OUTPUT_MODE;
197 opt.output_file = DFL_OUTPUT_FILENAME;
198
199 for( i = 1; i < argc; i++ )
200 {
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000201 p = argv[i];
202 if( ( q = strchr( p, '=' ) ) == NULL )
203 goto usage;
204 *q++ = '\0';
205
206 if( strcmp( p, "mode" ) == 0 )
207 {
208 if( strcmp( q, "private" ) == 0 )
209 opt.mode = MODE_PRIVATE;
210 else if( strcmp( q, "public" ) == 0 )
211 opt.mode = MODE_PUBLIC;
212 else
213 goto usage;
214 }
215 else if( strcmp( p, "output_mode" ) == 0 )
216 {
217 if( strcmp( q, "private" ) == 0 )
218 opt.output_mode = OUTPUT_MODE_PRIVATE;
219 else if( strcmp( q, "public" ) == 0 )
220 opt.output_mode = OUTPUT_MODE_PUBLIC;
221 else
222 goto usage;
223 }
224 else if( strcmp( p, "filename" ) == 0 )
225 opt.filename = q;
226 else if( strcmp( p, "output_file" ) == 0 )
227 opt.output_file = q;
228 else if( strcmp( p, "debug_level" ) == 0 )
229 {
230 opt.debug_level = atoi( q );
231 if( opt.debug_level < 0 || opt.debug_level > 65535 )
232 goto usage;
233 }
234 else
235 goto usage;
236 }
237
238 if( opt.mode == MODE_NONE && opt.output_mode != OUTPUT_MODE_NONE )
239 {
240 printf( "\nCannot output a key without reading one.\n");
241 goto exit;
242 }
243
244 if( opt.mode == MODE_PUBLIC && opt.output_mode == OUTPUT_MODE_PRIVATE )
245 {
246 printf( "\nCannot output a private key from a public key.\n");
247 goto exit;
248 }
249
250 if( opt.mode == MODE_PRIVATE )
251 {
252 /*
253 * 1.1. Load the key
254 */
255 printf( "\n . Loading the private key ..." );
256 fflush( stdout );
257
258 ret = x509parse_keyfile( &rsa, opt.filename, NULL );
259
260 if( ret != 0 )
261 {
262#ifdef POLARSSL_ERROR_C
263 error_strerror( ret, buf, 1024 );
264#endif
265 printf( " failed\n ! x509parse_key returned %d - %s\n\n", ret, buf );
266 rsa_free( &rsa );
267 goto exit;
268 }
269
270 printf( " ok\n" );
271
272 /*
273 * 1.2 Print the key
274 */
275 printf( " . Key information ...\n" );
276 mpi_write_file( "N: ", &rsa.N, 16, NULL );
277 mpi_write_file( "E: ", &rsa.E, 16, NULL );
278 mpi_write_file( "D: ", &rsa.D, 16, NULL );
279 mpi_write_file( "P: ", &rsa.P, 16, NULL );
280 mpi_write_file( "Q: ", &rsa.Q, 16, NULL );
281 mpi_write_file( "DP: ", &rsa.DP, 16, NULL );
282 mpi_write_file( "DQ: ", &rsa.DQ, 16, NULL );
283 mpi_write_file( "QP: ", &rsa.QP, 16, NULL );
284
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
294 ret = x509parse_public_keyfile( &rsa, opt.filename );
295
296 if( ret != 0 )
297 {
298#ifdef POLARSSL_ERROR_C
299 error_strerror( ret, buf, 1024 );
300#endif
301 printf( " failed\n ! x509parse_public_key returned %d - %s\n\n", ret, buf );
302 rsa_free( &rsa );
303 goto exit;
304 }
305
306 printf( " ok\n" );
307
308 /*
309 * 1.2 Print the key
310 */
311 printf( " . Key information ...\n" );
312 mpi_write_file( "N: ", &rsa.N, 16, NULL );
313 mpi_write_file( "E: ", &rsa.E, 16, NULL );
314 }
315 else
316 goto usage;
317
318 if( opt.output_mode == OUTPUT_MODE_PUBLIC )
319 {
320 write_public_key( &rsa, opt.output_file );
321 }
322 if( opt.output_mode == OUTPUT_MODE_PRIVATE )
323 {
324 write_private_key( &rsa, opt.output_file );
325 }
326
327exit:
328
329 rsa_free( &rsa );
330
331#if defined(_WIN32)
332 printf( " + Press Enter to exit this program.\n" );
333 fflush( stdout ); getchar();
334#endif
335
336 return( ret );
337}
338#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C &&
339 POLARSSL_X509_PARSE_C && POLARSSL_FS_IO */