Fix base32 API to take any source length in bytes

Fixes #18280

Signed-off-by: David Goulet <dgoulet@ev0ke.net>
This commit is contained in:
David Goulet 2016-02-08 15:00:56 -05:00 committed by Nick Mathewson
parent a427a7c479
commit 4e4a7d2b0c
2 changed files with 25 additions and 12 deletions

View File

@ -21,33 +21,46 @@
#include <string.h>
#include <stdlib.h>
/** Implements base32 encoding as in RFC 4648. Limitation: Requires
* that srclen*8 is a multiple of 5.
*/
/* Return the base32 encoded size in bytes using the source length srclen.
* The NUL terminated byte is added as well since every base32 encoding
* requires enough space for it. */
size_t
base32_encoded_size(size_t srclen)
{
size_t enclen;
enclen = CEIL_DIV(srclen*8, 5) + 1;
tor_assert(enclen < INT_MAX && enclen > srclen);
return enclen;
}
/** Implements base32 encoding as in RFC 4648. */
void
base32_encode(char *dest, size_t destlen, const char *src, size_t srclen)
{
unsigned int i, v, u;
size_t nbits = srclen * 8, bit;
size_t nbits = srclen * 8;
size_t bit;
tor_assert(srclen < SIZE_T_CEILING/8);
tor_assert((nbits%5) == 0); /* We need an even multiple of 5 bits. */
tor_assert((nbits/5)+1 <= destlen); /* We need enough space. */
/* We need enough space for the encoded data and the extra NUL byte. */
tor_assert(base32_encoded_size(srclen) <= destlen);
tor_assert(destlen < SIZE_T_CEILING);
for (i=0,bit=0; bit < nbits; ++i, bit+=5) {
/* set v to the 16-bit value starting at src[bits/8], 0-padded. */
v = ((uint8_t)src[bit/8]) << 8;
if (bit+5<nbits) v += (uint8_t)src[(bit/8)+1];
/* set u to the 5-bit value at the bit'th bit of src. */
if (bit+5<nbits)
v += (uint8_t)src[(bit/8)+1];
/* set u to the 5-bit value at the bit'th bit of buf. */
u = (v >> (11-(bit%8))) & 0x1F;
dest[i] = BASE32_CHARS[u];
}
dest[i] = '\0';
}
/** Implements base32 decoding as in RFC 4648. Limitation: Requires
* that srclen*5 is a multiple of 8. Returns 0 if successful, -1 otherwise.
/** Implements base32 decoding as in RFC 4648.
* Returns 0 if successful, -1 otherwise.
*/
int
base32_decode(char *dest, size_t destlen, const char *src, size_t srclen)
@ -57,10 +70,9 @@ base32_decode(char *dest, size_t destlen, const char *src, size_t srclen)
unsigned int i;
size_t nbits, j, bit;
char *tmp;
nbits = srclen * 5;
nbits = ((srclen * 5) / 8) * 8;
tor_assert(srclen < SIZE_T_CEILING / 5);
tor_assert((nbits%8) == 0); /* We need an even multiple of 8 bits. */
tor_assert((nbits/8) <= destlen); /* We need enough space. */
tor_assert(destlen < SIZE_T_CEILING);

View File

@ -24,6 +24,7 @@ int base64_decode_nopad(uint8_t *dest, size_t destlen,
#define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567"
void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base32_decode(char *dest, size_t destlen, const char *src, size_t srclen);
size_t base32_encoded_size(size_t srclen);
int hex_decode_digit(char c);
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen);