~ubuntu-branches/debian/sid/botan/sid

« back to all changes in this revision

Viewing changes to src/base64.cpp

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2018-03-01 22:23:25 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20180301222325-7p7vc45gu3hta34d
Tags: 2.4.0-2
* Don't remove .doctrees from the manual if it doesn't exist.
* Don't specify parallel to debhelper.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*************************************************
2
 
* Base64 Encoder/Decoder Source File             *
3
 
* (C) 1999-2007 The Botan Project                *
4
 
*************************************************/
5
 
 
6
 
#include <botan/base64.h>
7
 
#include <botan/charset.h>
8
 
#include <algorithm>
9
 
 
10
 
namespace Botan {
11
 
 
12
 
/*************************************************
13
 
* Base64_Encoder Constructor                     *
14
 
*************************************************/
15
 
Base64_Encoder::Base64_Encoder(bool breaks, u32bit length, bool t_n) :
16
 
   line_length(breaks ? length : 0), trailing_newline(t_n)
17
 
   {
18
 
   in.create(48);
19
 
   out.create(4);
20
 
 
21
 
   counter = position = 0;
22
 
   }
23
 
 
24
 
/*************************************************
25
 
* Base64 Encoding Operation                      *
26
 
*************************************************/
27
 
void Base64_Encoder::encode(const byte in[3], byte out[4])
28
 
   {
29
 
   out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)];
30
 
   out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
31
 
   out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
32
 
   out[3] = BIN_TO_BASE64[((in[2] & 0x3F)     )];
33
 
   }
34
 
 
35
 
/*************************************************
36
 
* Encode and send a block                        *
37
 
*************************************************/
38
 
void Base64_Encoder::encode_and_send(const byte block[], u32bit length)
39
 
   {
40
 
   for(u32bit j = 0; j != length; j += 3)
41
 
      {
42
 
      encode(block + j, out);
43
 
      do_output(out, 4);
44
 
      }
45
 
   }
46
 
 
47
 
/*************************************************
48
 
* Handle the output                              *
49
 
*************************************************/
50
 
void Base64_Encoder::do_output(const byte input[], u32bit length)
51
 
   {
52
 
   if(line_length == 0)
53
 
      send(input, length);
54
 
   else
55
 
      {
56
 
      u32bit remaining = length, offset = 0;
57
 
      while(remaining)
58
 
         {
59
 
         u32bit sent = std::min(line_length - counter, remaining);
60
 
         send(input + offset, sent);
61
 
         counter += sent;
62
 
         remaining -= sent;
63
 
         offset += sent;
64
 
         if(counter == line_length)
65
 
            {
66
 
            send('\n');
67
 
            counter = 0;
68
 
            }
69
 
         }
70
 
      }
71
 
   }
72
 
 
73
 
/*************************************************
74
 
* Convert some data into Base64                  *
75
 
*************************************************/
76
 
void Base64_Encoder::write(const byte input[], u32bit length)
77
 
   {
78
 
   in.copy(position, input, length);
79
 
   if(position + length >= in.size())
80
 
      {
81
 
      encode_and_send(in, in.size());
82
 
      input += (in.size() - position);
83
 
      length -= (in.size() - position);
84
 
      while(length >= in.size())
85
 
         {
86
 
         encode_and_send(input, in.size());
87
 
         input += in.size();
88
 
         length -= in.size();
89
 
         }
90
 
      in.copy(input, length);
91
 
      position = 0;
92
 
      }
93
 
   position += length;
94
 
   }
95
 
 
96
 
/*************************************************
97
 
* Flush buffers                                  *
98
 
*************************************************/
99
 
