Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions tests/api/test_asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,3 +920,111 @@ int test_wc_DecodeRsaPssParams(void)
#endif /* WC_RSA_PSS && !NO_RSA && !NO_ASN */
return EXPECT_RESULT();
}

/* Test that DecodeAltNames rejects a SAN entry whose length exceeds the
* remaining SEQUENCE length (integer underflow on the length tracker). */
int test_DecodeAltNames_length_underflow(void)
{
EXPECT_DECLS;

#if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_ASN)
/* Self-signed DER certificate with a well-formed SAN extension.
* Byte at offset 418 is the SAN SEQUENCE length (0x06). The negative
* test below copies this cert and shrinks that byte to 0x03 so the
* DNS entry length exceeds the SEQUENCE bounds. */
static const unsigned char good_san_cert[] = {
0x30, 0x82, 0x02, 0xf9, 0x30, 0x82, 0x01, 0xe1, 0xa0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x02, 0x10, 0x21, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x0f, 0x31, 0x0d,
0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x04, 0x61, 0x61, 0x31,
0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x32, 0x30, 0x37, 0x31,
0x37, 0x32, 0x34, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x34, 0x30, 0x32,
0x31, 0x34, 0x30, 0x36, 0x32, 0x36, 0x35, 0x33, 0x5a, 0x30, 0x0f, 0x31,
0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x04, 0x61, 0x61,
0x61, 0x61, 0x30, 0x82, 0x01, 0x20, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
0x0d, 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa8,
0x8a, 0x5e, 0x26, 0x23, 0x1b, 0x31, 0xd3, 0x37, 0x1a, 0x70, 0xb2, 0xec,
0x3f, 0x74, 0xd4, 0xb4, 0x44, 0xe3, 0x7a, 0xa5, 0xc0, 0xf5, 0xaa, 0x97,
0x26, 0x9a, 0x04, 0xff, 0xda, 0xbe, 0xe5, 0x09, 0x03, 0x98, 0x3d, 0xb5,
0xbf, 0x01, 0x2c, 0x9a, 0x0a, 0x3a, 0xfb, 0xbc, 0x3c, 0xe7, 0xbe, 0x83,
0x5c, 0xb3, 0x70, 0xe8, 0x5c, 0xe3, 0xd1, 0x83, 0xc3, 0x94, 0x08, 0xcd,
0x1a, 0x87, 0xe5, 0xe0, 0x5b, 0x9c, 0x5c, 0x6e, 0xb0, 0x7d, 0xe2, 0x58,
0x6c, 0xc3, 0xb5, 0xc8, 0x9d, 0x11, 0xf1, 0x5d, 0x96, 0x0d, 0x66, 0x1e,
0x56, 0x7f, 0x8f, 0x59, 0xa7, 0xa5, 0xe1, 0xc5, 0xe7, 0x81, 0x4c, 0x09,
0x9d, 0x5e, 0x96, 0xf0, 0x9a, 0xc2, 0x8b, 0x70, 0xd5, 0xab, 0x79, 0x58,
0x5d, 0xb7, 0x58, 0xaa, 0xfd, 0x75, 0x52, 0xaa, 0x4b, 0xa7, 0x25, 0x68,
0x76, 0x59, 0x00, 0xee, 0x78, 0x2b, 0x91, 0xc6, 0x59, 0x91, 0x99, 0x38,
0x3e, 0xa1, 0x76, 0xc3, 0xf5, 0x23, 0x6b, 0xe6, 0x07, 0xea, 0x63, 0x1c,
0x97, 0x49, 0xef, 0xa0, 0xfe, 0xfd, 0x13, 0xc9, 0xa9, 0x9f, 0xc2, 0x0b,
0xe6, 0x87, 0x92, 0x5b, 0xcc, 0xf5, 0x42, 0x95, 0x4a, 0xa4, 0x6d, 0x64,
0xba, 0x7d, 0xce, 0xcb, 0x04, 0xd0, 0xf8, 0xe7, 0xe3, 0xda, 0x75, 0x60,
0xd3, 0x8b, 0x6a, 0x64, 0xfc, 0x78, 0x56, 0x21, 0x69, 0x5a, 0xe8, 0xa7,
0x8f, 0xfb, 0x8f, 0x82, 0xe3, 0xae, 0x36, 0xa2, 0x93, 0x66, 0x92, 0xcb,
0x82, 0xa3, 0xbe, 0x84, 0x00, 0x86, 0xdc, 0x7e, 0x6d, 0x53, 0x77, 0x84,
0x17, 0xb9, 0x55, 0x43, 0x0d, 0xf1, 0x16, 0x1f, 0xd5, 0x43, 0x75, 0x99,
0x66, 0x19, 0x52, 0xd0, 0xac, 0x5f, 0x74, 0xad, 0xb2, 0x90, 0x15, 0x50,
0x04, 0x74, 0x43, 0xdf, 0x6c, 0x35, 0xd0, 0xfd, 0x32, 0x37, 0xb3, 0x8d,
0xf5, 0xe5, 0x09, 0x02, 0x01, 0x03, 0xa3, 0x61, 0x30, 0x5f, 0x30, 0x0c,
0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
/* SAN extension: correct SEQUENCE length 0x06 */
0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x08, 0x30, 0x06, 0x82,
0x04, 0x61, 0x2a, 0x00, 0x2a, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
0x04, 0x16, 0x04, 0x14, 0x92, 0x6a, 0x1e, 0x52, 0x3a, 0x1a, 0x57, 0x9f,
0xc9, 0x82, 0x9a, 0xce, 0xc8, 0xc0, 0xa9, 0x51, 0x9d, 0x2f, 0xc7, 0x72,
0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
0x14, 0x6b, 0xf9, 0xa4, 0x2d, 0xa5, 0xe9, 0x39, 0x89, 0xa8, 0x24, 0x58,
0x79, 0x87, 0x11, 0xfc, 0x6f, 0x07, 0x91, 0xef, 0xa6, 0x30, 0x0d, 0x06,
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
0x03, 0x82, 0x01, 0x01, 0x00, 0x3f, 0xd5, 0x37, 0x2f, 0xc7, 0xf8, 0x8b,
0x39, 0x1c, 0xe3, 0xdf, 0x77, 0xee, 0xc6, 0x4b, 0x5f, 0x84, 0xcf, 0xfa,
0x33, 0x2c, 0xb2, 0xb5, 0x4b, 0x09, 0xee, 0x56, 0xc0, 0xf2, 0xf0, 0xeb,
0xad, 0x1c, 0x02, 0xef, 0xae, 0x09, 0x53, 0xc0, 0x06, 0xad, 0x4e, 0xfd,
0x3e, 0x8c, 0x13, 0xb3, 0xbf, 0x80, 0x05, 0x36, 0xb5, 0x3f, 0x2b, 0xc7,
0x60, 0x53, 0x14, 0xbf, 0x33, 0x63, 0x47, 0xc3, 0xc6, 0x28, 0xda, 0x10,
0x12, 0xe2, 0xc4, 0xeb, 0xc5, 0x64, 0x66, 0xc0, 0xcc, 0x6b, 0x84, 0xda,
0x0c, 0xe9, 0xf6, 0xe3, 0xf8, 0x8e, 0x3d, 0x95, 0x5f, 0xba, 0x9f, 0xe1,
0xc7, 0xed, 0x6e, 0x97, 0xcc, 0xbd, 0x7d, 0xe5, 0x4e, 0xab, 0xbc, 0x1b,
0xf1, 0x3a, 0x09, 0x33, 0x09, 0xe1, 0xcc, 0xec, 0x21, 0x16, 0x8e, 0xb1,
0x74, 0x9e, 0xc8, 0x13, 0x7c, 0xdf, 0x07, 0xaa, 0xeb, 0x70, 0xd7, 0x91,
0x5c, 0xc4, 0xef, 0x83, 0x88, 0xc3, 0xe4, 0x97, 0xfa, 0xe4, 0xdf, 0xd7,
0x0d, 0xff, 0xba, 0x78, 0x22, 0xfc, 0x3f, 0xdc, 0xd8, 0x02, 0x8d, 0x93,
0x57, 0xf9, 0x9e, 0x39, 0x3a, 0x77, 0x00, 0xd9, 0x19, 0xaa, 0x68, 0xa1,
0xe6, 0x9e, 0x13, 0xeb, 0x37, 0x16, 0xf5, 0x77, 0xa4, 0x0b, 0x40, 0x04,
0xd3, 0xa5, 0x49, 0x78, 0x35, 0xfa, 0x3b, 0xf6, 0x02, 0xab, 0x85, 0xee,
0xcb, 0x9b, 0x62, 0xda, 0x05, 0x00, 0x22, 0x2f, 0xf8, 0xbd, 0x0b, 0xe5,
0x2c, 0xb2, 0x53, 0x78, 0x0a, 0xcb, 0x69, 0xc0, 0xb6, 0x9f, 0x96, 0xff,
0x58, 0x22, 0x70, 0x9c, 0x01, 0x2e, 0x56, 0x60, 0x5d, 0x37, 0xe3, 0x40,
0x25, 0xc9, 0x90, 0xc8, 0x0f, 0x41, 0x68, 0xb4, 0xfd, 0x10, 0xe2, 0x09,
0x99, 0x08, 0x5d, 0x7b, 0xc9, 0xe3, 0x29, 0xd4, 0x5a, 0xcf, 0xc9, 0x34,
0x55, 0xa1, 0x40, 0x44, 0xd6, 0x88, 0x16, 0xbb, 0xdd
};

/* Offset of the SAN SEQUENCE length byte inside good_san_cert. */
#define SAN_SEQ_LEN_OFFSET 418

DecodedCert cert;
unsigned char bad_san_cert[sizeof(good_san_cert)];

/* Control: the original cert with correct SAN SEQUENCE length should
* parse successfully (signature won't verify, but NO_VERIFY skips that). */
wc_InitDecodedCert(&cert, good_san_cert, (word32)sizeof(good_san_cert),
NULL);
ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0);
wc_FreeDecodedCert(&cert);

