• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Convert PEM to DER
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  */
7 
8 #if !defined(MBEDTLS_CONFIG_FILE)
9 #include "mbedtls/config.h"
10 #else
11 #include MBEDTLS_CONFIG_FILE
12 #endif
13 
14 #include "mbedtls/platform.h"
15 
16 #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_FS_IO)
17 #include "mbedtls/error.h"
18 #include "mbedtls/base64.h"
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #endif
24 
25 #define DFL_FILENAME            "file.pem"
26 #define DFL_OUTPUT_FILENAME     "file.der"
27 
28 #define USAGE \
29     "\n usage: pem2der param=<>...\n"                   \
30     "\n acceptable parameters:\n"                       \
31     "    filename=%%s         default: file.pem\n"      \
32     "    output_file=%%s      default: file.der\n"      \
33     "\n"
34 
35 #if !defined(MBEDTLS_BASE64_C) || !defined(MBEDTLS_FS_IO)
main(void)36 int main(void)
37 {
38     mbedtls_printf("MBEDTLS_BASE64_C and/or MBEDTLS_FS_IO not defined.\n");
39     mbedtls_exit(0);
40 }
41 #else
42 
43 
44 /*
45  * global options
46  */
47 struct options {
48     const char *filename;       /* filename of the input file             */
49     const char *output_file;    /* where to store the output              */
50 } opt;
51 
convert_pem_to_der(const unsigned char * input,size_t ilen,unsigned char * output,size_t * olen)52 int convert_pem_to_der(const unsigned char *input, size_t ilen,
53                        unsigned char *output, size_t *olen)
54 {
55     int ret;
56     const unsigned char *s1, *s2, *end = input + ilen;
57     size_t len = 0;
58 
59     s1 = (unsigned char *) strstr((const char *) input, "-----BEGIN");
60     if (s1 == NULL) {
61         return -1;
62     }
63 
64     s2 = (unsigned char *) strstr((const char *) input, "-----END");
65     if (s2 == NULL) {
66         return -1;
67     }
68 
69     s1 += 10;
70     while (s1 < end && *s1 != '-') {
71         s1++;
72     }
73     while (s1 < end && *s1 == '-') {
74         s1++;
75     }
76     if (*s1 == '\r') {
77         s1++;
78     }
79     if (*s1 == '\n') {
80         s1++;
81     }
82 
83     if (s2 <= s1 || s2 > end) {
84         return -1;
85     }
86 
87     ret = mbedtls_base64_decode(NULL, 0, &len, (const unsigned char *) s1, s2 - s1);
88     if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
89         return ret;
90     }
91 
92     if (len > *olen) {
93         return -1;
94     }
95 
96     if ((ret = mbedtls_base64_decode(output, len, &len, (const unsigned char *) s1,
97                                      s2 - s1)) != 0) {
98         return ret;
99     }
100 
101     *olen = len;
102 
103     return 0;
104 }
105 
106 /*
107  * Load all data from a file into a given buffer.
108  */
load_file(const char * path,unsigned char ** buf,size_t * n)109 static int load_file(const char *path, unsigned char **buf, size_t *n)
110 {
111     FILE *f;
112     long size;
113 
114     if ((f = fopen(path, "rb")) == NULL) {
115         return -1;
116     }
117 
118     fseek(f, 0, SEEK_END);
119     if ((size = ftell(f)) == -1) {
120         fclose(f);
121         return -1;
122     }
123     fseek(f, 0, SEEK_SET);
124 
125     *n = (size_t) size;
126 
127     if (*n + 1 == 0 ||
128         (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
129         fclose(f);
130         return -1;
131     }
132 
133     if (fread(*buf, 1, *n, f) != *n) {
134         fclose(f);
135         free(*buf);
136         *buf = NULL;
137         return -1;
138     }
139 
140     fclose(f);
141 
142     (*buf)[*n] = '\0';
143 
144     return 0;
145 }
146 
147 /*
148  * Write buffer to a file
149  */
write_file(const char * path,unsigned char * buf,size_t n)150 static int write_file(const char *path, unsigned char *buf, size_t n)
151 {
152     FILE *f;
153 
154     if ((f = fopen(path, "wb")) == NULL) {
155         return -1;
156     }
157 
158     if (fwrite(buf, 1, n, f) != n) {
159         fclose(f);
160         return -1;
161     }
162 
163     fclose(f);
164     return 0;
165 }
166 
main(int argc,char * argv[])167 int main(int argc, char *argv[])
168 {
169     int ret = 1;
170     int exit_code = MBEDTLS_EXIT_FAILURE;
171     unsigned char *pem_buffer = NULL;
172     unsigned char der_buffer[4096];
173     char buf[1024];
174     size_t pem_size, der_size = sizeof(der_buffer);
175     int i;
176     char *p, *q;
177 
178     /*
179      * Set to sane values
180      */
181     memset(buf, 0, sizeof(buf));
182     memset(der_buffer, 0, sizeof(der_buffer));
183 
184     if (argc < 2) {
185 usage:
186         mbedtls_printf(USAGE);
187         goto exit;
188     }
189 
190     opt.filename            = DFL_FILENAME;
191     opt.output_file         = DFL_OUTPUT_FILENAME;
192 
193     for (i = 1; i < argc; i++) {
194 
195         p = argv[i];
196         if ((q = strchr(p, '=')) == NULL) {
197             goto usage;
198         }
199         *q++ = '\0';
200 
201         if (strcmp(p, "filename") == 0) {
202             opt.filename = q;
203         } else if (strcmp(p, "output_file") == 0) {
204             opt.output_file = q;
205         } else {
206             goto usage;
207         }
208     }
209 
210     /*
211      * 1.1. Load the PEM file
212      */
213     mbedtls_printf("\n  . Loading the PEM file ...");
214     fflush(stdout);
215 
216     ret = load_file(opt.filename, &pem_buffer, &pem_size);
217 
218     if (ret != 0) {
219 #ifdef MBEDTLS_ERROR_C
220         mbedtls_strerror(ret, buf, 1024);
221 #endif
222         mbedtls_printf(" failed\n  !  load_file returned %d - %s\n\n", ret, buf);
223         goto exit;
224     }
225 
226     mbedtls_printf(" ok\n");
227 
228     /*
229      * 1.2. Convert from PEM to DER
230      */
231     mbedtls_printf("  . Converting from PEM to DER ...");
232     fflush(stdout);
233 
234     if ((ret = convert_pem_to_der(pem_buffer, pem_size, der_buffer, &der_size)) != 0) {
235 #ifdef MBEDTLS_ERROR_C
236         mbedtls_strerror(ret, buf, 1024);
237 #endif
238         mbedtls_printf(" failed\n  !  convert_pem_to_der %d - %s\n\n", ret, buf);
239         goto exit;
240     }
241 
242     mbedtls_printf(" ok\n");
243 
244     /*
245      * 1.3. Write the DER file
246      */
247     mbedtls_printf("  . Writing the DER file ...");
248     fflush(stdout);
249 
250     ret = write_file(opt.output_file, der_buffer, der_size);
251 
252     if (ret != 0) {
253 #ifdef MBEDTLS_ERROR_C
254         mbedtls_strerror(ret, buf, 1024);
255 #endif
256         mbedtls_printf(" failed\n  !  write_file returned %d - %s\n\n", ret, buf);
257         goto exit;
258     }
259 
260     mbedtls_printf(" ok\n");
261 
262     exit_code = MBEDTLS_EXIT_SUCCESS;
263 
264 exit:
265     free(pem_buffer);
266 
267 #if defined(_WIN32)
268     mbedtls_printf("  + Press Enter to exit this program.\n");
269     fflush(stdout); getchar();
270 #endif
271 
272     mbedtls_exit(exit_code);
273 }
274 #endif /* MBEDTLS_BASE64_C && MBEDTLS_FS_IO */
275