Skip to content

Commit 0d9c824

Browse files
committed
tests: cover extended key usage oid sum collision in non-wolfssh builds
1 parent 01426d0 commit 0d9c824

3 files changed

Lines changed: 125 additions & 0 deletions

File tree

tests/api/test_asn.c

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3685,6 +3685,105 @@ int test_wc_DecodeExtKeyUsage_ssh_oid_collision(void)
36853685
return EXPECT_RESULT();
36863686
}
36873687

3688+
#if !defined(NO_ASN) && !defined(NO_RSA) && !defined(NO_CERTS) && \
3689+
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \
3690+
defined(WOLFSSL_EKU_OID) && !defined(NO_SHA256) && \
3691+
defined(USE_CERT_BUFFERS_2048) && !defined(NO_ASN_TIME) && \
3692+
!defined(WC_NO_RNG) && !defined(NO_ASN_CRYPT)
3693+
#define TEST_EKU_OID_SUM_COLLISION
3694+
#endif
3695+
3696+
/* A KeyPurposeId whose wc_oid_sum() collides with id-kp-serverAuth must not
3697+
* authorize server authentication, while the real OID still does. */
3698+
int test_wc_DecodeExtKeyUsage_oidSumCollision(void)
3699+
{
3700+
EXPECT_DECLS;
3701+
#ifdef TEST_EKU_OID_SUM_COLLISION
3702+
static const struct {
3703+
const char* oid; /* custom EKU OID, NULL to use a named purpose */
3704+
const char* name; /* named purpose, used when oid is NULL */
3705+
byte expected;
3706+
} ekuCases[] = {
3707+
/* id-kp-serverAuth. */
3708+
{ NULL, "serverAuth", EXTKEYUSE_SERVER_AUTH },
3709+
#ifdef WOLFSSL_OLD_OID_SUM
3710+
/* 1.5.6.1.5.5.3.1, the same byte sum (71) as id-kp-serverAuth. */
3711+
{ "1.5.6.1.5.5.3.1", NULL, 0 },
3712+
#else
3713+
/* 1.19.6.1.5.21.7.3.1, the same XOR-shift sum (0x0402012e) as
3714+
* id-kp-serverAuth. */
3715+
{ "1.19.6.1.5.21.7.3.1", NULL, 0 },
3716+
#endif
3717+
};
3718+
WC_RNG rng;
3719+
RsaKey key;
3720+
byte* der = NULL;
3721+
word32 idx = 0;
3722+
int rngInit = 0;
3723+
int keyInit = 0;
3724+
size_t c;
3725+
3726+
XMEMSET(&rng, 0, sizeof(rng));
3727+
XMEMSET(&key, 0, sizeof(key));
3728+
3729+
ExpectIntEQ(wc_InitRng(&rng), 0);
3730+
if (EXPECT_SUCCESS()) rngInit = 1;
3731+
3732+
ExpectNotNull(der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,
3733+
DYNAMIC_TYPE_TMP_BUFFER));
3734+
3735+
ExpectIntEQ(wc_InitRsaKey_ex(&key, HEAP_HINT, testDevId), 0);
3736+
if (EXPECT_SUCCESS()) keyInit = 1;
3737+
ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &key,
3738+
sizeof_server_key_der_2048), 0);
3739+
3740+
for (c = 0; c < XELEM_CNT(ekuCases); c++) {
3741+
Cert cert;
3742+
DecodedCert dCert;
3743+
int dCertInit = 0;
3744+
int derSz = 0;
3745+
3746+
if (!EXPECT_SUCCESS()) break;
3747+
3748+
XMEMSET(&cert, 0, sizeof(cert));
3749+
ExpectIntEQ(wc_InitCert(&cert), 0);
3750+
if (EXPECT_SUCCESS()) {
3751+
cert.sigType = CTC_SHA256wRSA;
3752+
cert.isCA = 0;
3753+
XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
3754+
XSTRNCPY(cert.subject.org, "wolfSSL", CTC_NAME_SIZE);
3755+
XSTRNCPY(cert.subject.commonName, "extKeyUsage", CTC_NAME_SIZE);
3756+
}
3757+
if (ekuCases[c].oid != NULL) {
3758+
ExpectIntEQ(wc_SetExtKeyUsageOID(&cert, ekuCases[c].oid,
3759+
(word32)XSTRLEN(ekuCases[c].oid), 0, HEAP_HINT), 0);
3760+
}
3761+
else {
3762+
ExpectIntEQ(wc_SetExtKeyUsage(&cert, ekuCases[c].name), 0);
3763+
}
3764+
ExpectIntGT(derSz = wc_MakeSelfCert(&cert, der, FOURK_BUF, &key, &rng),
3765+
0);
3766+
3767+
if (EXPECT_SUCCESS() && (der != NULL)) {
3768+
wc_InitDecodedCert(&dCert, der, (word32)derSz, HEAP_HINT);
3769+
dCertInit = 1;
3770+
ExpectIntEQ(wc_ParseCert(&dCert, CERT_TYPE, NO_VERIFY, NULL), 0);
3771+
/* The extension must be seen in both cases - an unrecognized
3772+
* KeyPurposeId is skipped, not an error - but only the real OID
3773+
* may authorize a purpose. */
3774+
ExpectIntNE(dCert.extExtKeyUsageSet, 0);
3775+
ExpectIntEQ(dCert.extExtKeyUsage, ekuCases[c].expected);
3776+
}
3777+
if (dCertInit) wc_FreeDecodedCert(&dCert);
3778+
}
3779+
3780+
if (keyInit) wc_FreeRsaKey(&key);
3781+
if (rngInit) wc_FreeRng(&rng);
3782+
XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
3783+
#endif /* TEST_EKU_OID_SUM_COLLISION */
3784+
return EXPECT_RESULT();
3785+
}
3786+
36883787
int test_wc_SignCert_buffer_bounds(void)
36893788
{
36903789
EXPECT_DECLS;

tests/api/test_asn.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ int test_wc_SignCert_buffer_bounds(void);
5050
int test_wc_DecodeKeyUsage_decipherOnly(void);
5151
int test_wc_DecodeExtKeyUsage_ssh(void);
5252
int test_wc_DecodeExtKeyUsage_ssh_oid_collision(void);
53+
int test_wc_DecodeExtKeyUsage_oidSumCollision(void);
5354
int test_wc_AsnDecisionCoverage(void);
5455
int test_wc_AsnFeatureCoverage(void);
5556

@@ -80,6 +81,7 @@ int test_wc_AsnFeatureCoverage(void);
8081
TEST_DECL_GROUP("asn", test_wc_DecodeKeyUsage_decipherOnly), \
8182
TEST_DECL_GROUP("asn", test_wc_DecodeExtKeyUsage_ssh), \
8283
TEST_DECL_GROUP("asn", test_wc_DecodeExtKeyUsage_ssh_oid_collision), \
84+
TEST_DECL_GROUP("asn", test_wc_DecodeExtKeyUsage_oidSumCollision), \
8385
TEST_DECL_GROUP("asn", test_wc_AsnDecisionCoverage), \
8486
TEST_DECL_GROUP("asn", test_wc_AsnFeatureCoverage)
8587

tests/unit-mcdc/test_asn_ext_whitebox.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,30 @@ static void wb_decode_ext_key_usage(void)
12641264
&ssh, NULL);
12651265
WB_CHECK(ret == 0, "extExtKeyUsageOidCnt==NULL out-ptr (2nd operand false)");
12661266

