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