From c1cf06e217ee2b6176347d175d37839f114df460 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 12 Oct 2018 16:54:59 -0600 Subject: [PATCH] add simple CMS examples for different content types --- certs/ecc-client-key.der | Bin 0 -> 121 bytes pkcs7/Makefile | 11 +- pkcs7/README.md | 8 +- pkcs7/encryptedData.c | 133 +++++++ pkcs7/envelopedData-kari.c | 226 +++++++++++ pkcs7/envelopedData-ktri.c | 217 +++++++++++ pkcs7/envelopedData-ori.c | 292 +++++++++++++++ pkcs7/envelopedData-pwri.c | 228 ++++++++++++ pkcs7/signedData-CompressedFirmwarePkgData.c | 305 +++++++++++++++ ...dData-EncryptedCompressedFirmwarePkgData.c | 350 ++++++++++++++++++ pkcs7/signedData-EncryptedFirmwarePkgData.c | 329 ++++++++++++++++ pkcs7/signedData-FirmwarePkgData.c | 282 ++++++++++++++ pkcs7/signedData.c | 314 ++++++++++++++++ 13 files changed, 2692 insertions(+), 3 deletions(-) create mode 100644 certs/ecc-client-key.der create mode 100644 pkcs7/encryptedData.c create mode 100644 pkcs7/envelopedData-kari.c create mode 100644 pkcs7/envelopedData-ktri.c create mode 100644 pkcs7/envelopedData-ori.c create mode 100644 pkcs7/envelopedData-pwri.c create mode 100644 pkcs7/signedData-CompressedFirmwarePkgData.c create mode 100644 pkcs7/signedData-EncryptedCompressedFirmwarePkgData.c create mode 100644 pkcs7/signedData-EncryptedFirmwarePkgData.c create mode 100644 pkcs7/signedData-FirmwarePkgData.c create mode 100644 pkcs7/signedData.c diff --git a/certs/ecc-client-key.der b/certs/ecc-client-key.der new file mode 100644 index 0000000000000000000000000000000000000000..063739078888e7b0e0a84ad4c92ddc0929db6997 GIT binary patch literal 121 zcmV-<0EYiCcLD(c1R(g&l54#lDDkMPp(9T+bQp+Gt$xSslK798O|MpoWyhcj1_&yK zNX|V20SBQ(13~} +#include +#include +#include +#include + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static const byte aes256Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 +}; + +static int encryptedData_encrypt(byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, 0); + if (pkcs7 == NULL) + return -1; + + pkcs7->content = (byte*)data; + pkcs7->contentSz = sizeof(data); + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + pkcs7->encryptionKey = (byte*)aes256Key; + pkcs7->encryptionKeySz = sizeof(aes256Key); + + /* encode encryptedData, returns size */ + ret = wc_PKCS7_EncodeEncryptedData(pkcs7, out, outSz); + if (ret <= 0) { + wc_PKCS7_Free(pkcs7); + return -1; + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int encryptedData_decrypt(byte* in, word32 inSz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, 0); + if (pkcs7 == NULL) + return -1; + + pkcs7->encryptionKey = (byte*)aes256Key; + pkcs7->encryptionKeySz = sizeof(aes256Key); + + /* decrypt encryptedData, returns size */ + ret = wc_PKCS7_DecodeEncryptedData(pkcs7, in, inSz, out, outSz); + if (ret <= 0) { + wc_PKCS7_Free(pkcs7); + return -1; + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int encryptedSz, decryptedSz; + byte encrypted[1024]; + byte decrypted[1024]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + encryptedSz = encryptedData_encrypt(encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + printf("EncryptedData DER (%d byte):\n", encryptedSz); + WOLFSSL_BUFFER(encrypted, encryptedSz); + + decryptedSz = encryptedData_decrypt(encrypted, encryptedSz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + printf("DecryptedData DER (%d byte):\n", decryptedSz); + WOLFSSL_BUFFER(decrypted, decryptedSz); + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/envelopedData-kari.c b/pkcs7/envelopedData-kari.c new file mode 100644 index 00000000..9d752b9f --- /dev/null +++ b/pkcs7/envelopedData-kari.c @@ -0,0 +1,226 @@ +/* envelopedData-kari.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ +#include +#include +#include +#include +#include + +#define certFile "../certs/client-ecc-cert.der" +#define keyFile "../certs/ecc-client-key.der" + +#define encodedFileKARI "envelopedDataKARI.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) { + printf("ERROR: failed to open file: %s\n", certFile); + return -1; + } + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) { + printf("ERROR: failed to open file: %s\n", keyFile); + return -1; + } + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +static int envelopedData_encrypt(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + pkcs7->content = (byte*)data; + pkcs7->contentSz = sizeof(data); + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + + /* add recipient using ECC certificate (KARI type) */ + ret = wc_PKCS7_AddRecipient_KARI(pkcs7, cert, certSz, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, + NULL, 0, 0); + if (ret < 0) { + printf("wc_PKCS7_AddRecipient_KARI() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode envelopedData, returns size */ + ret = wc_PKCS7_EncodeEnvelopedData(pkcs7, out, outSz); + if (ret <= 0) { + printf("wc_PKCS7_EncodeEnvelopedData() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded EnvelopedData bundle.\n"); + + if (write_file_buffer(encodedFileKARI, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int envelopedData_decrypt(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* init with recipient cert */ + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert(), ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* set recipient private key */ + ret = wc_PKCS7_SetKey(pkcs7, key, keySz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_SetKey(), ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* decode envelopedData, returns size */ + ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, in, inSz, out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_DecodeEnvelopedData(), ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[1024]; + byte decrypted[1024]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + encryptedSz = envelopedData_encrypt(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + printf("EnvelopedData DER (%d byte):\n", encryptedSz); + WOLFSSL_BUFFER(encrypted, encryptedSz); + + decryptedSz = envelopedData_decrypt(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + printf("Decrypted content (%d byte):\n", decryptedSz); + WOLFSSL_BUFFER(decrypted, decryptedSz); + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/envelopedData-ktri.c b/pkcs7/envelopedData-ktri.c new file mode 100644 index 00000000..cbd8cb8b --- /dev/null +++ b/pkcs7/envelopedData-ktri.c @@ -0,0 +1,217 @@ +/* envelopedData-ktri.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ +#include +#include +#include +#include +#include + +#define certFile "../certs/client-cert.der" +#define keyFile "../certs/client-key.der" + +#define encodedFileKTRI "envelopedDataKTRI.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) + return -1; + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) + return -1; + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +static int envelopedData_encrypt(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + pkcs7->content = (byte*)data; + pkcs7->contentSz = sizeof(data); + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + + /* add recipient using RSA certificate (KTRI type) */ + ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, cert, certSz, 0); + if (ret < 0) { + printf("wc_PKCS7_AddRecipient_KTRI() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode envelopedData, returns size */ + ret = wc_PKCS7_EncodeEnvelopedData(pkcs7, out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeEnvelopedData() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded EnvelopedData bundle.\n"); + + if (write_file_buffer(encodedFileKTRI, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int envelopedData_decrypt(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* init with recipient cert */ + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* set recipient private key */ + ret = wc_PKCS7_SetKey(pkcs7, key, keySz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* decode envelopedData, returns size */ + ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, in, inSz, out, outSz); + if (ret <= 0) { + wc_PKCS7_Free(pkcs7); + return -1; + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[1024]; + byte decrypted[1024]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + encryptedSz = envelopedData_encrypt(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + printf("EnvelopedData DER (%d byte):\n", encryptedSz); + WOLFSSL_BUFFER(encrypted, encryptedSz); + + decryptedSz = envelopedData_decrypt(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + printf("Decrypted content (%d byte):\n", decryptedSz); + WOLFSSL_BUFFER(decrypted, decryptedSz); + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/envelopedData-ori.c b/pkcs7/envelopedData-ori.c new file mode 100644 index 00000000..1a218606 --- /dev/null +++ b/pkcs7/envelopedData-ori.c @@ -0,0 +1,292 @@ +/* envelopedData-ori.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ +#include +#include +#include +#include + +#define certFile "../certs/client-ecc-cert.der" +#define keyFile "../certs/ecc-client-key.der" + +#define encodedFileORI "envelopedDataORI.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static const byte asnDataOid[] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 +}; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) { + printf("ERROR: failed to open file: %s\n", certFile); + return -1; + } + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) { + printf("ERROR: failed to open file: %s\n", keyFile); + return -1; + } + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +/* ORI encrypt callback, responsible for encrypting content-encryption key (CEK) + * and giving wolfCrypt the value for oriOID and oriValue to place in + * OtherRecipientInfo. + * + * Returns 0 on success, negative upon error. */ +static int myOriEncryptCb(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* oriType, + word32* oriTypeSz, byte* oriValue, word32* oriValueSz, + void* ctx) +{ + int i; + + /* make sure buffers are large enough */ + if ((*oriValueSz < (2 + cekSz)) || (*oriTypeSz < sizeof(oriType))) + return -1; + + /* our simple encryption algorithm will be take the bitwise complement */ + oriValue[0] = 0x04; /*ASN OCTET STRING */ + oriValue[1] = (byte)cekSz; /* length */ + for (i = 0; i < (int)cekSz; i++) { + oriValue[2 + i] = ~cek[i]; + } + *oriValueSz = 2 + cekSz; + + /* set oriType to ASN.1 encoded data OID */ + XMEMCPY(oriType, asnDataOid, sizeof(asnDataOid)); + *oriTypeSz = sizeof(asnDataOid); + + (void)pkcs7; + (void)ctx; + + return 0; +} + +/* ORI decrypt callback, responsible for providing a decrypted content + * encryption key (CEK) placed into decryptedKey and size placed into + * decryptedKeySz. oriOID and oriValue are given to the callback to help + * in decrypting the encrypted CEK. + * + * Returns 0 on success, negative upon error. */ +static int myOriDecryptCb(PKCS7* pkcs7, byte* oriType, word32 oriTypeSz, + byte* oriValue, word32 oriValueSz, byte* decryptedKey, + word32* decryptedKeySz, void* ctx) +{ + int i; + + /* make sure oriType matches what we expect */ + if (oriTypeSz != sizeof(asnDataOid)) + return -1; + + if (XMEMCMP(oriType, asnDataOid, sizeof(asnDataOid)) != 0) + return -1; + + /* make sure decrypted buffer is large enough */ + if (*decryptedKeySz < oriValueSz) + return -1; + + /* decrypt encrypted CEK using simple bitwise complement, + only for example */ + for (i = 0; i < (int)oriValueSz - 2; i++) { + decryptedKey[i] = ~oriValue[2 + i]; + } + + *decryptedKeySz = oriValueSz - 2; + + (void)pkcs7; + (void)ctx; + + return 0; +} + +static int envelopedData_encrypt(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + pkcs7->content = (byte*)data; + pkcs7->contentSz = sizeof(data); + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + + /* add recipient using otherRecipientInfo (ORI) with custom encrypt + * callback to handle encryption. ORI is loosely defined, allowing + * advanced users or future protocols to extend the CMS RecipientInfo + * model. */ + ret = wc_PKCS7_AddRecipient_ORI(pkcs7, myOriEncryptCb, 0); + if (ret < 0) { + printf("wc_PKCS7_AddRecipient_ORI() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode envelopedData, returns size */ + ret = wc_PKCS7_EncodeEnvelopedData(pkcs7, out, outSz); + if (ret <= 0) { + printf("wc_PKCS7_EncodeEnvelopedData() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded EnvelopedData bundle.\n"); + + if (write_file_buffer(encodedFileORI, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int envelopedData_decrypt(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* set decrypt callback for decryption */ + ret = wc_PKCS7_SetOriDecryptCb(pkcs7, myOriDecryptCb); + if (ret != 0) { + printf("ERROR: wc_PKCS7_SetOriDecryptCb(), ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* decode envelopedData, returns size */ + ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, in, inSz, out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_DecodeEnvelopedData(), ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[1024]; + byte decrypted[1024]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + encryptedSz = envelopedData_encrypt(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + printf("EnvelopedData DER (%d byte):\n", encryptedSz); + WOLFSSL_BUFFER(encrypted, encryptedSz); + + decryptedSz = envelopedData_decrypt(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + printf("Decrypted content (%d byte):\n", decryptedSz); + WOLFSSL_BUFFER(decrypted, decryptedSz); + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/envelopedData-pwri.c b/pkcs7/envelopedData-pwri.c new file mode 100644 index 00000000..9fc1b0e7 --- /dev/null +++ b/pkcs7/envelopedData-pwri.c @@ -0,0 +1,228 @@ +/* envelopedData-pwri.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ +#include +#include +#include +#include + +#define certFile "../certs/client-ecc-cert.der" +#define keyFile "../certs/ecc-client-key.der" + +#define encodedFilePWRI "envelopedDataPWRI.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +const char password[] = "wolfsslPassword"; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) { + printf("ERROR: failed to open file: %s\n", certFile); + return -1; + } + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) { + printf("ERROR: failed to open file: %s\n", keyFile); + return -1; + } + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +static int envelopedData_encrypt(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + int kdfIterations = 5; + + byte salt[] = { + 0x12, 0x34, 0x56, 0x78, 0x56, 0x34, 0x12 + }; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + pkcs7->content = (byte*)data; + pkcs7->contentSz = sizeof(data); + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + + /* add recipient using password (PWRI type) */ + ret = wc_PKCS7_AddRecipient_PWRI(pkcs7, (byte*)password, + (word32)XSTRLEN(password), + salt, sizeof(salt), + PBKDF2_OID, WC_SHA, kdfIterations, + AES256CBCb, 0); + if (ret < 0) { + printf("wc_PKCS7_AddRecipient_PWRI() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode envelopedData, returns size */ + ret = wc_PKCS7_EncodeEnvelopedData(pkcs7, out, outSz); + if (ret <= 0) { + printf("wc_PKCS7_EncodeEnvelopedData() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded EnvelopedData bundle.\n"); + + if (write_file_buffer(encodedFilePWRI, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int envelopedData_decrypt(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* set password, for decryption */ + ret = wc_PKCS7_SetPassword(pkcs7, (byte*)password, + (word32)XSTRLEN(password)); + if (ret != 0) { + printf("ERROR: wc_PKCS7_SetPassword(), ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* decode envelopedData, returns size */ + ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, in, inSz, out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_DecodeEnvelopedData(), ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[1024]; + byte decrypted[1024]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + encryptedSz = envelopedData_encrypt(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + printf("EnvelopedData DER (%d byte):\n", encryptedSz); + WOLFSSL_BUFFER(encrypted, encryptedSz); + + decryptedSz = envelopedData_decrypt(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + printf("Decrypted content (%d byte):\n", decryptedSz); + WOLFSSL_BUFFER(decrypted, decryptedSz); + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/signedData-CompressedFirmwarePkgData.c b/pkcs7/signedData-CompressedFirmwarePkgData.c new file mode 100644 index 00000000..605c99c9 --- /dev/null +++ b/pkcs7/signedData-CompressedFirmwarePkgData.c @@ -0,0 +1,305 @@ +/* signedCompressedFirmwarePkgData.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + * + * DESCRIPTION: + * + * This file includes an example of generating a PKCS7/CMS signedData + * bundle which encapsulates a compressedData content type. The compressedData + * that is encapsulated has a content type of FirmwarePkgData. It uses the + * single-shot API to do this. + * + * There are two output files generated by this example: + * + * signedCompressedFPD_noattrs.der - without example of optional attributes + * signedCompressedFPD_attrs.der - with example of optional attributes + */ +#include +#include +#include +#include +#include + +#define certFile "../certs/client-cert.der" +#define keyFile "../certs/client-key.der" +#define encodedFileNoAttrs "signedCompressedFPD_noattrs.der" +#define encodedFileAttrs "signedCompressedFPD_attrs.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) + return -1; + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) + return -1; + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +static int signedData_sign_noattrs(byte* cert, word32 certSz, byte* privateKey, + word32 privateKeySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode Signed Compressed FirmwarePkgData */ + ret = wc_PKCS7_EncodeSignedCompressedFPD(pkcs7, privateKey, privateKeySz, + RSAk, SHA256h, (byte*)data, + sizeof(data), NULL, 0, out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedCompressedFPD() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded Signed Compressed FirmwarePkgData.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileNoAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int signedData_sign_attrs(byte* cert, word32 certSz, byte* privateKey, + word32 privateKeySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte messageType[] = { 0x13, 2, '1', '9' }; + + PKCS7Attrib attribs[] = + { + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) } + }; + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode Signed Compressed FirmwarePkgData */ + ret = wc_PKCS7_EncodeSignedCompressedFPD(pkcs7, privateKey, privateKeySz, + RSAk, SHA256h, (byte*)data, + sizeof(data), attribs, + sizeof(attribs)/sizeof(PKCS7Attrib), + out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedCompressedFPD() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded Signed Compressed FirmwarePkgData.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int signedData_verify(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* decode signedData, returns size */ + ret = wc_PKCS7_VerifySignedData(pkcs7, in, inSz); + + if (ret < 0) { + printf("ERROR: Failed to verify SignedData bundle, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* decode inner compressedData */ + ret = wc_PKCS7_DecodeCompressedData(pkcs7, pkcs7->content, pkcs7->contentSz, + out, outSz); + if (ret < 0) { + printf("ERROR: failed to decode inner CompressedData, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } + + /* compare decoded to expected */ + if ((ret != sizeof(data)) || XMEMCMP(data, out, ret)) { + printf("Extracted FirmwarePkgData data does not match expected!\n"); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully extracted and verified bundle contents\n"); + printf("Decoded content (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[2048]; + byte decrypted[2048]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + /* no attributes */ + encryptedSz = signedData_sign_noattrs(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + /* default attributes + messageType attribute */ + encryptedSz = signedData_sign_attrs(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/signedData-EncryptedCompressedFirmwarePkgData.c b/pkcs7/signedData-EncryptedCompressedFirmwarePkgData.c new file mode 100644 index 00000000..21c3943b --- /dev/null +++ b/pkcs7/signedData-EncryptedCompressedFirmwarePkgData.c @@ -0,0 +1,350 @@ +/* signedEncryptedCompressedFirmwarePkgData.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + * + * DESCRIPTION: + * + * This file includes an example of generating a PKCS7/CMS signedData + * bundle which encapsulates a compressedData content type, which then + * encapsulates an encryptedData content type. The compressedData + * that is encapsulated has a content type of FirmwarePkgData. It uses the + * single-shot API to do this. + * + * There are two output files generated by this example: + * + * signedEncryptedCompressedFPD_noattrs.der + * - without example of optional attributes + * signedEncryptedCompressedFPD_attrs.der + * - with example of optional attributes + */ +#include +#include +#include +#include +#include + +#define certFile "../certs/client-cert.der" +#define keyFile "../certs/client-key.der" +#define encodedFileNoAttrs "signedEncryptedCompressedFPD_noattrs.der" +#define encodedFileAttrs "signedEncryptedCompressedFPD_attrs.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static byte aes256Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 +}; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) + return -1; + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) + return -1; + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +static int signedData_sign_noattrs(byte* cert, word32 certSz, byte* privateKey, + word32 privateKeySz, byte* encryptKey, + word32 encryptKeySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode Signed Encrypted FirmwarePkgData */ + ret = wc_PKCS7_EncodeSignedEncryptedCompressedFPD(pkcs7, encryptKey, + encryptKeySz, privateKey, + privateKeySz, AES256CBCb, RSAk, + SHA256h, (byte*)data, sizeof(data), + NULL, 0, NULL, 0, + out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedEncryptedCompressedFPD() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded Signed Encrypted Compressed " + "FirmwarePkgData.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileNoAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int signedData_sign_attrs(byte* cert, word32 certSz, byte* privateKey, + word32 privateKeySz, byte* encryptKey, + word32 encryptKeySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte messageType[] = { 0x13, 2, '1', '9' }; + + PKCS7Attrib attribs[] = + { + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) } + }; + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode Signed Encrypted FirmwarePkgData */ + ret = wc_PKCS7_EncodeSignedEncryptedCompressedFPD(pkcs7, encryptKey, + encryptKeySz, privateKey, + privateKeySz, AES256CBCb, RSAk, + SHA256h, (byte*)data, sizeof(data), + attribs, + sizeof(attribs)/sizeof(PKCS7Attrib), + attribs, + sizeof(attribs)/sizeof(PKCS7Attrib), + out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedEncryptedCompressedFPD() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded Signed Encrypted Compressed " + "FirmwarePkgData.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int signedData_verify(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* encryptKey, word32 encryptKeySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + int encryptedSz = 0; + byte encrypted[2048]; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* decode signedData, returns size */ + ret = wc_PKCS7_VerifySignedData(pkcs7, in, inSz); + + if (ret < 0) { + printf("ERROR: Failed to verify SignedData bundle, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* decrypt inner encryptedData */ + pkcs7->encryptionKey = encryptKey; + pkcs7->encryptionKeySz = encryptKeySz; + + XMEMSET(encrypted, 0, sizeof(encrypted)); + encryptedSz = sizeof(encrypted); + + encryptedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, pkcs7->content, + pkcs7->contentSz, + encrypted, encryptedSz); + if (encryptedSz < 0) { + printf("ERROR: failed to decrypt inner EncryptedData, ret = %d\n", + encryptedSz); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* decompress inner compressedData */ + ret = wc_PKCS7_DecodeCompressedData(pkcs7, encrypted, encryptedSz, + out, outSz); + if (ret < 0) { + printf("ERROR: failed to decode inner CompressedData, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* compare decompressed to expected */ + if ((ret != sizeof(data)) || XMEMCMP(data, out, ret)) { + printf("Extracted FirmwarePkgData data does not match expected!\n"); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully extracted and verified bundle contents\n"); + printf("Decoded content (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[2048]; + byte decrypted[2048]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + /* no attributes */ + encryptedSz = signedData_sign_noattrs(cert, certSz, key, keySz, + aes256Key, sizeof(aes256Key), + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + aes256Key, sizeof(aes256Key), + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + /* default attributes + messageType attribute */ + encryptedSz = signedData_sign_attrs(cert, certSz, key, keySz, + aes256Key, sizeof(aes256Key), + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + aes256Key, sizeof(aes256Key), + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/signedData-EncryptedFirmwarePkgData.c b/pkcs7/signedData-EncryptedFirmwarePkgData.c new file mode 100644 index 00000000..836cdce0 --- /dev/null +++ b/pkcs7/signedData-EncryptedFirmwarePkgData.c @@ -0,0 +1,329 @@ +/* signedEncryptedFirmwarePkgData.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + * + * DESCRIPTION: + * + * This file includes an example of generating a PKCS7/CMS signedData + * bundle which encapsulates an encryptedData content type. The encryptedData + * that is encapsulated has a content type of FirmwarePkgData. It uses the + * single-shot API to do this. + * + * There are two output files generated by this example: + * + * signedEncryptedFPD_noattrs.der - without example of optional attributes + * signedEncryptedFPD_attrs.der - with example of optional attributes + */ +#include +#include +#include +#include +#include + +#define certFile "../certs/client-cert.der" +#define keyFile "../certs/client-key.der" +#define encodedFileNoAttrs "signedEncryptedFPD_noattrs.der" +#define encodedFileAttrs "signedEncryptedFPD_attrs.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static byte aes256Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 +}; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) + return -1; + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) + return -1; + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +static int signedData_sign_noattrs(byte* cert, word32 certSz, byte* privateKey, + word32 privateKeySz, byte* encryptKey, + word32 encryptKeySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode Signed Encrypted FirmwarePkgData */ + ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, encryptKey, encryptKeySz, + privateKey, privateKeySz, + AES256CBCb, RSAk, SHA256h, + (byte*)data, sizeof(data), + NULL, 0, NULL, 0, + out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedEncryptedFPD() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded Signed Encrypted FirmwarePkgData.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileNoAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int signedData_sign_attrs(byte* cert, word32 certSz, byte* privateKey, + word32 privateKeySz, byte* encryptKey, + word32 encryptKeySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte messageType[] = { 0x13, 2, '1', '9' }; + + PKCS7Attrib attribs[] = + { + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) } + }; + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode Signed Encrypted FirmwarePkgData */ + ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, encryptKey, encryptKeySz, + privateKey, privateKeySz, + AES256CBCb, RSAk, SHA256h, + (byte*)data, sizeof(data), + attribs, + sizeof(attribs)/sizeof(PKCS7Attrib), + attribs, + sizeof(attribs)/sizeof(PKCS7Attrib), + out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedEncryptedFPD() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded Signed Encrypted FirmwarePkgData.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int signedData_verify(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* encryptKey, word32 encryptKeySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* decode signedData, returns size */ + ret = wc_PKCS7_VerifySignedData(pkcs7, in, inSz); + + if (ret < 0) { + printf("ERROR: Failed to verify SignedData bundle, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* decrypt inner encryptedData */ + pkcs7->encryptionKey = encryptKey; + pkcs7->encryptionKeySz = encryptKeySz; + + ret = wc_PKCS7_DecodeEncryptedData(pkcs7, pkcs7->content, pkcs7->contentSz, + out, outSz); + if (ret < 0) { + printf("ERROR: failed to decrypt inner EncryptedData, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } + + /* compare decrypted to expected */ + if ((ret != sizeof(data)) || XMEMCMP(data, out, ret)) { + printf("Extracted FirmwarePkgData data does not match expected!\n"); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully extracted and verified bundle contents\n"); + printf("Decoded content (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[2048]; + byte decrypted[2048]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + /* no attributes */ + encryptedSz = signedData_sign_noattrs(cert, certSz, key, keySz, + aes256Key, sizeof(aes256Key), + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + aes256Key, sizeof(aes256Key), + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + /* default attributes + messageType attribute */ + encryptedSz = signedData_sign_attrs(cert, certSz, key, keySz, + aes256Key, sizeof(aes256Key), + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + aes256Key, sizeof(aes256Key), + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/signedData-FirmwarePkgData.c b/pkcs7/signedData-FirmwarePkgData.c new file mode 100644 index 00000000..570479be --- /dev/null +++ b/pkcs7/signedData-FirmwarePkgData.c @@ -0,0 +1,282 @@ +/* signedData_firmwarePkgData.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + * + * DESCRIPTION: + * + * This file includes an example of generating a PKCS7/CMS signedData + * bundle with an inner content type of FirmwarePkgData. It uses the + * single-shot API to do this. The same could be accomplished using the + * normal API (not single-shot) but by settings the pkcs7->contentOID to + * FIRMWARE_PKG_DATA before calling wc_PKCS7_EncodeSignedData() + */ +#include +#include +#include +#include +#include + +#define certFile "../certs/client-cert.der" +#define keyFile "../certs/client-key.der" +#define encodedFileNoAttrs "signedFirmwarePkgData_noattrs.der" +#define encodedFileAttrs "signedFirmwarePkgData_attrs.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) + return -1; + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) + return -1; + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +static int signedData_sign_noattrs(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode Signed FirmwarePkgData */ + ret = wc_PKCS7_EncodeSignedFPD(pkcs7, key, keySz, RSAk, SHA256h, + (byte*)data, sizeof(data), NULL, 0, + out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedFirmwarePkgData() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded Signed FirmwarePkgData bundle.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileNoAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int signedData_sign_attrs(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte messageType[] = { 0x13, 2, '1', '9' }; + + PKCS7Attrib attribs[] = + { + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) } + }; + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } + + /* encode Signed FirmwarePkgData */ + ret = wc_PKCS7_EncodeSignedFPD(pkcs7, key, keySz, RSAk, SHA256h, + (byte*)data, sizeof(data), attribs, + sizeof(attribs)/sizeof(PKCS7Attrib), + out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedFirmwarePkgData() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + + } else { + printf("Successfully encoded Signed FirmwarePkgData bundle.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +static int signedData_verify(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* decode signedData, returns size */ + ret = wc_PKCS7_VerifySignedData(pkcs7, in, inSz); + + if (ret < 0) { + printf("ERROR: Failed to verify SignedData bundle, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } else { + printf("Successfully verified SignedData bundle.\n"); + printf("Decoded content (%d bytes):\n", pkcs7->contentSz); + WOLFSSL_BUFFER(pkcs7->content, pkcs7->contentSz); + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[2048]; + byte decrypted[2048]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + /* no attributes */ + encryptedSz = signedData_sign_noattrs(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + /* default attributes + messageType attribute */ + encryptedSz = signedData_sign_attrs(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif + diff --git a/pkcs7/signedData.c b/pkcs7/signedData.c new file mode 100644 index 00000000..e4b6be6b --- /dev/null +++ b/pkcs7/signedData.c @@ -0,0 +1,314 @@ +/* signedData.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ +#include +#include +#include +#include +#include + +#define certFile "../certs/client-cert.der" +#define keyFile "../certs/client-key.der" +#define encodedFileNoAttrs "signedData_noattrs.der" +#define encodedFileAttrs "signedData_attrs.der" + +static const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 +}; + +static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) +{ + FILE* file; + + /* certificate file */ + file = fopen(certFile, "rb"); + if (!file) + return -1; + + *certSz = (word32)fread(cert, 1, *certSz, file); + fclose(file); + + /* key file */ + file = fopen(keyFile, "rb"); + if (!file) + return -1; + + *keySz = (word32)fread(key, 1, *keySz, file); + fclose(file); + + return 0; +} + +static int write_file_buffer(const char* fileName, byte* in, word32 inSz) +{ + int ret; + FILE* file; + + file = fopen(fileName, "wb"); + if (file == NULL) { + printf("ERROR: opening file for writing: %s\n", fileName); + return -1; + } + + ret = (int)fwrite(in, 1, inSz, file); + if (ret == 0) { + printf("ERROR: writing buffer to output file\n"); + return -1; + } + fclose(file); + + return 0; +} + +static int signedData_sign_noattrs(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + WC_RNG rng; + + /* init rng */ + ret = wc_InitRng(&rng); + if (ret != 0) { + printf("ERROR: wc_InitRng() failed, ret = %d\n", ret); + return -1; + } + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) { + wc_FreeRng(&rng); + return -1; + } + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + return -1; + } + + pkcs7->rng = &rng; + pkcs7->content = (byte*)data; + pkcs7->contentSz = sizeof(data); + pkcs7->contentOID = DATA; + pkcs7->hashOID = SHA256h; + pkcs7->encryptOID = RSAk; + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + pkcs7->signedAttribs = NULL; + pkcs7->signedAttribsSz = 0; + + /* encode signedData, returns size */ + ret = wc_PKCS7_EncodeSignedData(pkcs7, out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedData() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + return -1; + + } else { + printf("Successfully encoded SignedData bundle.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileNoAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + } + + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + + return ret; +} + +static int signedData_sign_attrs(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + WC_RNG rng; + + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte messageType[] = { 0x13, 2, '1', '9' }; + + PKCS7Attrib attribs[] = + { + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) } + }; + + /* init rng */ + ret = wc_InitRng(&rng); + if (ret != 0) { + printf("ERROR: wc_InitRng() failed, ret = %d\n", ret); + return -1; + } + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) { + wc_FreeRng(&rng); + return -1; + } + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + return -1; + } + + pkcs7->rng = &rng; + pkcs7->content = (byte*)data; + pkcs7->contentSz = sizeof(data); + pkcs7->contentOID = DATA; + pkcs7->hashOID = SHA256h; + pkcs7->encryptOID = RSAk; + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + pkcs7->signedAttribs = attribs; + pkcs7->signedAttribsSz = sizeof(attribs)/sizeof(PKCS7Attrib); + + /* encode signedData, returns size */ + ret = wc_PKCS7_EncodeSignedData(pkcs7, out, outSz); + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedData() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + return -1; + + } else { + printf("Successfully encoded SignedData bundle.\n"); + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); + + if (write_file_buffer(encodedFileAttrs, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + + return ret; +} + +static int signedData_verify(byte* in, word32 inSz, byte* cert, + word32 certSz, byte* key, word32 keySz, + byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + /* decode signedData, returns size */ + ret = wc_PKCS7_VerifySignedData(pkcs7, in, inSz); + + if (ret < 0) { + printf("ERROR: Failed to verify SignedData bundle, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -1; + } else { + printf("Successfully verified SignedData bundle.\n"); + printf("Decoded content (%d bytes):\n", pkcs7->contentSz); + WOLFSSL_BUFFER(pkcs7->content, pkcs7->contentSz); + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret; + int encryptedSz, decryptedSz; + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + byte encrypted[2048]; + byte decrypted[2048]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + /* no attributes */ + encryptedSz = signedData_sign_noattrs(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + /* default attributes + messageType attribute */ + encryptedSz = signedData_sign_attrs(cert, certSz, key, keySz, + encrypted, sizeof(encrypted)); + if (encryptedSz < 0) + return -1; + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, sizeof(decrypted)); + if (decryptedSz < 0) + return -1; + + (void)argc; + (void)argv; + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif +