diff --git a/.gitignore b/.gitignore index 9191dbe7..623487a5 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/certgen/Makefile b/certgen/Makefile index 3ede287d..0b6156b4 100644 --- a/certgen/Makefile +++ b/certgen/Makefile @@ -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.* diff --git a/certgen/README.md b/certgen/README.md index 8819c38a..68ad2328 100644 --- a/certgen/README.md +++ b/certgen/README.md @@ -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----- +``` diff --git a/certgen/certgen_example.c b/certgen/certgen_example.c index 4edda004..a5e3f097 100644 --- a/certgen/certgen_example.c +++ b/certgen/certgen_example.c @@ -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"); diff --git a/certgen/certgen_with_altnames.c b/certgen/certgen_with_altnames.c new file mode 100644 index 00000000..34ddd51a --- /dev/null +++ b/certgen/certgen_with_altnames.c @@ -0,0 +1,286 @@ +#include +#include +#include +#include +#include +#include +#include + +#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 +}