add setter function for ctx and pkcs7 callback, add test cases

This commit is contained in:
Jacob Barthelmeh
2019-05-29 19:28:47 +07:00
parent 2972b1c467
commit ab0029f9ac
3 changed files with 380 additions and 2 deletions

View File

@@ -11339,7 +11339,8 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz,
if (pkcs7->decryptionCb != NULL) {
ret = pkcs7->decryptionCb(pkcs7, encOID, tmpIv, expBlockSz,
NULL, 0, NULL, 0, encryptedContent,
encryptedContentSz, encryptedContent);
encryptedContentSz, encryptedContent,
pkcs7->decryptionCtx);
}
else {
ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey,
@@ -11427,6 +11428,32 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz,
return ret;
}
/* Function to set callback during decryption, this overrides the default
* decryption function and can be used for choosing a key at run time based
* on the parsed bundle so far.
* returns 0 on success
*/
int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7,
CallbackDecryptContent decryptionCb)
{
if (pkcs7 != NULL) {
pkcs7->decryptionCb = decryptionCb;
}
return 0;
}
/* Set an optional user context that gets passed to callback
* returns 0 on success
*/
int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx)
{
if (pkcs7 != NULL) {
pkcs7->decryptionCtx = ctx;
}
return 0;
}
#endif /* NO_PKCS7_ENCRYPTED_DATA */
#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)

View File

