Line | Count | Source (jump to first uncovered line) |
1 | | // asn.cpp - originally written and placed in the public domain by Wei Dai |
2 | | // CryptoPP::Test namespace added by JW in February 2017 |
3 | | |
4 | | #include "pch.h" |
5 | | #include "config.h" |
6 | | |
7 | | #ifndef CRYPTOPP_IMPORTS |
8 | | |
9 | | #include "cryptlib.h" |
10 | | #include "asn.h" |
11 | | #include "misc.h" |
12 | | |
13 | | #include <iostream> |
14 | | #include <iomanip> |
15 | | #include <sstream> |
16 | | #include <time.h> |
17 | | |
18 | | NAMESPACE_BEGIN(CryptoPP) |
19 | | |
20 | | size_t DERLengthEncode(BufferedTransformation &bt, lword length) |
21 | 0 | { |
22 | 0 | size_t i=0; |
23 | 0 | if (length <= 0x7f) |
24 | 0 | { |
25 | 0 | bt.Put(byte(length)); |
26 | 0 | i++; |
27 | 0 | } |
28 | 0 | else |
29 | 0 | { |
30 | 0 | bt.Put(byte(BytePrecision(length) | 0x80)); |
31 | 0 | i++; |
32 | 0 | for (int j=BytePrecision(length); j; --j) |
33 | 0 | { |
34 | 0 | bt.Put(byte(length >> (j-1)*8)); |
35 | 0 | i++; |
36 | 0 | } |
37 | 0 | } |
38 | 0 | return i; |
39 | 0 | } |
40 | | |
41 | | bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength) |
42 | 0 | { |
43 | 0 | byte b; |
44 | |
|
45 | 0 | if (!bt.Get(b)) |
46 | 0 | return false; |
47 | | |
48 | 0 | if (!(b & 0x80)) |
49 | 0 | { |
50 | 0 | definiteLength = true; |
51 | 0 | length = b; |
52 | 0 | } |
53 | 0 | else |
54 | 0 | { |
55 | 0 | unsigned int lengthBytes = b & 0x7f; |
56 | |
|
57 | 0 | if (lengthBytes == 0) |
58 | 0 | { |
59 | 0 | definiteLength = false; |
60 | 0 | return true; |
61 | 0 | } |
62 | | |
63 | 0 | definiteLength = true; |
64 | 0 | length = 0; |
65 | 0 | while (lengthBytes--) |
66 | 0 | { |
67 | 0 | if (length >> (8*(sizeof(length)-1))) |
68 | 0 | BERDecodeError(); // length about to overflow |
69 | |
|
70 | 0 | if (!bt.Get(b)) |
71 | 0 | return false; |
72 | | |
73 | 0 | length = (length << 8) | b; |
74 | 0 | } |
75 | 0 | } |
76 | 0 | return true; |
77 | 0 | } |
78 | | |
79 | | bool BERLengthDecode(BufferedTransformation &bt, size_t &length) |
80 | 0 | { |
81 | 0 | lword lw = 0; |
82 | 0 | bool definiteLength = false; |
83 | 0 | if (!BERLengthDecode(bt, lw, definiteLength)) |
84 | 0 | BERDecodeError(); |
85 | 0 | if (!SafeConvert(lw, length)) |
86 | 0 | BERDecodeError(); |
87 | 0 | return definiteLength; |
88 | 0 | } |
89 | | |
90 | | void DEREncodeNull(BufferedTransformation &out) |
91 | 0 | { |
92 | 0 | out.Put(TAG_NULL); |
93 | 0 | out.Put(0); |
94 | 0 | } |
95 | | |
96 | | void BERDecodeNull(BufferedTransformation &in) |
97 | 0 | { |
98 | 0 | byte b; |
99 | 0 | if (!in.Get(b) || b != TAG_NULL) |
100 | 0 | BERDecodeError(); |
101 | 0 | size_t length; |
102 | 0 | if (!BERLengthDecode(in, length) || length != 0) |
103 | 0 | BERDecodeError(); |
104 | 0 | } |
105 | | |
106 | | /// ASN Strings |
107 | | size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen) |
108 | 0 | { |
109 | 0 | bt.Put(OCTET_STRING); |
110 | 0 | size_t lengthBytes = DERLengthEncode(bt, strLen); |
111 | 0 | bt.Put(str, strLen); |
112 | 0 | return 1+lengthBytes+strLen; |
113 | 0 | } |
114 | | |
115 | | size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str) |
116 | 0 | { |
117 | 0 | return DEREncodeOctetString(bt, ConstBytePtr(str), BytePtrSize(str)); |
118 | 0 | } |
119 | | |
120 | | size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str) |
121 | 0 | { |
122 | 0 | byte b; |
123 | 0 | if (!bt.Get(b) || b != OCTET_STRING) |
124 | 0 | BERDecodeError(); |
125 | |
|
126 | 0 | size_t bc; |
127 | 0 | if (!BERLengthDecode(bt, bc)) |
128 | 0 | BERDecodeError(); |
129 | 0 | if (bc > bt.MaxRetrievable()) // Issue 346 |
130 | 0 | BERDecodeError(); |
131 | |
|
132 | 0 | str.New(bc); |
133 | 0 | if (bc != bt.Get(BytePtr(str), bc)) |
134 | 0 | BERDecodeError(); |
135 | 0 | return bc; |
136 | 0 | } |
137 | | |
138 | | size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str) |
139 | 0 | { |
140 | 0 | byte b; |
141 | 0 | if (!bt.Get(b) || b != OCTET_STRING) |
142 | 0 | BERDecodeError(); |
143 | |
|
144 | 0 | size_t bc; |
145 | 0 | if (!BERLengthDecode(bt, bc)) |
146 | 0 | BERDecodeError(); |
147 | 0 | if (bc > bt.MaxRetrievable()) // Issue 346 |
148 | 0 | BERDecodeError(); |
149 | |
|
150 | 0 | bt.TransferTo(str, bc); |
151 | 0 | return bc; |
152 | 0 | } |
153 | | |
154 | | size_t DEREncodeTextString(BufferedTransformation &bt, const byte* str, size_t strLen, byte asnTag) |
155 | 0 | { |
156 | 0 | bt.Put(asnTag); |
157 | 0 | size_t lengthBytes = DERLengthEncode(bt, strLen); |
158 | 0 | bt.Put(str, strLen); |
159 | 0 | return 1+lengthBytes+strLen; |
160 | 0 | } |
161 | | |
162 | | size_t DEREncodeTextString(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag) |
163 | 0 | { |
164 | 0 | return DEREncodeTextString(bt, ConstBytePtr(str), BytePtrSize(str), asnTag); |
165 | 0 | } |
166 | | |
167 | | size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag) |
168 | 0 | { |
169 | 0 | return DEREncodeTextString(bt, ConstBytePtr(str), BytePtrSize(str), asnTag); |
170 | 0 | } |
171 | | |
172 | | size_t BERDecodeTextString(BufferedTransformation &bt, SecByteBlock &str, byte asnTag) |
173 | 0 | { |
174 | 0 | byte b; |
175 | 0 | if (!bt.Get(b) || b != asnTag) |
176 | 0 | BERDecodeError(); |
177 | |
|
178 | 0 | size_t bc; |
179 | 0 | if (!BERLengthDecode(bt, bc)) |
180 | 0 | BERDecodeError(); |
181 | 0 | if (bc > bt.MaxRetrievable()) // Issue 346 |
182 | 0 | BERDecodeError(); |
183 | |
|
184 | 0 | str.resize(bc); |
185 | 0 | if (bc != bt.Get(BytePtr(str), BytePtrSize(str))) |
186 | 0 | BERDecodeError(); |
187 | |
|
188 | 0 | return bc; |
189 | 0 | } |
190 | | |
191 | | size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag) |
192 | 0 | { |
193 | 0 | byte b; |
194 | 0 | if (!bt.Get(b) || b != asnTag) |
195 | 0 | BERDecodeError(); |
196 | |
|
197 | 0 | size_t bc; |
198 | 0 | if (!BERLengthDecode(bt, bc)) |
199 | 0 | BERDecodeError(); |
200 | 0 | if (bc > bt.MaxRetrievable()) // Issue 346 |
201 | 0 | BERDecodeError(); |
202 | |
|
203 | 0 | str.resize(bc); |
204 | 0 | if (bc != bt.Get(BytePtr(str), BytePtrSize(str))) |
205 | 0 | BERDecodeError(); |
206 | |
|
207 | 0 | return bc; |
208 | 0 | } |
209 | | |
210 | | size_t DEREncodeDate(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag) |
211 | 0 | { |
212 | 0 | bt.Put(asnTag); |
213 | 0 | size_t lengthBytes = DERLengthEncode(bt, str.size()); |
214 | 0 | bt.Put(ConstBytePtr(str), BytePtrSize(str)); |
215 | 0 | return 1+lengthBytes+str.size(); |
216 | 0 | } |
217 | | |
218 | | size_t BERDecodeDate(BufferedTransformation &bt, SecByteBlock &str, byte asnTag) |
219 | 0 | { |
220 | 0 | byte b; |
221 | 0 | if (!bt.Get(b) || b != asnTag) |
222 | 0 | BERDecodeError(); |
223 | |
|
224 | 0 | size_t bc; |
225 | 0 | if (!BERLengthDecode(bt, bc)) |
226 | 0 | BERDecodeError(); |
227 | 0 | if (bc > bt.MaxRetrievable()) // Issue 346 |
228 | 0 | BERDecodeError(); |
229 | |
|
230 | 0 | str.resize(bc); |
231 | 0 | if (bc != bt.Get(BytePtr(str), BytePtrSize(str))) |
232 | 0 | BERDecodeError(); |
233 | |
|
234 | 0 | return bc; |
235 | 0 | } |
236 | | |
237 | | size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits) |
238 | 0 | { |
239 | 0 | bt.Put(BIT_STRING); |
240 | 0 | size_t lengthBytes = DERLengthEncode(bt, strLen+1); |
241 | 0 | bt.Put((byte)unusedBits); |
242 | 0 | bt.Put(str, strLen); |
243 | 0 | return 2+lengthBytes+strLen; |
244 | 0 | } |
245 | | |
246 | | size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits) |
247 | 0 | { |
248 | 0 | byte b; |
249 | 0 | if (!bt.Get(b) || b != BIT_STRING) |
250 | 0 | BERDecodeError(); |
251 | |
|
252 | 0 | size_t bc; |
253 | 0 | if (!BERLengthDecode(bt, bc)) |
254 | 0 | BERDecodeError(); |
255 | 0 | if (bc == 0) |
256 | 0 | BERDecodeError(); |
257 | 0 | if (bc > bt.MaxRetrievable()) // Issue 346 |
258 | 0 | BERDecodeError(); |
259 | | |
260 | | // X.690, 8.6.2.2: "The number [of unused bits] shall be in the range zero to seven" |
261 | 0 | byte unused; |
262 | 0 | if (!bt.Get(unused) || unused > 7) |
263 | 0 | BERDecodeError(); |
264 | 0 | unusedBits = unused; |
265 | 0 | str.resize(bc-1); |
266 | 0 | if ((bc-1) != bt.Get(BytePtr(str), bc-1)) |
267 | 0 | BERDecodeError(); |
268 | 0 | return bc-1; |
269 | 0 | } |
270 | | |
271 | | void DERReencode(BufferedTransformation &source, BufferedTransformation &dest) |
272 | 0 | { |
273 | 0 | byte tag; |
274 | 0 | source.Peek(tag); |
275 | 0 | BERGeneralDecoder decoder(source, tag); |
276 | 0 | DERGeneralEncoder encoder(dest, tag); |
277 | 0 | if (decoder.IsDefiniteLength()) |
278 | 0 | decoder.TransferTo(encoder, decoder.RemainingLength()); |
279 | 0 | else |
280 | 0 | { |
281 | 0 | while (!decoder.EndReached()) |
282 | 0 | DERReencode(decoder, encoder); |
283 | 0 | } |
284 | 0 | decoder.MessageEnd(); |
285 | 0 | encoder.MessageEnd(); |
286 | 0 | } |
287 | | |
288 | | size_t BERDecodePeekLength(const BufferedTransformation &bt) |
289 | 0 | { |
290 | 0 | lword count = (std::min)(bt.MaxRetrievable(), static_cast<lword>(16)); |
291 | 0 | if (count == 0) return 0; |
292 | | |
293 | 0 | ByteQueue tagAndLength; |
294 | 0 | bt.CopyTo(tagAndLength, count); |
295 | | |
296 | | // Skip tag |
297 | 0 | tagAndLength.Skip(1); |
298 | | |
299 | | // BERLengthDecode fails for indefinite length. |
300 | 0 | size_t length; |
301 | 0 | if (!BERLengthDecode(tagAndLength, length)) |
302 | 0 | return 0; |
303 | | |
304 | 0 | return length; |
305 | 0 | } |
306 | | |
307 | | void OID::EncodeValue(BufferedTransformation &bt, word32 v) |
308 | 0 | { |
309 | 0 | for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7) |
310 | 0 | bt.Put((byte)(0x80 | ((v >> i) & 0x7f))); |
311 | 0 | bt.Put((byte)(v & 0x7f)); |
312 | 0 | } |
313 | | |
314 | | size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v) |
315 | 0 | { |
316 | 0 | byte b; |
317 | 0 | size_t i=0; |
318 | 0 | v = 0; |
319 | 0 | while (true) |
320 | 0 | { |
321 | 0 | if (!bt.Get(b)) |
322 | 0 | BERDecodeError(); |
323 | 0 | i++; |
324 | 0 | if (v >> (8*sizeof(v)-7)) // v about to overflow |
325 | 0 | BERDecodeError(); |
326 | 0 | v <<= 7; |
327 | 0 | v += b & 0x7f; |
328 | 0 | if (!(b & 0x80)) |
329 | 0 | return i; |
330 | 0 | } |
331 | 0 | } |
332 | | |
333 | | void OID::DEREncode(BufferedTransformation &bt) const |
334 | 0 | { |
335 | 0 | CRYPTOPP_ASSERT(m_values.size() >= 2); |
336 | 0 | ByteQueue temp; |
337 | 0 | temp.Put(byte(m_values[0] * 40 + m_values[1])); |
338 | 0 | for (size_t i=2; i<m_values.size(); i++) |
339 | 0 | EncodeValue(temp, m_values[i]); |
340 | 0 | bt.Put(OBJECT_IDENTIFIER); |
341 | 0 | DERLengthEncode(bt, temp.CurrentSize()); |
342 | 0 | temp.TransferTo(bt); |
343 | 0 | } |
344 | | |
345 | | void OID::BERDecode(BufferedTransformation &bt) |
346 | 0 | { |
347 | 0 | byte b; |
348 | 0 | if (!bt.Get(b) || b != OBJECT_IDENTIFIER) |
349 | 0 | BERDecodeError(); |
350 | |
|
351 | 0 | size_t length; |
352 | 0 | if (!BERLengthDecode(bt, length) || length < 1) |
353 | 0 | BERDecodeError(); |
354 | |
|
355 | 0 | if (!bt.Get(b)) |
356 | 0 | BERDecodeError(); |
357 | |
|
358 | 0 | length--; |
359 | 0 | m_values.resize(2); |
360 | 0 | m_values[0] = b / 40; |
361 | 0 | m_values[1] = b % 40; |
362 | |
|
363 | 0 | while (length > 0) |
364 | 0 | { |
365 | 0 | word32 v; |
366 | 0 | size_t valueLen = DecodeValue(bt, v); |
367 | 0 | if (valueLen > length) |
368 | 0 | BERDecodeError(); |
369 | 0 | m_values.push_back(v); |
370 | 0 | length -= valueLen; |
371 | 0 | } |
372 | 0 | } |
373 | | |
374 | | void OID::BERDecodeAndCheck(BufferedTransformation &bt) const |
375 | 0 | { |
376 | 0 | OID oid(bt); |
377 | 0 | if (*this != oid) |
378 | 0 | BERDecodeError(); |
379 | 0 | } |
380 | | |
381 | | std::ostream& OID::Print(std::ostream& out) const |
382 | 0 | { |
383 | 0 | std::ostringstream oss; |
384 | 0 | for (size_t i = 0; i < m_values.size(); ++i) |
385 | 0 | { |
386 | 0 | oss << m_values[i]; |
387 | 0 | if (i+1 < m_values.size()) |
388 | 0 | oss << "."; |
389 | 0 | } |
390 | 0 | return out << oss.str(); |
391 | 0 | } |
392 | | |
393 | | inline BufferedTransformation & EncodedObjectFilter::CurrentTarget() |
394 | 0 | { |
395 | 0 | if (m_flags & PUT_OBJECTS) |
396 | 0 | return *AttachedTransformation(); |
397 | 0 | else |
398 | 0 | return TheBitBucket(); |
399 | 0 | } |
400 | | |
401 | | void EncodedObjectFilter::Put(const byte *inString, size_t length) |
402 | 0 | { |
403 | 0 | if (m_nCurrentObject == m_nObjects) |
404 | 0 | { |
405 | 0 | AttachedTransformation()->Put(inString, length); |
406 | 0 | return; |
407 | 0 | } |
408 | | |
409 | 0 | LazyPutter lazyPutter(m_queue, inString, length); |
410 | |
|
411 | 0 | while (m_queue.AnyRetrievable()) |
412 | 0 | { |
413 | 0 | switch (m_state) |
414 | 0 | { |
415 | 0 | case IDENTIFIER: |
416 | 0 | if (!m_queue.Get(m_id)) |
417 | 0 | return; |
418 | 0 | m_queue.TransferTo(CurrentTarget(), 1); |
419 | 0 | m_state = LENGTH; |
420 | | // fall through |
421 | 0 | case LENGTH: |
422 | 0 | { |
423 | 0 | byte b; |
424 | 0 | if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0) |
425 | 0 | { |
426 | 0 | m_queue.TransferTo(CurrentTarget(), 1); |
427 | 0 | m_level--; |
428 | 0 | m_state = IDENTIFIER; |
429 | 0 | break; |
430 | 0 | } |
431 | 0 | ByteQueue::Walker walker(m_queue); |
432 | 0 | bool definiteLength = false; |
433 | 0 | if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength)) |
434 | 0 | return; |
435 | 0 | m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition()); |
436 | 0 | if (!((m_id & CONSTRUCTED) || definiteLength)) |
437 | 0 | BERDecodeError(); |
438 | 0 | if (!definiteLength) |
439 | 0 | { |
440 | 0 | if (!(m_id & CONSTRUCTED)) |
441 | 0 | BERDecodeError(); |
442 | 0 | m_level++; |
443 | 0 | m_state = IDENTIFIER; |
444 | 0 | break; |
445 | 0 | } |
446 | 0 | m_state = BODY; |
447 | 0 | } |
448 | | // fall through |
449 | 0 | case BODY: |
450 | 0 | m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining); |
451 | |
|
452 | 0 | if (m_lengthRemaining == 0) |
453 | 0 | m_state = IDENTIFIER; |
454 | | // fall through |
455 | 0 | case TAIL: |
456 | 0 | case ALL_DONE: |
457 | 0 | default: ; |
458 | 0 | } |
459 | | |
460 | 0 | if (m_state == IDENTIFIER && m_level == 0) |
461 | 0 | { |
462 | | // just finished processing a level 0 object |
463 | 0 | ++m_nCurrentObject; |
464 | |
|
465 | 0 | if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT) |
466 | 0 | AttachedTransformation()->MessageEnd(); |
467 | |
|
468 | 0 | if (m_nCurrentObject == m_nObjects) |
469 | 0 | { |
470 | 0 | if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS) |
471 | 0 | AttachedTransformation()->MessageEnd(); |
472 | |
|
473 | 0 | if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS) |
474 | 0 | AttachedTransformation()->MessageSeriesEnd(); |
475 | |
|
476 | 0 | m_queue.TransferAllTo(*AttachedTransformation()); |
477 | 0 | return; |
478 | 0 | } |
479 | 0 | } |
480 | 0 | } |
481 | 0 | } |
482 | | |
483 | | BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue) |
484 | | : m_inQueue(inQueue), m_length(0), m_finished(false) |
485 | 0 | { |
486 | 0 | Init(DefaultTag); |
487 | 0 | } |
488 | | |
489 | | BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag) |
490 | | : m_inQueue(inQueue), m_length(0), m_finished(false) |
491 | 0 | { |
492 | 0 | Init(asnTag); |
493 | 0 | } |
494 | | |
495 | | BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag) |
496 | | : m_inQueue(inQueue), m_length(0), m_finished(false) |
497 | 0 | { |
498 | 0 | Init(asnTag); |
499 | 0 | } |
500 | | |
501 | | void BERGeneralDecoder::Init(byte asnTag) |
502 | 0 | { |
503 | 0 | byte b; |
504 | 0 | if (!m_inQueue.Get(b) || b != asnTag) |
505 | 0 | BERDecodeError(); |
506 | |
|
507 | 0 | if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength)) |
508 | 0 | BERDecodeError(); |
509 | |
|
510 | 0 | if (!m_definiteLength && !(asnTag & CONSTRUCTED)) |
511 | 0 | BERDecodeError(); // cannot be primitive and have indefinite length |
512 | 0 | } |
513 | | |
514 | | BERGeneralDecoder::~BERGeneralDecoder() |
515 | 0 | { |
516 | 0 | try // avoid throwing in destructor |
517 | 0 | { |
518 | 0 | if (!m_finished) |
519 | 0 | MessageEnd(); |
520 | 0 | } |
521 | 0 | catch (const Exception&) |
522 | 0 | { |
523 | | // CRYPTOPP_ASSERT(0); |
524 | 0 | } |
525 | 0 | } |
526 | | |
527 | | bool BERGeneralDecoder::EndReached() const |
528 | 0 | { |
529 | 0 | if (m_definiteLength) |
530 | 0 | return m_length == 0; |
531 | 0 | else |
532 | 0 | { // check end-of-content octets |
533 | 0 | word16 i; |
534 | 0 | return (m_inQueue.PeekWord16(i)==2 && i==0); |
535 | 0 | } |
536 | 0 | } |
537 | | |
538 | | byte BERGeneralDecoder::PeekByte() const |
539 | 0 | { |
540 | 0 | byte b; |
541 | 0 | if (!Peek(b)) |
542 | 0 | BERDecodeError(); |
543 | 0 | return b; |
544 | 0 | } |
545 | | |
546 | | void BERGeneralDecoder::CheckByte(byte check) |
547 | 0 | { |
548 | 0 | byte b; |
549 | 0 | if (!Get(b) || b != check) |
550 | 0 | BERDecodeError(); |
551 | 0 | } |
552 | | |
553 | | void BERGeneralDecoder::MessageEnd() |
554 | 0 | { |
555 | 0 | m_finished = true; |
556 | 0 | if (m_definiteLength) |
557 | 0 | { |
558 | 0 | if (m_length != 0) |
559 | 0 | BERDecodeError(); |
560 | 0 | } |
561 | 0 | else |
562 | 0 | { // remove end-of-content octets |
563 | 0 | word16 i; |
564 | 0 | if (m_inQueue.GetWord16(i) != 2 || i != 0) |
565 | 0 | BERDecodeError(); |
566 | 0 | } |
567 | 0 | } |
568 | | |
569 | | size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) |
570 | 0 | { |
571 | 0 | if (m_definiteLength && transferBytes > m_length) |
572 | 0 | transferBytes = m_length; |
573 | 0 | size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking); |
574 | 0 | ReduceLength(transferBytes); |
575 | 0 | return blockedBytes; |
576 | 0 | } |
577 | | |
578 | | size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const |
579 | 0 | { |
580 | 0 | if (m_definiteLength) |
581 | 0 | end = STDMIN(m_length, end); |
582 | 0 | return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking); |
583 | 0 | } |
584 | | |
585 | | lword BERGeneralDecoder::ReduceLength(lword delta) |
586 | 0 | { |
587 | 0 | if (m_definiteLength) |
588 | 0 | { |
589 | 0 | if (m_length < delta) |
590 | 0 | BERDecodeError(); |
591 | 0 | m_length -= delta; |
592 | 0 | } |
593 | 0 | return delta; |
594 | 0 | } |
595 | | |
596 | | DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue) |
597 | | : m_outQueue(outQueue), m_asnTag(DefaultTag), m_finished(false) |
598 | 0 | { |
599 | 0 | } |
600 | | |
601 | | DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag) |
602 | | : m_outQueue(outQueue), m_asnTag(asnTag), m_finished(false) |
603 | 0 | { |
604 | 0 | } |
605 | | |
606 | | DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag) |
607 | | : m_outQueue(outQueue), m_asnTag(asnTag), m_finished(false) |
608 | 0 | { |
609 | 0 | } |
610 | | |
611 | | DERGeneralEncoder::~DERGeneralEncoder() |
612 | 0 | { |
613 | 0 | try // avoid throwing in constructor |
614 | 0 | { |
615 | 0 | if (!m_finished) |
616 | 0 | MessageEnd(); |
617 | 0 | } |
618 | 0 | catch (const Exception&) |
619 | 0 | { |
620 | 0 | CRYPTOPP_ASSERT(0); |
621 | 0 | } |
622 | 0 | } |
623 | | |
624 | | void DERGeneralEncoder::MessageEnd() |
625 | 0 | { |
626 | 0 | m_finished = true; |
627 | 0 | lword length = CurrentSize(); |
628 | 0 | m_outQueue.Put(m_asnTag); |
629 | 0 | DERLengthEncode(m_outQueue, length); |
630 | 0 | TransferTo(m_outQueue); |
631 | 0 | } |
632 | | |
633 | | // ************************************************************* |
634 | | |
635 | | void X509PublicKey::BERDecode(BufferedTransformation &bt) |
636 | 0 | { |
637 | 0 | BERSequenceDecoder subjectPublicKeyInfo(bt); |
638 | 0 | BERSequenceDecoder algorithm(subjectPublicKeyInfo); |
639 | 0 | GetAlgorithmID().BERDecodeAndCheck(algorithm); |
640 | 0 | bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); |
641 | 0 | algorithm.MessageEnd(); |
642 | |
|
643 | 0 | BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); |
644 | 0 | subjectPublicKey.CheckByte(0); // unused bits |
645 | 0 | BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength()); |
646 | 0 | subjectPublicKey.MessageEnd(); |
647 | 0 | subjectPublicKeyInfo.MessageEnd(); |
648 | 0 | } |
649 | | |
650 | | void X509PublicKey::DEREncode(BufferedTransformation &bt) const |
651 | 0 | { |
652 | 0 | DERSequenceEncoder subjectPublicKeyInfo(bt); |
653 | |
|
654 | 0 | DERSequenceEncoder algorithm(subjectPublicKeyInfo); |
655 | 0 | GetAlgorithmID().DEREncode(algorithm); |
656 | 0 | DEREncodeAlgorithmParameters(algorithm); |
657 | 0 | algorithm.MessageEnd(); |
658 | |
|
659 | 0 | DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); |
660 | 0 | subjectPublicKey.Put(0); // unused bits |
661 | 0 | DEREncodePublicKey(subjectPublicKey); |
662 | 0 | subjectPublicKey.MessageEnd(); |
663 | |
|
664 | 0 | subjectPublicKeyInfo.MessageEnd(); |
665 | 0 | } |
666 | | |
667 | | void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt) |
668 | 0 | { |
669 | 0 | BERSequenceDecoder privateKeyInfo(bt); |
670 | 0 | word32 version; |
671 | 0 | BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version |
672 | |
|
673 | 0 | BERSequenceDecoder algorithm(privateKeyInfo); |
674 | 0 | GetAlgorithmID().BERDecodeAndCheck(algorithm); |
675 | 0 | bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); |
676 | 0 | algorithm.MessageEnd(); |
677 | |
|
678 | 0 | BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); |
679 | 0 | BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength()); |
680 | 0 | octetString.MessageEnd(); |
681 | |
|
682 | 0 | if (!privateKeyInfo.EndReached()) |
683 | 0 | BERDecodeOptionalAttributes(privateKeyInfo); |
684 | 0 | privateKeyInfo.MessageEnd(); |
685 | 0 | } |
686 | | |
687 | | void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const |
688 | 0 | { |
689 | 0 | DERSequenceEncoder privateKeyInfo(bt); |
690 | 0 | DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version |
691 | |
|
692 | 0 | DERSequenceEncoder algorithm(privateKeyInfo); |
693 | 0 | GetAlgorithmID().DEREncode(algorithm); |
694 | 0 | DEREncodeAlgorithmParameters(algorithm); |
695 | 0 | algorithm.MessageEnd(); |
696 | |
|
697 | 0 | DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); |
698 | 0 | DEREncodePrivateKey(octetString); |
699 | 0 | octetString.MessageEnd(); |
700 | |
|
701 | 0 | DEREncodeOptionalAttributes(privateKeyInfo); |
702 | 0 | privateKeyInfo.MessageEnd(); |
703 | 0 | } |
704 | | |
705 | | void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt) |
706 | 0 | { |
707 | 0 | DERReencode(bt, m_optionalAttributes); |
708 | 0 | } |
709 | | |
710 | | void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const |
711 | 0 | { |
712 | 0 | m_optionalAttributes.CopyTo(bt); |
713 | 0 | } |
714 | | |
715 | | NAMESPACE_END |
716 | | |
717 | | #endif |