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