Skip to content

Commit 1e9f191

Browse files
Updated size of OID represention to be word32 instead of word16 so OIDs
will not be truncated. Added tests for updated OID handling.
1 parent c685293 commit 1e9f191

8 files changed

Lines changed: 198 additions & 106 deletions

File tree

doc/dox_comments/header_files/asn.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,16 @@ void FreeAltNames(DNS_entry* altNames, void* heap);
8080
\note This API is not public by default. Define WOLFSSL_PUBLIC_ASN to
8181
expose APIs marked WOLFSSL_ASN_API.
8282
83+
\note The oid argument passed to the callback is an array of word32
84+
elements, one per OID arc, so that arcs > 65535 are represented without
85+
truncation. Callbacks must declare their oid parameter as const word32*.
86+
The same applies to wc_SetUnknownExtCallback.
87+
8388
_Example_
8489
\code
8590
DecodedCert cert;
8691
87-
int UnknownExtCallback(const byte* oid, word32 oidSz, int crit,
92+
int UnknownExtCallback(const word32* oid, word32 oidSz, int crit,
8893
const byte* der, word32 derSz, void* ctx) {
8994
// handle unknown extension
9095
return 0;
@@ -140,28 +145,31 @@ int wc_CheckCertSignature(const byte* cert, word32 certSz, void* heap,
140145

141146
/*!
142147
\ingroup ASN
143-
\brief This function encodes an array of word16 values into an ASN.1
148+
\brief This function encodes an array of word32 values into an ASN.1
144149
Object Identifier (OID) in DER format. OIDs are used to identify
145150
algorithms, extensions, and other objects in certificates and
146151
cryptographic protocols.
147152
153+
Each OID arc is a word32, so OIDs containing arcs with values > 65535 are
154+
represented without truncation.
155+
148156
\return 0 On success.
149157
\return BAD_FUNC_ARG If in, inSz, or outSz are invalid.
150158
\return BUFFER_E If out is not NULL and outSz is too small.
151159
152-
\param in pointer to array of word16 values representing OID components
160+
\param in pointer to array of word32 values representing OID components
153161
\param inSz number of components in the OID
154162
\param out pointer to buffer to store encoded OID (can be NULL to
155163
calculate size)
156164
\param outSz pointer to size of out buffer; updated with actual size
157165
158166
_Example_
159167
\code
160-
word16 oid[] = {1, 2, 840, 113549, 1, 1, 11}; // sha256WithRSAEncryption
168+
word32 oid[] = {1, 2, 840, 113549, 1, 1, 11}; // sha256WithRSAEncryption
161169
byte encoded[32];
162170
word32 encodedSz = sizeof(encoded);
163171
164-
int ret = wc_EncodeObjectId(oid, sizeof(oid)/sizeof(word16),
172+
int ret = wc_EncodeObjectId(oid, sizeof(oid)/sizeof(*oid),
165173
encoded, &encodedSz);
166174
if (ret == 0) {
167175
// encoded contains DER encoded OID
@@ -170,7 +178,7 @@ int wc_CheckCertSignature(const byte* cert, word32 certSz, void* heap,
170178
171179
\sa wc_BerToDer
172180
*/
173-
int wc_EncodeObjectId(const word16* in, word32 inSz, byte* out,
181+
int wc_EncodeObjectId(const word32* in, word32 inSz, byte* out,
174182
word32* outSz);
175183

176184
/*!

doc/dox_comments/header_files/asn_public.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3953,7 +3953,7 @@ int wc_SetCustomExtension(Cert *cert, int critical, const char *oid,
39533953
\code
39543954
int ret = 0;
39553955
// Unknown extension callback prototype
3956-
int myUnknownExtCallback(const word16* oid, word32 oidSz, int crit,
3956+
int myUnknownExtCallback(const word32* oid, word32 oidSz, int crit,
39573957
const unsigned char* der, word32 derSz);
39583958
39593959
// Register it
@@ -3967,7 +3967,7 @@ int wc_SetCustomExtension(Cert *cert, int critical, const char *oid,
39673967
// crit: Whether the extension was mark critical.
39683968
// der: The der encoding of the content of the extension.
39693969
// derSz: The size in bytes of the der encoding.
3970-
int myCustomExtCallback(const word16* oid, word32 oidSz, int crit,
3970+
int myCustomExtCallback(const word32* oid, word32 oidSz, int crit,
39713971
const unsigned char* der, word32 derSz) {
39723972
39733973
// Logic to parse extension goes here.

tests/api/test_asn.c

Lines changed: 140 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,29 +1631,41 @@ int test_wc_DecodeObjectId(void)
16311631
#if !defined(NO_ASN) && \
16321632
(defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT))
16331633
{
1634-
/* OID 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
1635-
* DER encoding: 2a 86 48 86 f7 0d 01 01 0b
1636-
* First byte 0x2a = 42 => arc0 = 42/40 = 1, arc1 = 42%40 = 2
1637-
* Remaining arcs: 840, 113549, 1, 1, 11
1634+
word32 i;
1635+
static const word32 oid_dot_2[] = {
1636+
2, 100, 4, 6
1637+
};
1638+
1639+
static const byte oid_start_with_2[] = {
1640+
0x81, 0x34, 0x04, 0x06
1641+
};
1642+
1643+
1644+
/* OID 1.3.132.0.6 (secp112r1)
1645+
* DER encoding: 2b 81 04 00 06
1646+
* First byte 0x2b = 43 => arc0 = 43/40 = 1, arc1 = 43%40 = 3
1647+
* Remaining arcs: 132 0 6
16381648
*/
16391649
static const byte oid_sha256rsa[] = {
1640-
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b
1650+
0x2B, 0x81, 0x04, 0x00, 0x06
1651+
};
1652+
1653+
static const word32 oid_dot_form[] = {
1654+
1U, 3U, 132U, 0U, 6U
16411655
};
1642-
word16 out[MAX_OID_SZ];
1656+
1657+
word32 out[MAX_OID_SZ];
16431658
word32 outSz;
16441659

1660+
word32 trueOutSz = sizeof(oid_dot_form) / sizeof(word32);
16451661
/* Test 1: Normal decode */
16461662
outSz = MAX_OID_SZ;
16471663
ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa),
16481664
out, &outSz), 0);
1649-
ExpectIntEQ((int)outSz, 7);
1650-
ExpectIntEQ(out[0], 1);
1651-
ExpectIntEQ(out[1], 2);
1652-
ExpectIntEQ(out[2], 840);
1653-
ExpectIntEQ(out[3], (word16)113549); /* truncated to word16 */
1654-
ExpectIntEQ(out[4], 1);
1655-
ExpectIntEQ(out[5], 1);
1656-
ExpectIntEQ(out[6], 11);
1665+
ExpectIntEQ((int)outSz, trueOutSz);
1666+
for (i = 0; i < ((outSz <= trueOutSz) ? outSz : trueOutSz); i++) {
1667+
ExpectIntEQ(out[i], oid_dot_form[i]);
1668+
}
16571669

16581670
/* Test 2: NULL args */
16591671
outSz = MAX_OID_SZ;
@@ -1692,12 +1704,126 @@ int test_wc_DecodeObjectId(void)
16921704
ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa),
16931705
out, &outSz),
16941706
WC_NO_ERR_TRACE(BUFFER_E));
1707+
1708+
/* Test 7: first Arc is 2 */
1709+
{
1710+
word32 trueOutSz2 = sizeof(oid_dot_2) / sizeof(word32);
1711+
outSz = MAX_OID_SZ;
1712+
ExpectIntEQ(DecodeObjectId(oid_start_with_2,
1713+
sizeof(oid_start_with_2),
1714+
out, &outSz), 0);
1715+
ExpectIntEQ((int)outSz, trueOutSz2);
1716+
for (i = 0; i < ((outSz <= trueOutSz2) ?
1717+
outSz : trueOutSz2); i++) {
1718+
ExpectIntEQ(out[i], oid_dot_2[i]);
1719+
}
1720+
}
1721+
1722+
/* Test 8: an OID with an arc that exceeds word16.
1723+
*/
1724+
{
1725+
static const byte oid_large_arc[] = {
1726+
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b
1727+
};
1728+
static const word32 oid_dot_large_arc[] = {
1729+
1U, 2U, 840U, 113549U, 1U, 1U, 11U
1730+
};
1731+
word32 trueOutSz3 = sizeof(oid_dot_large_arc) / sizeof(word32);
1732+
1733+
outSz = MAX_OID_SZ;
1734+
ExpectIntEQ(DecodeObjectId(oid_large_arc, sizeof(oid_large_arc),
1735+
out, &outSz), 0);
1736+
ExpectIntEQ((int)outSz, (int)trueOutSz3);
1737+
for (i = 0; i < ((outSz <= trueOutSz3) ? outSz : trueOutSz3); i++) {
1738+
ExpectIntEQ(out[i], oid_dot_large_arc[i]);
1739+
}
1740+
#undef LARGE_ARC_EXPECTED
1741+
}
16951742
}
16961743
#endif /* !NO_ASN && (HAVE_OID_DECODING || WOLFSSL_ASN_PRINT) */
16971744

