blob: 241e3c5777274437be9c46f87d0b89dbfb7bdc05 [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001/*
2cencoder.c - c source to a base64 encoding algorithm implementation
3
4This is part of the libb64 project, and has been placed in the public domain.
5For details, see http://sourceforge.net/projects/libb64
6*/
7
8#include <libzrtpcpp/zrtpB64Encode.h>
9
10const int CHARS_PER_LINE = 72;
11
12void 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
23char 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
30int 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
93int 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