From ba6a8b84f855b75dc20d124b5c3608c6d9e1e348 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 29 May 2019 20:49:47 +0700 Subject: [PATCH 1/3] add firmware callback example --- pkcs7/Makefile | 2 + pkcs7/scripts/runall.sh | 1 + pkcs7/signedData-EncryptedFirmwareCB.c | 407 +++++++++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 pkcs7/signedData-EncryptedFirmwareCB.c diff --git a/pkcs7/Makefile b/pkcs7/Makefile index 3c14c10e..58e0a9ff 100644 --- a/pkcs7/Makefile +++ b/pkcs7/Makefile @@ -38,6 +38,8 @@ clean: rm -f $(TARGETS) signedData_attrs.der signedData_noattrs.der \ signedFirmwarePkgData.der signedFirmwarePkgData_attrs.der \ signedFirmwarePkgData_noattrs.der \ + signedData_EncryptedFPD_callback.der \ + signedData_EncryptedFPD_AES128_callback.der \ signedEncryptedFPD_attrs.der signedEncryptedFPD_noattrs.der \ signedCompressedFPD_attrs.der signedCompressedFPD_noattrs.der \ signedEncryptedCompressedFPD_attrs.der signedEncryptedCompressedFPD_noattrs.der \ diff --git a/pkcs7/scripts/runall.sh b/pkcs7/scripts/runall.sh index d667cf3c..8967f4a0 100755 --- a/pkcs7/scripts/runall.sh +++ b/pkcs7/scripts/runall.sh @@ -42,6 +42,7 @@ fileArray=( "signedData-CompressedFirmwarePkgData" "signedData-EncryptedCompressedFirmwarePkgData" "signedData-EncryptedFirmwarePkgData" + "signedData-EncryptedFirmwareCB" "signedData-FirmwarePkgData" "signedData-DetachedSignature" "signedData-cryptodev" diff --git a/pkcs7/signedData-EncryptedFirmwareCB.c b/pkcs7/signedData-EncryptedFirmwareCB.c new file mode 100644 index 00000000..3ad4115b --- /dev/null +++ b/pkcs7/signedData-EncryptedFirmwareCB.c @@ -0,0 +1,407 @@ +/* signedData-EncryptedFirmwareCB.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 + +#ifdef HAVE_PKCS7 + +#define certFile "../certs/client-cert.der" +#define keyFile "../certs/client-key.der" + +static byte defKey[] = { + 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 byte altKey[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 +}; + +#define OUTPUT_FILE "signedData_EncryptedFPD_callback.der" + +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 myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, + byte* aad, word32 aadSz, byte* authTag, word32 authTagSz, + byte* in, int inSz, byte* out, void* usrCtx) +{ + int i, keyId = -1, ret, keySz; + word32 keyIdSz = 8; + byte* key; + byte keyIdRaw[8]; + Aes aes; + + /* looking for KEY ID + * fwDecryptKeyID OID "1.2.840.113549.1.9.16.2.37 + */ + unsigned char OID[] = { + /* 0x06, 0x0B do not pass in tag and length */ + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x02, 0x25 + }; + + /* if needing to find keyIdSz can call with NULL */ + ret = wc_PKCS7_GetAttributeValue(pkcs7, OID, sizeof(OID), NULL, + &keyIdSz); + if (ret != LENGTH_ONLY_E) { + printf("Unexpected error %d when getting keyIdSz\n", ret); + printf("Possibly no KEY ID attribute set\n"); + } + else { + printf("Found keyID OID expected size of = %d bytes\n", keyIdSz); + memset(keyIdRaw, 0, sizeof(keyIdRaw)); + ret = wc_PKCS7_GetAttributeValue(pkcs7, OID, sizeof(OID), keyIdRaw, + &keyIdSz); + if (keyIdSz < 3) { + printf("keyIdSz is smaller than expected\n"); + return -1; + } + if (keyIdSz > 2 + sizeof(int)) { + printf("example case was only expecting a keyId of int size\n"); + return -1; + } + + /* keyIdRaw[0] OCTET TAG */ + /* keyIdRaw[1] Length */ + + if (ret > 0) { + printf("Found KEY ID RAW ASN1 :"); + for (i = 0; i < ret; i++) + printf("%02X", keyIdRaw[i]); + printf("\n"); + } + keyId = *(int*)(keyIdRaw + 2); + printf("\tstripping off OCTET TAG and length the keyId = %d\n", keyId); + } + + + /* Use keyID here if found to select key and decrypt in HSM or in this + * example just select key and do software decryption */ + if (keyId == 1) { + printf("Using AES-CBC 128 bit key\n"); + key = altKey; + keySz = sizeof(altKey); + } + else { + printf("Using default 256 bit AES key\n"); + key = defKey; + keySz = sizeof(defKey); + } + + + switch (encryptOID) { + case AES256CBCb: + if ((encryptOID == AES256CBCb && keySz != 32 ) || + (ivSz != AES_BLOCK_SIZE) ) + return BAD_FUNC_ARG; + /* fall through */ + + case AES128CBCb: + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(&aes, key, keySz, iv, AES_DECRYPTION); + if (ret == 0) + ret = wc_AesCbcDecrypt(&aes, out, in, inSz); + wc_AesFree(&aes); + } + break; + default: + printf("Unsupported content cipher type for example"); + return ALGO_ID_E; + }; + + return ret; +} + + +/* + * keyHint is the KeyID to be set in the fwDecryptKeyID attribute + * returns size of buffer output on success + */ +static int generateBundle(byte* out, word32 *outSz, byte* encryptKey, + word32 encryptKeySz, byte keyHint, char* fileName) +{ + int ret; + PKCS7* pkcs7; + + /* KEY ID + * fwDecryptKeyID OID 1.2.840.113549.1.9.16.2.37 + */ + unsigned char keyOID[] = { + 0x06, 0x0B, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x02, 0x25 + }; + byte keyID[] = { 0x04, 0x01, 0x00 }; + byte data[] = "Test of wolfSSL PKCS7 decrypt callback"; + + PKCS7Attrib attribs[] = + { + { keyOID, sizeof(keyOID), keyID, sizeof(keyID) } + }; + + word32 certSz, keySz; + + byte cert[2048]; + byte key[2048]; + + keyID[2] = keyHint; + certSz = sizeof(cert); + keySz = sizeof(key); + ret = load_certs(cert, &certSz, key, &keySz); + if (ret != 0) + return -1; + + /* 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 */ + if (encryptKeySz == 16) { + ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, encryptKey, encryptKeySz, + key, keySz, + AES128CBCb, RSAk, SHA256h, + (byte*)data, sizeof(data), + attribs, + sizeof(attribs)/sizeof(PKCS7Attrib), + attribs, + sizeof(attribs)/sizeof(PKCS7Attrib), + out, *outSz); + } + else { + ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, encryptKey, encryptKeySz, + key, keySz, + 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 (%s) with" + " key ID attribute\n", fileName); + +#ifdef DEBUG_WOLFSSL + printf("Encoded DER (%d bytes):\n", ret); + WOLFSSL_BUFFER(out, ret); +#endif + + *outSz = ret; + if (write_file_buffer(fileName, out, ret) != 0) { + printf("ERROR: error writing encoded to output file\n"); + return -1; + } + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + + +static int verifyBundle(byte* derBuf, word32 derSz) +{ + int ret = 0; + PKCS7 pkcs7; + byte* sid; + word32 sidSz; + word32 i; + + byte decoded[2048]; + int decodedSz = 2048; + + /* Test verify */ + ret = wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID); + if (ret != 0) goto exit; + ret = wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); + if (ret != 0) goto exit; + ret = wc_PKCS7_VerifySignedData(&pkcs7, derBuf, derSz); + if (ret != 0) goto exit; + + printf("PKCS7 Verify Success\n"); + + /* Get size of SID and print it out */ + ret = wc_PKCS7_GetSignerSID(&pkcs7, NULL, &sidSz); + if (ret != LENGTH_ONLY_E) goto exit; + + sid = (byte*)XMALLOC(sidSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sid == NULL) { + ret = MEMORY_E; + goto exit; + } + + ret = wc_PKCS7_GetSignerSID(&pkcs7, sid, &sidSz); + if (ret == 0) { + printf("Signers SID (SKID or issuerAndSerial):"); + for (i = 0; i < sidSz; i++) + printf("%02X", sid[i]); + printf("\n"); + } + XFREE(sid, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + printf("\nTrying to decode the enveloped data\n"); + decodedSz = sizeof(decoded); + ret = wc_PKCS7_SetDecodeEncryptedCb(&pkcs7, myDecryptionFunc); + decodedSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, pkcs7.content, + pkcs7.contentSz, decoded, decodedSz); + if (decodedSz < 0) { + ret = decodedSz; + printf("unable to decode enveloped data\n"); + } + else { + printf("Decoded successfully\n"); + } +exit: + + if (ret != 0) + printf("RC=%d\n", ret); + + wc_PKCS7_Free(&pkcs7); + return ret; +} + +int main(int argc, char** argv) +{ + int ret = 0; + XFILE derFile; + byte derBuf[2048]; + word32 derSz = 2048; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + if (argc < 2) { + printf("Doing default generation and verify\n"); + ret = generateBundle(derBuf, &derSz, defKey, sizeof(defKey), 0, + "signedData_EncryptedFPD_callback.der"); + if (ret <= 0) { + printf("unable to generate AES CBC bundle\n"); + return ret; + } + + derSz = 2048; + ret = generateBundle(derBuf, &derSz, altKey, sizeof(altKey), 1, + "signedData_EncryptedFPD_AES128_callback.der"); + if (ret <= 0) { + printf("unable to generate AES GCM bundle\n"); + return ret; + } + } + else { + printf("Trying to verify %s\n", argv[1]); + derFile = fopen(argv[1], "rb"); + if (derFile) { + ret = (int)fread(derBuf, 1, derSz, derFile); + fclose(derFile); + + if (ret >= derSz || ret < 0) { + printf("Failed to read der file!\n"); + return -1; + } + derSz = ret; + } + } + ret = verifyBundle(derBuf, derSz); + if (ret != 0) { + printf("Unable to verify bundle, error [%d]\n", ret); + } + + return 0; +} + +#else + +int main(int argc, char** argv) +{ + printf("Not compiled in: Must build wolfSSL using ./configure --enable-pkcs7\n"); + return 0; +} + +#endif From 107c93c6126ee5ab8141b4a7a862a22940c3d8c0 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 3 Jun 2019 22:44:29 +0700 Subject: [PATCH 2/3] update callback functions for kari --- pkcs7/signedData-EncryptedFirmwareCB.c | 352 ++++++++++++++++++++----- 1 file changed, 284 insertions(+), 68 deletions(-) diff --git a/pkcs7/signedData-EncryptedFirmwareCB.c b/pkcs7/signedData-EncryptedFirmwareCB.c index 3ad4115b..b1f567ed 100644 --- a/pkcs7/signedData-EncryptedFirmwareCB.c +++ b/pkcs7/signedData-EncryptedFirmwareCB.c @@ -89,43 +89,95 @@ static int write_file_buffer(const char* fileName, byte* in, word32 inSz) } +static int myCEKwrapFunc(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* keyId, + word32 keyIdSz, byte* originKey, word32 originKeySz, + byte* out, word32 outSz, int keyWrapAlgo, int type, int direction) +{ + int ret; + word32 i; + const char* name; + + switch (type) { + case PKCS7_KEKRI: name = "KEKRI"; break; + case PKCS7_KARI: name = "KARI"; break; + default: + name = "Not listed"; + break; + } + + printf("\t\tCEK unwrap callback for (%s)\n", name); + if (cek == NULL || out == NULL) + return BAD_FUNC_ARG; + + printf("\t\tKey ID (SKID for KARI) = "); + for (i = 0; i < keyIdSz; i++) + printf("%02X", keyId[i]); + printf("\n"); + + if (type == PKCS7_KARI && originKey != NULL) { + word32 i; + printf("\t\tDER origin key = "); + for (i = 0; i < originKeySz; i++) + printf("%02X", originKey[i]); + printf("\n"); + } + + switch (keyWrapAlgo) { + case AES256_WRAP: + ret = wc_AesKeyUnWrap(defKey, sizeof(defKey), cek, cekSz, + out, outSz, NULL); + break; + + default: + WOLFSSL_MSG("\t\tUnsupported key wrap algorithm in example"); + return BAD_KEYWRAP_ALG_E; + }; + + if (ret <= 0) { + printf("\t\tError %d when unwrapping CEK\n", ret); + } + + return ret; +} + + static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, byte* aad, word32 aadSz, byte* authTag, word32 authTagSz, byte* in, int inSz, byte* out, void* usrCtx) { int i, keyId = -1, ret, keySz; - word32 keyIdSz = 8; + word32 keyIdSz = 256; byte* key; - byte keyIdRaw[8]; + byte keyIdRaw[256]; Aes aes; /* looking for KEY ID * fwDecryptKeyID OID "1.2.840.113549.1.9.16.2.37 */ - unsigned char OID[] = { + const unsigned char fwDecryptKeyID[] = { /* 0x06, 0x0B do not pass in tag and length */ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x02, 0x25 }; /* if needing to find keyIdSz can call with NULL */ - ret = wc_PKCS7_GetAttributeValue(pkcs7, OID, sizeof(OID), NULL, - &keyIdSz); + ret = wc_PKCS7_GetAttributeValue(pkcs7, fwDecryptKeyID, + sizeof(fwDecryptKeyID), NULL, &keyIdSz); if (ret != LENGTH_ONLY_E) { - printf("Unexpected error %d when getting keyIdSz\n", ret); - printf("Possibly no KEY ID attribute set\n"); + printf("\tUnexpected error %d when getting keyIdSz\n", ret); + printf("\tPossibly no fwDecryptKeyID attribute set\n"); } else { - printf("Found keyID OID expected size of = %d bytes\n", keyIdSz); - memset(keyIdRaw, 0, sizeof(keyIdRaw)); - ret = wc_PKCS7_GetAttributeValue(pkcs7, OID, sizeof(OID), keyIdRaw, - &keyIdSz); + printf("\t\tFound keyID from fwDecryptKeyID\n"); + XMEMSET(keyIdRaw, 0, sizeof(keyIdRaw)); + ret = wc_PKCS7_GetAttributeValue(pkcs7, fwDecryptKeyID, + sizeof(fwDecryptKeyID), keyIdRaw, &keyIdSz); if (keyIdSz < 3) { - printf("keyIdSz is smaller than expected\n"); + printf("\t\tkeyIdSz is smaller than expected\n"); return -1; } if (keyIdSz > 2 + sizeof(int)) { - printf("example case was only expecting a keyId of int size\n"); + printf("\t\texample case was only expecting a keyId of int size\n"); return -1; } @@ -133,25 +185,24 @@ static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, /* keyIdRaw[1] Length */ if (ret > 0) { - printf("Found KEY ID RAW ASN1 :"); + printf("\t\tFound KEY ID RAW ASN1 :"); for (i = 0; i < ret; i++) printf("%02X", keyIdRaw[i]); printf("\n"); } keyId = *(int*)(keyIdRaw + 2); - printf("\tstripping off OCTET TAG and length the keyId = %d\n", keyId); + printf("\t\tStripping off OCTET TAG and length the keyId = %d\n", keyId); } - /* Use keyID here if found to select key and decrypt in HSM or in this * example just select key and do software decryption */ if (keyId == 1) { - printf("Using AES-CBC 128 bit key\n"); + printf("\t\tUsing AES-CBC 128 bit key\n"); key = altKey; keySz = sizeof(altKey); } else { - printf("Using default 256 bit AES key\n"); + printf("\t\tUsing default 256 bit AES key\n"); key = defKey; keySz = sizeof(defKey); } @@ -175,7 +226,7 @@ static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, } break; default: - printf("Unsupported content cipher type for example"); + printf("\t\tUnsupported content cipher type for example"); return ALGO_ID_E; }; @@ -183,11 +234,55 @@ static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, } +/* create a KEKRI enveloped data + * return size on success */ +static int envelopedData_encrypt(byte* in, word32 inSz, byte* out, word32 outSz) +{ + int ret; + PKCS7* pkcs7; + const byte keyId[] = { 0x01 }; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -1; + + pkcs7->content = in; + pkcs7->contentSz = inSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->encryptOID = AES256CBCb; + pkcs7->ukm = NULL; + pkcs7->ukmSz = 0; + + /* add recipient (KEKRI type) */ + ret = wc_PKCS7_AddRecipient_KEKRI(pkcs7, AES256_WRAP, defKey, + sizeof(defKey), (byte*)keyId, + sizeof(keyId), NULL, NULL, 0, NULL, 0, 0); + if (ret < 0) { + printf("wc_PKCS7_AddRecipient_KEKRI() 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; + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + + /* * keyHint is the KeyID to be set in the fwDecryptKeyID attribute * returns size of buffer output on success */ -static int generateBundle(byte* out, word32 *outSz, byte* encryptKey, +static int generateBundle(byte* out, word32 *outSz, const byte* encryptKey, word32 encryptKeySz, byte keyHint, char* fileName) { int ret; @@ -196,17 +291,27 @@ static int generateBundle(byte* out, word32 *outSz, byte* encryptKey, /* KEY ID * fwDecryptKeyID OID 1.2.840.113549.1.9.16.2.37 */ - unsigned char keyOID[] = { + const unsigned char fwDecryptKeyID[] = { 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x02, 0x25 }; + + /* fwWrappedFirmwareKey 1.2.840.113529.1.9.16.1.16 */ + const unsigned char fwWrappedFirmwareKey[] = { + 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x02, 0x27 + }; + byte keyID[] = { 0x04, 0x01, 0x00 }; - byte data[] = "Test of wolfSSL PKCS7 decrypt callback"; + byte env[256]; + char data[] = "Test of wolfSSL PKCS7 decrypt callback"; + int attribsNum = 1; PKCS7Attrib attribs[] = { - { keyOID, sizeof(keyOID), keyID, sizeof(keyID) } + { fwDecryptKeyID, sizeof(fwDecryptKeyID), keyID, sizeof(keyID) }, + { fwWrappedFirmwareKey, sizeof(fwWrappedFirmwareKey), env, 0 } }; word32 certSz, keySz; @@ -215,6 +320,16 @@ static int generateBundle(byte* out, word32 *outSz, byte* encryptKey, byte key[2048]; keyID[2] = keyHint; + + if (keyHint == 0) { + ret = envelopedData_encrypt(defKey, sizeof(defKey), env, sizeof(env)); + if (ret <= 0) { + return ret; + } + attribs[1].valueSz = ret; + attribsNum++; + } + certSz = sizeof(cert); keySz = sizeof(key); ret = load_certs(cert, &certSz, key, &keySz); @@ -233,28 +348,24 @@ static int generateBundle(byte* out, word32 *outSz, byte* encryptKey, return -1; } + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -1; + } + /* encode Signed Encrypted FirmwarePkgData */ if (encryptKeySz == 16) { - ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, encryptKey, encryptKeySz, - key, keySz, - AES128CBCb, RSAk, SHA256h, - (byte*)data, sizeof(data), - attribs, - sizeof(attribs)/sizeof(PKCS7Attrib), - attribs, - sizeof(attribs)/sizeof(PKCS7Attrib), - out, *outSz); + ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, (byte*)encryptKey, + encryptKeySz, key, keySz, AES128CBCb, RSAk, SHA256h, + (byte*)data, sizeof(data), NULL, 0, attribs, attribsNum, + out, *outSz); } else { - ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, encryptKey, encryptKeySz, - key, keySz, - AES256CBCb, RSAk, SHA256h, - (byte*)data, sizeof(data), - attribs, - sizeof(attribs)/sizeof(PKCS7Attrib), - attribs, - sizeof(attribs)/sizeof(PKCS7Attrib), - out, *outSz); + ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, (byte*)encryptKey, + encryptKeySz, key, keySz, AES256CBCb, RSAk, SHA256h, + (byte*)data, sizeof(data), NULL, 0, attribs, attribsNum, + out, *outSz); } if (ret <= 0) { printf("ERROR: wc_PKCS7_EncodeSignedEncryptedFPD() failed, " @@ -285,29 +396,115 @@ static int generateBundle(byte* out, word32 *outSz, byte* encryptKey, } +/* returns key size on success */ +static int getFirmwareKey(PKCS7* pkcs7, byte* key, word32 keySz) +{ + int ret, i; + word32 atrSz; + byte atr[256]; + + /* Additionally can look for fwWrappedFirmwareKey + * 1.2.840.113529.1.9.16.1.16 */ + const unsigned char fwWrappedFirmwareKey[] = { + /* 0x06, 0x0B */ + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x02, 0x27 + }; + + /* find keyID in fwWrappedFirmwareKey */ + printf("\tChecking for KEKRI firmware attribute ... "); + ret = wc_PKCS7_GetAttributeValue(pkcs7, fwWrappedFirmwareKey, + sizeof(fwWrappedFirmwareKey), NULL, &atrSz); + if (ret == LENGTH_ONLY_E) { + XMEMSET(atr, 0, sizeof(atr)); + ret = wc_PKCS7_GetAttributeValue(pkcs7, fwWrappedFirmwareKey, + sizeof(fwWrappedFirmwareKey), atr, &atrSz); + + /* keyIdRaw[0] OCTET TAG */ + /* keyIdRaw[1] Length */ + + if (ret > 0) { + PKCS7* envPkcs7; + + printf("Found attribute\n\tRAW ASN1 :"); + for (i = 0; i < ret; i++) + printf("%02X", atr[i]); + printf("\n"); + + envPkcs7 = wc_PKCS7_New(NULL, 0); + if (envPkcs7 == NULL) { + return MEMORY_E; + } + + wc_PKCS7_Init(envPkcs7, NULL, 0); + wc_PKCS7_SetWrapCEKCb(envPkcs7, myCEKwrapFunc); + envPkcs7->contentOID = FIRMWARE_PKG_DATA; + ret = wc_PKCS7_DecodeEnvelopedData(envPkcs7, atr, ret, + key, keySz); + wc_PKCS7_Free(envPkcs7); + } + } + else { + printf("not found\n"); + } + + if (ret != 0) { + printf("\tError %d (%s) parsing fwWrappedFirmwareKey enveloped data\n", + ret, wc_GetErrorString(ret)); + } + + return ret; +} + + static int verifyBundle(byte* derBuf, word32 derSz) { int ret = 0; - PKCS7 pkcs7; + PKCS7* pkcs7; byte* sid; word32 sidSz; word32 i; + byte key[256]; + int keySz; byte decoded[2048]; int decodedSz = 2048; - /* Test verify */ - ret = wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID); - if (ret != 0) goto exit; - ret = wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); - if (ret != 0) goto exit; - ret = wc_PKCS7_VerifySignedData(&pkcs7, derBuf, derSz); - if (ret != 0) goto exit; + pkcs7 = wc_PKCS7_New(NULL, 0); + + /* Test verify */ + ret = wc_PKCS7_Init(pkcs7, NULL, INVALID_DEVID); + if (ret != 0) goto exit; + ret = wc_PKCS7_InitWithCert(pkcs7, NULL, 0); + if (ret != 0) goto exit; + ret = wc_PKCS7_VerifySignedData(pkcs7, derBuf, derSz); + if (ret == PKCS7_SIGNEEDS_CHECK) { + printf("\tNo certificates available to verify!!!\n"); + printf("\tSignature : "); + for (i = 0; i < pkcs7->signatureSz; i++) + printf("%02X", pkcs7->signature[i]); + printf("\n"); + + printf("\t(CMS / ECC) Digest: "); + for (i = 0; i < pkcs7->plainDigestSz; i++) + printf("%02X", pkcs7->plainDigest[i]); + printf("\n"); + + printf("\tRSA Digest: "); + for (i = 0; i < pkcs7->plainDigestSz; i++) + printf("%02X", pkcs7->plainDigest[i]); + printf("\n"); + + printf("\tUser should verify here, continuing on\n"); + } + else { + if (ret != 0) goto exit; + printf("\tPKCS7 Verify Success\n"); + } - printf("PKCS7 Verify Success\n"); /* Get size of SID and print it out */ - ret = wc_PKCS7_GetSignerSID(&pkcs7, NULL, &sidSz); + ret = wc_PKCS7_GetSignerSID(pkcs7, NULL, &sidSz); if (ret != LENGTH_ONLY_E) goto exit; sid = (byte*)XMALLOC(sidSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -316,33 +513,44 @@ static int verifyBundle(byte* derBuf, word32 derSz) goto exit; } - ret = wc_PKCS7_GetSignerSID(&pkcs7, sid, &sidSz); + ret = wc_PKCS7_GetSignerSID(pkcs7, sid, &sidSz); if (ret == 0) { - printf("Signers SID (SKID or issuerAndSerial):"); + printf("\tSigners SID (SKID or issuerAndSerial):"); for (i = 0; i < sidSz; i++) printf("%02X", sid[i]); printf("\n"); } XFREE(sid, NULL, DYNAMIC_TYPE_TMP_BUFFER); - printf("\nTrying to decode the enveloped data\n"); - decodedSz = sizeof(decoded); - ret = wc_PKCS7_SetDecodeEncryptedCb(&pkcs7, myDecryptionFunc); - decodedSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, pkcs7.content, - pkcs7.contentSz, decoded, decodedSz); - if (decodedSz < 0) { - ret = decodedSz; - printf("unable to decode enveloped data\n"); + keySz = getFirmwareKey(pkcs7, key, sizeof(key)); + + printf("\tTrying to decode the enveloped data"); + if (keySz > 0) { + printf(" using firmware key from fwWrappedFirmwareKey\n"); + pkcs7->encryptionKey = key; + pkcs7->encryptionKeySz = keySz; } else { - printf("Decoded successfully\n"); + printf(" using decrypt function callback\n"); + ret = wc_PKCS7_SetDecodeEncryptedCb(pkcs7, myDecryptionFunc); + } + + decodedSz = sizeof(decoded); + decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, pkcs7->content, + pkcs7->contentSz, decoded, decodedSz); + if (decodedSz < 0) { + ret = decodedSz; + printf("\tUnable to decode enveloped data\n"); + } + else { + printf("\tDecoded successfully\n"); } exit: if (ret != 0) - printf("RC=%d\n", ret); + printf("\tERROR = %d\n", ret); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); return ret; } @@ -350,8 +558,8 @@ int main(int argc, char** argv) { int ret = 0; XFILE derFile; - byte derBuf[2048]; - word32 derSz = 2048; + byte derBuf[4096]; + word32 derSz = 4096; #ifdef DEBUG_WOLFSSL wolfSSL_Debugging_ON(); @@ -366,11 +574,19 @@ int main(int argc, char** argv) return ret; } - derSz = 2048; + printf("\nTrying to verify signedData_EncryptedFPD_callback.der\n"); + ret = verifyBundle(derBuf, derSz); + if (ret != 0) { + printf("\tUnable to verify bundle, error [%d]\n", ret); + return ret; + } + + derSz = 4096; ret = generateBundle(derBuf, &derSz, altKey, sizeof(altKey), 1, "signedData_EncryptedFPD_AES128_callback.der"); + printf("\nTrying to verify signedData_EncryptedFPD_AES128_callback.der\n"); if (ret <= 0) { - printf("unable to generate AES GCM bundle\n"); + printf("\tunable to generate AES GCM bundle\n"); return ret; } } From 538cd30774e35dcf21d3b6e7759c8bf4424bdd29 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 5 Jun 2019 09:32:26 +0700 Subject: [PATCH 3/3] macro for file name and formating --- pkcs7/signedData-EncryptedFirmwareCB.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/pkcs7/signedData-EncryptedFirmwareCB.c b/pkcs7/signedData-EncryptedFirmwareCB.c index b1f567ed..b07d5ced 100644 --- a/pkcs7/signedData-EncryptedFirmwareCB.c +++ b/pkcs7/signedData-EncryptedFirmwareCB.c @@ -43,6 +43,7 @@ static byte altKey[] = { }; #define OUTPUT_FILE "signedData_EncryptedFPD_callback.der" +#define OUTPUT_FILE_AES128 "signedData_EncryptedFPD_AES128_callback.der" static int load_certs(byte* cert, word32* certSz, byte* key, word32* keySz) { @@ -141,6 +142,7 @@ static int myCEKwrapFunc(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* keyId, } +/* callback function for wc_PKCS7_DeocdeEncryptedData */ static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, byte* aad, word32 aadSz, byte* authTag, word32 authTagSz, byte* in, int inSz, byte* out, void* usrCtx) @@ -412,7 +414,7 @@ static int getFirmwareKey(PKCS7* pkcs7, byte* key, word32 keySz) }; /* find keyID in fwWrappedFirmwareKey */ - printf("\tChecking for KEKRI firmware attribute ... "); + printf("\tChecking for fwWrappedFirmwareKey attribute ... "); ret = wc_PKCS7_GetAttributeValue(pkcs7, fwWrappedFirmwareKey, sizeof(fwWrappedFirmwareKey), NULL, &atrSz); if (ret == LENGTH_ONLY_E) { @@ -420,9 +422,6 @@ static int getFirmwareKey(PKCS7* pkcs7, byte* key, word32 keySz) ret = wc_PKCS7_GetAttributeValue(pkcs7, fwWrappedFirmwareKey, sizeof(fwWrappedFirmwareKey), atr, &atrSz); - /* keyIdRaw[0] OCTET TAG */ - /* keyIdRaw[1] Length */ - if (ret > 0) { PKCS7* envPkcs7; @@ -437,8 +436,11 @@ static int getFirmwareKey(PKCS7* pkcs7, byte* key, word32 keySz) } wc_PKCS7_Init(envPkcs7, NULL, 0); - wc_PKCS7_SetWrapCEKCb(envPkcs7, myCEKwrapFunc); - envPkcs7->contentOID = FIRMWARE_PKG_DATA; + if (wc_PKCS7_SetWrapCEKCb(envPkcs7, myCEKwrapFunc) != 0) { + printf("\tIssue setting CEK wrap callback\n"); + return ret; + } + envPkcs7->contentOID = FIRMWARE_PKG_DATA; /* expected content */ ret = wc_PKCS7_DecodeEnvelopedData(envPkcs7, atr, ret, key, keySz); wc_PKCS7_Free(envPkcs7); @@ -448,7 +450,7 @@ static int getFirmwareKey(PKCS7* pkcs7, byte* key, word32 keySz) printf("not found\n"); } - if (ret != 0) { + if (ret <= 0) { printf("\tError %d (%s) parsing fwWrappedFirmwareKey enveloped data\n", ret, wc_GetErrorString(ret)); } @@ -568,13 +570,13 @@ int main(int argc, char** argv) if (argc < 2) { printf("Doing default generation and verify\n"); ret = generateBundle(derBuf, &derSz, defKey, sizeof(defKey), 0, - "signedData_EncryptedFPD_callback.der"); + OUTPUT_FILE); if (ret <= 0) { printf("unable to generate AES CBC bundle\n"); return ret; } - printf("\nTrying to verify signedData_EncryptedFPD_callback.der\n"); + printf("\nTrying to verify %s\n", OUTPUT_FILE); ret = verifyBundle(derBuf, derSz); if (ret != 0) { printf("\tUnable to verify bundle, error [%d]\n", ret); @@ -583,8 +585,8 @@ int main(int argc, char** argv) derSz = 4096; ret = generateBundle(derBuf, &derSz, altKey, sizeof(altKey), 1, - "signedData_EncryptedFPD_AES128_callback.der"); - printf("\nTrying to verify signedData_EncryptedFPD_AES128_callback.der\n"); + OUTPUT_FILE_AES128); + printf("\nTrying to verify %s\n", OUTPUT_FILE_AES128); if (ret <= 0) { printf("\tunable to generate AES GCM bundle\n"); return ret;