16981745
return EXPECT_RESULT();
16991746
}
17001747

1748+
int test_wc_EncodeObjectId(void)
1749+
{
1750+
EXPECT_DECLS;
1751+
#if defined(HAVE_OID_ENCODING) && !defined(NO_ASN)
1752+
{
1753+
/* 1.3.132.0.6 (secp112r1) -- every arc fits in word16, so this
1754+
* encodes identically in both build configs. */
1755+
static const word32 oid_small[] = { 1U, 3U, 132U, 0U, 6U };
1756+
static const byte oid_small_der[] = {
1757+
0x2b, 0x81, 0x04, 0x00, 0x06
1758+
};
1759+
const word32 oid_small_cnt = sizeof(oid_small) / sizeof(word32);
1760+
byte out[MAX_OID_SZ];
1761+
word32 outSz;
1762+
word32 i;
1763+
1764+
/* Test 1: length-only query (out == NULL) */
1765+
outSz = 0;
1766+
ExpectIntEQ(wc_EncodeObjectId(oid_small, oid_small_cnt, NULL, &outSz),
1767+
0);
1768+
ExpectIntEQ((int)outSz, (int)sizeof(oid_small_der));
1769+
1770+
/* Test 2: normal encode matches expected DER */
1771+
outSz = sizeof(out);
1772+
ExpectIntEQ(wc_EncodeObjectId(oid_small, oid_small_cnt, out, &outSz), 0);
1773+
ExpectIntEQ((int)outSz, (int)sizeof(oid_small_der));
1774+
for (i = 0; i < outSz && i < sizeof(oid_small_der); i++) {
1775+
ExpectIntEQ(out[i], oid_small_der[i]);
1776+
}
1777+
1778+
/* Test 3: NULL args */
1779+
outSz = sizeof(out);
1780+
ExpectIntEQ(wc_EncodeObjectId(NULL, oid_small_cnt, out, &outSz),
1781+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
1782+
ExpectIntEQ(wc_EncodeObjectId(oid_small, oid_small_cnt, out, NULL),
1783+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
1784+
1785+
/* Test 4: output buffer too small */
1786+
outSz = 1;
1787+
ExpectIntEQ(wc_EncodeObjectId(oid_small, oid_small_cnt, out, &outSz),
1788+
WC_NO_ERR_TRACE(BUFFER_E));
1789+
1790+
/* Test 5 : an arc > word16 can only be represented in the
1791+
*/
1792+
{
1793+
static const word32 oid_large[] = {
1794+
1U, 2U, 840U, 113549U, 1U, 1U, 11U
1795+
};
1796+
static const byte oid_large_der[] = {
1797+
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b
1798+
};
1799+
const word32 oid_large_cnt = sizeof(oid_large) / sizeof(word32);
1800+
1801+
outSz = sizeof(out);
1802+
ExpectIntEQ(wc_EncodeObjectId(oid_large, oid_large_cnt, out, &outSz),
1803+
0);
1804+
ExpectIntEQ((int)outSz, (int)sizeof(oid_large_der));
1805+
for (i = 0; i < outSz && i < sizeof(oid_large_der); i++) {
1806+
ExpectIntEQ(out[i], oid_large_der[i]);
1807+
}
1808+
1809+
#if defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT)
1810+
{
1811+
word32 dec[MAX_OID_SZ];
1812+
word32 decSz = MAX_OID_SZ;
1813+
ExpectIntEQ(DecodeObjectId(out, outSz, dec, &decSz), 0);
1814+
ExpectIntEQ((int)decSz, (int)oid_large_cnt);
1815+
for (i = 0; i < decSz && i < oid_large_cnt; i++) {
1816+
ExpectIntEQ(dec[i], oid_large[i]);
1817+
}
1818+
}
1819+
#endif /* HAVE_OID_DECODING || WOLFSSL_ASN_PRINT */
1820+
}
1821+
}
1822+
#endif /* HAVE_OID_ENCODING && !NO_ASN */
1823+
1824+
return EXPECT_RESULT();
1825+
}
1826+
17011827
#if defined(HAVE_PKCS8) && !defined(NO_ASN) && \
17021828
(defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \
17031829
defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_PUBLIC_ASN)) && \

tests/api/test_asn.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ int test_SerialNumber0_RootCA(void);
3737
int test_DecodeAltNames_length_underflow(void);
3838
int test_ParseCert_SM3wSM2_short_pubkey(void);
3939
int test_wc_DecodeObjectId(void);
40+
int test_wc_EncodeObjectId(void);
4041
int test_ToTraditional_ex_handcrafted(void);
4142
int test_ToTraditional_ex_roundtrip(void);
4243
int test_ToTraditional_ex_negative(void);
@@ -56,6 +57,7 @@ int test_ToTraditional_ex_mldsa_bad_params(void);
5657
TEST_DECL_GROUP("asn", test_DecodeAltNames_length_underflow), \
5758
TEST_DECL_GROUP("asn", test_ParseCert_SM3wSM2_short_pubkey), \
5859
TEST_DECL_GROUP("asn", test_wc_DecodeObjectId), \
60+
TEST_DECL_GROUP("asn", test_wc_EncodeObjectId), \
5961
TEST_DECL_GROUP("asn", test_ToTraditional_ex_handcrafted), \
6062
TEST_DECL_GROUP("asn", test_ToTraditional_ex_roundtrip), \
6163
TEST_DECL_GROUP("asn", test_ToTraditional_ex_negative), \

0 commit comments

Comments
 (0)