Merge pull request #203 from kaleb-himes/ZD10204-alt-name-to-cert

Example of setting alt names with crafted ASN.1 string
pull/204/head
David Garske 2020-05-08 06:50:58 -07:00 committed by GitHub
commit 792b04e4e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 364 additions and 13 deletions

1
.gitignore vendored
View File

@ -105,6 +105,7 @@ certgen/newCert*
certgen/certgen_example
certgen/csr_example
certgen/csr_w_ed25519_example
certgen/certgen_with_altnames
btle/ecc-client
btle/ecc-server

View File

@ -1,12 +1,11 @@
CC=gcc
#if you installed wolfssl to an alternate location use CFLAGS and LIBS to
#control your build:
#CFLAGS=-Wall -I/path/to/include
#LIBS=-L/path/to/lib -lwolfssl
#
#EXAMPLE:
#CFLAGS=-Wall -I/Users/khimes/work/testDir/wolf-install-dir-for-testing/include
#LIBS=-L/Users/khimes/work/testDir/wolf-install-dir-for-testing/lib -lwolfssl
#EXAMPLE: set WOLF_INSTALL_DIR to point to your install location like so:
# WOLF_INSTALL_DIR=/Users/kalebhimes/work/testDir/wolf-install-dir-for-testing
#END EXAMPLE
WOLF_INSTALL_DIR=/usr/local
@ -14,7 +13,7 @@ CFLAGS=-I$(WOLF_INSTALL_DIR)/include -Wall
LIBS=-L$(WOLF_INSTALL_DIR)/lib -lwolfssl
all:certgen_example csr_example csr_w_ed25519_example
all:certgen_example csr_example csr_w_ed25519_example certgen_with_altnames
certgen_example:certgen_example.o
$(CC) -o $@ $^ $(CFLAGS) $(CPPFLAGS) $(LIBS)
@ -25,8 +24,11 @@ csr_example:csr_example.o
csr_w_ed25519_example:csr_w_ed25519_example.o
$(CC) -o $@ $^ $(CFLAGS) $(CPPFLAGS) $(LIBS)
certgen_with_altnames:certgen_with_altnames.o
$(CC) -o $@ $^ $(CFLAGS) $(CPPFLAGS) $(LIBS)
.PHONY: clean all
clean:
rm -f *.o certgen_example csr_example csr_w_ed25519_example
rm -f *.o certgen_example csr_example csr_w_ed25519_example certgen_with_altnames
rm newCert.*

View File