@@ -364,6 +364,7 @@ int scrypt_test(void);
#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
int pkcs7authenveloped_test(void);
#endif
int pkcs7callback_test(byte* cert, word32 certSz, byte* key, word32 keySz);
#endif
#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) && \
!defined(NO_FILESYSTEM)
@@ -20779,6 +20780,113 @@ static int myOriDecryptCb(PKCS7* pkcs7, byte* oriType, word32 oriTypeSz,
}
/* returns 0 on success */
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 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
};
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
};
byte altKey[] = {
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08
};
/* test user context passed in */
if (*(int*)usrCtx != 1) {
return -1;
}
/* 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");
return -1;
}
else {
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 */
keyId = *(int*)(keyIdRaw + 2);
}
/* 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) {
key = altKey;
keySz = sizeof(altKey);
}
else {
key = defKey;
keySz = sizeof(defKey);
}
switch (encryptOID) {
case AES256CBCb:
if ((keySz != 32 ) || (ivSz != AES_BLOCK_SIZE))
return BAD_FUNC_ARG;
break;
case AES128CBCb:
if ((keySz != 16 ) || (ivSz != AES_BLOCK_SIZE))
return BAD_FUNC_ARG;
break;
default:
printf("Unsupported content cipher type for example");
return ALGO_ID_E;
};
ret = wc_AesInit(&aes, HEAP_HINT, 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);
}
(void)aad;
(void)aadSz;
(void)authTag;
(void)authTagSz;
return ret;
}
static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
byte* rsaPrivKey, word32 rsaPrivKeySz,
byte* eccCert, word32 eccCertSz,
@@ -21901,6 +22009,240 @@ int pkcs7authenveloped_test(void)
#endif /* HAVE_AESGCM || HAVE_AESCCM */
/*
* 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, byte* cert, word32 certSz,
byte* key, word32 keySz)
{
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) }
};
keyID[2] = keyHint;
/* 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;
}
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);
}
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 {
*outSz = ret;
}
wc_PKCS7_Free(pkcs7);
return ret;
}
/* test verification and decryption of PKCS7 bundle
* return 0 on success
*/
static int verifyBundle(byte* derBuf, word32 derSz)
{
int ret = 0;
int usrCtx = 1; /* test value to pass as user context to callback */
PKCS7 pkcs7;
byte* sid;
word32 sidSz;
byte decoded[FOURK_BUF/2];
int decodedSz = FOURK_BUF/2;
byte expectedSid[] = {
0x33, 0xD8, 0x45, 0x66, 0xD7, 0x68, 0x87, 0x18,
0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, 0xC7, 0x26,
0xD7, 0x85, 0x65, 0xC0
};
/* Test verify */
ret = wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID);
if (ret != 0) {
wc_PKCS7_Free(&pkcs7);
return -10001;
}
ret = wc_PKCS7_InitWithCert(&pkcs7, NULL, 0);
if (ret != 0) {
wc_PKCS7_Free(&pkcs7);
return -10001;
}
ret = wc_PKCS7_VerifySignedData(&pkcs7, derBuf, derSz);
if (ret != 0) {
wc_PKCS7_Free(&pkcs7);
return -10001;
}
/* Get size of SID and print it out */
ret = wc_PKCS7_GetSignerSID(&pkcs7, NULL, &sidSz);
if (ret != LENGTH_ONLY_E) {
wc_PKCS7_Free(&pkcs7);
return ret;
}
sid = (byte*)XMALLOC(sidSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (sid == NULL) {
wc_PKCS7_Free(&pkcs7);
return ret;
}
ret = wc_PKCS7_GetSignerSID(&pkcs7, sid, &sidSz);
if (ret != 0) {
wc_PKCS7_Free(&pkcs7);
XFREE(sid, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
ret = XMEMCMP(sid, expectedSid, sidSz);
XFREE(sid, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (ret != 0) {
wc_PKCS7_Free(&pkcs7);
return ret;
}
decodedSz = sizeof(decoded);
ret = wc_PKCS7_SetDecodeEncryptedCb(&pkcs7, myDecryptionFunc);
if (ret != 0) {
wc_PKCS7_Free(&pkcs7);
return ret;
}
ret = wc_PKCS7_SetDecodeEncryptedCtx(&pkcs7, (void*)&usrCtx);
if (ret != 0) {
wc_PKCS7_Free(&pkcs7);
return ret;
}
decodedSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, pkcs7.content,
pkcs7.contentSz, decoded, decodedSz);
if (decodedSz < 0) {
ret = decodedSz;
wc_PKCS7_Free(&pkcs7);
return ret;
}
wc_PKCS7_Free(&pkcs7);
return 0;
}
int pkcs7callback_test(byte* cert, word32 certSz, byte* key, word32 keySz)
{
int ret = 0;
byte derBuf[FOURK_BUF/2];
word32 derSz = FOURK_BUF/2;
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
};
byte altKey[] = {
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08
};
/* Doing default generation and verify */
ret = generateBundle(derBuf, &derSz, defKey, sizeof(defKey), 0, cert,
certSz, key, keySz);
if (ret <= 0) {
return -10000;
}
ret = verifyBundle(derBuf, derSz);
if (ret != 0) {
return -10001;
}
/* test choosing other key with keyID */
derSz = FOURK_BUF/2;
ret = generateBundle(derBuf, &derSz, altKey, sizeof(altKey), 1,
cert, certSz, key, keySz);
if (ret <= 0) {
return -10002;
}
ret = verifyBundle(derBuf, derSz);
if (ret != 0) {
return -10003;
}
/* test fail case with wrong keyID */
derSz = FOURK_BUF/2;
ret = generateBundle(derBuf, &derSz, defKey, sizeof(defKey), 1,
cert, certSz, key, keySz);
if (ret <= 0) {
return -10004;
}
ret = verifyBundle(derBuf, derSz);
if (ret == 0) {
return -10005;
}
return 0;
}
#ifndef NO_PKCS7_ENCRYPTED_DATA
@@ -23463,6 +23805,11 @@ int pkcs7signed_test(void)
eccClientCertBuf, (word32)eccClientCertBufSz,
eccClientPrivKeyBuf, (word32)eccClientPrivKeyBufSz);
if (ret >= 0)
ret = pkcs7callback_test(
rsaClientCertBuf, (word32)rsaClientCertBufSz,
rsaClientPrivKeyBuf, (word32)rsaClientPrivKeyBufSz);
XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(rsaServerCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);

View File

@@ -212,7 +212,7 @@ typedef int (*CallbackOriEncrypt)(PKCS7* pkcs7, byte* cek, word32 cekSz,
typedef int (*CallbackDecryptContent)(PKCS7* pkcs7, int encryptOID,
byte* iv, int ivSz, byte* aad, word32 aadSz,
byte* authTag, word32 authTagSz, byte* in,
int inSz, byte* out);
int inSz, byte* out, void* ctx);
/* Public Structure Warning:
* Existing members must not be changed to maintain backwards compatibility!
@@ -303,6 +303,7 @@ struct PKCS7 {
byte version; /* 1 for RFC 2315 and 3 for RFC 4108 */
PKCS7SignerInfo* signerInfo;
CallbackDecryptContent decryptionCb;
void* decryptionCtx;
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
};
@@ -444,6 +445,9 @@ WOLFSSL_API int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7,
WOLFSSL_API int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg,
word32 pkiMsgSz, byte* output,
word32 outputSz);
WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7,
CallbackDecryptContent decryptionCb);
WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx);
#endif /* NO_PKCS7_ENCRYPTED_DATA */
/* CMS/PKCS#7 CompressedData */