Skip to content

Commit 3cf4aea

Browse files
authored
Merge pull request #10025 from embhorn/zd21392
Fix DecodeObjectId unknown ext parse
2 parents 03beeae + 2b7e966 commit 3cf4aea

4 files changed

Lines changed: 90 additions & 7 deletions

File tree

tests/api/test_asn.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,3 +1028,77 @@ int test_DecodeAltNames_length_underflow(void)
10281028
#endif /* !NO_CERTS && !NO_RSA && !NO_ASN */
10291029
return EXPECT_RESULT();
10301030
}
1031+
1032+
int test_wc_DecodeObjectId(void)
1033+
{
1034+
EXPECT_DECLS;
1035+
1036+
#if !defined(NO_ASN) && \
1037+
(defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT))
1038+
{
1039+
/* OID 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
1040+
* DER encoding: 2a 86 48 86 f7 0d 01 01 0b
1041+
* First byte 0x2a = 42 => arc0 = 42/40 = 1, arc1 = 42%40 = 2
1042+
* Remaining arcs: 840, 113549, 1, 1, 11
1043+
*/
1044+
static const byte oid_sha256rsa[] = {
1045+
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b
1046+
};
1047+
word16 out[MAX_OID_SZ];
1048+
word32 outSz;
1049+
1050+
/* Test 1: Normal decode */
1051+
outSz = MAX_OID_SZ;
1052+
ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa),
1053+
out, &outSz), 0);
1054+
ExpectIntEQ((int)outSz, 7);
1055+
ExpectIntEQ(out[0], 1);
1056+
ExpectIntEQ(out[1], 2);
1057+
ExpectIntEQ(out[2], 840);
1058+
ExpectIntEQ(out[3], (word16)113549); /* truncated to word16 */
1059+
ExpectIntEQ(out[4], 1);
1060+
ExpectIntEQ(out[5], 1);
1061+
ExpectIntEQ(out[6], 11);
1062+
1063+
/* Test 2: NULL args */
1064+
outSz = MAX_OID_SZ;
1065+
ExpectIntEQ(DecodeObjectId(NULL, sizeof(oid_sha256rsa), out, &outSz),
1066+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
1067+
ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa),
1068+
out, NULL),
1069+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
1070+
1071+
/* Test 3 (Bug 1): outSz=1 must return BUFFER_E, not OOB write.
1072+
* The first OID byte decodes into two arcs, so outSz must be >= 2. */
1073+
outSz = 1;
1074+
ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa),
1075+
out, &outSz),
1076+
WC_NO_ERR_TRACE(BUFFER_E));
1077+
1078+
/* Test 4: outSz=0 must also return BUFFER_E */
1079+
outSz = 0;
1080+
ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa),
1081+
out, &outSz),
1082+
WC_NO_ERR_TRACE(BUFFER_E));
1083+
1084+
/* Test 5: outSz=2 is enough for a single-byte OID (two arcs) */
1085+
{
1086+
static const byte oid_one_byte[] = { 0x2a }; /* 1.2 */
1087+
outSz = 2;
1088+
ExpectIntEQ(DecodeObjectId(oid_one_byte, sizeof(oid_one_byte),
1089+
out, &outSz), 0);
1090+
ExpectIntEQ((int)outSz, 2);
1091+
ExpectIntEQ(out[0], 1);
1092+
ExpectIntEQ(out[1], 2);
1093+
}
1094+
1095+
/* Test 6: Buffer too small for later arcs */
1096+
outSz = 3; /* only room for 3 arcs, but OID has 7 */
1097+
ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa),
1098+
out, &outSz),
1099+
WC_NO_ERR_TRACE(BUFFER_E));
1100+
}
1101+
#endif /* !NO_ASN && (HAVE_OID_DECODING || WOLFSSL_ASN_PRINT) */
1102+
1103+
return EXPECT_RESULT();
1104+
}

tests/api/test_asn.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ int test_wc_IndexSequenceOf(void);
3030
int test_wolfssl_local_MatchBaseName(void);
3131
int test_wc_DecodeRsaPssParams(void);
3232
int test_DecodeAltNames_length_underflow(void);
33+
int test_wc_DecodeObjectId(void);
3334

3435
#define TEST_ASN_DECLS \
3536
TEST_DECL_GROUP("asn", test_SetAsymKeyDer), \
3637
TEST_DECL_GROUP("asn", test_GetSetShortInt), \
3738
TEST_DECL_GROUP("asn", test_wc_IndexSequenceOf), \
3839
TEST_DECL_GROUP("asn", test_wolfssl_local_MatchBaseName), \
3940
TEST_DECL_GROUP("asn", test_wc_DecodeRsaPssParams), \
40-
TEST_DECL_GROUP("asn", test_DecodeAltNames_length_underflow)
41+
TEST_DECL_GROUP("asn", test_DecodeAltNames_length_underflow), \
42+
TEST_DECL_GROUP("asn", test_wc_DecodeObjectId)
4143

4244
#endif /* WOLFCRYPT_TEST_ASN_H */

wolfcrypt/src/asn.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6895,15 +6895,18 @@ int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz)
68956895
t = (t << 7) | (in[x] & 0x7F);
68966896
cnt++;
68976897
if (!(in[x] & 0x80)) {
6898-
if (y >= (int)*outSz) {
6899-
return BUFFER_E;
6900-
}
69016898
if (y == 0) {
6899+
if ((int)*outSz < 2) {
6900+
return BUFFER_E;
6901+
}
69026902
out[0] = (word16)(t / 40);
69036903
out[1] = (word16)(t % 40);
69046904
y = 2;
69056905
}
69066906
else {
6907+
if (y >= (int)*outSz) {
6908+
return BUFFER_E;
6909+
}
69076910
out[y++] = (word16)t;
69086911
}
69096912
t = 0; /* reset tmp */
@@ -7000,7 +7003,7 @@ static int DumpOID(const byte* oidData, word32 oidSz, word32 oid,
70007003
#ifdef HAVE_OID_DECODING
70017004
{
70027005
word16 decOid[MAX_OID_SZ];
7003-
word32 decOidSz = sizeof(decOid);
7006+
word32 decOidSz = MAX_OID_SZ;
70047007
/* Decode the OID into dotted form. */
70057008
ret = DecodeObjectId(oidData, oidSz, decOid, &decOidSz);
70067009
if (ret == 0) {
@@ -20023,7 +20026,7 @@ static int DecodeCertExtensions(DecodedCert* cert)
2002320026
if (isUnknownExt && (cert->unknownExtCallback != NULL ||
2002420027
cert->unknownExtCallbackEx != NULL)) {
2002520028
word16 decOid[MAX_OID_SZ];
20026-
word32 decOidSz = sizeof(decOid);
20029+
word32 decOidSz = MAX_OID_SZ;
2002720030
ret = DecodeObjectId(
2002820031
dataASN[CERTEXTASN_IDX_OID].data.oid.data,
2002920032
dataASN[CERTEXTASN_IDX_OID].data.oid.length,

wolfssl/wolfcrypt/asn.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,10 @@ typedef enum MimeStatus
22472247
#define SetAlgoID wc_SetAlgoID
22482248
#define SetAsymKeyDer wc_SetAsymKeyDer
22492249
#define CalcHashId wc_CalcHashId
2250+
#if defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT) || \
2251+
defined(OPENSSL_ALL)
2252+
#define DecodeObjectId wc_DecodeObjectId
2253+
#endif
22502254
#if defined(WOLFSSL_AKID_NAME) && !defined(GetCAByAKID)
22512255
/* GetCAByAKID() has two implementations, a full implementation in
22522256
* src/ssl.c, and a dummy implementation in wolfcrypt/src/asn.c for
@@ -2489,7 +2493,7 @@ WOLFSSL_LOCAL word32 wc_oid_sum(const byte* input, int length);
24892493
#endif
24902494
#if defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT) || \
24912495
defined(OPENSSL_ALL)
2492-
WOLFSSL_LOCAL int DecodeObjectId(const byte* in, word32 inSz,
2496+
WOLFSSL_TEST_VIS int DecodeObjectId(const byte* in, word32 inSz,
24932497
word16* out, word32* outSz);
24942498
#endif
24952499
WOLFSSL_LOCAL int GetASNObjectId(const byte* input, word32* inOutIdx, int* len,

0 commit comments

Comments
 (0)