Crypto++  5.6.5
Free C++ class library of cryptographic schemes
asn.cpp
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 "asn.h"
10 
11 #include <iomanip>
12 #include <time.h>
13 
14 NAMESPACE_BEGIN(CryptoPP)
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 = false;
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  if (bc)
175  str.assign((char *)temp.begin(), bc);
176  else
177  str.clear();
178  return bc;
179 }
180 
181 /// ASN BitString
182 size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)
183 {
184  bt.Put(BIT_STRING);
185  size_t lengthBytes = DERLengthEncode(bt, strLen+1);
186  bt.Put((byte)unusedBits);
187  bt.Put(str, strLen);
188  return 2+lengthBytes+strLen;
189 }
190 
191 size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
192 {
193  byte b;
194  if (!bt.Get(b) || b != BIT_STRING)
195  BERDecodeError();
196 
197  size_t bc;
198  if (!BERLengthDecode(bt, bc))
199  BERDecodeError();
200  if (bc == 0)
201  BERDecodeError();
202  if (bc > bt.MaxRetrievable()) // Issue 346
203  BERDecodeError();
204 
205  // X.690, 8.6.2.2: "The number [of unused bits] shall be in the range zero to seven"
206  byte unused;
207  if (!bt.Get(unused) || unused > 7)
208  BERDecodeError();
209  unusedBits = unused;
210  str.resize(bc-1);
211  if ((bc-1) != bt.Get(str, bc-1))
212  BERDecodeError();
213  return bc-1;
214 }
215 
217 {
218  byte tag;
219  source.Peek(tag);
220  BERGeneralDecoder decoder(source, tag);
221  DERGeneralEncoder encoder(dest, tag);
222  if (decoder.IsDefiniteLength())
223  decoder.TransferTo(encoder, decoder.RemainingLength());
224  else
225  {
226  while (!decoder.EndReached())
227  DERReencode(decoder, encoder);
228  }
229  decoder.MessageEnd();
230  encoder.MessageEnd();
231 }
232 
233 void OID::EncodeValue(BufferedTransformation &bt, word32 v)
234 {
235  for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
236  bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
237  bt.Put((byte)(v & 0x7f));
238 }
239 
240 size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)
241 {
242  byte b;
243  size_t i=0;
244  v = 0;
245  while (true)
246  {
247  if (!bt.Get(b))
248  BERDecodeError();
249  i++;
250  if (v >> (8*sizeof(v)-7)) // v about to overflow
251  BERDecodeError();
252  v <<= 7;
253  v += b & 0x7f;
254  if (!(b & 0x80))
255  return i;
256  }
257 }
258 
260 {
261  CRYPTOPP_ASSERT(m_values.size() >= 2);
262  ByteQueue temp;
263  temp.Put(byte(m_values[0] * 40 + m_values[1]));
264  for (size_t i=2; i<m_values.size(); i++)
265  EncodeValue(temp, m_values[i]);
266  bt.Put(OBJECT_IDENTIFIER);
267  DERLengthEncode(bt, temp.CurrentSize());
268  temp.TransferTo(bt);
269 }
270 
272 {
273  byte b;
274  if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
275  BERDecodeError();
276 
277  size_t length;
278  if (!BERLengthDecode(bt, length) || length < 1)
279  BERDecodeError();
280 
281  if (!bt.Get(b))
282  BERDecodeError();
283 
284  length--;
285  m_values.resize(2);
286  m_values[0] = b / 40;
287  m_values[1] = b % 40;
288 
289  while (length > 0)
290  {
291  word32 v;
292  size_t valueLen = DecodeValue(bt, v);
293  if (valueLen > length)
294  BERDecodeError();
295  m_values.push_back(v);
296  length -= valueLen;
297  }
298 }
299 
301 {
302  OID oid(bt);
303  if (*this != oid)
304  BERDecodeError();
305 }
306 
307 inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
308 {
309  if (m_flags & PUT_OBJECTS)
310  return *AttachedTransformation();
311  else
312  return TheBitBucket();
313 }
314 
315 void EncodedObjectFilter::Put(const byte *inString, size_t length)
316 {
317  if (m_nCurrentObject == m_nObjects)
318  {
319  AttachedTransformation()->Put(inString, length);
320  return;
321  }
322 
323  LazyPutter lazyPutter(m_queue, inString, length);
324 
325  while (m_queue.AnyRetrievable())
326  {
327  switch (m_state)
328  {
329  case IDENTIFIER:
330  if (!m_queue.Get(m_id))
331  return;
332  m_queue.TransferTo(CurrentTarget(), 1);
333  m_state = LENGTH;
334  // fall through
335  case LENGTH:
336  {
337  byte b;
338  if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
339  {
340  m_queue.TransferTo(CurrentTarget(), 1);
341  m_level--;
342  m_state = IDENTIFIER;
343  break;
344  }
345  ByteQueue::Walker walker(m_queue);
346  bool definiteLength = false;
347  if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
348  return;
349  m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
350  if (!((m_id & CONSTRUCTED) || definiteLength))
351  BERDecodeError();
352  if (!definiteLength)
353  {
354  if (!(m_id & CONSTRUCTED))
355  BERDecodeError();
356  m_level++;
357  m_state = IDENTIFIER;
358  break;
359  }
360  m_state = BODY;
361  }
362  // fall through
363  case BODY:
364  m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
365 
366  if (m_lengthRemaining == 0)
367  m_state = IDENTIFIER;
368  // fall through
369  case TAIL:
370  case ALL_DONE:
371  default: ;;
372  }
373 
374  if (m_state == IDENTIFIER && m_level == 0)
375  {
376  // just finished processing a level 0 object
377  ++m_nCurrentObject;
378 
379  if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
380  AttachedTransformation()->MessageEnd();
381 
382  if (m_nCurrentObject == m_nObjects)
383  {
384  if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
385  AttachedTransformation()->MessageEnd();
386 
387  if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
388  AttachedTransformation()->MessageSeriesEnd();
389 
390  m_queue.TransferAllTo(*AttachedTransformation());
391  return;
392  }
393  }
394  }
395 }
396 
397 BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
398  : m_inQueue(inQueue), m_finished(false)
399 {
400  Init(asnTag);
401 }
402 
403 BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
404  : m_inQueue(inQueue), m_finished(false)
405 {
406  Init(asnTag);
407 }
408 
409 void BERGeneralDecoder::Init(byte asnTag)
410 {
411  byte b;
412  if (!m_inQueue.Get(b) || b != asnTag)
413  BERDecodeError();
414 
415  if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
416  BERDecodeError();
417 
418  if (!m_definiteLength && !(asnTag & CONSTRUCTED))
419  BERDecodeError(); // cannot be primitive and have indefinite length
420 }
421 
422 BERGeneralDecoder::~BERGeneralDecoder()
423 {
424  try // avoid throwing in destructor
425  {
426  if (!m_finished)
427  MessageEnd();
428  }
429  catch (const Exception&)
430  {
431  // CRYPTOPP_ASSERT(0);
432  }
433 }
434 
435 bool BERGeneralDecoder::EndReached() const
436 {
437  if (m_definiteLength)
438  return m_length == 0;
439  else
440  { // check end-of-content octets
441  word16 i;
442  return (m_inQueue.PeekWord16(i)==2 && i==0);
443  }
444 }
445 
446 byte BERGeneralDecoder::PeekByte() const
447 {
448  byte b;
449  if (!Peek(b))
450  BERDecodeError();
451  return b;
452 }
453 
454 void BERGeneralDecoder::CheckByte(byte check)
455 {
456  byte b;
457  if (!Get(b) || b != check)
458  BERDecodeError();
459 }
460 
461 void BERGeneralDecoder::MessageEnd()
462 {
463  m_finished = true;
464  if (m_definiteLength)
465  {
466  if (m_length != 0)
467  BERDecodeError();
468  }
469  else
470  { // remove end-of-content octets
471  word16 i;
472  if (m_inQueue.GetWord16(i) != 2 || i != 0)
473  BERDecodeError();
474  }
475 }
476 
477 size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
478 {
479  if (m_definiteLength && transferBytes > m_length)
480  transferBytes = m_length;
481  size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
482  ReduceLength(transferBytes);
483  return blockedBytes;
484 }
485 
486 size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
487 {
488  if (m_definiteLength)
489  end = STDMIN(m_length, end);
490  return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
491 }
492 
493 lword BERGeneralDecoder::ReduceLength(lword delta)
494 {
495  if (m_definiteLength)
496  {
497  if (m_length < delta)
498  BERDecodeError();
499  m_length -= delta;
500  }
501  return delta;
502 }
503 
504 DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
505  : ByteQueue(), m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
506 {
507 }
508 
509 // TODO: GCC (and likely other compilers) identify this as a copy constructor; and not a constructor.
510 // We have to wait until Crypto++ 6.0 to fix it because the signature change breaks versioning.
511 DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
512  : ByteQueue(), m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
513 {
514 }
515 
516 DERGeneralEncoder::~DERGeneralEncoder()
517 {
518  try // avoid throwing in constructor
519  {
520  if (!m_finished)
521  MessageEnd();
522  }
523  catch (const Exception&)
524  {
525  CRYPTOPP_ASSERT(0);
526  }
527 }
528 
529 void DERGeneralEncoder::MessageEnd()
530 {
531  m_finished = true;
532  lword length = CurrentSize();
533  m_outQueue.Put(m_asnTag);
534  DERLengthEncode(m_outQueue, length);
535  TransferTo(m_outQueue);
536 }
537 
538 // *************************************************************
539 
541 {
542  BERSequenceDecoder subjectPublicKeyInfo(bt);
543  BERSequenceDecoder algorithm(subjectPublicKeyInfo);
544  GetAlgorithmID().BERDecodeAndCheck(algorithm);
545  bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
546  algorithm.MessageEnd();
547 
548  BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
549  subjectPublicKey.CheckByte(0); // unused bits
550  BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
551  subjectPublicKey.MessageEnd();
552  subjectPublicKeyInfo.MessageEnd();
553 }
554 
556 {
557  DERSequenceEncoder subjectPublicKeyInfo(bt);
558 
559  DERSequenceEncoder algorithm(subjectPublicKeyInfo);
560  GetAlgorithmID().DEREncode(algorithm);
561  DEREncodeAlgorithmParameters(algorithm);
562  algorithm.MessageEnd();
563 
564  DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
565  subjectPublicKey.Put(0); // unused bits
566  DEREncodePublicKey(subjectPublicKey);
567  subjectPublicKey.MessageEnd();
568 
569  subjectPublicKeyInfo.MessageEnd();
570 }
571 
573 {
574  BERSequenceDecoder privateKeyInfo(bt);
575  word32 version;
576  BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
577 
578  BERSequenceDecoder algorithm(privateKeyInfo);
579  GetAlgorithmID().BERDecodeAndCheck(algorithm);
580  bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
581  algorithm.MessageEnd();
582 
583  BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
584  BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
585  octetString.MessageEnd();
586 
587  if (!privateKeyInfo.EndReached())
588  BERDecodeOptionalAttributes(privateKeyInfo);
589  privateKeyInfo.MessageEnd();
590 }
591 
593 {
594  DERSequenceEncoder privateKeyInfo(bt);
595  DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
596 
597  DERSequenceEncoder algorithm(privateKeyInfo);
598  GetAlgorithmID().DEREncode(algorithm);
599  DEREncodeAlgorithmParameters(algorithm);
600  algorithm.MessageEnd();
601 
602  DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
603  DEREncodePrivateKey(octetString);
604  octetString.MessageEnd();
605 
606  DEREncodeOptionalAttributes(privateKeyInfo);
607  privateKeyInfo.MessageEnd();
608 }
609 
611 {
612  DERReencode(bt, m_optionalAttributes);
613 }
614 
616 {
617  m_optionalAttributes.CopyTo(bt);
618 }
619 
620 NAMESPACE_END
621 
622 #endif
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:156
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const
encode optional attributes including context-specific tag
Definition: asn.cpp:615
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition: asn.cpp:540
bool SafeConvert(T1 from, T2 &to)
Tests whether a conversion from -> to is safe to perform.
Definition: misc.h:558
use this to make sure LazyPut is finalized in event of exception
Definition: queue.h:126
virtual size_t Peek(byte &outByte) const
Peek a 8-bit byte.
Definition: cryptlib.cpp:510
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:477
void resize(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:795
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:667
BufferedTransformation & TheBitBucket()
An input discarding BufferedTransformation.
Definition: cryptlib.cpp:46
Library configuration file.
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: asn.cpp:555
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:729
SecBlock<byte> typedef.
Definition: secblock.h:822
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition: asn.cpp:572
BER Sequence Decoder.
Definition: asn.h:303
Interface for buffered transformations.
Definition: cryptlib.h:1472
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:1775
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:1494
size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
BER decode octet string.
Definition: asn.cpp:117
void DEREncode(BufferedTransformation &bt) const
DER encode this OID.
Definition: asn.cpp:259
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:503
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:60
void BERDecode(BufferedTransformation &bt)
BER decode an OID.
Definition: asn.cpp:271
void BERDecodeError()
Raises a BERDecodeErr.
Definition: asn.h:69
Data structure used to store byte strings.
Definition: queue.h:18
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:315
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:536
void DERReencode(BufferedTransformation &bt, BufferedTransformation &dest)
BER decode and DER re-encode.
Definition: asn.cpp:216
DER Sequence Encoder.
Definition: asn.h:313
virtual lword MaxRetrievable() const
Provides the number of bytes ready for retrieval.
Definition: cryptlib.cpp:472
void BERDecodeAndCheck(BufferedTransformation &bt) const
BER decode an OID.
Definition: asn.cpp:300
DER General Encoder.
Definition: asn.h:284
virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt)
decode optional attributes including context-specific tag
Definition: asn.cpp:610
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: asn.cpp:592
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:486
size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
DER encode octet string.
Definition: asn.cpp:104
T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
Rounds a value up to a multiple of a second value.
Definition: misc.h:967
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:514
size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
DER decode bit string.
Definition: asn.cpp:191
virtual size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Definition: cryptlib.cpp:491
Crypto++ library namespace.
A ByteQueue iterator.
Definition: queue.h:76
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:690
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:561
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:182