Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 1 | /* |
| 2 | * cdecoder.c - c source to a base64 decoding algorithm implementation |
| 3 | * |
| 4 | * This is part of the libb64 project, and has been placed in the public domain. |
| 5 | * For details, see http://sourceforge.net/projects/libb64 |
| 6 | */ |
| 7 | |
| 8 | #include <libzrtpcpp/zrtpB64Decode.h> |
| 9 | |
| 10 | int base64_decode_value(char value_in) |
| 11 | { |
| 12 | static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; |
| 13 | static const char decoding_size = sizeof(decoding); |
| 14 | value_in -= 43; |
| 15 | if (value_in < 0 || value_in > decoding_size) return -1; |
| 16 | return decoding[(int)value_in]; |
| 17 | } |
| 18 | |
| 19 | void base64_init_decodestate(base64_decodestate* state_in) |
| 20 | { |
| 21 | state_in->step = step_a; |
| 22 | state_in->plainchar = 0; |
| 23 | } |
| 24 | |
| 25 | int base64_decode_block(const char* code_in, const int length_in, uint8_t *plaintext_out, base64_decodestate* state_in) |
| 26 | { |
| 27 | const char* codechar = code_in; |
| 28 | uint8_t *plainchar = plaintext_out; |
| 29 | char fragment; |
| 30 | |
| 31 | *plainchar = state_in->plainchar; |
| 32 | |
| 33 | switch (state_in->step) |
| 34 | { |
| 35 | while (1) |
| 36 | { |
| 37 | case step_a: |
| 38 | do { |
| 39 | if (codechar == code_in+length_in) |
| 40 | { |
| 41 | state_in->step = step_a; |
| 42 | state_in->plainchar = *plainchar; |
| 43 | return plainchar - plaintext_out; |
| 44 | } |
| 45 | fragment = (char)base64_decode_value(*codechar++); |
| 46 | } while (fragment < 0); |
| 47 | *plainchar = (fragment & 0x03f) << 2; |
| 48 | case step_b: |
| 49 | do { |
| 50 | if (codechar == code_in+length_in) |
| 51 | { |
| 52 | state_in->step = step_b; |
| 53 | state_in->plainchar = *plainchar; |
| 54 | return plainchar - plaintext_out; |
| 55 | } |
| 56 | fragment = (char)base64_decode_value(*codechar++); |
| 57 | } while (fragment < 0); |
| 58 | *plainchar++ |= (fragment & 0x030) >> 4; |
| 59 | *plainchar = (fragment & 0x00f) << 4; |
| 60 | case step_c: |
| 61 | do { |
| 62 | if (codechar == code_in+length_in) |
| 63 | { |
| 64 | state_in->step = step_c; |
| 65 | state_in->plainchar = *plainchar; |
| 66 | return plainchar - plaintext_out; |
| 67 | } |
| 68 | fragment = (char)base64_decode_value(*codechar++); |
| 69 | } while (fragment < 0); |
| 70 | *plainchar++ |= (fragment & 0x03c) >> 2; |
| 71 | *plainchar = (fragment & 0x003) << 6; |
| 72 | case step_d: |
| 73 | do { |
| 74 | if (codechar == code_in+length_in) |
| 75 | { |
| 76 | state_in->step = step_d; |
| 77 | state_in->plainchar = *plainchar; |
| 78 | return plainchar - plaintext_out; |
| 79 | } |
| 80 | fragment = (char)base64_decode_value(*codechar++); |
| 81 | } while (fragment < 0); |
| 82 | *plainchar++ |= (fragment & 0x03f); |
| 83 | } |
| 84 | } |
| 85 | /* control should not reach here */ |
| 86 | return plainchar - plaintext_out; |
| 87 | } |
| 88 | |