blob: edf6d9e7d7c794e571da2f4834926b770c3cfe42 [file] [log] [blame]
Paul Bakker8adf13b2013-08-25 14:50:09 +02001/*
2 * Convert PEM to DER
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker8adf13b2013-08-25 14:50:09 +020018 */
19
Bence Szépkútic662b362021-05-27 11:25:03 +020020#include "mbedtls/build_info.h"
Paul Bakker8adf13b2013-08-25 14:50:09 +020021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020022#if defined(MBEDTLS_PLATFORM_C)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020023# include "mbedtls/platform.h"
Rich Evansf90016a2015-01-19 14:26:37 +000024#else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020025# include <stdio.h>
26# include <stdlib.h>
27# define mbedtls_free free
28# define mbedtls_calloc calloc
29# define mbedtls_printf printf
30# define mbedtls_exit exit
31# define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
32# define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
Andres Amaya Garcia78dabe02018-04-29 22:08:41 +010033#endif /* MBEDTLS_PLATFORM_C */
Rich Evansf90016a2015-01-19 14:26:37 +000034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_FS_IO)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020036# include "mbedtls/error.h"
37# include "mbedtls/base64.h"
Paul Bakker8adf13b2013-08-25 14:50:09 +020038
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020039# include <stdio.h>
40# include <stdlib.h>
41# include <string.h>
Rich Evans18b78c72015-02-11 14:06:19 +000042#endif
43
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020044#define DFL_FILENAME "file.pem"
45#define DFL_OUTPUT_FILENAME "file.der"
Paul Bakker8adf13b2013-08-25 14:50:09 +020046
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020047#define USAGE \
48 "\n usage: pem2der param=<>...\n" \
49 "\n acceptable parameters:\n" \
50 " filename=%%s default: file.pem\n" \
51 " output_file=%%s default: file.der\n" \
Rich Evans18b78c72015-02-11 14:06:19 +000052 "\n"
53
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#if !defined(MBEDTLS_BASE64_C) || !defined(MBEDTLS_FS_IO)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020055int main(void)
Manuel Pégourié-Gonnard7831b0c2013-09-20 12:29:56 +020056{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057 mbedtls_printf("MBEDTLS_BASE64_C and/or MBEDTLS_FS_IO not defined.\n");
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020058 mbedtls_exit(0);
Manuel Pégourié-Gonnard7831b0c2013-09-20 12:29:56 +020059}
60#else
Manuel Pégourié-Gonnard3ef6a6d2018-12-10 14:31:45 +010061
Paul Bakker8adf13b2013-08-25 14:50:09 +020062/*
63 * global options
64 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020065struct options {
66 const char *filename; /* filename of the input file */
67 const char *output_file; /* where to store the output */
Paul Bakker8adf13b2013-08-25 14:50:09 +020068} opt;
69
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020070int convert_pem_to_der(const unsigned char *input,
71 size_t ilen,
72 unsigned char *output,
73 size_t *olen)
Paul Bakker8adf13b2013-08-25 14:50:09 +020074{
75 int ret;
76 const unsigned char *s1, *s2, *end = input + ilen;
77 size_t len = 0;
78
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020079 s1 = (unsigned char *)strstr((const char *)input, "-----BEGIN");
80 if (s1 == NULL)
81 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +020082
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020083 s2 = (unsigned char *)strstr((const char *)input, "-----END");
84 if (s2 == NULL)
85 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +020086
87 s1 += 10;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020088 while (s1 < end && *s1 != '-')
Paul Bakker8adf13b2013-08-25 14:50:09 +020089 s1++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020090 while (s1 < end && *s1 == '-')
Paul Bakker8adf13b2013-08-25 14:50:09 +020091 s1++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020092 if (*s1 == '\r')
93 s1++;
94 if (*s1 == '\n')
95 s1++;
Paul Bakker8adf13b2013-08-25 14:50:09 +020096
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020097 if (s2 <= s1 || s2 > end)
98 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +020099
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200100 ret = mbedtls_base64_decode(NULL, 0, &len, (const unsigned char *)s1,
101 s2 - s1);
102 if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER)
103 return ret;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200104
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200105 if (len > *olen)
106 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200107
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200108 if ((ret = mbedtls_base64_decode(
109 output, len, &len, (const unsigned char *)s1, s2 - s1)) != 0) {
110 return ret;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200111 }
112
113 *olen = len;
114
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200115 return 0;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200116}
117
118/*
119 * Load all data from a file into a given buffer.
120 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200121static int load_file(const char *path, unsigned char **buf, size_t *n)
Paul Bakker8adf13b2013-08-25 14:50:09 +0200122{
123 FILE *f;
124 long size;
125
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200126 if ((f = fopen(path, "rb")) == NULL)
127 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200128
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200129 fseek(f, 0, SEEK_END);
130 if ((size = ftell(f)) == -1) {
131 fclose(f);
132 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200133 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200134 fseek(f, 0, SEEK_SET);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200135
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200136 *n = (size_t)size;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200137
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200138 if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
139 fclose(f);
140 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200141 }
142
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200143 if (fread(*buf, 1, *n, f) != *n) {
144 fclose(f);
145 free(*buf);
Alfred Klomp1d42b3e2014-07-14 22:09:21 +0200146 *buf = NULL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200147 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200148 }
149
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200150 fclose(f);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200151
152 (*buf)[*n] = '\0';
153
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200154 return 0;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200155}
156
157/*
158 * Write buffer to a file
159 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200160static int write_file(const char *path, unsigned char *buf, size_t n)
Paul Bakker8adf13b2013-08-25 14:50:09 +0200161{
162 FILE *f;
163
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200164 if ((f = fopen(path, "wb")) == NULL)
165 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200166
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200167 if (fwrite(buf, 1, n, f) != n) {
168 fclose(f);
169 return -1;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200170 }
171
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200172 fclose(f);
173 return 0;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200174}
175
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200176int main(int argc, char *argv[])
Paul Bakker8adf13b2013-08-25 14:50:09 +0200177{
Andres Amaya Garcia78dabe02018-04-29 22:08:41 +0100178 int ret = 1;
179 int exit_code = MBEDTLS_EXIT_FAILURE;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200180 unsigned char *pem_buffer = NULL;
181 unsigned char der_buffer[4096];
182 char buf[1024];
183 size_t pem_size, der_size = sizeof(der_buffer);
Paul Bakkerc97f9f62013-11-30 15:13:02 +0100184 int i;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200185 char *p, *q;
186
187 /*
188 * Set to sane values
189 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200190 memset(buf, 0, sizeof(buf));
191 memset(der_buffer, 0, sizeof(der_buffer));
Paul Bakker8adf13b2013-08-25 14:50:09 +0200192
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200193 if (argc == 0) {
194usage:
195 mbedtls_printf(USAGE);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200196 goto exit;
197 }
198
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200199 opt.filename = DFL_FILENAME;
200 opt.output_file = DFL_OUTPUT_FILENAME;
Paul Bakker8adf13b2013-08-25 14:50:09 +0200201
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200202 for (i = 1; i < argc; i++) {
Paul Bakker8adf13b2013-08-25 14:50:09 +0200203 p = argv[i];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200204 if ((q = strchr(p, '=')) == NULL)
Paul Bakker8adf13b2013-08-25 14:50:09 +0200205 goto usage;
206 *q++ = '\0';
207
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200208 if (strcmp(p, "filename") == 0)
Paul Bakker8adf13b2013-08-25 14:50:09 +0200209 opt.filename = q;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200210 else if (strcmp(p, "output_file") == 0)
Paul Bakker8adf13b2013-08-25 14:50:09 +0200211 opt.output_file = q;
212 else
213 goto usage;
214 }
215
216 /*
217 * 1.1. Load the PEM file
218 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200219 mbedtls_printf("\n . Loading the PEM file ...");
220 fflush(stdout);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200221
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200222 ret = load_file(opt.filename, &pem_buffer, &pem_size);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200223
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200224 if (ret != 0) {
225# ifdef MBEDTLS_ERROR_C
226 mbedtls_strerror(ret, buf, 1024);
227# endif
228 mbedtls_printf(" failed\n ! load_file returned %d - %s\n\n", ret,
229 buf);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200230 goto exit;
231 }
232
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200233 mbedtls_printf(" ok\n");
Paul Bakker8adf13b2013-08-25 14:50:09 +0200234
235 /*
236 * 1.2. Convert from PEM to DER
237 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200238 mbedtls_printf(" . Converting from PEM to DER ...");
239 fflush(stdout);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200240
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200241 if ((ret = convert_pem_to_der(pem_buffer, pem_size, der_buffer,
242 &der_size)) != 0) {
243# ifdef MBEDTLS_ERROR_C
244 mbedtls_strerror(ret, buf, 1024);
245# endif
246 mbedtls_printf(" failed\n ! convert_pem_to_der %d - %s\n\n", ret,
247 buf);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200248 goto exit;
249 }
250
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200251 mbedtls_printf(" ok\n");
Paul Bakker8adf13b2013-08-25 14:50:09 +0200252
253 /*
254 * 1.3. Write the DER file
255 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200256 mbedtls_printf(" . Writing the DER file ...");
257 fflush(stdout);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200258
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200259 ret = write_file(opt.output_file, der_buffer, der_size);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200260
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200261 if (ret != 0) {
262# ifdef MBEDTLS_ERROR_C
263 mbedtls_strerror(ret, buf, 1024);
264# endif
265 mbedtls_printf(" failed\n ! write_file returned %d - %s\n\n", ret,
266 buf);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200267 goto exit;
268 }
269
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200270 mbedtls_printf(" ok\n");
Paul Bakker8adf13b2013-08-25 14:50:09 +0200271
Andres Amaya Garcia78dabe02018-04-29 22:08:41 +0100272 exit_code = MBEDTLS_EXIT_SUCCESS;
273
Paul Bakker8adf13b2013-08-25 14:50:09 +0200274exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200275 free(pem_buffer);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200276
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200277# if defined(_WIN32)
278 mbedtls_printf(" + Press Enter to exit this program.\n");
279 fflush(stdout);
280 getchar();
281# endif
Paul Bakker8adf13b2013-08-25 14:50:09 +0200282
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200283 mbedtls_exit(exit_code);
Paul Bakker8adf13b2013-08-25 14:50:09 +0200284}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285#endif /* MBEDTLS_BASE64_C && MBEDTLS_FS_IO */