~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

Viewing changes to extra/yassl/taocrypt/src/coding.cpp

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
 
3
 
 
4
   This program is free software; you can redistribute it and/or modify
 
5
   it under the terms of the GNU General Public License as published by
 
6
   the Free Software Foundation; version 2 of the License.
 
7
 
 
8
   This program is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
   GNU General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU General Public License
 
14
   along with this program; see the file COPYING. If not, write to the
 
15
   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 
16
   MA  02110-1301  USA.
 
17
*/
 
18
 
 
19
/* coding.cpp implements hex and base64 encoding/decoing
 
20
*/
 
21
 
 
22
#include "runtime.hpp"
 
23
#include "coding.hpp"
 
24
#include "file.hpp"
 
25
 
 
26
 
 
27
namespace TaoCrypt {
 
28
 
 
29
 
 
30
namespace { // locals
 
31
 
 
32
const byte bad = 0xFF;  // invalid encoding
 
33
 
 
34
const byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 
35
                           'A', 'B', 'C', 'D', 'E', 'F'
 
36
                         };
 
37
 
 
38
const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
 
39
                           bad, bad, bad, bad, bad, bad, bad,
 
40
                           10, 11, 12, 13, 14, 15 
 
41
                         };  // A starts at 0x41 not 0x3A
 
42
 
 
43
 
 
44
const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
 
45
                              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
 
46
                              'U', 'V', 'W', 'X', 'Y', 'Z',
 
47
                              'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
 
48
                              'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
 
49
                              'u', 'v', 'w', 'x', 'y', 'z',
 
50
                              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 
51
                              '+', '/'
 
52
                            };
 
53
 
 
54
const byte base64Decode[] = { 62, bad, bad, bad, 63,   // + starts at 0x2B
 
55
                              52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
 
56
                              bad, bad, bad, bad, bad, bad, bad,
 
57
                              0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
 
58
                              10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
 
59
                              20, 21, 22, 23, 24, 25,
 
60
                              bad, bad, bad, bad, bad, bad,
 
61
                              26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
 
62
                              36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
 
63
                              46, 47, 48, 49, 50, 51
 
64
                            };
 
65
 
 
66
const byte pad = '=';
 
67
const int pemLineSz = 64;
 
68
 
 
69
}  // local namespace
 
70
 
 
71
 
 
72
// Hex Encode
 
73
void HexEncoder::Encode()
 
74
{
 
75
    word32 bytes = plain_.size();
 
76
    encoded_.New(bytes * 2);
 
77
 
 
78
    word32 i = 0;
 
79
 
 
80
    while (bytes--) {
 
81
        byte p = plain_.next();
 
82
 
 
83
        byte b  = p >> 4;
 
84
        byte b2 = p & 0xF;
 
85
 
 
86
        encoded_[i++] = hexEncode[b];
 
87
        encoded_[i++] = hexEncode[b2];
 
88
    }
 
89
 
 
90
    plain_.reset(encoded_);
 
91
}
 
92
 
 
93
 
 
94
// Hex Decode
 
95
void HexDecoder::Decode()
 
96
{
 
97
    word32 bytes = coded_.size();
 
98
    decoded_.New(bytes / 2);
 
99
 
 
100
    word32 i(0);
 
101
 
 
102
    while (bytes) {
 
103
        byte b  = coded_.next() - 0x30;  // 0 starts at 0x30
 
104
        byte b2 = coded_.next() - 0x30;
 
105
 
 
106
        // sanity checks
 
107
        if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) {
 
108
            coded_.SetError(PEM_E);
 
109
            return;
 
110
        }
 
111
        if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0])) {
 
112
            coded_.SetError(PEM_E);
 
113
            return;
 
114
        }
 
115
 
 
116
        b  = hexDecode[b];
 
117
        b2 = hexDecode[b2];
 
118
 
 
119
        decoded_[i++] = (b << 4) | b2;
 
120
        bytes -= 2;
 
121
    }
 
122
 
 
123
    coded_.reset(decoded_);
 
124
}
 
125
 
 
126
 
 
127
// Base 64 Encode
 
128
void Base64Encoder::Encode()
 
