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