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