Crypto++  5.6.5
Free C++ class library of cryptographic schemes
asn.cpp
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)
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 
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 
76 bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
77 {
78  lword lw = 0;
79  bool definiteLength;
80  if (!BERLengthDecode(bt, lw, definiteLength))
82  if (!SafeConvert(lw, length))
84  return definiteLength;
85 }
86 
88 {
89  out.Put(TAG_NULL);
90  out.Put(0);
91 }
92 
94 {
95  byte b;
96  if (!in.Get(b) || b != TAG_NULL)
98  size_t length;
99  if (!BERLengthDecode(in, length) || length != 0)
100  BERDecodeError();
101 }
102 
103 /// ASN Strings
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 
113 {
114  return DEREncodeOctetString(bt, str.begin(), str.size());
115 }
116 
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 
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 
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 
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
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 
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 
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 
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 
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 
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 
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 
298 {
299  OID oid(bt);
300  if (*this != oid)
301  BERDecodeError();
302 }
303 
304 inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
305 {
306  if (m_flags & PUT_OBJECTS)
307  return *AttachedTransformation();
308  else
309  return TheBitBucket();
310 }
311 
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 
392 BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
393  : m_inQueue(inQueue), m_finished(false)
394 {
395  Init(asnTag);
396 }
397 
398 BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
399  : m_inQueue(inQueue), m_finished(false)
400 {
401  Init(asnTag);
402 }
403 
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 
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 
430 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 
441 byte BERGeneralDecoder::PeekByte() const
442 {
443  byte b;
444  if (!Peek(b))
445  BERDecodeError();
446  return b;
447 }
448 
449 void BERGeneralDecoder::CheckByte(byte check)
450 {
451  byte b;
452  if (!Get(b) || b != check)
453  BERDecodeError();
454 }
455 
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 
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 
481 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 
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 
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.
506 DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
507  : ByteQueue(), m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
508 {
509 }
510 
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 
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 
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 
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 
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 
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 
606 {
607  DERReencode(bt, m_optionalAttributes);
608 }
609 
611 {
612  m_optionalAttributes.CopyTo(bt);
613 }
614 
615 NAMESPACE_END
616 
617 #endif
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:140
void DEREncode(BufferedTransformation &bt) const
DER encode this OID.
Definition: asn.cpp:256
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition: asn.cpp:535
bool SafeConvert(T1 from, T2 &to)
Tests whether a conversion from -> to is safe to perform.
Definition: misc.h:526
use this to make sure LazyPut is finalized in event of exception
Definition: queue.h:129
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: asn.cpp:550
virtual size_t Peek(byte &outByte) const
Peek a 8-bit byte.
Definition: cryptlib.cpp:534
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true)
Transfer bytes from this object to another BufferedTransformation.
Definition: asn.cpp:472
void resize(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:705
void DEREncodeNull(BufferedTransformation &bt)
DER encode NULL.
Definition: asn.cpp:87
unsigned int BytePrecision(const T &value)
Returns the number of 8-bit bytes or octets required for a value.
Definition: misc.h:632
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
Copy bytes from this object to another BufferedTransformation.
Definition: asn.cpp:481
BufferedTransformation & TheBitBucket()
An input discarding BufferedTransformation.
Definition: cryptlib.cpp:79
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:524
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: asn.cpp:587
Library configuration file.
STL namespace.
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:647
void BERDecodeAndCheck(BufferedTransformation &bt) const
BER decode an OID.
Definition: asn.cpp:297
SecBlock<byte> typedef.
Definition: secblock.h:731
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition: asn.cpp:567
BER Sequence Decoder.
Definition: asn.h:303
Interface for buffered transformations.
Definition: cryptlib.h:1352
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const
encode optional attributes including context-specific tag
Definition: asn.cpp:610
lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL)
move transferMax bytes of the buffered output to target as input
Definition: cryptlib.h:1654
void BERDecodeNull(BufferedTransformation &bt)
BER decode NULL.
Definition: asn.cpp:93
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1376
size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
BER decode octet string.
Definition: asn.cpp:117
size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
DER encode text string.
Definition: asn.cpp:151
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:477
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:62
void BERDecode(BufferedTransformation &bt)
BER decode an OID.
Definition: asn.cpp:268
void BERDecodeError()
Raises a BERDecodeErr.
Definition: asn.h:69
Data structure used to store byte strings.
Definition: queue.h:20
Classes and functions for working with ANS.1 objects.
size_t DERLengthEncode(BufferedTransformation &bt, lword length)
DER encode a length.
Definition: asn.cpp:17
void Put(const byte *inString, size_t length)
Input a byte buffer for processing.
Definition: asn.cpp:312
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:499
void DERReencode(BufferedTransformation &bt, BufferedTransformation &dest)
BER decode and DER re-encode.
Definition: asn.cpp:213
DER Sequence Encoder.
Definition: asn.h:313
DER General Encoder.
Definition: asn.h:284
virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt)
decode optional attributes including context-specific tag
Definition: asn.cpp:605
size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
DER encode octet string.
Definition: asn.cpp:104
virtual lword MaxRetrievable() const
Provides the number of bytes ready for retrieval.
Definition: cryptlib.cpp:496
T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
Rounds a value up to a multiple of a second value.
Definition: misc.h:905
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:487
size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
DER decode bit string.
Definition: asn.cpp:188
virtual size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Definition: cryptlib.cpp:515
Crypto++ library namespace.
A ByteQueue iterator.
Definition: queue.h:79
BER General Decoder.
Definition: asn.h:246
size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
BER decode text string.
Definition: asn.cpp:159
Object Identifier.
Definition: asn.h:166
unsigned int BitPrecision(const T &value)
Returns the number of bits required for a value.
Definition: misc.h:654
bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
BER decode a length.
Definition: asn.cpp:76
size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits=0)
DER encode bit string.
Definition: asn.cpp:179