Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/asn.cpp
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