@ -126,3 +126,62 @@ U3XQZoBnoAAwCgYIKoZIzj0EAwIDRwAwRAIgVh5iGYVmbwR4fhdjzCMI06wn2lGS
SmRM6YTRfMWRoSICIAlMGjRJlBKB9dlmukCdlHH3GXNOiKw1+iP/kApE8tRm
-----END CERTIFICATE REQUEST-----
```
## Certificate Generation Example with alt names
Pretty much the same as the certgen_example but adds some alt names to the cert
Unfortunately wolfSSL does not yet have an API for this but this example shows
how to setup your own ASN.1 format string for using with the wolfSSL certificate
structure. TODO: Add an API for this!
Example of a cert being generated with this example
```
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
08:1a:be:1b:2e:5a:c5:aa:2c:e5:6d:db:20:22:31:b5
Signature Algorithm: ecdsa-with-SHA256
Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com
Validity
Not Before: May 6 21:14:47 2020 GMT
Not After : Sep 19 21:14:47 2021 GMT
Subject: C = US, ST = MT, L = Bozeman, O = yourOrgNameHere, OU = yourUnitNameHere, CN = www.yourDomain.com, emailAddress = yourEmail@yourDomain.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:8e:dc:b9:92:59:51:40:2e:3f:33:44:55:70:80:
16:bc:41:84:ab:47:3e:8b:93:6a:a0:16:78:0a:e9:
49:9a:d5:fe:08:cc:c3:23:2f:26:5a:14:cc:b1:8e:
db:94:8d:ad:3c:57:a4:3b:4f:e2:f0:7e:28:33:01:
40:57:f0:85:b5
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:localhost, DNS:example.com, DNS:127.0.0.1
Signature Algorithm: ecdsa-with-SHA256
30:44:02:20:36:08:d9:df:9e:7f:c2:1c:0c:db:06:26:3d:fe:
8e:82:6e:64:07:6e:9b:fb:47:97:0a:d0:63:f6:6c:59:2a:82:
02:20:37:5c:00:eb:0d:7d:95:51:5d:8e:e9:06:c7:a5:6f:7d:
8b:1d:69:8d:8e:f8:5b:ba:13:0e:2a:5f:b4:86:1b:12
-----BEGIN CERTIFICATE-----
MIICbjCCAhWgAwIBAgIQCBq+Gy5axaos5W3bICIxtTAKBggqhkjOPQQDAjCBlDEL
MAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4x
ETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQD
DA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j
b20wIhgPMjAyMDA1MDYyMTE0NDdaGA8yMDIxMDkxOTIxMTQ0N1owgacxCzAJBgNV
BAYTAlVTMQswCQYDVQQIDAJNVDEQMA4GA1UEBwwHQm96ZW1hbjEYMBYGA1UECgwP
eW91ck9yZ05hbWVIZXJlMRkwFwYDVQQLDBB5b3VyVW5pdE5hbWVIZXJlMRswGQYD
VQQDDBJ3d3cueW91ckRvbWFpbi5jb20xJzAlBgkqhkiG9w0BCQEWGHlvdXJFbWFp
bEB5b3VyRG9tYWluLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI7cuZJZ
UUAuPzNEVXCAFrxBhKtHPouTaqAWeArpSZrV/gjMwyMvJloUzLGO25SNrTxXpDtP
4vB+KDMBQFfwhbWjMDAuMCwGA1UdEQQlMCOCCWxvY2FsaG9zdIILZXhhbXBsZS5j
b22CCTEyNy4wLjAuMTAKBggqhkjOPQQDAgNHADBEAiA2CNnfnn/CHAzbBiY9/o6C
bmQHbpv7R5cK0GP2bFkqggIgN1wA6w19lVFdjukGx6VvfYsdaY2O+Fu6Ew4qX7SG
GxI=
-----END CERTIFICATE-----
```

View File

@ -43,7 +43,8 @@ int main(void) {
word32 idx3 = 0;
/*---------------------------------------------------------------------------*/
/* open and read the der formatted certificate */
/* open the CA der formatted certificate, we need to get it's subject line to
* use in the new cert we're creating as the "Issuer" line */
/*---------------------------------------------------------------------------*/
printf("Open and read in der formatted certificate\n");
@ -61,13 +62,14 @@ int main(void) {
derBufSz = fread(derBuf, 1, FOURK_SZ, file);
fclose(file);
printf("Successfully read %d bytes\n\n", derBufSz);
printf("Successfully read the CA cert we are using to sign our new cert\n");
printf("Cert was %d bytes\n\n", derBufSz);
/*---------------------------------------------------------------------------*/
/* END */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* open caKey file and get the caKey */
/* open caKey file and get the caKey, we need it to sign our new cert */
/*---------------------------------------------------------------------------*/
printf("Getting the caKey from %s\n", caKeyFile);
@ -102,7 +104,7 @@ int main(void) {
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Generate new ecc key */
/* Generate new private key to go with our new cert */
/*---------------------------------------------------------------------------*/
printf("initializing the rng\n");
ret = wc_InitRng(&rng);
@ -121,7 +123,8 @@ int main(void) {
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Create a new certificate using header information from der cert */
/* Create a new certificate using SUBJECT information from ca cert
* for ISSUER information in generated cert */
/*---------------------------------------------------------------------------*/
printf("Setting new cert issuer to subject of signer\n");

View File

@ -0,0 +1,286 @@
#include <stdio.h>
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#define HEAP_HINT NULL
#define FOURK_SZ 4096
#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN)
void free_things(byte** a, byte** b, byte** c, ecc_key* d, ecc_key* e,
WC_RNG* f);
#endif
int main(void) {
#if !defined(WOLFSSL_CERT_REQ) || !defined(WOLFSSL_CERT_GEN) && \
!defined(WOLFSSL_ALT_NAMES)
printf("Please compile wolfSSL with the following and try again:\n");
printf(" --enable-certreq --enable-certgen CFLAGS=-DWOLFSSL_ALT_NAMES\n");
return 0;
#else
int ret = 0;
Cert newCert;
FILE* file;
char certToUse[] = "./ca-cert.der";
char caKeyFile[] = "./ca-key.der";
char newCertOutput[] = "./newCert.der";
int derBufSz;
int caKeySz;
byte* derBuf = NULL;
byte* pemBuf = NULL;
byte* caKeyBuf = NULL;
/* for MakeCert and SignCert */
WC_RNG rng;
ecc_key caKey;
ecc_key newKey;
word32 idx3 = 0;
/*---------------------------------------------------------------------------*/
/* open the CA der formatted certificate, we need to get it's subject line to
* use in the new cert we're creating as the "Issuer" line */
/*---------------------------------------------------------------------------*/
printf("Open and read in der formatted certificate\n");
derBuf = (byte*) XMALLOC(FOURK_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (derBuf == NULL) goto fail;
XMEMSET(derBuf, 0, FOURK_SZ);
file = fopen(certToUse, "rb");
if (!file) {
printf("failed to find file: %s\n", certToUse);
goto fail;
}
derBufSz = fread(derBuf, 1, FOURK_SZ, file);
fclose(file);
printf("Successfully read the CA cert we are using to sign our new cert\n");
printf("Cert was %d bytes\n\n", derBufSz);
derBufSz = FOURK_SZ;
/*---------------------------------------------------------------------------*/
/* END */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* open caKey file and get the caKey, we need it to sign our new cert */
/*---------------------------------------------------------------------------*/
printf("Getting the caKey from %s\n", caKeyFile);
caKeyBuf = (byte*) XMALLOC(FOURK_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (caKeyBuf == NULL) goto fail;
file = fopen(caKeyFile, "rb");
if (!file) {
printf("failed to open file: %s\n", caKeyFile);
goto fail;
}
caKeySz = fread(caKeyBuf, 1, FOURK_SZ, file);
if (caKeySz <= 0) {
printf("Failed to read caKey from file\n");
goto fail;
}
fclose(file);
printf("Successfully read %d bytes\n", caKeySz);
printf("Init ecc Key\n");
wc_ecc_init(&caKey);
printf("Decode the private key\n");
ret = wc_EccPrivateKeyDecode(caKeyBuf, &idx3, &caKey, (word32)caKeySz);
if (ret != 0) goto fail;
printf("Successfully retrieved caKey\n\n");
/*---------------------------------------------------------------------------*/
/* END */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Generate new private key to go with our new cert */
/*---------------------------------------------------------------------------*/
printf("initializing the rng\n");
ret = wc_InitRng(&rng);
if (ret != 0) goto fail;
printf("Generating a new ecc key\n");
ret = wc_ecc_init(&newKey);
if (ret != 0) goto fail;
ret = wc_ecc_make_key(&rng, 32, &newKey);
if (ret != 0) goto fail;
printf("Successfully created new ecc key\n\n");
/*---------------------------------------------------------------------------*/
/* END */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Create a new certificate using SUBJECT information from ca cert
* for ISSUER information in generated cert */
/*---------------------------------------------------------------------------*/
printf("Setting new cert issuer to subject of signer\n");
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);
/* Add some alt names to our cert: */
char myAltNames[] = {
/* SEQUENCE (1 element with 3 segements. Entire length is 35
* (0x29 in hex))
*/
/* 0x30 -> SEQUENCE, 0x23 -> Length of entire sequence */
0x30, 0x23,
/* This is a String 0x8, it denotes a DNSName 0x2 -> 0x82
* This strings' length is 9 (0x09)
*/
0x82, 0x09,
/* This strings value is "localhost" (in hex) */
0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74,
/* This is a String 0x8, it denotes a DNSName 0x2 -> 0x82
* This strings' length is 11 (0x0B)
*/
0x82, 0x0B,
/* This strings value is "example.com" (in hex) */
0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
/* This is a String 0x8, it denotes a DNSName 0x2 -> 0x82
* This strings' length is 9 (0x09)
*/
0x82, 0x09,
/* This strings value is "127.0.0.1" (in hex) */
0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31
};
XMEMCPY(newCert.altNames, myAltNames, sizeof(myAltNames));
newCert.altNamesSz = (int) sizeof(myAltNames);
newCert.isCA = 0;
newCert.sigType = CTC_SHA256wECDSA;
ret = wc_SetIssuerBuffer(&newCert, derBuf, derBufSz);
if (ret != 0) goto fail;
ret = wc_MakeCert(&newCert, derBuf, FOURK_SZ, NULL, &newKey, &rng); //ecc certificate
if (ret < 0) goto fail;
printf("MakeCert returned %d\n", ret);
ret = wc_SignCert(newCert.bodySz, newCert.sigType, derBuf, FOURK_SZ, NULL,
&caKey, &rng);
if (ret < 0) goto fail;
printf("SignCert returned %d\n", ret);
derBufSz = ret;
printf("Successfully created new certificate\n");
/*---------------------------------------------------------------------------*/
/* END */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* write the new cert to file in der format */
/*---------------------------------------------------------------------------*/
printf("Writing newly generated certificate to file \"%s\"\n",
newCertOutput);
file = fopen(newCertOutput, "wb");
if (!file) {
printf("failed to open file: %s\n", newCertOutput);
goto fail;
}
ret = (int) fwrite(derBuf, 1, derBufSz, file);
fclose(file);
printf("Successfully output %d bytes\n", ret);
/*---------------------------------------------------------------------------*/
/* END */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* convert the der to a pem and write it to a file */
/*---------------------------------------------------------------------------*/
{
char pemOutput[] = "./newCert.pem";
int pemBufSz;
printf("Convert the der cert to pem formatted cert\n");
pemBuf = (byte*) XMALLOC(FOURK_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (pemBuf == NULL) goto fail;
XMEMSET(pemBuf, 0, FOURK_SZ);
pemBufSz = wc_DerToPem(derBuf, derBufSz, pemBuf, FOURK_SZ, CERT_TYPE);
if (pemBufSz < 0) goto fail;
printf("Resulting pem buffer is %d bytes\n", pemBufSz);
file = fopen(pemOutput, "wb");
if (!file) {
printf("failed to open file: %s\n", pemOutput);
goto fail;
}
fwrite(pemBuf, 1, pemBufSz, file);
fclose(file);
printf("Successfully converted the der to pem. Result is in: %s\n\n",
pemOutput);
}
/*---------------------------------------------------------------------------*/
/* END */
/*---------------------------------------------------------------------------*/
goto success;
fail:
free_things(&derBuf, &pemBuf, &caKeyBuf, &caKey, &newKey, &rng);
printf("Failure code was %d\n", ret);
return -1;
success:
free_things(&derBuf, &pemBuf, &caKeyBuf, &caKey, &newKey, &rng);
printf("Tests passed\n");
return 0;
}
void free_things(byte** a, byte** b, byte** c, ecc_key* d, ecc_key* e,
WC_RNG* f)
{
if (a != NULL) {
if (*a != NULL) {
XFREE(*a, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
*a = NULL;
}
}
if (b != NULL) {
if (*b != NULL) {
XFREE(*b, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
*b = NULL;
}
}
if (c != NULL) {
if (*c != NULL) {
XFREE(*c, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
*c = NULL;
}
}
wc_ecc_free(d);
wc_ecc_free(e);
wc_FreeRng(f);
#endif
}