/* Build a malformed variant: shrink the SAN SEQUENCE length from 6 to 3
* so the DNS entry length (4) exceeds the SEQUENCE bounds. Without a
* bounds check DecodeAltNames would underflow the length tracker. */
XMEMCPY(bad_san_cert, good_san_cert, sizeof(good_san_cert));
bad_san_cert[SAN_SEQ_LEN_OFFSET] = 0x03;

wc_InitDecodedCert(&cert, bad_san_cert, (word32)sizeof(bad_san_cert),
NULL);
ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL),
WC_NO_ERR_TRACE(ASN_PARSE_E));
wc_FreeDecodedCert(&cert);

#endif /* !NO_CERTS && !NO_RSA && !NO_ASN */
return EXPECT_RESULT();
}
4 changes: 3 additions & 1 deletion tests/api/test_asn.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ int test_GetSetShortInt(void);
int test_wc_IndexSequenceOf(void);
int test_wolfssl_local_MatchBaseName(void);
int test_wc_DecodeRsaPssParams(void);
int test_DecodeAltNames_length_underflow(void);

#define TEST_ASN_DECLS \
TEST_DECL_GROUP("asn", test_SetAsymKeyDer), \
TEST_DECL_GROUP("asn", test_GetSetShortInt), \
TEST_DECL_GROUP("asn", test_wc_IndexSequenceOf), \
TEST_DECL_GROUP("asn", test_wolfssl_local_MatchBaseName), \
TEST_DECL_GROUP("asn", test_wc_DecodeRsaPssParams)
TEST_DECL_GROUP("asn", test_wc_DecodeRsaPssParams), \
TEST_DECL_GROUP("asn", test_DecodeAltNames_length_underflow)

