]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
util/base64: use decoder fns per RFC
authorShivani Bhardwaj <shivani@oisf.net>
Fri, 19 Apr 2024 11:47:30 +0000 (17:17 +0530)
committerVictor Julien <victor@inliniac.net>
Thu, 25 Apr 2024 04:52:26 +0000 (06:52 +0200)
instead of the common decoder fn.

Bug 6964

src/util-base64.c

index 9882676b7b8c313f4ff41c93a770da1bedfcb1de..43bc4d467ac3442d32692e1392a41fa0a048b64c 100644 (file)
@@ -269,104 +269,24 @@ static inline Base64Ecode DecodeBase64RFC4648(uint8_t *dest, uint32_t dest_size,
 Base64Ecode DecodeBase64(uint8_t *dest, uint32_t dest_size, const uint8_t *src, uint32_t len,
         uint32_t *consumed_bytes, uint32_t *decoded_bytes, Base64Mode mode)
 {
-    int val;
-    uint32_t padding = 0, bbidx = 0, sp = 0, leading_sp = 0;
-    uint8_t *dptr = dest;
-    uint8_t b64[B64_BLOCK] = { 0,0,0,0 };
-    bool valid = true;
-    Base64Ecode ecode = BASE64_ECODE_OK;
     *decoded_bytes = 0;
-
-    /* Traverse through each alpha-numeric letter in the source array */
-    for (uint32_t i = 0; i < len; i++) {
-        /* Get decimal representation */
-        val = GetBase64Value(src[i]);
-        if (val < 0) {
-            if (mode == BASE64_MODE_RFC2045 && src[i] != '=') {
-                if (bbidx == 0) {
-                    /* Special case where last block of data has a leading space or invalid char */
-                    leading_sp++;
-                }
-                sp++;
-                continue;
-            }
-            /* Invalid character found, so decoding fails */
-            if (src[i] != '=') {
-                valid = false;
-                ecode = BASE64_ECODE_ERR;
-                if (mode == BASE64_MODE_STRICT) {
-                    *decoded_bytes = 0;
-                }
-                break;
-            }
-            padding++;
-        }
-
-        /* For each alpha-numeric letter in the source array, find the numeric
-         * value */
-        b64[bbidx++] = (val > 0 ? (uint8_t)val : 0);
-
-        /* Decode every 4 base64 bytes into 3 ascii bytes */
-        if (bbidx == B64_BLOCK) {
-
-            /* For every 4 bytes, add 3 bytes but deduct the '=' padded blocks */
-            uint32_t numDecoded_blk = ASCII_BLOCK - (padding < B64_BLOCK ? padding : ASCII_BLOCK);
-            if (dest_size < *decoded_bytes + numDecoded_blk) {
-                SCLogDebug("Destination buffer full");
-                ecode = BASE64_ECODE_BUF;
-                break;
-            }
-            if (dest_size - *decoded_bytes < ASCII_BLOCK)
-                return BASE64_ECODE_BUF;
-
-            /* Decode base-64 block into ascii block and move pointer */
-            DecodeBase64Block(dptr, b64);
-            dptr += numDecoded_blk;
-            *decoded_bytes += numDecoded_blk;
-            /* Reset base-64 block and index */
-            bbidx = 0;
-            padding = 0;
-            *consumed_bytes += B64_BLOCK + sp;
-            sp = 0;
-            leading_sp = 0;
-            memset(&b64, 0, sizeof(b64));
-        }
-    }
-
-    if (bbidx > 0 && bbidx < 4 && ((!valid && mode == BASE64_MODE_RFC4648))) {
-        /* Decoded bytes for 1 or 2 base64 encoded bytes is 1 */
-        padding = bbidx > 1 ? B64_BLOCK - bbidx : 2;
-        uint32_t numDecoded_blk = ASCII_BLOCK - (padding < B64_BLOCK ? padding : ASCII_BLOCK);
-        if (dest_size < *decoded_bytes + numDecoded_blk) {
-            SCLogDebug("Destination buffer full");
-            ecode = BASE64_ECODE_BUF;
-            return ecode;
-        }
-        /* if the destination size is not at least 3 Bytes long, it'll give a dynamic
-         * buffer overflow while decoding, so, return and let the caller take care of the
-         * remaining bytes to be decoded which should always be < 4 at this stage */
-        if (dest_size - *decoded_bytes < ASCII_BLOCK)
-            return BASE64_ECODE_BUF;
-        *decoded_bytes += numDecoded_blk;
-        DecodeBase64Block(dptr, b64);
-        *consumed_bytes += bbidx;
+    Base64Ecode ret = BASE64_ECODE_OK;
+    switch (mode) {
+        case BASE64_MODE_RFC4648:
+            ret = DecodeBase64RFC4648(
+                    dest, dest_size, src, len, consumed_bytes, decoded_bytes, false);
+            break;
+        case BASE64_MODE_RFC2045:
+            ret = DecodeBase64RFC2045(dest, dest_size, src, len, consumed_bytes, decoded_bytes);
+            break;
+        case BASE64_MODE_STRICT:
+            ret = DecodeBase64RFC4648(
+                    dest, dest_size, src, len, consumed_bytes, decoded_bytes, true);
+            break;
+        default:
+            return BASE64_ECODE_ERR;
     }
-
-    /* Finish remaining b64 bytes by padding */
-    if (valid && bbidx > 0 && (mode != BASE64_MODE_RFC2045)) {
-        /* Decode remaining */
-        if (dest_size - *decoded_bytes < ASCII_BLOCK)
-            return BASE64_ECODE_BUF;
-        *decoded_bytes += ASCII_BLOCK - (B64_BLOCK - bbidx);
-        DecodeBase64Block(dptr, b64);
-    }
-
-    if (*decoded_bytes == 0) {
-        SCLogDebug("base64 decoding failed");
-    }
-
-    *consumed_bytes += leading_sp;
-    return ecode;
+    return ret;
 }
 
 #ifdef UNITTESTS