blob: 0ac256c82c929d660f991dea2cd3e110e3223e23 [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
#include "tomcrypt_private.h"
#ifdef LTC_BASE32
/**
Base32 encode a buffer
@param in The input buffer to encode
@param inlen The length of the input buffer
@param out [out] The destination of the Base32 encoded data
@param outlen [in/out] The max size and resulting size of the encoded data
@param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD
@return CRYPT_OK if successful
*/
int base32_encode(const unsigned char *in, unsigned long inlen,
char *out, unsigned long *outlen,
base32_alphabet id)
{
unsigned long i, x;
const char *codes;
const char *alphabet[4] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", /* id = BASE32_RFC4648 */
"0123456789ABCDEFGHIJKLMNOPQRSTUV", /* id = BASE32_BASE32HEX */
"ybndrfg8ejkmcpqxot1uwisza345h769", /* id = BASE32_ZBASE32 */
"0123456789ABCDEFGHJKMNPQRSTVWXYZ" /* id = BASE32_CROCKFORD */
};
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(id >= BASE32_RFC4648);
LTC_ARGCHK(id <= BASE32_CROCKFORD);
/* check the size of output buffer +1 byte for terminating NUL */
x = (8 * inlen + 4) / 5 + 1;
if (*outlen < x) {
*outlen = x;
return CRYPT_BUFFER_OVERFLOW;
}
*outlen = x - 1; /* returning the length without terminating NUL */
/* no input, nothing to do */
if (inlen == 0) {
*out = '\0';
return CRYPT_OK;
}
codes = alphabet[id];
x = 5 * (inlen / 5);
for (i = 0; i < x; i += 5) {
*out++ = codes[(in[0] >> 3) & 0x1F];
*out++ = codes[(((in[0] & 0x7) << 2) + (in[1] >> 6)) & 0x1F];
*out++ = codes[(in[1] >> 1) & 0x1F];
*out++ = codes[(((in[1] & 0x1) << 4) + (in[2] >> 4)) & 0x1F];
*out++ = codes[(((in[2] & 0xF) << 1) + (in[3] >> 7)) & 0x1F];
*out++ = codes[(in[3] >> 2) & 0x1F];
*out++ = codes[(((in[3] & 0x3) << 3) + (in[4] >> 5)) & 0x1F];
*out++ = codes[in[4] & 0x1F];
in += 5;
}
if (i < inlen) {
unsigned a = in[0];
unsigned b = (i+1 < inlen) ? in[1] : 0;
unsigned c = (i+2 < inlen) ? in[2] : 0;
unsigned d = (i+3 < inlen) ? in[3] : 0;
*out++ = codes[(a >> 3) & 0x1F];
*out++ = codes[(((a & 0x7) << 2) + (b >> 6)) & 0x1F];
if (i+1 < inlen) {
*out++ = codes[(b >> 1) & 0x1F];
*out++ = codes[(((b & 0x1) << 4) + (c >> 4)) & 0x1F];
}
if (i+2 < inlen) {
*out++ = codes[(((c & 0xF) << 1) + (d >> 7)) & 0x1F];
}
if (i+3 < inlen) {
*out++ = codes[(d >> 2) & 0x1F];
*out++ = codes[((d & 0x3) << 3) & 0x1F];
}
}
*out = '\0';
return CRYPT_OK;
}
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */