]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
ASN.1: Reject invalid extended tags in DER encoding
authorJouni Malinen <j@w1.fi>
Sat, 13 Mar 2021 14:49:07 +0000 (16:49 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 14 Mar 2021 09:37:58 +0000 (11:37 +0200)
The extended tag case is allowed only for tag values that are 31 or
larger (i.e., the ones that would not fit in the single octet identifier
case with five bits). Extended tag format was previously accepted even
for the values 0..31 and this would enable multiple different encodings
for the same tag value. That is not allowed for DER.

Perform more strict checks to reject invalid extended tag values. This
is needed for a compliant implementation and this is especially
important for the case of verifying DER encoded signatures to prevent
potential forging attacks.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/tls/asn1.c

index f4d06e5569e68edc9f4e72bd41816a0191feeec1..57e2d538700e971ef0b9ff0939e7a067a7167677 100644 (file)
@@ -186,18 +186,35 @@ int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
        hdr->constructed = !!(hdr->identifier & (1 << 5));
 
        if ((hdr->identifier & 0x1f) == 0x1f) {
+               size_t ext_len = 0;
+
                hdr->tag = 0;
+               if (pos == end || (*pos & 0x7f) == 0) {
+                       wpa_printf(MSG_DEBUG,
+                                  "ASN.1: Invalid extended tag (first octet has to be included with at least one nonzero bit for the tag value)");
+                       return -1;
+               }
                do {
                        if (pos >= end) {
                                wpa_printf(MSG_DEBUG, "ASN.1: Identifier "
                                           "underflow");
                                return -1;
                        }
+                       ext_len++;
                        tmp = *pos++;
                        wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: "
                                   "0x%02x", tmp);
                        hdr->tag = (hdr->tag << 7) | (tmp & 0x7f);
                } while (tmp & 0x80);
+               wpa_printf(MSG_MSGDUMP, "ASN.1: Extended Tag: 0x%x (len=%zu)",
+                          hdr->tag, ext_len);
+               if ((hdr->class != ASN1_CLASS_PRIVATE && hdr->tag < 31) ||
+                   ext_len * 7 > sizeof(hdr->tag) * 8) {
+                       wpa_printf(MSG_DEBUG,
+                                  "ASN.1: Invalid or unsupported (too large) extended Tag: 0x%x (len=%zu)",
+                                  hdr->tag, ext_len);
+                       return -1;
+               }
        } else
                hdr->tag = hdr->identifier & 0x1f;