Changeset 771 in openpam for trunk/lib/liboath/oath_base32.c
- Timestamp:
- Mar 6, 2014, 5:54:58 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/liboath/oath_base32.c
r770 r771 38 38 #include <errno.h> 39 39 #include <stdint.h> 40 #include <stdio.h> 40 41 41 42 #include <security/oath.h> 42 43 43 static const char b32 [] =44 static const char b32enc[] = 44 45 "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 45 46 47 static const uint8_t b32dec[256] = { 48 ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, 49 ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7, 50 ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, 51 ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15, 52 ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, 53 ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, 54 ['Y'] = 24, ['Z'] = 25, 55 56 ['a'] = 0, ['b'] = 1, ['c'] = 2, ['d'] = 3, 57 ['e'] = 4, ['f'] = 5, ['g'] = 6, ['h'] = 7, 58 ['i'] = 8, ['j'] = 9, ['k'] = 10, ['l'] = 11, 59 ['m'] = 12, ['n'] = 13, ['o'] = 14, ['p'] = 15, 60 ['q'] = 16, ['r'] = 17, ['s'] = 18, ['t'] = 19, 61 ['u'] = 20, ['v'] = 21, ['w'] = 22, ['x'] = 23, 62 ['y'] = 24, ['z'] = 25, 63 64 ['2'] = 26, ['3'] = 27, ['4'] = 28, ['5'] = 29, 65 ['6'] = 30, ['7'] = 31, 66 }; 67 46 68 /* 47 * Encode data in RFC 3548 base 32 representation. The target buffer must69 * Encode data in RFC 4648 base 32 representation. The target buffer must 48 70 * have room for base32_enclen(len) characters and a terminating NUL. 49 71 */ … … 53 75 uint64_t bits; 54 76 55 if (*olen <= base32_enclen(ilen)) 77 if (*olen <= base32_enclen(ilen)) { 78 errno = ENOSPC; 56 79 return (-1); 80 } 57 81 *olen = 0; 58 82 while (ilen >= 5) { … … 65 89 ilen -= 5; 66 90 in += 5; 67 out[0] = b32 [bits >> 35 & 0x1f];68 out[1] = b32 [bits >> 30 & 0x1f];69 out[2] = b32 [bits >> 25 & 0x1f];70 out[3] = b32 [bits >> 20 & 0x1f];71 out[4] = b32 [bits >> 15 & 0x1f];72 out[5] = b32 [bits >> 10 & 0x1f];73 out[6] = b32 [bits >> 5 & 0x1f];74 out[7] = b32 [bits & 0x1f];91 out[0] = b32enc[bits >> 35 & 0x1f]; 92 out[1] = b32enc[bits >> 30 & 0x1f]; 93 out[2] = b32enc[bits >> 25 & 0x1f]; 94 out[3] = b32enc[bits >> 20 & 0x1f]; 95 out[4] = b32enc[bits >> 15 & 0x1f]; 96 out[5] = b32enc[bits >> 10 & 0x1f]; 97 out[6] = b32enc[bits >> 5 & 0x1f]; 98 out[7] = b32enc[bits & 0x1f]; 75 99 *olen += 8; 76 100 out += 8; … … 88 112 bits |= (uint64_t)in[0] << 32; 89 113 } 90 out[0] = b32 [bits >> 35 & 0x1f];91 out[1] = b32 [bits >> 30 & 0x1f];92 out[2] = ilen > 1 ? b32 [bits >> 25 & 0x1f] : '=';93 out[3] = ilen > 1 ? b32 [bits >> 20 & 0x1f] : '=';94 out[4] = ilen > 2 ? b32 [bits >> 15 & 0x1f] : '=';95 out[5] = ilen > 3 ? b32 [bits >> 10 & 0x1f] : '=';96 out[6] = ilen > 3 ? b32 [bits >> 5 & 0x1f] : '=';114 out[0] = b32enc[bits >> 35 & 0x1f]; 115 out[1] = b32enc[bits >> 30 & 0x1f]; 116 out[2] = ilen > 1 ? b32enc[bits >> 25 & 0x1f] : '='; 117 out[3] = ilen > 1 ? b32enc[bits >> 20 & 0x1f] : '='; 118 out[4] = ilen > 2 ? b32enc[bits >> 15 & 0x1f] : '='; 119 out[5] = ilen > 3 ? b32enc[bits >> 10 & 0x1f] : '='; 120 out[6] = ilen > 3 ? b32enc[bits >> 5 & 0x1f] : '='; 97 121 out[7] = '='; 98 122 *olen += 8; … … 105 129 106 130 /* 107 * Decode data in RFC 2548 base 32 representation, stopping at the131 * Decode data in RFC 4648 base 32 representation, stopping at the 108 132 * terminating NUL, the first invalid (non-base32, non-whitespace) 109 133 * character or after len characters, whichever comes first. 134 * 135 * Padding is handled sloppily: any padding character following the data 136 * is silently consumed. This not only simplifies the code but ensures 137 * compatibility with implementations which do not emit or understand 138 * padding. 110 139 * 111 140 * The olen argument is used by the caller to pass the size of the buffer … … 118 147 { 119 148 size_t len; 120 uint64_t bits; 121 int shift; 149 int bits, shift, padding; 122 150 123 for (len = 0, bits = 0, shift = 40; ilen && *in && *in != '='; --ilen, ++in) { 124 if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n') { 151 for (bits = shift = padding = len = 0; ilen && *in; --ilen, ++in) { 152 if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n' || 153 (padding && *in == '=')) { 154 /* consume */ 125 155 continue; 126 } else if (*in >= 'A' && *in <= 'Z') { 127 shift -= 5; 128 bits |= (uint64_t)(*in - 'A') << shift; 129 } else if (*in >= 'a' && *in <= 'z') { 130 shift -= 5; 131 bits |= (uint64_t)(*in - 'a') << shift; 132 } else if (*in >= '2' && *in <= '7') { 133 shift -= 5; 134 bits |= (uint64_t)(*in - '2' + 26) << shift; 135 } else if (*in == '=') { 136 /* handled below */ 137 break; 156 } else if (!padding && b32dec[(int)*in]) { 157 /* shift into accumulator */ 158 shift += 5; 159 bits = bits << 5 | b32dec[(int)*in]; 160 } else if (!padding && shift && *in == '=') { 161 /* final byte */ 162 shift = 0; 163 padding = 1; 138 164 } else { 139 goto bad; 165 /* error */ 166 *olen = 0; 167 errno = EINVAL; 168 return (-1); 140 169 } 141 if (shift == 0) { 142 if ((len += 5) <= *olen) { 143 *out++ = (bits >> 32) & 0xff; 144 *out++ = (bits >> 24) & 0xff; 145 *out++ = (bits >> 16) & 0xff; 146 *out++ = (bits >> 8) & 0xff; 147 *out++ = bits & 0xff; 148 } 149 bits = 0; 150 shift = 40; 170 if (shift >= 8) { 171 /* output accumulated byte */ 172 shift -= 8; 173 if (len++ < *olen) 174 *out++ = (bits >> shift) & 0xff; 151 175 } 152 176 } 153 if (ilen && *in == '=' && 154 (shift == 30 || shift == 20 || shift == 15 || shift == 5)) { 155 /* 156 * Padding: 157 * 158 * 00 8 AA====== 30 159 * 00 00 16 AAAA==== 20 160 * 00 00 00 24 AAAAA=== 15 161 * 00 00 00 00 32 AAAAAAA= 5 162 * 163 * XXX We should check that the last few bits before the 164 * padding starts are zero. 165 */ 166 switch (shift) { 167 case 5: 168 if (++len <= *olen) 169 *out++ = (bits >> 32) & 0xff; 170 bits <<= 8; 171 case 15: 172 if (++len <= *olen) 173 *out++ = (bits >> 32) & 0xff; 174 bits <<= 8; 175 case 20: 176 if (++len <= *olen) 177 *out++ = (bits >> 32) & 0xff; 178 bits <<= 8; 179 case 30: 180 if (++len <= *olen) 181 *out++ = (bits >> 32) & 0xff; 182 bits <<= 8; 183 break; 184 default: 185 goto bad; 186 } 187 /* consume remaining padding and whitespace */ 188 for (; ilen && *in; --ilen, ++in) { 189 if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n') 190 continue; 191 else if (*in == '=' && shift) 192 shift -= 5; 193 else 194 goto bad; 195 } 177 /* report decoded length */ 178 *olen = len; 179 if (len > *olen) { 180 /* overflow */ 181 errno = ENOSPC; 182 return (-1); 196 183 } 197 if (ilen)198 goto bad;199 *olen = len;200 if (len > *olen)201 return (-1);202 184 return (0); 203 bad:204 *olen = 0;205 return (-1);206 185 }
Note: See TracChangeset
for help on using the changeset viewer.