diff --git a/src/util-base64.c b/src/util-base64.c index 9882676b7b..43bc4d467a 100644 --- a/src/util-base64.c +++ b/src/util-base64.c @@ -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