blob: f1da438dca40301015ddde88c1625603a69c1a71 [file] [log] [blame]
Paul Bakker8adf13b2013-08-25 14:50:09 +02001/*
2 * Convert PEM to DER
3 *
4 * Copyright (C) 2006-2013, 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
Manuel Pégourié-Gonnardabd6e022013-09-20 13:30:43 +020026#include "polarssl/config.h"
Paul Bakker8adf13b2013-08-25 14:50:09 +020027
28#include <string.h>
29#include <stdlib.h>
30#include <stdio.h>
31
Paul Bakker8adf13b2013-08-25 14:50:09 +020032#include "polarssl/error.h"
33#include "polarssl/base64.h"
34
35#define DFL_FILENAME "file.pem"
36#define DFL_OUTPUT_FILENAME "file.der"
37
Manuel Pégourié-Gonnard7831b0c2013-09-20 12:29:56 +020038#if !defined(POLARSSL_BASE64_C) || !defined(POLARSSL_FS_IO)
39int main( int argc, char *argv[] )
40{
41 ((void) argc);
42 ((void) argv);
43
44 printf("POLARSSL_BASE64_C and/or POLARSSL_FS_IO not defined.\n");
45 return( 0 );
46}
47#else
Paul Bakker8adf13b2013-08-25 14:50:09 +020048/*
49 * global options
50 */
51struct options
52{
Paul Bakker8fc30b12013-11-25 13:29:43 +010053 const char *filename; /* filename of the input file */
54 const char *output_file; /* where to store the output */
Paul Bakker8adf13b2013-08-25 14:50:09 +020055} opt;
56
57int convert_pem_to_der( const unsigned char *input, size_t ilen,
58 unsigned char *output, size_t *olen )
59{
60 int ret;
61 const unsigned char *s1, *s2, *end = input + ilen;
62 size_t len = 0;
63
Paul Bakker8fc30b12013-11-25 13:29:43 +010064 s1 = (unsigned char *) strstr( (const char *) input, "-----BEGIN" );
Paul Bakker8adf13b2013-08-25 14:50:09 +020065 if( s1 == NULL )
66 return( -1 );
67
Paul Bakker8fc30b12013-11-25 13:29:43 +010068 s2 = (unsigned char *) strstr( (const char *) input, "-----END" );
Paul Bakker8adf13b2013-08-25 14:50:09 +020069 if( s2 == NULL )
70 return( -1 );
71
72 s1 += 10;
73 while( s1 < end && *s1 != '-' )
74 s1++;
75 while( s1 < end && *s1 == '-' )
76 s1++;
77 if( *s1 == '\r' ) s1++;
78 if( *s1 == '\n' ) s1++;
79
80 if( s2 <= s1 || s2 > end )
81 return( -1 );
82
83 ret = base64_decode( NULL, &len, (const unsigned char *) s1, s2 - s1 );
84 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
85 return( ret );
86
87 if( len > *olen )
88 return( -1 );
89
90 if( ( ret = base64_decode( output, &len, (const unsigned char *) s1,
91 s2 - s1 ) ) != 0 )
92 {
93 return( ret );
94 }
95
96 *olen = len;
97
98 return( 0 );
99}
100
101/*
102 * Load all data from a file into a given buffer.
103 */
104static int load_file( const char *path, unsigned char **buf, size_t *n )
105{
106 FILE *f;
107 long size;
108
109 if( ( f = fopen( path, "rb" ) ) == NULL )
110 return( -1 );
111
112 fseek( f, 0, SEEK_END );
113 if( ( size = ftell( f ) ) == -1 )
114 {
115 fclose( f );
116 return( -1 );
117 }
118 fseek( f, 0, SEEK_SET );
119
120 *n = (size_t) size;
121
122 if( *n + 1 == 0 ||
123 ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
124 {
125 fclose( f );
126 return( -1 );
127 }
128
129 if( fread( *buf, 1, *n, f ) != *n )
130 {
131 fclose( f );
132 free( *buf );
133 return( -1 );
134 }
135
136 fclose( f );
137
138 (*buf)[*n] = '\0';
139
140 return( 0 );
141}
142
143/*
144 * Write buffer to a file
145 */
146static int write_file( const char *path, unsigned char *buf, size_t n )
147{
148 FILE *f;
149
150 if( ( f = fopen( path, "wb" ) ) == NULL )
151 return( -1 );
152
153 if( fwrite( buf, 1, n, f ) != n )
154 {
155 fclose( f );
156 return( -1 );
157 }
158
159 fclose( f );
160 return( 0 );
161}
162
163#define USAGE \
164 "\n usage: pem2der param=<>...\n" \
165 "\n acceptable parameters:\n" \
166 " filename=%%s default: file.pem\n" \
167 " output_file=%%s default: file.der\n" \
168 "\n"
169
Paul Bakker8adf13b2013-08-25 14:50:09 +0200170int main( int argc, char *argv[] )
171{
172 int ret = 0;
173 unsigned char *pem_buffer = NULL;
174 unsigned char der_buffer[4096];
175 char buf[1024];
176 size_t pem_size, der_size = sizeof(der_buffer);
Paul Bakkerc97f9f62013-11-30 15:13:02 +0100177 int i;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200178 char *p, *q;
179
180 /*
181 * Set to sane values
182 */
183 memset( buf, 0, sizeof(buf) );
184 memset( der_buffer, 0, sizeof(der_buffer) );
185
186 if( argc == 0 )
187 {
188 usage:
189 printf( USAGE );
190 goto exit;
191 }
192
193 opt.filename = DFL_FILENAME;
194 opt.output_file = DFL_OUTPUT_FILENAME;
195
196 for( i = 1; i < argc; i++ )
197 {
198
199 p = argv[i];
200 if( ( q = strchr( p, '=' ) ) == NULL )
201 goto usage;
202 *q++ = '\0';
203
Paul Bakker8adf13b2013-08-25 14:50:09 +0200204 if( strcmp( p, "filename" ) == 0 )
205 opt.filename = q;
206 else if( strcmp( p, "output_file" ) == 0 )
207 opt.output_file = q;
208 else
209 goto usage;
210 }
211
212 /*
213 * 1.1. Load the PEM file
214 */
215 printf( "\n . Loading the PEM file ..." );
216 fflush( stdout );
217
218 ret = load_file( opt.filename, &pem_buffer, &pem_size );
219
220 if( ret != 0 )
221 {
222#ifdef POLARSSL_ERROR_C
223 error_strerror( ret, buf, 1024 );
224#endif
225 printf( " failed\n ! load_file returned %d - %s\n\n", ret, buf );
226 goto exit;
227 }
228
229 printf( " ok\n" );
230
231 /*
232 * 1.2. Convert from PEM to DER
233 */
234 printf( " . Converting from PEM to DER ..." );
235 fflush( stdout );
236
237 if( ( ret = convert_pem_to_der( pem_buffer, pem_size, der_buffer, &der_size ) ) != 0 )
238 {
239#ifdef POLARSSL_ERROR_C
240 error_strerror( ret, buf, 1024 );
241#endif
242 printf( " failed\n ! convert_pem_to_der %d - %s\n\n", ret, buf );
243 goto exit;
244 }
245
246 printf( " ok\n" );
247
248 /*
249 * 1.3. Write the DER file
250 */
251 printf( " . Writing the DER file ..." );
252 fflush( stdout );
253
254 ret = write_file( opt.output_file, der_buffer, der_size );
255
256 if( ret != 0 )
257 {
258#ifdef POLARSSL_ERROR_C
259 error_strerror( ret, buf, 1024 );
260#endif
261 printf( " failed\n ! write_file returned %d - %s\n\n", ret, buf );
262 goto exit;
263 }
264
265 printf( " ok\n" );
266
267exit:
268 free( pem_buffer );
269
270#if defined(_WIN32)
271 printf( " + Press Enter to exit this program.\n" );
272 fflush( stdout ); getchar();
273#endif
274
275 return( ret );
276}
277#endif /* POLARSSL_BASE64_C && POLARSSL_FS_IO */