1 /* vim: set ts=8 sts=4 sw=4 tw=80 noet: */
2 /*======================================================================
3 Copyright (C) 2004,2005,2009,2013 Walter Doekes <walter+tthsum@wjd.nu>
4 This file is part of tthsum.
5
6 tthsum is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 tthsum is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with tthsum. If not, see <http://www.gnu.org/licenses/>.
18 ======================================================================*/
19 #include "base32.h"
20
21 #include "endian.h"
22 #include <assert.h>
23
24 #if BYTE_ORDER == BIG_ENDIAN
25 # include <stdlib.h>
26 # include <string.h>
27 #endif /* BYTE_ORDER == BIG_ENDIAN */
28
29 #ifdef USE_TEXTS
30 # include "texts.h"
31 #endif
32
33
34 static const int8_t base32_table[] = {
35 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
36 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
37 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
38 -1,-1,26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1,
39 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
40 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
41 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
42 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
43 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
44 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
45 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
46 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
47 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
48 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
49 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
50 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
51 };
52
53 static const unsigned char base32_alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
54
uint64tobase32(char * dest,const uint64_t * src,unsigned len)55 int uint64tobase32(char* dest, const uint64_t* src, unsigned len) {
56 #if BYTE_ORDER == BIG_ENDIAN
57 int i;
58 uint8_t* tmp;
59 len *= 8;
60 if ((tmp = (uint8_t*)malloc(len)) == NULL) {
61 #ifdef USE_TEXTS
62 set_error("malloc", ERROR_FROM_OS);
63 #endif /* USE_TEXTS */
64 return -1;
65 }
66 for (i = 0; i < len; ++i)
67 tmp[i ^ 7] = ((uint8_t*)src)[i];
68 i = uint8tobase32(dest, tmp, len);
69 free(tmp);
70 return i;
71 #else /* BYTE_ORDER != BIG_ENDIAN */
72 return uint8tobase32(dest, (const uint8_t*)src, len * 8);
73 #endif /* BYTE_ORDER != BIG_ENDIAN */
74 }
75
uint8tobase32(char * dest,const uint8_t * src,unsigned len)76 int uint8tobase32(char* dest, const uint8_t* src, unsigned len) {
77 unsigned index = 0;
78 uint8_t word;
79 const uint8_t* srce = src + len;
80 while (src != srce) {
81 /* Spanning byte boundary? */
82 if (index > 3) {
83 word = (*src & (0xFF >> index));
84 index = (index + 5) % 8;
85 word <<= index;
86 if (src + 1 != srce)
87 word |= *(src + 1) >> (8 - index);
88 ++src;
89 } else {
90 word = (*src >> (8 - (index + 5))) & 0x1F;
91 index = (index + 5) % 8;
92 if (index == 0)
93 ++src;
94 }
95 assert(word < 32);
96 *dest++ = base32_alpha[word];
97 }
98 *dest = '\0';
99 return 0;
100 }
101
base32touint64(uint64_t * dest,const char * src,unsigned len)102 int base32touint64(uint64_t* dest, const char* src, unsigned len) {
103 #if BYTE_ORDER == BIG_ENDIAN
104 int ret, i;
105 uint8_t* tmp;
106 len *= 8;
107 if ((tmp = (uint8_t*)malloc(len)) == NULL) {
108 #ifdef USE_TEXTS
109 set_error("malloc", ERROR_FROM_OS);
110 #endif /* USE_TEXTS */
111 return -1;
112 }
113 memset(tmp, 0, len); /* dest must be initialized to zeroes */
114 ret = base32touint8(tmp, src, len);
115 for (i = 0; i < len; ++i)
116 ((uint8_t*)dest)[i ^ 7] = tmp[i];
117 free(tmp);
118 return ret;
119 #else /* BYTE_ORDER != BIG_ENDIAN */
120 return base32touint8((uint8_t*)dest, src, len * 8);
121 #endif /* BYTE_ORDER != BIG_ENDIAN */
122 }
123
base32touint8(uint8_t * dest,const char * src,unsigned len)124 int base32touint8(uint8_t* dest, const char* src, unsigned len) {
125 unsigned index = 0;
126 int8_t tmp;
127 const uint8_t* deste = dest + len;
128 for (; dest != deste; ++src) {
129 if ((tmp = base32_table[(unsigned)*src]) == -1) {
130 #ifdef USE_TEXTS
131 set_error("base32touint8", BASE32_INVALID_CHARACTER);
132 #endif /* USE_TEXTS */
133 return -1;
134 }
135 if (index <= 3) {
136 index = (index + 5) % 8;
137 if (index == 0)
138 *dest++ |= tmp;
139 else
140 *dest |= tmp << (8 - index);
141 } else {
142 index = (index + 5) % 8;
143 *dest++ |= (tmp >> index);
144 *dest |= tmp << (8 - index);
145 }
146 }
147 return 0;
148 }
149