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 decode a buffer
17    @param in       The Base32 data to decode
18    @param inlen    The length of the Base32 data
19    @param out      [out] The destination of the binary decoded data
20    @param outlen   [in/out] The max size and resulting size of the decoded data
21    @param id       Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD
22    @return CRYPT_OK if successful
23 */
base32_decode(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,base32_alphabet id)24 int base32_decode(const          char *in,  unsigned long inlen,
25                         unsigned char *out, unsigned long *outlen,
26                         base32_alphabet id)
27 {
28    unsigned long x;
29    int y = 0;
30    ulong64 t = 0;
31    char c;
32    const unsigned char *map;
33    const unsigned char tables[4][43] = {
34       {  /* id = BASE32_RFC4648 : ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 */
35          99/*0*/,99/*1*/,26/*2*/,27/*3*/,28/*4*/,29/*5*/,30/*6*/,31/*7*/,99/*8*/,99/*9*/,
36          99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
37           0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, 7/*H*/, 8/*I*/, 9/*J*/,10/*K*/,11/*L*/,12/*M*/,
38          13/*N*/,14/*O*/,15/*P*/,16/*Q*/,17/*R*/,18/*S*/,19/*T*/,20/*U*/,21/*V*/,22/*W*/,23/*X*/,24/*Y*/,25/*Z*/
39       },
40       {  /* id = BASE32_BASE32HEX : 0123456789ABCDEFGHIJKLMNOPQRSTUV */
41            0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/,
42           99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
43           10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/,18/*I*/,19/*J*/,20/*K*/,21/*L*/,22/*M*/,
44           23/*N*/,24/*O*/,25/*P*/,26/*Q*/,27/*R*/,28/*S*/,29/*T*/,30/*U*/,31/*V*/,99/*W*/,99/*X*/,99/*Y*/,99/*Z*/
45       },
46       {  /* id = BASE32_ZBASE32 : YBNDRFG8EJKMCPQXOT1UWISZA345H769 */
47          99/*0*/,18/*1*/,99/*2*/,25/*3*/,26/*4*/,27/*5*/,30/*6*/,29/*7*/, 7/*8*/,31/*9*/,
48          99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
49          24/*A*/, 1/*B*/,12/*C*/, 3/*D*/, 8/*E*/, 5/*F*/, 6/*G*/,28/*H*/,21/*I*/, 9/*J*/,10/*K*/,99/*L*/,11/*M*/,
50           2/*N*/,16/*O*/,13/*P*/,14/*Q*/, 4/*R*/,22/*S*/,17/*T*/,19/*U*/,99/*V*/,20/*W*/,15/*X*/, 0/*Y*/,23/*Z*/
51       },
52       {  /* id = BASE32_CROCKFORD : 0123456789ABCDEFGHJKMNPQRSTVWXYZ + O=>0 + IL=>1 */
53           0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/,
54          99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/,
55          10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/, 1/*I*/,18/*J*/,19/*K*/, 1/*L*/,20/*M*/,
56          21/*N*/, 0/*O*/,22/*P*/,23/*Q*/,24/*R*/,25/*S*/,26/*T*/,99/*U*/,27/*V*/,28/*W*/,29/*X*/,30/*Y*/,31/*Z*/
57       }
58    };
59 
60    LTC_ARGCHK(in     != NULL);
61    LTC_ARGCHK(out    != NULL);
62    LTC_ARGCHK(outlen != NULL);
63    LTC_ARGCHK(id >= BASE32_RFC4648);
64    LTC_ARGCHK(id <= BASE32_CROCKFORD);
65 
66    /* ignore all trailing = */
67    while (inlen > 0 && in[inlen-1] == '=') inlen--;
68 
69    /* no input, nothing to do */
70    if (inlen == 0) {
71       *outlen = 0;
72       return CRYPT_OK;
73    }
74 
75    /* check the size of output buffer */
76    x = (inlen * 5) / 8;
77    if (*outlen < x) {
78       *outlen = x;
79       return CRYPT_BUFFER_OVERFLOW;
80    }
81    *outlen = x;
82 
83    /* check input data length */
84    x = inlen % 8;
85    if (x == 1 || x == 3 || x == 6) {
86       return CRYPT_INVALID_PACKET;
87    }
88 
89    map = tables[id];
90    for (x = 0; x < inlen; x++) {
91       c = in[x];
92       /* convert to upper case */
93       if ((c >= 'a') && (c <= 'z')) c -= 32;
94       if (c < '0' || c > 'Z' || map[c-'0'] > 31) {
95          return CRYPT_INVALID_PACKET;
96       }
97       t = (t<<5) | map[c-'0'];
98       if (++y == 8) {
99          *out++ = (unsigned char)((t>>32) & 255);
100          *out++ = (unsigned char)((t>>24) & 255);
101          *out++ = (unsigned char)((t>>16) & 255);
102          *out++ = (unsigned char)((t>> 8) & 255);
103          *out++ = (unsigned char)( t      & 255);
104          y = 0;
105          t = 0;
106       }
107    }
108    if (y > 0) {
109       t = t << (5 * (8 - y));
110       if (y >= 2) *out++ = (unsigned char)((t>>32) & 255);
111       if (y >= 4) *out++ = (unsigned char)((t>>24) & 255);
112       if (y >= 5) *out++ = (unsigned char)((t>>16) & 255);
113       if (y >= 7) *out++ = (unsigned char)((t>> 8) & 255);
114    }
115    return CRYPT_OK;
116 }
117 
118 #endif
119 
120 /* ref:         $Format:%D$ */
121 /* git commit:  $Format:%H$ */
122 /* commit time: $Format:%ai$ */
123