diff --git a/.gitignore b/.gitignore index f3b34ad3..2c62aa9c 100644 --- a/.gitignore +++ b/.gitignore @@ -177,10 +177,12 @@ pkcs7/compressedData pkcs7/*.der pkcs7/envelopedData-kari pkcs7/envelopedData-ktri +pkcs7/envelopedData-ktri-stream pkcs7/envelopedData-kekri pkcs7/envelopedData-pwri pkcs7/envelopedData-ori pkcs7/signedData +pkcs7/signedData-stream pkcs7/signedData-cryptodev pkcs7/signedData-FirmwarePkgData pkcs7/signedData-DetachedSignature diff --git a/pkcs7/envelopedData-ktri-stream.c b/pkcs7/envelopedData-ktri-stream.c new file mode 100644 index 00000000..653c34b1 --- /dev/null +++ b/pkcs7/envelopedData-ktri-stream.c @@ -0,0 +1,292 @@ +/* envelopedData-ktri-stream.c + * + * Copyright (C) 2006-2020 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-stream.der" + +FILE *fileOut, *fileIn; +#define TEST_SIZE 256 +static byte* contentRead = NULL; + +static int GetContentCB(PKCS7* pkcs7, byte** content) +{ + int ret; + + ret = fread(contentRead, 1, TEST_SIZE, fileIn); + *content = contentRead; + + return ret; +} + + +static int StreamOutputCB(PKCS7* pkcs7, const byte* output, word32 outputSz) +{ + if (outputSz > 0) { + if (fwrite(output, 1, outputSz, fileOut) != outputSz) { + return -1; + } + } + return 0; +} + + +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 envelopedData_encrypt(byte* cert, word32 certSz, byte* key, + word32 keySz, byte* out, word32 outSz, + word32 contentSz, byte useStreamMode) +{ + int ret; + PKCS7* pkcs7; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + pkcs7->content = NULL; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + + if (useStreamMode) { + wc_PKCS7_SetStreamMode(pkcs7, 1, GetContentCB, StreamOutputCB); + } + + /* 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 (%s), stream mode" + " %d\n", encodedFileKTRI, useStreamMode); + } + + 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) { + printf("Failed to decode EnvelopedData bundle (%s), error %d\n", + encodedFileKTRI, ret); + wc_PKCS7_Free(pkcs7); + return -1; + } else { + printf("Successfully decoded EnvelopedData bundle (%s)\n", + encodedFileKTRI); + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#if defined(HAVE_PKCS7) && defined(ASN_BER_TO_DER) + +#define EXTRA_ASN1_SIZE 1024 + +int main(int argc, char** argv) +{ + int ret = 0; + int encryptedSz = 0, decryptedSz; + word32 certSz, keySz, contentSz; + + byte cert[2048]; + byte key[2048]; + byte* encrypted = NULL; + byte* decrypted = NULL; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + if (argc != 2) { + printf("USAGE: ./%s \n", argv[0]); + return -1; + } + + if (wolfCrypt_Init() != 0) { + printf("Issue with wolfcrypt init\n"); + return -1; + } + + fileIn = fopen(argv[1], "rb"); + if (fileIn == NULL) { + printf("Issue opening file %s\n", argv[1]); + return -1; + } + + fileOut = fopen(encodedFileKTRI, "wb"); + if (fileOut == NULL) { + printf("Issue opening file %s\n", encodedFileKTRI); + fclose(fileIn); + return -1; + } + + contentRead = (byte*)XMALLOC(TEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (contentRead == NULL) { + printf("Unable to malloc content read buffer\n"); + ret = MEMORY_E; + } + + if (ret == 0) { + fseek(fileIn, 0, SEEK_END); + contentSz = ftell(fileIn); + fseek(fileIn, 0, SEEK_SET); + printf("contentSz = %d\n", contentSz); + + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + } + + if (ret == 0) { + encryptedSz = envelopedData_encrypt(cert, certSz, key, keySz, + encrypted, encryptedSz, contentSz, 1); + if (encryptedSz < 0) { + ret = encryptedSz; + printf("Issue %d with encrypt\n", ret); + } + } + fclose(fileIn); + fclose(fileOut); + + +#if 1 + decryptedSz = encryptedSz = contentSz + EXTRA_ASN1_SIZE; + if (ret == 0) { + encrypted = (byte*)XMALLOC(encryptedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + decrypted = (byte*)XMALLOC(decryptedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encrypted == NULL || decrypted == NULL) { + ret = MEMORY_E; + } + } + + if (ret == 0) { + FILE* f = fopen(encodedFileKTRI, "rb"); + encryptedSz = fread(encrypted, 1, encryptedSz, f); + fclose(f); + if (encryptedSz <= 0) { + printf("error reading file %s\n", encodedFileKTRI); + ret = -1; + } + } + + if (ret == 0) { + decryptedSz = envelopedData_decrypt(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, decryptedSz); + if (decryptedSz < 0) { + ret = decryptedSz; + printf("Issue %d with decrypt\n", ret); + } + } + +#endif + + if (contentRead != NULL) + XFREE(contentRead, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encrypted != NULL) + XFREE(encrypted, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (decrypted != NULL) + XFREE(decrypted, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +#else + +int main(int argc, char** argv) +{ + printf("Must build wolfSSL using ./configure --enable-pkcs7 --enable-indef\n"); + return 0; +} + +#endif + diff --git a/pkcs7/envelopedData-ktri.c b/pkcs7/envelopedData-ktri.c index f96c3b69..bb253a9d 100644 --- a/pkcs7/envelopedData-ktri.c +++ b/pkcs7/envelopedData-ktri.c @@ -95,7 +95,7 @@ static int envelopedData_encrypt(byte* cert, word32 certSz, byte* key, pkcs7->encryptOID = AES256CBCb; if (useStreamMode) { - wc_PKCS7_SetStreamMode(pkcs7, 1); + wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL); } /* add recipient using RSA certificate (KTRI type) */ diff --git a/pkcs7/signedData-stream.c b/pkcs7/signedData-stream.c new file mode 100644 index 00000000..0798601c --- /dev/null +++ b/pkcs7/signedData-stream.c @@ -0,0 +1,355 @@ +/* signedData-stream.c + * + * Copyright (C) 2006-2020 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 encodedFile "signedData_stream.der" + + +FILE *fileOut, *fileIn; +#define TEST_SIZE 256 +static byte* contentRead = NULL; + +static int GetContentCB(PKCS7* pkcs7, byte** content) +{ + int ret; + + ret = fread(contentRead, 1, TEST_SIZE, fileIn); + *content = contentRead; + + return ret; +} + + +static int StreamOutputCB(PKCS7* pkcs7, const byte* output, word32 outputSz) +{ + if (outputSz > 0) { + #if 0 + word32 z; + printf("Writing out %d bytes : ", outputSz); + for ( z = 0; z < outputSz; z++)printf("%02X", output[z]); + printf("\n"); + #endif + + if (fwrite(output, 1, outputSz, fileOut) != outputSz) { + return -1; + } + } + return 0; +} + + +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 signedData(byte* cert, word32 certSz, byte* key, word32 keySz, + int contentSz, byte* contentHash) +{ + int ret; + PKCS7* pkcs7; + WC_RNG rng; + word32 outputSz; + + 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 = NULL; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = DATA; + pkcs7->hashOID = SHA256h; + pkcs7->encryptOID = RSAk; + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + pkcs7->signedAttribs = attribs; + pkcs7->signedAttribsSz = sizeof(attribs)/sizeof(PKCS7Attrib); + + /* use streaming mode with IO callbacks */ + wc_PKCS7_SetStreamMode(pkcs7, 1, GetContentCB, StreamOutputCB); + + /* encode signedData, returns size */ + ret = wc_PKCS7_EncodeSignedData_ex(pkcs7, contentHash, WC_SHA256_DIGEST_SIZE, NULL, &outputSz, NULL, NULL); + 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 (%s)\n", + encodedFile); + +#ifdef DEBUG_WOLFSSL + printf("Encoded DER (%d bytes):\n", ret); + //WOLFSSL_BUFFER(out, ret); +#endif + } + + 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) { + if (ret == PKCS7_SIGNEEDS_CHECK) { + printf("WARNING: Parsed through bundle but no certificates found to" + " verify signature with\n"); + } + else { + printf("ERROR: Failed to verify SignedData bundle, ret = %d\n", + ret); + } + } else { + printf("Successfully verified SignedData bundle.\n"); + +#ifdef DEBUG_WOLFSSL + printf("Decoded content (%d bytes):\n", pkcs7->contentSz); + WOLFSSL_BUFFER(pkcs7->content, pkcs7->contentSz); +#endif + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + +#ifdef HAVE_PKCS7 + +int main(int argc, char** argv) +{ + int ret = 0; + int encryptedSz = 0, decryptedSz = 0, contentSz = 0; + word32 certSz, keySz; + + byte contentHash[WC_SHA256_DIGEST_SIZE]; + byte cert[2048]; + byte key[2048]; + byte *encrypted = NULL; + byte *decrypted = NULL; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + contentRead = (byte*)XMALLOC(TEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (contentRead == NULL) { + printf("Unable to malloc content read buffer\n"); + ret = MEMORY_E; + } + + if (ret == 0) { + fileIn = fopen(argv[1], "rb"); + if (fileIn == NULL) { + printf("Issue opening file %s\n", argv[1]); + XFREE(contentRead, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1; + } + } + + if (ret == 0) { + fileOut = fopen(encodedFile, "wb"); + if (fileOut == NULL) { + printf("Issue opening file %s\n", encodedFile); + fclose(fileIn); + XFREE(contentRead, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1; + } + } + + /* create hash of content, should be same hash type as pkcs7->hashOID */ + if (ret == 0) { + int readSz; + + wc_Sha256 sha256; + ret = wc_InitSha256(&sha256); + if (ret != 0) { + printf("Sha256 init failed, ret = %d\n", ret); + } + + if (ret == 0) { + do { + readSz = fread(contentRead, 1, TEST_SIZE, fileIn); + if (readSz > 0) { + ret = wc_Sha256Update(&sha256, contentRead, readSz); + if (ret != 0) { + printf("Sha256 update failed, ret = %d\n", ret); + break; + } + } + } while (readSz >= TEST_SIZE); + } + + if (ret == 0) { + ret = wc_Sha256Final(&sha256, contentHash); + if (ret != 0) { + printf("Sha256 final failed, ret = %d\n", ret); + } + } + wc_Sha256Free(&sha256); + } + + contentSz = ftell(fileIn); + fseek(fileIn, 0, SEEK_SET); + printf("contentSz = %d\n", contentSz); + + if (ret == 0) { + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + } + + /* default attributes + messageType attribute */ + if (ret == 0) { + encryptedSz = signedData(cert, certSz, key, keySz, contentSz, + contentHash); + } + + fclose(fileIn); + fclose(fileOut); + if (encryptedSz < 0) { + ret = encryptedSz; + printf("Error %d with signing data\n", ret); + goto out; + } + + if (ret != 0) + goto out; + +#if 1 + decryptedSz = encryptedSz; + encrypted = XMALLOC(encryptedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + decrypted = XMALLOC(decryptedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encrypted == NULL || decrypted == NULL) { + ret = MEMORY_E; + goto out; + } + + { + FILE* f = fopen(encodedFile, "rb"); + encryptedSz = fread(encrypted, 1, encryptedSz, f); + fclose(f); + } + if (encryptedSz <= 0) { + printf("error reading file %s\n", encodedFile); + goto out; + } + printf("read %d bytes from file\n", encryptedSz); + + decryptedSz = signedData_verify(encrypted, encryptedSz, + cert, certSz, key, keySz, + decrypted, decryptedSz); + if (decryptedSz < 0) + return -1; +#endif +out: + + if (contentRead != NULL) + XFREE(contentRead, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encrypted != NULL) + XFREE(encrypted, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (decrypted != NULL) + XFREE(decrypted, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +#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 index e54de988..37bdff6e 100644 --- a/pkcs7/signedData.c +++ b/pkcs7/signedData.c @@ -120,7 +120,7 @@ static int signedData_sign_noattrs(byte* cert, word32 certSz, byte* key, pkcs7->signedAttribsSz = 0; if (streamMode) { - wc_PKCS7_SetStreamMode(pkcs7, 1); + wc_PKCS7_SetStreamMode(pkcs7, 1, NULL, NULL); } if (noCerts) {