129
{
 
130
    word32 bytes = plain_.size();
 
131
    word32 outSz = (bytes + 3 - 1) / 3 * 4;
 
132
 
 
133
    outSz += (outSz + pemLineSz - 1) / pemLineSz;  // new lines
 
134
    encoded_.New(outSz);
 
135
 
 
136
    word32 i = 0;
 
137
    word32 j = 0;
 
138
    
 
139
    while (bytes > 2) {
 
140
        byte b1 = plain_.next();
 
141
        byte b2 = plain_.next();
 
142
        byte b3 = plain_.next();
 
143
 
 
144
        // encoded idx
 
145
        byte e1 = b1 >> 2;
 
146
        byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
 
147
        byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
 
148
        byte e4 = b3 & 0x3F;
 
149
 
 
150
        // store
 
151
        encoded_[i++] = base64Encode[e1];
 
152
        encoded_[i++] = base64Encode[e2];
 
153
        encoded_[i++] = base64Encode[e3];
 
154
        encoded_[i++] = base64Encode[e4];
 
155
 
 
156
        bytes -= 3;
 
157
 
 
158
        if ((++j % 16) == 0 && bytes)
 
159
            encoded_[i++] = '\n';
 
160
    }
 
161
 
 
162
    // last integral
 
163
    if (bytes) {
 
164
        bool twoBytes = (bytes == 2);
 
165
 
 
166
        byte b1 = plain_.next();
 
167
        byte b2 = (twoBytes) ? plain_.next() : 0;
 
168
 
 
169
        byte e1 = b1 >> 2;
 
170
        byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
 
171
        byte e3 =  (b2 & 0xF) << 2;
 
172
 
 
173
        encoded_[i++] = base64Encode[e1];
 
174
        encoded_[i++] = base64Encode[e2];
 
175
        encoded_[i++] = (twoBytes) ? base64Encode[e3] : pad;
 
176
        encoded_[i++] = pad;
 
177
    } 
 
178
 
 
179
    encoded_[i++] = '\n';
 
180
    
 
181
    if (i == outSz)
 
182
        plain_.reset(encoded_);
 
183
}
 
184
 
 
185
 
 
186
// Base 64 Decode
 
187
void Base64Decoder::Decode()
 
188
{
 
189
    word32 bytes = coded_.size();
 
190
    word32 plainSz = bytes - ((bytes + (pemLineSz - 1)) / pemLineSz); 
 
191
    const  byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
 
192
    plainSz = ((plainSz * 3) / 4) + 3;
 
193
    decoded_.New(plainSz);
 
194
 
 
195
    word32 i = 0;
 
196
    word32 j = 0;
 
197
 
 
198
    while (bytes > 3) {
 
199
        byte e1 = coded_.next();
 
200
        byte e2 = coded_.next();
 
201
        byte e3 = coded_.next();
 
202
        byte e4 = coded_.next();
 
203
 
 
204
        if (e1 == 0)            // end file 0's
 
205
            break;
 
206
 
 
207
        bool pad3 = false;
 
208
        bool pad4 = false;
 
209
        if (e3 == pad)
 
210
            pad3 = true;
 
211
        if (e4 == pad)
 
212
            pad4 = true;
 
213
 
 
214
        if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
 
215
            coded_.SetError(PEM_E);
 
216
            return;
 
217
        }
 
218
 
 
219
        if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
 
220
            coded_.SetError(PEM_E);
 
221
            return;
 
222
        }
 
223
 
 
224
        e1 = base64Decode[e1 - 0x2B];
 
225
        e2 = base64Decode[e2 - 0x2B];
 
226
        e3 = (e3 == pad) ? 0 : base64Decode[e3 - 0x2B];
 
227
        e4 = (e4 == pad) ? 0 : base64Decode[e4 - 0x2B];
 
228
 
 
229
        byte b1 = (e1 << 2) | (e2 >> 4);
 
230
        byte b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
 
231
        byte b3 = ((e3 & 0x3) << 6) | e4;
 
232
 
 
233
        decoded_[i++] = b1;
 
234
        if (!pad3)
 
235
            decoded_[i++] = b2;
 
236
        if (!pad4)
 
237
            decoded_[i++] = b3;
 
238
        else
 
239
            break;
 
240
        
 
241
        bytes -= 4;
 
242
        if ((++j % 16) == 0) {
 
243
            byte endLine = coded_.next();
 
244
            bytes--;
 
245
            while (endLine == ' ') {        // remove possible whitespace
 
246
                endLine = coded_.next();
 
247
                bytes--;
 
248
            }
 
249
            if (endLine == '\r') {
 
250
                endLine = coded_.next();
 
251
                bytes--;
 
252
            }
 
253
            if (endLine != '\n') {
 
254
                coded_.SetError(PEM_E); 
 
255
                return;
 
256
            }
 
257
        }
 
258
    }
 
259
 
 
260
    if (i != decoded_.size())
 
261
        decoded_.resize(i);
 
262
    coded_.reset(decoded_);
 
263
}
 
264
 
 
265
 
 
266
} // namespace