1267+
/* An OID that is not id-kp-serverAuth but whose wc_oid_sum() collides with
1268+
* it must not be treated as serverAuth. */
1269+
{
1270+
#ifdef WOLFSSL_OLD_OID_SUM
1271+
/* 1.5.6.1.5.5.3.1, the same byte sum (71) as serverAuth. */
1272+
static const byte ekuCollide[] = {
1273+
0x30,0x0A,
1274+
0x06,0x08, 0x2D,0x06,0x01,0x05,0x05,0x05,0x03,0x01
1275+
};
1276+
#else
1277+
/* 1.19.6.1.5.21.7.3.1, the same XOR-shift sum (0x0402012e) as
1278+
* serverAuth. */
1279+
static const byte ekuCollide[] = {
1280+
0x30,0x0A,
1281+
0x06,0x08, 0x3B,0x06,0x01,0x05,0x15,0x07,0x03,0x01
1282+
};
1283+
#endif
1284+
src = NULL; srcSz = 0; count = 0; usage = 0; ssh = 0; oidCnt = 0;
1285+
ret = DecodeExtKeyUsage(ekuCollide, sizeof(ekuCollide), &src, &srcSz,
1286+
&count, &usage, &ssh, &oidCnt);
1287+
WB_CHECK(ret == 0 && usage == 0 && oidCnt == 1,
1288+
"OID colliding with serverAuth checksum not set as serverAuth");
1289+
}
1290+
12671291
/* Empty SEQUENCE OF -> loop condition false immediately. */
12681292
{
12691293
static const byte ekuEmpty[] = { 0x30, 0x00 };

0 commit comments

Comments
 (0)