forked from wolfSSL/wolfssl
add test for degenerate case and allow degenerate case by default
This commit is contained in:
@ -37,6 +37,7 @@ EXTRA_DIST += \
|
||||
certs/server-revoked-cert.pem \
|
||||
certs/server-revoked-key.pem \
|
||||
certs/wolfssl-website-ca.pem \
|
||||
certs/test-degenerate.p7b \
|
||||
certs/test-servercert.p12 \
|
||||
certs/ecc-rsa-server.p12 \
|
||||
certs/dsaparams.pem \
|
||||
|
@ -30,6 +30,9 @@
|
||||
# crl/crl.revoked
|
||||
# crl/eccCliCRL.pem
|
||||
# crl/eccSrvCRL.pem
|
||||
#
|
||||
# pkcs7:
|
||||
# test-degenerate.p7b
|
||||
# if HAVE_NTRU
|
||||
# ntru-cert.pem
|
||||
# ntru-key.raw
|
||||
@ -570,6 +573,19 @@ run_renewcerts(){
|
||||
echo "ran ./gencrls.sh"
|
||||
echo ""
|
||||
|
||||
############################################################
|
||||
########## generate PKCS7 bundles ##########################
|
||||
############################################################
|
||||
echo "Changing directory to wolfssl certs..."
|
||||
echo ""
|
||||
cd ../ || exit 1
|
||||
echo "Creating test-degenerate.p7b..."
|
||||
echo ""
|
||||
openssl crl2pkcs7 -nocrl -certfile ./client-cert.pem -out test-degenerate.p7b -outform DER
|
||||
check_result $? ""
|
||||
echo "End of section"
|
||||
echo "---------------------------------------------------------------------"
|
||||
|
||||
#cleanup the file system now that we're done
|
||||
echo "Performing final steps, cleaning up the file system..."
|
||||
echo ""
|
||||
|
BIN
certs/test-degenerate.p7b
Normal file
BIN
certs/test-degenerate.p7b
Normal file
Binary file not shown.
37
tests/api.c
37
tests/api.c
@ -15897,6 +15897,42 @@ static void test_wc_PKCS7_EncodeEncryptedData (void)
|
||||
#endif
|
||||
} /* END test_wc_PKCS7_EncodeEncryptedData() */
|
||||
|
||||
/*
|
||||
* Testing wc_PKCS7_Degenerate()
|
||||
*/
|
||||
static void test_wc_PKCS7_Degenerate(void)
|
||||
{
|
||||
#if defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM)
|
||||
PKCS7 pkcs7;
|
||||
char fName[] = "./certs/test-degenerate.p7b";
|
||||
XFILE f;
|
||||
byte der[4096];
|
||||
word32 derSz;
|
||||
|
||||
printf(testingFmt, "wc_PKCS7_Degenerate()");
|
||||
|
||||
AssertNotNull(f = XFOPEN(fName, "rb"));
|
||||
AssertIntGT((derSz = fread(der, 1, sizeof(der), f)), 0);
|
||||
XFCLOSE(f);
|
||||
|
||||
/* test degenerate success */
|
||||
AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0);
|
||||
AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0);
|
||||
AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, der, derSz), 0);
|
||||
wc_PKCS7_Free(&pkcs7);
|
||||
|
||||
/* test with turning off degenerate cases */
|
||||
AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0);
|
||||
AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0);
|
||||
wc_PKCS7_AllowDegenerate(&pkcs7, 0); /* override allowing degenerate case */
|
||||
AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, der, derSz), PKCS7_NO_SIGNER_E);
|
||||
wc_PKCS7_Free(&pkcs7);
|
||||
|
||||
printf(resultFmt, passed);
|
||||
#endif
|
||||
} /* END test_wc_PKCS7_Degenerate() */
|
||||
|
||||
|
||||
/* Testing wc_SignatureGetSize() for signature type ECC */
|
||||
static int test_wc_SignatureGetSize_ecc(void)
|
||||
{
|
||||
@ -22474,6 +22510,7 @@ void ApiTest(void)
|
||||
test_wc_PKCS7_VerifySignedData();
|
||||
test_wc_PKCS7_EncodeDecodeEnvelopedData();
|
||||
test_wc_PKCS7_EncodeEncryptedData();
|
||||
test_wc_PKCS7_Degenerate();
|
||||
|
||||
test_wolfSSL_CTX_LoadCRL();
|
||||
|
||||
|
@ -1897,7 +1897,33 @@ static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz)
|
||||
return found;
|
||||
}
|
||||
|
||||
/* Finds the certificates in the message and saves it. */
|
||||
|
||||
/* option to turn off support for degenerate cases
|
||||
* flag 0 turns off support
|
||||
* flag 1 turns on support
|
||||
*
|
||||
* by default support for SignedData degenerate cases is on
|
||||
*/
|
||||
void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag)
|
||||
{
|
||||
if (pkcs7) {
|
||||
if (flag) { /* flag of 1 turns on support for degenerate */
|
||||
pkcs7->noDegenerate = 0;
|
||||
}
|
||||
else { /* flag of 0 turns off support */
|
||||
pkcs7->noDegenerate = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finds the certificates in the message and saves it. By default allows
|
||||
* degenerate cases which can have no signer.
|
||||
*
|
||||
* By default expects type SIGNED_DATA (SignedData) which can have any number of
|
||||
* elements in signerInfos collection, inluding zero. (RFC2315 section 9.1)
|
||||
* When adding support for the case of SignedAndEnvelopedData content types a
|
||||
* signer is required. In this case the PKCS7 flag noDegenerate could be set.
|
||||
*/
|
||||
static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
|
||||
word32 hashSz, byte* pkiMsg, word32 pkiMsgSz,
|
||||
byte* pkiMsg2, word32 pkiMsg2Sz)
|
||||
@ -1993,6 +2019,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
|
||||
/* Skip the set. */
|
||||
idx += length;
|
||||
degenerate = (length == 0)? 1 : 0;
|
||||
if (pkcs7->noDegenerate == 1 && degenerate == 1) {
|
||||
return PKCS7_NO_SIGNER_E;
|
||||
}
|
||||
|
||||
/* Get the inner ContentInfo sequence */
|
||||
if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0)
|
||||
@ -2135,8 +2164,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
|
||||
/* update idx if successful */
|
||||
if (ret == 0)
|
||||
idx = localIdx;
|
||||
else
|
||||
pkiMsg2 = pkiMsg;
|
||||
else {
|
||||
pkiMsg2 = pkiMsg;
|
||||
pkiMsg2Sz = pkiMsgSz;
|
||||
}
|
||||
|
||||
/* If getting the content info failed with non degenerate then return the
|
||||
* error case. Otherwise with a degenerate it is ok if the content
|
||||
@ -2223,88 +2254,96 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
|
||||
if (GetSet(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (length == 0)
|
||||
/* require a signer if degenerate case not allowed */
|
||||
if (length == 0 && pkcs7->noDegenerate == 1)
|
||||
return PKCS7_NO_SIGNER_E;
|
||||
|
||||
/* Get the sequence of the first signerInfo */
|
||||
if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Get the version */
|
||||
if (GetMyVersion(pkiMsg2, &idx, &version, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (version != 1) {
|
||||
WOLFSSL_MSG("PKCS#7 signerInfo needs to be of version 1");
|
||||
return ASN_VERSION_E;
|
||||
if (degenerate == 0 && length == 0) {
|
||||
WOLFSSL_MSG("PKCS7 signers expected");
|
||||
return PKCS7_NO_SIGNER_E;
|
||||
}
|
||||
|
||||
/* Get the sequence of IssuerAndSerialNumber */
|
||||
if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Skip it */
|
||||
idx += length;
|
||||
|
||||
/* Get the sequence of digestAlgorithm */
|
||||
if (GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, pkiMsg2Sz) < 0) {
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
pkcs7->hashOID = (int)hashOID;
|
||||
|
||||
/* Get the IMPLICIT[0] SET OF signedAttributes */
|
||||
if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
|
||||
idx++;
|
||||
|
||||
if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
if (length > 0 && degenerate == 0) {
|
||||
/* Get the sequence of the first signerInfo */
|
||||
if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* save pointer and length */
|
||||
signedAttrib = &pkiMsg2[idx];
|
||||
signedAttribSz = length;
|
||||
/* Get the version */
|
||||
if (GetMyVersion(pkiMsg2, &idx, &version, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) {
|
||||
WOLFSSL_MSG("Error parsing signed attributes");
|
||||
if (version != 1) {
|
||||
WOLFSSL_MSG("PKCS#7 signerInfo needs to be of version 1");
|
||||
return ASN_VERSION_E;
|
||||
}
|
||||
|
||||
/* Get the sequence of IssuerAndSerialNumber */
|
||||
if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Skip it */
|
||||
idx += length;
|
||||
|
||||
/* Get the sequence of digestAlgorithm */
|
||||
if (GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, pkiMsg2Sz) < 0) {
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
pkcs7->hashOID = (int)hashOID;
|
||||
|
||||
/* Get the IMPLICIT[0] SET OF signedAttributes */
|
||||
if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
|
||||
idx++;
|
||||
|
||||
if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* save pointer and length */
|
||||
signedAttrib = &pkiMsg2[idx];
|
||||
signedAttribSz = length;
|
||||
|
||||
if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) {
|
||||
WOLFSSL_MSG("Error parsing signed attributes");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
idx += length;
|
||||
}
|
||||
|
||||
/* Get digestEncryptionAlgorithm */
|
||||
if (GetAlgoId(pkiMsg2, &idx, &sigOID, oidSigType, pkiMsg2Sz) < 0) {
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
idx += length;
|
||||
}
|
||||
/* store public key type based on digestEncryptionAlgorithm */
|
||||
ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID);
|
||||
if (ret <= 0) {
|
||||
WOLFSSL_MSG("Failed to set public key OID from signature");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get digestEncryptionAlgorithm */
|
||||
if (GetAlgoId(pkiMsg2, &idx, &sigOID, oidSigType, pkiMsg2Sz) < 0) {
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
/* Get the signature */
|
||||
if (pkiMsg2[idx] == ASN_OCTET_STRING) {
|
||||
idx++;
|
||||
|
||||
/* store public key type based on digestEncryptionAlgorithm */
|
||||
ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID);
|
||||
if (ret <= 0) {
|
||||
WOLFSSL_MSG("Failed to set public key OID from signature");
|
||||
return ret;
|
||||
}
|
||||
if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Get the signature */
|
||||
if (pkiMsg2[idx] == ASN_OCTET_STRING) {
|
||||
idx++;
|
||||
/* save pointer and length */
|
||||
sig = &pkiMsg2[idx];
|
||||
sigSz = length;
|
||||
|
||||
if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
idx += length;
|
||||
}
|
||||
|
||||
/* save pointer and length */
|
||||
sig = &pkiMsg2[idx];
|
||||
sigSz = length;
|
||||
pkcs7->content = content;
|
||||
pkcs7->contentSz = contentSz;
|
||||
|
||||
idx += length;
|
||||
}
|
||||
|
||||
pkcs7->content = content;
|
||||
pkcs7->contentSz = contentSz;
|
||||
|
||||
ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz,
|
||||
ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz,
|
||||
signedAttrib, signedAttribSz,
|
||||
hashBuf, hashSz);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -145,6 +145,7 @@ typedef struct PKCS7 {
|
||||
|
||||
/* flags - up to 16-bits */
|
||||
word16 isDynamic:1;
|
||||
word16 noDegenerate:1; /* allow degenerate case in verify function */
|
||||
|
||||
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
|
||||
} PKCS7;
|
||||
@ -164,6 +165,7 @@ WOLFSSL_API int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7,
|
||||
WOLFSSL_API int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf,
|
||||
word32 hashSz, byte* outputHead, word32* outputHeadSz, byte* outputFoot,
|
||||
word32* outputFootSz);
|
||||
WOLFSSL_API void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag);
|
||||
WOLFSSL_API int wc_PKCS7_VerifySignedData(PKCS7* pkcs7,
|
||||
byte* pkiMsg, word32 pkiMsgSz);
|
||||
WOLFSSL_API int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf,
|
||||
|
Reference in New Issue
Block a user