ASN.1 template: validate UTF8STRING and OBJECT IDENTIFER data

Check the data of UTF8STRING and OBJECT IDENTIFIER to ensure it is
properly encoded.
This commit is contained in:
Sean Parkinson
2024-03-07 16:48:01 +10:00
parent f011012d8e
commit faea635ee2

View File

@ -1116,6 +1116,98 @@ static int GetASN_BitString(const byte* input, word32 idx, int length)
return 0;
}
/* Check a UTF8STRING's data is valid.
*
* @param [in] input BER encoded data.
* @param [in] idx Index of UTF8STRING data.
* @param [in] length Length of input data.
* @return 0 on success.
* @return ASN_PARSE_E when data is invalid.
*/
static int GetASN_UTF8String(const byte* input, word32 idx, int length)
{
int ret = 0;
int i = 0;
while ((ret == 0) && (i < length)) {
int cnt;
/* Check code points and get count of following bytes. */
if ((input[idx + i] & 0x80) == 0x00) {
cnt = 0;
}
else if ((input[idx + i] & 0xe0) == 0xc0) {
cnt = 1;
}
else if ((input[idx + i] & 0xf0) == 0xe0) {
cnt = 2;
}
else if ((input[idx + i] & 0xf8) == 0xf0) {
cnt = 3;
}
else {
WOLFSSL_MSG("Invalid character in UTF8STRING\n");
ret = ASN_PARSE_E;
break;
}
/* Have checked first byte. */
i++;
/* Check each following byte. */
for (; cnt > 0; cnt--) {
/* Check we have enough data. */
if (i == length) {
WOLFSSL_MSG("Missing character in UTF8STRING\n");
ret = ASN_PARSE_E;
break;
}
/* Check following byte has top bit set. */
if ((input[idx + i] & 0x80) != 0x80) {
WOLFSSL_MSG("Invalid character in UTF8STRING\n");
ret = ASN_PARSE_E;
break;
}
i++;
}
}
return ret;
}
/* Check an OBJECT IDENTIFIER's data is valid.
*
* X.690 8.19
*
* @param [in] input BER encoded data.
* @param [in] idx Index of OBJECT IDENTIFIER data.
* @param [in] length Length of input data.
* @return 0 on success.
* @return ASN_PARSE_E when data is invalid.
*/
static int GetASN_ObjectId(const byte* input, word32 idx, int length)
{
int ret = 0;
/* OID data must be at least 3 bytes. */
if (length < 3) {
#ifdef WOLFSSL_DEBUG_ASN_TEMPLATE
WOLFSSL_MSG_VSNPRINTF("OID length must be 3 or more: %d", len);
#else
WOLFSSL_MSG("OID length less than 3");
#endif
ret = ASN_PARSE_E;
}
/* Last octet of a subidentifier has bit 8 clear. Last octet must be last
* of a subidentifier. Ensure last octet hasn't got top bit set indicating.
*/
else if ((input[idx + length - 1] & 0x80) != 0x00) {
WOLFSSL_MSG("OID last octet has top bit set");
ret = ASN_PARSE_E;
}
return ret;
}
/* Get the ASN.1 items from the BER encoding.
*
* @param [in] asn ASN.1 item expected.
@ -1581,11 +1673,18 @@ int GetASN_Items(const ASNItem* asn, ASNGetData *data, int count, int complete,
idx++;
len--;
}
else if ((asn[i].tag == ASN_OBJECT_ID) && (len < 3)) {
#ifdef WOLFSSL_DEBUG_ASN_TEMPLATE
WOLFSSL_MSG_VSNPRINTF("OID length must be 3 or more: %d", len);
#endif
return ASN_PARSE_E;
else if ((asn[i].tag == ASN_UTF8STRING) ||
(data[i].tag == ASN_UTF8STRING)) {
/* Check validity of data. */
err = GetASN_UTF8String(input, idx, len);
if (err != 0)
return err;
}
else if (asn[i].tag == ASN_OBJECT_ID) {
/* Check validity of data. */
err = GetASN_ObjectId(input, idx, len);
if (err != 0)
return err;
}
/* Don't parse data if only header required. */