Skip to content

Commit faea635

Browse files
committed
ASN.1 template: validate UTF8STRING and OBJECT IDENTIFER data
Check the data of UTF8STRING and OBJECT IDENTIFIER to ensure it is properly encoded.
1 parent f011012 commit faea635

1 file changed

Lines changed: 104 additions & 5 deletions

File tree

wolfcrypt/src/asn.c

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,98 @@ static int GetASN_BitString(const byte* input, word32 idx, int length)
11161116
return 0;
11171117
}
11181118

1119+
/* Check a UTF8STRING's data is valid.
1120+
*
1121+
* @param [in] input BER encoded data.
1122+
* @param [in] idx Index of UTF8STRING data.
1123+
* @param [in] length Length of input data.
1124+
* @return 0 on success.
1125+
* @return ASN_PARSE_E when data is invalid.
1126+
*/
1127+
static int GetASN_UTF8String(const byte* input, word32 idx, int length)
1128+
{
1129+
int ret = 0;
1130+
int i = 0;
1131+
1132+
while ((ret == 0) && (i < length)) {
1133+
int cnt;
1134+
1135+
/* Check code points and get count of following bytes. */
1136+
if ((input[idx + i] & 0x80) == 0x00) {
1137+
cnt = 0;
1138+
}
1139+
else if ((input[idx + i] & 0xe0) == 0xc0) {
1140+
cnt = 1;
1141+
}
1142+
else if ((input[idx + i] & 0xf0) == 0xe0) {
1143+
cnt = 2;
1144+
}
1145+
else if ((input[idx + i] & 0xf8) == 0xf0) {
1146+
cnt = 3;
1147+
}
1148+
else {
1149+
WOLFSSL_MSG("Invalid character in UTF8STRING\n");
1150+
ret = ASN_PARSE_E;
1151+
break;
1152+
}
1153+
1154+
/* Have checked first byte. */
1155+
i++;
1156+
/* Check each following byte. */
1157+
for (; cnt > 0; cnt--) {
1158+
/* Check we have enough data. */
1159+
if (i == length) {
1160+
WOLFSSL_MSG("Missing character in UTF8STRING\n");
1161+
ret = ASN_PARSE_E;
1162+
break;
1163+
}
1164+
/* Check following byte has top bit set. */
1165+
if ((input[idx + i] & 0x80) != 0x80) {
1166+
WOLFSSL_MSG("Invalid character in UTF8STRING\n");
1167+
ret = ASN_PARSE_E;
1168+
break;
1169+
}
1170+
i++;
1171+
}
1172+
}
1173+
1174+
return ret;
1175+
}
1176+
1177+
/* Check an OBJECT IDENTIFIER's data is valid.
1178+
*
1179+
* X.690 8.19
1180+
*
1181+
* @param [in] input BER encoded data.
1182+
* @param [in] idx Index of OBJECT IDENTIFIER data.
1183+
* @param [in] length Length of input data.
1184+
* @return 0 on success.
1185+
* @return ASN_PARSE_E when data is invalid.
1186+
*/
1187+
static int GetASN_ObjectId(const byte* input, word32 idx, int length)
1188+
{
1189+
int ret = 0;
1190+
1191+
/* OID data must be at least 3 bytes. */
1192+
if (length < 3) {
1193+
#ifdef WOLFSSL_DEBUG_ASN_TEMPLATE
1194+
WOLFSSL_MSG_VSNPRINTF("OID length must be 3 or more: %d", len);
1195+
#else
1196+
WOLFSSL_MSG("OID length less than 3");
1197+
#endif
1198+
ret = ASN_PARSE_E;
1199+
}
1200+
/* Last octet of a subidentifier has bit 8 clear. Last octet must be last
1201+
* of a subidentifier. Ensure last octet hasn't got top bit set indicating.
1202+
*/
1203+
else if ((input[idx + length - 1] & 0x80) != 0x00) {
1204+
WOLFSSL_MSG("OID last octet has top bit set");
1205+
ret = ASN_PARSE_E;
1206+
}
1207+
1208+
return ret;
1209+
}
1210+
11191211
/* Get the ASN.1 items from the BER encoding.
11201212
*
11211213
* @param [in] asn ASN.1 item expected.
@@ -1581,11 +1673,18 @@ int GetASN_Items(const ASNItem* asn, ASNGetData *data, int count, int complete,
15811673
idx++;
15821674
len--;
15831675
}
1584-
else if ((asn[i].tag == ASN_OBJECT_ID) && (len < 3)) {
1585-
#ifdef WOLFSSL_DEBUG_ASN_TEMPLATE
1586-
WOLFSSL_MSG_VSNPRINTF("OID length must be 3 or more: %d", len);
1587-
#endif
1588-
return ASN_PARSE_E;
1676+
else if ((asn[i].tag == ASN_UTF8STRING) ||
1677+
(data[i].tag == ASN_UTF8STRING)) {
1678+
/* Check validity of data. */
1679+
err = GetASN_UTF8String(input, idx, len);
1680+
if (err != 0)
1681+
return err;
1682+
}
1683+
else if (asn[i].tag == ASN_OBJECT_ID) {
1684+
/* Check validity of data. */
1685+
err = GetASN_ObjectId(input, idx, len);
1686+
if (err != 0)
1687+
return err;
15891688
}
15901689

15911690
/* Don't parse data if only header required. */

0 commit comments

Comments
 (0)