Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
mbedtls/programs/util/pem2der.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
265 lines (212 sloc)
5.45 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Convert PEM to DER | |
* | |
* Copyright The Mbed TLS Contributors | |
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later | |
*/ | |
#include "mbedtls/build_info.h" | |
#include "mbedtls/platform.h" | |
#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_FS_IO) | |
#include "mbedtls/error.h" | |
#include "mbedtls/base64.h" | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#endif | |
#define DFL_FILENAME "file.pem" | |
#define DFL_OUTPUT_FILENAME "file.der" | |
#define USAGE \ | |
"\n usage: pem2der param=<>...\n" \ | |
"\n acceptable parameters:\n" \ | |
" filename=%%s default: file.pem\n" \ | |
" output_file=%%s default: file.der\n" \ | |
"\n" | |
#if !defined(MBEDTLS_BASE64_C) || !defined(MBEDTLS_FS_IO) | |
int main(void) | |
{ | |
mbedtls_printf("MBEDTLS_BASE64_C and/or MBEDTLS_FS_IO not defined.\n"); | |
mbedtls_exit(0); | |
} | |
#else | |
/* | |
* global options | |
*/ | |
struct options { | |
const char *filename; /* filename of the input file */ | |
const char *output_file; /* where to store the output */ | |
} opt; | |
int convert_pem_to_der(const unsigned char *input, size_t ilen, | |
unsigned char *output, size_t *olen) | |
{ | |
int ret; | |
const unsigned char *s1, *s2, *end = input + ilen; | |
size_t len = 0; | |
s1 = (unsigned char *) strstr((const char *) input, "-----BEGIN"); | |
if (s1 == NULL) { | |
return -1; | |
} | |
s2 = (unsigned char *) strstr((const char *) input, "-----END"); | |
if (s2 == NULL) { | |
return -1; | |
} | |
s1 += 10; | |
while (s1 < end && *s1 != '-') { | |
s1++; | |
} | |
while (s1 < end && *s1 == '-') { | |
s1++; | |
} | |
if (*s1 == '\r') { | |
s1++; | |
} | |
if (*s1 == '\n') { | |
s1++; | |
} | |
if (s2 <= s1 || s2 > end) { | |
return -1; | |
} | |
ret = mbedtls_base64_decode(NULL, 0, &len, (const unsigned char *) s1, s2 - s1); | |
if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) { | |
return ret; | |
} | |
if (len > *olen) { | |
return -1; | |
} | |
if ((ret = mbedtls_base64_decode(output, len, &len, (const unsigned char *) s1, | |
s2 - s1)) != 0) { | |
return ret; | |
} | |
*olen = len; | |
return 0; | |
} | |
/* | |
* Load all data from a file into a given buffer. | |
*/ | |
static int load_file(const char *path, unsigned char **buf, size_t *n) | |
{ | |
FILE *f; | |
long size; | |
if ((f = fopen(path, "rb")) == NULL) { | |
return -1; | |
} | |
fseek(f, 0, SEEK_END); | |
if ((size = ftell(f)) == -1) { | |
fclose(f); | |
return -1; | |
} | |
fseek(f, 0, SEEK_SET); | |
*n = (size_t) size; | |
if (*n + 1 == 0 || | |
(*buf = mbedtls_calloc(1, *n + 1)) == NULL) { | |
fclose(f); | |
return -1; | |
} | |
if (fread(*buf, 1, *n, f) != *n) { | |
fclose(f); | |
free(*buf); | |
*buf = NULL; | |
return -1; | |
} | |
fclose(f); | |
(*buf)[*n] = '\0'; | |
return 0; | |
} | |
/* | |
* Write buffer to a file | |
*/ | |
static int write_file(const char *path, unsigned char *buf, size_t n) | |
{ | |
FILE *f; | |
if ((f = fopen(path, "wb")) == NULL) { | |
return -1; | |
} | |
if (fwrite(buf, 1, n, f) != n) { | |
fclose(f); | |
return -1; | |
} | |
fclose(f); | |
return 0; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int ret = 1; | |
int exit_code = MBEDTLS_EXIT_FAILURE; | |
unsigned char *pem_buffer = NULL; | |
unsigned char der_buffer[4096]; | |
char buf[1024]; | |
size_t pem_size, der_size = sizeof(der_buffer); | |
int i; | |
char *p, *q; | |
/* | |
* Set to sane values | |
*/ | |
memset(buf, 0, sizeof(buf)); | |
memset(der_buffer, 0, sizeof(der_buffer)); | |
if (argc < 2) { | |
usage: | |
mbedtls_printf(USAGE); | |
goto exit; | |
} | |
opt.filename = DFL_FILENAME; | |
opt.output_file = DFL_OUTPUT_FILENAME; | |
for (i = 1; i < argc; i++) { | |
p = argv[i]; | |
if ((q = strchr(p, '=')) == NULL) { | |
goto usage; | |
} | |
*q++ = '\0'; | |
if (strcmp(p, "filename") == 0) { | |
opt.filename = q; | |
} else if (strcmp(p, "output_file") == 0) { | |
opt.output_file = q; | |
} else { | |
goto usage; | |
} | |
} | |
/* | |
* 1.1. Load the PEM file | |
*/ | |
mbedtls_printf("\n . Loading the PEM file ..."); | |
fflush(stdout); | |
ret = load_file(opt.filename, &pem_buffer, &pem_size); | |
if (ret != 0) { | |
#ifdef MBEDTLS_ERROR_C | |
mbedtls_strerror(ret, buf, 1024); | |
#endif | |
mbedtls_printf(" failed\n ! load_file returned %d - %s\n\n", ret, buf); | |
goto exit; | |
} | |
mbedtls_printf(" ok\n"); | |
/* | |
* 1.2. Convert from PEM to DER | |
*/ | |
mbedtls_printf(" . Converting from PEM to DER ..."); | |
fflush(stdout); | |
if ((ret = convert_pem_to_der(pem_buffer, pem_size, der_buffer, &der_size)) != 0) { | |
#ifdef MBEDTLS_ERROR_C | |
mbedtls_strerror(ret, buf, 1024); | |
#endif | |
mbedtls_printf(" failed\n ! convert_pem_to_der %d - %s\n\n", ret, buf); | |
goto exit; | |
} | |
mbedtls_printf(" ok\n"); | |
/* | |
* 1.3. Write the DER file | |
*/ | |
mbedtls_printf(" . Writing the DER file ..."); | |
fflush(stdout); | |
ret = write_file(opt.output_file, der_buffer, der_size); | |
if (ret != 0) { | |
#ifdef MBEDTLS_ERROR_C | |
mbedtls_strerror(ret, buf, 1024); | |
#endif | |
mbedtls_printf(" failed\n ! write_file returned %d - %s\n\n", ret, buf); | |
goto exit; | |
} | |
mbedtls_printf(" ok\n"); | |
exit_code = MBEDTLS_EXIT_SUCCESS; | |
exit: | |
free(pem_buffer); | |
mbedtls_exit(exit_code); | |
} | |
#endif /* MBEDTLS_BASE64_C && MBEDTLS_FS_IO */ |