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