From 81827fac5d9b41fd413b85d92bcb25c4ddbfe890 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 18 Mar 2020 18:19:00 -0600 Subject: [PATCH] add PKCS12 create example --- crypto/pkcs12/Makefile | 7 +- crypto/pkcs12/README | 10 + crypto/pkcs12/pkcs12-create-example.c | 273 ++++++++++++++++++++++++++ 3 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 crypto/pkcs12/pkcs12-create-example.c diff --git a/crypto/pkcs12/Makefile b/crypto/pkcs12/Makefile index af716a09..2d5a988a 100644 --- a/crypto/pkcs12/Makefile +++ b/crypto/pkcs12/Makefile @@ -2,10 +2,15 @@ CC=gcc CFLAGS=-Wall LIBS= -lwolfssl +all:pkcs12-example pkcs12-create-example + pkcs12-example: pkcs12-example.o $(CC) -o $@ $^ $(CFLAGS) $(LIBS) +pkcs12-create-example: pkcs12-create-example.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + .PHONY: clean clean: - rm -f *.o pkcs12-example + rm -f *.o pkcs12-example pkcs12-create-example output.p12 diff --git a/crypto/pkcs12/README b/crypto/pkcs12/README index 2aa5f7e6..4e70338a 100644 --- a/crypto/pkcs12/README +++ b/crypto/pkcs12/README @@ -10,3 +10,13 @@ How to use pkcs12-example.c 3) Running 'make clean' will delete the excecutable as well as any created files. Making sure that the only files left are 'pkcs12-example.c', 'Makefile', 'test-servercert.p12'and 'README'. + +How to use pkcs12-create-example + +1) Compile wolfSSL with PKCS12 enabled then run 'make' from this directory. + +2) A new key and certificate is generated then output into the output.p12 pkcs12 + bundled created. The default password is "test password" + + ./pkcs12-create-example + diff --git a/crypto/pkcs12/pkcs12-create-example.c b/crypto/pkcs12/pkcs12-create-example.c new file mode 100644 index 00000000..53fbde48 --- /dev/null +++ b/crypto/pkcs12/pkcs12-create-example.c @@ -0,0 +1,273 @@ +/* pkcs12-create-example.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include +#include +#include +#include + +#define WC_RSA_KEYSIZE 2048 +#define HEAP_HINT NULL + + +static int createKey(byte** keyDer, word32* keySz, RsaKey* key, WC_RNG* rng) +{ + int ret; + + *keyDer = NULL; + *keySz = 0; + + ret = wc_InitRsaKey(key, HEAP_HINT); + if (ret == 0) { + ret = wc_InitRng(rng); + } + + if (ret == 0) { + ret = wc_MakeRsaKey(key, WC_RSA_KEYSIZE, WC_RSA_EXPONENT, rng); + } + + if (ret == 0) { + *keySz = wc_RsaKeyToDer(key, NULL, 0); + if (*keySz < 0) { + printf("unable to convert RSA key to DER\n"); + ret = *keySz; + } + } + + if (ret == 0) { + *keyDer = (byte*)XMALLOC(*keySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (*keyDer == NULL) { + ret = MEMORY_E; + } + } + + if (ret == 0) { + *keySz = wc_RsaKeyToDer(key, *keyDer, *keySz); + if (*keySz < 0) { + printf("unable to convert RSA key to DER\n"); + ret = *keySz; + } + } + + return ret; +} + + +static void outputFile(byte* out, word32 outSz, char* fileName) +{ + FILE* file; + + file = fopen(fileName, "wb"); + if (!file) { + printf("failed to open file: %s\n", fileName); + } + else { + printf("printing out %d bytes\n", outSz); + fwrite(out, 1, outSz, file); + fclose(file); + } +} + + +static int readFile(byte** out, word32* outSz, char* fileName) +{ + FILE* file; + int ret = 0; + + file = fopen(fileName, "rb"); + if (!file) { + printf("failed to open file: %s\n", fileName); + return -1; + } + + fseek(file, 0, SEEK_END); + *outSz = ftell(file); + rewind(file); + + *out = (byte*) XMALLOC(*outSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (*out == NULL) { + ret = MEMORY_E; + } + else { + *outSz = fread(*out, 1, *outSz, file); + if (*outSz <= 0) { + printf("Failed to read from file\n"); + ret = *outSz; + } + else { + printf("Successfully read %d bytes\n", *outSz); + } + } + fclose(file); + + return ret; +} + + +static int getCa(byte** caCert, word32* caCertSz, RsaKey* caKey) +{ + int ret; + char caCertFile[] = "../../certs/ca-cert.der"; + char caKeyFile[] = "../../certs/ca-key.der"; + + byte* caKeyDer = NULL; + word32 caKeyDerSz; + word32 idx = 0; + + *caCert = NULL; + *caCertSz = 0; + + + printf("Getting the caKey from %s\n", caKeyFile); + ret = readFile(&caKeyDer, &caKeyDerSz, caKeyFile); + if (ret == 0) { + ret = wc_InitRsaKey(caKey, HEAP_HINT); + } + + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(caKeyDer, &idx, caKey, caKeyDerSz); + if (ret != 0) { + printf("unable to decode RSA key\n"); + } + } + + + /* now get certificate */ + if (ret == 0) { + printf("Getting the caCert from %s\n", caCertFile); + ret = readFile(caCert, caCertSz, caCertFile); + } + + XFREE(caKeyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + + +static int createCert(byte** certDer, word32* certSz, RsaKey* key, WC_RNG* rng) +{ + int ret; + Cert newCert; + RsaKey caKey; + byte* caCert = NULL; + word32 caCertSz; + + *certDer = NULL; + *certSz = 4096; + + wc_InitCert(&newCert); + + strncpy(newCert.subject.country, "US", CTC_NAME_SIZE); + strncpy(newCert.subject.state, "MT", CTC_NAME_SIZE); + strncpy(newCert.subject.locality, "Bozeman", CTC_NAME_SIZE); + strncpy(newCert.subject.org, "yourOrgNameHere", CTC_NAME_SIZE); + strncpy(newCert.subject.unit, "yourUnitNameHere", CTC_NAME_SIZE); + strncpy(newCert.subject.commonName, "www.yourDomain.com", CTC_NAME_SIZE); + strncpy(newCert.subject.email, "yourEmail@yourDomain.com", CTC_NAME_SIZE); + newCert.isCA = 0; + newCert.sigType = CTC_SHA256wRSA; + + ret = getCa(&caCert, &caCertSz, &caKey); + if (ret == 0) { + ret = wc_SetIssuerBuffer(&newCert, caCert, caCertSz); + } + + if (ret == 0) { + *certDer = (byte*)XMALLOC(*certSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (*certDer == NULL) { + ret = MEMORY_E; + } + else { + ret = wc_MakeCert(&newCert, *certDer, *certSz, key, NULL, rng); + } + } + + printf("MakeCert returned %d\n", ret); + if (ret >= 0) { + ret = wc_SignCert(newCert.bodySz, newCert.sigType, *certDer, *certSz, + &caKey, NULL, rng); + if (ret < 0) { + printf("SignCert returned %d\n", ret); + } + else { + *certSz = ret; + ret = 0; /* return 0 on success */ + printf("Successfully created new certificate\n"); + } + } + XFREE(caCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + + +int main(int argc, char* argv[]) +{ + WC_PKCS12* pkcs12 = NULL; + WC_RNG rng; + RsaKey rsa; + + byte* keyDer = NULL; + word32 keySz; + byte* certDer = NULL; + word32 certSz; + + if (createKey(&keyDer, &keySz, &rsa, &rng) != 0) { + printf("Unable to create RSA key\n"); + return -1; + } + + if (createCert(&certDer, &certSz, &rsa, &rng) != 0) { + printf("Unable to create certificate\n"); + wc_FreeRsaKey(&rsa); + wc_FreeRng(&rng); + XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -1; + } + + pkcs12 = wc_PKCS12_create("test password", strlen("test password"), + NULL, keyDer, keySz, certDer, certSz, + NULL, PBE_SHA1_DES3, PBE_SHA1_DES3, 100, 100, 0, HEAP_HINT); + + if (pkcs12 != NULL) { + int ret; + int pkcs12DerSz = 0; + byte* pkcs12Der = NULL; + + printf("Created new PKCS12 structure now converting to DER\n"); + if ((ret = wc_i2d_PKCS12(pkcs12, &pkcs12Der, &pkcs12DerSz)) < 0) { + printf("unable to convert structure to DER\n"); + } + else { + char output[] = "output.p12"; + printf("Printing PKCS12 DER file to %s\n", output); + outputFile(pkcs12Der, ret, output); + XFREE(pkcs12Der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_PKCS12_free(pkcs12); + } + + wc_FreeRsaKey(&rsa); + wc_FreeRng(&rng); + XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +}