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