1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 #include "tomcrypt_private.h"
5
6 #ifdef LTC_BASE32
7
8 /**
9 Base32 encode a buffer
10 @param in The input buffer to encode
11 @param inlen The length of the input buffer
12 @param out [out] The destination of the Base32 encoded data
13 @param outlen [in/out] The max size and resulting size of the encoded data
14 @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD
15 @return CRYPT_OK if successful
16 */
base32_encode(const unsigned char * in,unsigned long inlen,char * out,unsigned long * outlen,base32_alphabet id)17 int base32_encode(const unsigned char *in, unsigned long inlen,
18 char *out, unsigned long *outlen,
19 base32_alphabet id)
20 {
21 unsigned long i, x;
22 const char *codes;
23 const char *alphabet[4] = {
24 "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", /* id = BASE32_RFC4648 */
25 "0123456789ABCDEFGHIJKLMNOPQRSTUV", /* id = BASE32_BASE32HEX */
26 "ybndrfg8ejkmcpqxot1uwisza345h769", /* id = BASE32_ZBASE32 */
27 "0123456789ABCDEFGHJKMNPQRSTVWXYZ" /* id = BASE32_CROCKFORD */
28 };
29
30 LTC_ARGCHK(in != NULL);
31 LTC_ARGCHK(out != NULL);
32 LTC_ARGCHK(outlen != NULL);
33 LTC_ARGCHK(id >= BASE32_RFC4648);
34 LTC_ARGCHK(id <= BASE32_CROCKFORD);
35
36 /* check the size of output buffer +1 byte for terminating NUL */
37 x = (8 * inlen + 4) / 5 + 1;
38 if (*outlen < x) {
39 *outlen = x;
40 return CRYPT_BUFFER_OVERFLOW;
41 }
42 *outlen = x - 1; /* returning the length without terminating NUL */
43
44 /* no input, nothing to do */
45 if (inlen == 0) {
46 *out = '\0';
47 return CRYPT_OK;
48 }
49
50 codes = alphabet[id];
51 x = 5 * (inlen / 5);
52 for (i = 0; i < x; i += 5) {
53 *out++ = codes[(in[0] >> 3) & 0x1F];
54 *out++ = codes[(((in[0] & 0x7) << 2) + (in[1] >> 6)) & 0x1F];
55 *out++ = codes[(in[1] >> 1) & 0x1F];
56 *out++ = codes[(((in[1] & 0x1) << 4) + (in[2] >> 4)) & 0x1F];
57 *out++ = codes[(((in[2] & 0xF) << 1) + (in[3] >> 7)) & 0x1F];
58 *out++ = codes[(in[3] >> 2) & 0x1F];
59 *out++ = codes[(((in[3] & 0x3) << 3) + (in[4] >> 5)) & 0x1F];
60 *out++ = codes[in[4] & 0x1F];
61 in += 5;
62 }
63 if (i < inlen) {
64 unsigned a = in[0];
65 unsigned b = (i+1 < inlen) ? in[1] : 0;
66 unsigned c = (i+2 < inlen) ? in[2] : 0;
67 unsigned d = (i+3 < inlen) ? in[3] : 0;
68 *out++ = codes[(a >> 3) & 0x1F];
69 *out++ = codes[(((a & 0x7) << 2) + (b >> 6)) & 0x1F];
70 if (i+1 < inlen) {
71 *out++ = codes[(b >> 1) & 0x1F];
72 *out++ = codes[(((b & 0x1) << 4) + (c >> 4)) & 0x1F];
73 }
74 if (i+2 < inlen) {
75 *out++ = codes[(((c & 0xF) << 1) + (d >> 7)) & 0x1F];
76 }
77 if (i+3 < inlen) {
78 *out++ = codes[(d >> 2) & 0x1F];
79 *out++ = codes[((d & 0x3) << 3) & 0x1F];
80 }
81 }
82 *out = '\0';
83 return CRYPT_OK;
84 }
85
86 #endif
87