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