void Base64_Encoder::end_msg()
100
 
   {
101
 
   u32bit start_of_last_block = 3 * (position / 3),
102
 
          left_over = position % 3;
103
 
   encode_and_send(in, start_of_last_block);
104
 
 
105
 
   if(left_over)
106
 
      {
107
 
      SecureBuffer<byte, 3> remainder(in + start_of_last_block, left_over);
108
 
 
109
 
      encode(remainder, out);
110
 
 
111
 
      u32bit empty_bits = 8 * (3 - left_over), index = 4 - 1;
112
 
      while(empty_bits >= 8)
113
 
         {
114
 
         out[index--] = '=';
115
 
         empty_bits -= 6;
116
 
         }
117
 
 
118
 
      do_output(out, 4);
119
 
      }
120
 
 
121
 
   if(trailing_newline || (counter && line_length))
122
 
      send('\n');
123
 
 
124
 
   counter = position = 0;
125
 
   }
126
 
 
127
 
/*************************************************
128
 
* Base64_Decoder Constructor                     *
129
 
*************************************************/
130
 
Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c)
131
 
   {
132
 
   in.create(48);
133
 
   out.create(3);
134
 
   position = 0;
135
 
   }
136
 
 
137
 
/*************************************************
138
 
* Check if a character is a valid Base64 char    *
139
 
*************************************************/
140
 
bool Base64_Decoder::is_valid(byte in)
141
 
   {
142
 
   return (BASE64_TO_BIN[in] != 0x80);
143
 
   }
144
 
 
145
 
/*************************************************
146
 
* Base64 Decoding Operation                      *
147
 
*************************************************/
148
 
void Base64_Decoder::decode(const byte in[4], byte out[3])
149
 
   {
150
 
   out[0] = (byte)((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4));
151
 
   out[1] = (byte)((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2));
152
 
   out[2] = (byte)((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]]));
153
 
   }
154
 
 
155
 
/*************************************************
156
 
* Decode and send a block                        *
157
 
*************************************************/
158
 
void Base64_Decoder::decode_and_send(const byte block[], u32bit length)
159
 
   {
160
 
   for(u32bit j = 0; j != length; j += 4)
161
 
      {
162
 
      decode(block + j, out);
163
 
      send(out, 3);
164
 
      }
165
 
   }
166
 
 
167
 
/*************************************************
168
 
* Handle processing an invalid character         *
169
 
*************************************************/
170
 
void Base64_Decoder::handle_bad_char(byte c)
171
 
   {
172
 
   if(c == '=' || checking == NONE)
173
 
      return;
174
 
 
175
 
   if((checking == IGNORE_WS) && Charset::is_space(c))
176
 
      return;
177
 
 
178
 
   throw Decoding_Error(
179
 
      std::string("Base64_Decoder: Invalid base64 character '") + (char)c + "'"
180
 
      );
181
 
   }
182
 
 
183
 
/*************************************************
184
 
* Convert some data from Base64                  *
185
 
*************************************************/
186
 
void Base64_Decoder::write(const byte input[], u32bit length)
187
 
   {
188
 
   for(u32bit j = 0; j != length; ++j)
189
 
      {
190
 
      if(is_valid(input[j]))
191
 
         in[position++] = input[j];
192
 
      else
193
 
         handle_bad_char(input[j]);
194
 
 
195
 
      if(position == in.size())
196
 
         {
197
 
         decode_and_send(in, in.size());
198
 
         position = 0;
199
 
         }
200
 
      }
201
 
   }
202
 
 
203
 
/*************************************************
204
 
* Flush buffers                                  *
205
 
*************************************************/
206
 
void Base64_Decoder::end_msg()
207
 
   {
208
 
   if(position != 0)
209
 
      {
210
 
      u32bit start_of_last_block = 4 * (position / 4),
211
 
             left_over = position % 4;
212
 
      decode_and_send(in, start_of_last_block);
213
 
 
214
 
      if(left_over)
215
 
         {
216
 
         SecureBuffer<byte, 4> remainder(in + start_of_last_block, left_over);
217
 
         decode(remainder, out);
218
 
         send(out, ((left_over == 1) ? (1) : (left_over - 1)));
219
 
         }
220
 
      }
221
 
   position = 0;
222
 
   }
223
 
 
224
 
}