#endif /* WOLFCRYPT_TEST_ASN_H */
24 changes: 24 additions & 0 deletions wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -20826,6 +20826,9 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert)

AddAltName(cert, dnsEntry);

if (strLen > length) {
return ASN_PARSE_E;
}
length -= strLen;
idx += (word32)strLen;
}
Expand Down Expand Up @@ -20867,6 +20870,9 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert)
dirEntry->next = cert->altDirNames;
cert->altDirNames = dirEntry;

if (strLen > length) {
return ASN_PARSE_E;
}
length -= strLen;
idx += (word32)strLen;
}
Expand Down Expand Up @@ -20902,6 +20908,9 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert)
emailEntry->next = cert->altEmailNames;
cert->altEmailNames = emailEntry;

if (strLen > length) {
return ASN_PARSE_E;
}
length -= strLen;
idx += (word32)strLen;
}
Expand Down Expand Up @@ -20981,6 +20990,9 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert)

AddAltName(cert, uriEntry);

if (strLen > length) {
return ASN_PARSE_E;
}
length -= strLen;
idx += (word32)strLen;
}
Expand Down Expand Up @@ -21027,6 +21039,9 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert)
}
AddAltName(cert, ipAddr);

if (strLen > length) {
return ASN_PARSE_E;
}
length -= strLen;
idx += (word32)strLen;
}
Expand Down Expand Up @@ -21075,6 +21090,9 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert)

AddAltName(cert, rid);

if (strLen > length) {
return ASN_PARSE_E;
}
length -= strLen;
idx += (word32)strLen;
}
Expand All @@ -21092,6 +21110,9 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert)
return ASN_PARSE_E;
}
/* Consume the rest of this sequence. */
if ((int)((word32)strLen + idx - lenStartIdx) > length) {
return ASN_PARSE_E;
}
length -= (int)(((word32)strLen + idx - lenStartIdx));

if (GetObjectId(input, &idx, &oid, oidCertAltNameType, sz) < 0) {
Expand Down Expand Up @@ -21144,6 +21165,9 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert)
WOLFSSL_MSG("\tfail: unsupported name length");
return ASN_PARSE_E;
}
if ((int)((word32)strLen + idx - lenStartIdx) > length) {
return ASN_PARSE_E;
}
length -= (int)((word32)strLen + idx - lenStartIdx);
idx += (word32)strLen;
}
Expand Down
Loading