util/base64: use decoder fns per RFC

instead of the common decoder fn.

Bug 6964
pull/10952/head
Shivani Bhardwaj 1 year ago committed by Victor Julien
parent 885d540dea
commit c0bc43c393

@ -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, 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) 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; *decoded_bytes = 0;
Base64Ecode ret = BASE64_ECODE_OK;
/* Traverse through each alpha-numeric letter in the source array */ switch (mode) {
for (uint32_t i = 0; i < len; i++) { case BASE64_MODE_RFC4648:
/* Get decimal representation */ ret = DecodeBase64RFC4648(
val = GetBase64Value(src[i]); dest, dest_size, src, len, consumed_bytes, decoded_bytes, false);
if (val < 0) { break;
if (mode == BASE64_MODE_RFC2045 && src[i] != '=') { case BASE64_MODE_RFC2045:
if (bbidx == 0) { ret = DecodeBase64RFC2045(dest, dest_size, src, len, consumed_bytes, decoded_bytes);
/* Special case where last block of data has a leading space or invalid char */ break;
leading_sp++; case BASE64_MODE_STRICT:
} ret = DecodeBase64RFC4648(
sp++; dest, dest_size, src, len, consumed_bytes, decoded_bytes, true);
continue; break;
} default:
/* Invalid character found, so decoding fails */ return BASE64_ECODE_ERR;
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;
} }
return ret;
/* 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;
} }
#ifdef UNITTESTS #ifdef UNITTESTS

Loading…
Cancel
Save