1 /*
2 cencoder.c - c source to a base64 encoding 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/zrtpB64Encode.h>
9 
10 const int CHARS_PER_LINE = 72;
11 
base64_init_encodestate(base64_encodestate * state_in,int lineLength)12 void base64_init_encodestate(base64_encodestate* state_in, int lineLength)
13 {
14     state_in->step = step_A;
15     state_in->result = 0;
16     state_in->stepcount = 0;
17     if (lineLength < 0)
18         state_in->lineLength = CHARS_PER_LINE / 4;
19     else
20         state_in->lineLength = (lineLength+3) / 4;
21 }
22 
base64_encode_value(const int8_t value_in)23 char base64_encode_value(const int8_t value_in)
24 {
25     static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
26     if (value_in > 63) return '=';
27     return encoding[(int)value_in];
28 }
29 
base64_encode_block(const uint8_t * plaintext_in,int length_in,char * code_out,base64_encodestate * state_in)30 int base64_encode_block(const uint8_t *plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
31 {
32     const uint8_t *plainchar = plaintext_in;
33     const uint8_t *const plaintextend = plaintext_in + length_in;
34     char* codechar = code_out;
35     char result;
36     char fragment;
37 
38     result = state_in->result;
39 
40     switch (state_in->step)
41     {
42         while (1)
43         {
44         case step_A:
45             if (plainchar == plaintextend)
46             {
47                 state_in->result = result;
48                 state_in->step = step_A;
49                 return codechar - code_out;
50             }
51             fragment = *plainchar++;
52             result = (fragment & 0x0fc) >> 2;
53             *codechar++ = base64_encode_value(result);
54             result = (fragment & 0x003) << 4;
55         case step_B:
56             if (plainchar == plaintextend)
57             {
58                 state_in->result = result;
59                 state_in->step = step_B;
60                 return codechar - code_out;
61             }
62             fragment = *plainchar++;
63             result |= (fragment & 0x0f0) >> 4;
64             *codechar++ = base64_encode_value(result);
65             result = (fragment & 0x00f) << 2;
66         case step_C:
67             if (plainchar == plaintextend)
68             {
69                 state_in->result = result;
70                 state_in->step = step_C;
71                 return codechar - code_out;
72             }
73             fragment = *plainchar++;
74             result |= (fragment & 0x0c0) >> 6;
75             *codechar++ = base64_encode_value(result);
76             result  = (fragment & 0x03f) >> 0;
77             *codechar++ = base64_encode_value(result);
78 
79             if (state_in->lineLength > 0) {
80                 state_in->stepcount++;
81                 if (state_in->stepcount == state_in->lineLength)
82                 {
83                     *codechar++ = '\n';
84                     state_in->stepcount = 0;
85                 }
86             }
87         }
88     }
89     /* control should not reach here */
90     return codechar - code_out;
91 }
92 
base64_encode_blockend(char * code_out,base64_encodestate * state_in)93 int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
94 {
95     char* codechar = code_out;
96 
97     switch (state_in->step)
98     {
99         case step_B:
100             *codechar++ = base64_encode_value(state_in->result);
101             *codechar++ = '=';
102             *codechar++ = '=';
103             break;
104         case step_C:
105             *codechar++ = base64_encode_value(state_in->result);
106             *codechar++ = '=';
107             break;
108         case step_A:
109             break;
110     }
111     if (state_in->lineLength > 0)
112         *codechar++ = '\n';
113 
114     return codechar - code_out;
115 }
116 
117