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;
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; // fall through
334  case LENGTH:
335  {
336  byte b;
337  if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
338  {
339  m_queue.TransferTo(CurrentTarget(), 1);
340  m_level--;
341  m_state = IDENTIFIER;
342  break;
343  }
344  ByteQueue::Walker walker(m_queue);
345  bool definiteLength;
346  if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
347  return;
348  m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
349  if (!((m_id & CONSTRUCTED) || definiteLength))
350  BERDecodeError();
351  if (!definiteLength)
352  {
353  if (!(m_id & CONSTRUCTED))
354  BERDecodeError();
355  m_level++;
356  m_state = IDENTIFIER;
357  break;
358  }
359  m_state = BODY; // fall through
360  }
361  case BODY:
362  m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
363 
364  if (m_lengthRemaining == 0)
365  m_state = IDENTIFIER;
366 
367  case TAIL: // silence warnings
368  case ALL_DONE:
369  default: ;;
370  }
371 
372  if (m_state == IDENTIFIER && m_level == 0)
373  {
374  // just finished processing a level 0 object
375  ++m_nCurrentObject;
376 
377  if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
378  AttachedTransformation()->MessageEnd();
379 
380  if (m_nCurrentObject == m_nObjects)
381  {
382  if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
383  AttachedTransformation()->MessageEnd();
384 
385  if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
386  AttachedTransformation()->MessageSeriesEnd();
387 
388  m_queue.TransferAllTo(*AttachedTransformation());
389  return;
390  }
391  }
392  }
393 }
394 
395 BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
396  : m_inQueue(inQueue), m_finished(false)
397 {
398  Init(asnTag);
399 }
400 
401 BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
402  : m_inQueue(inQueue), m_finished(false)
403 {
404  Init(asnTag);
405 }
406 
407 void BERGeneralDecoder::Init(byte asnTag)
408 {
409  byte b;
410  if (!m_inQueue.Get(b) || b != asnTag)
411  BERDecodeError();
412 
413  if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
414  BERDecodeError();
415 
416  if (!m_definiteLength && !(asnTag & CONSTRUCTED))
417  BERDecodeError(); // cannot be primitive and have indefinite length
418 }
419 
420 BERGeneralDecoder::~BERGeneralDecoder()
421 {
422  try // avoid throwing in destructor
423  {
424  if (!m_finished)
425  MessageEnd();
426  }
427  catch (const Exception&)
428  {
429  // CRYPTOPP_ASSERT(0);
430  }
431 }
432 
433 bool BERGeneralDecoder::EndReached() const
434 {
435  if (m_definiteLength)
436  return m_length == 0;
437  else
438  { // check end-of-content octets
439  word16 i;
440  return (m_inQueue.PeekWord16(i)==2 && i==0);
441  }
442 }
443 
444 byte BERGeneralDecoder::PeekByte() const
445 {
446  byte b;
447  if (!Peek(b))
448  BERDecodeError();
449  return b;
450 }
451 
452 void BERGeneralDecoder::CheckByte(byte check)
453 {
454  byte b;
455  if (!Get(b) || b != check)
456  BERDecodeError();
457 }
458 
459 void BERGeneralDecoder::MessageEnd()
460 {
461  m_finished = true;
462  if (m_definiteLength)
463  {
464  if (m_length != 0)
465  BERDecodeError();
466  }
467  else
468  { // remove end-of-content octets
469  word16 i;
470  if (m_inQueue.GetWord16(i) != 2 || i != 0)
471  BERDecodeError();
472  }
473 }
474 
475 size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
476 {
477  if (m_definiteLength && transferBytes > m_length)
478  transferBytes = m_length;
479  size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
480  ReduceLength(transferBytes);
481  return blockedBytes;
482 }
483 
484 size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
485 {
486  if (m_definiteLength)
487  end = STDMIN(m_length, end);
488  return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
489 }
490 
491 lword BERGeneralDecoder::ReduceLength(lword delta)
492 {
493  if (m_definiteLength)
494  {
495  if (m_length < delta)
496  BERDecodeError();
497  m_length -= delta;
498  }
499  return delta;
500 }
501 
502 DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
503  : ByteQueue(), m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
504 {
505 }
506 
507 // TODO: GCC (and likely other compilers) identify this as a copy constructor; and not a constructor.
508 // We have to wait until Crypto++ 6.0 to fix it because the signature change breaks versioning.
509 DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
510  : ByteQueue(), m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
511 {
512 }
513 
514 DERGeneralEncoder::~DERGeneralEncoder()
515 {
516  try // avoid throwing in constructor
517  {
518  if (!m_finished)
519  MessageEnd();
520  }
521  catch (const Exception&)
522  {
523  CRYPTOPP_ASSERT(0);
524  }
525 }
526 
527 void DERGeneralEncoder::MessageEnd()
528 {
529  m_finished = true;
530  lword length = CurrentSize();
531  m_outQueue.Put(m_asnTag);
532  DERLengthEncode(m_outQueue, length);
533  TransferTo(m_outQueue);
534 }
535 
536 // *************************************************************
537 
539 {
540  BERSequenceDecoder subjectPublicKeyInfo(bt);
541  BERSequenceDecoder algorithm(subjectPublicKeyInfo);
542  GetAlgorithmID().BERDecodeAndCheck(algorithm);
543  bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
544  algorithm.MessageEnd();
545 
546  BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
547  subjectPublicKey.CheckByte(0); // unused bits
548  BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
549  subjectPublicKey.MessageEnd();
550  subjectPublicKeyInfo.MessageEnd();
551 }
552 
554 {
555  DERSequenceEncoder subjectPublicKeyInfo(bt);
556 
557  DERSequenceEncoder algorithm(subjectPublicKeyInfo);
558  GetAlgorithmID().DEREncode(algorithm);
559  DEREncodeAlgorithmParameters(algorithm);
560  algorithm.MessageEnd();
561 
562  DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
563  subjectPublicKey.Put(0); // unused bits
564  DEREncodePublicKey(subjectPublicKey);
565  subjectPublicKey.MessageEnd();
566 
567  subjectPublicKeyInfo.MessageEnd();
568 }
569 
571 {
572  BERSequenceDecoder privateKeyInfo(bt);
573  word32 version;
574  BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
575 
576  BERSequenceDecoder algorithm(privateKeyInfo);
577  GetAlgorithmID().BERDecodeAndCheck(algorithm);
578  bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
579  algorithm.MessageEnd();
580 
581  BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
582  BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
583  octetString.MessageEnd();
584 
585  if (!privateKeyInfo.EndReached())
586  BERDecodeOptionalAttributes(privateKeyInfo);
587  privateKeyInfo.MessageEnd();
588 }
589 
591 {
592  DERSequenceEncoder privateKeyInfo(bt);
593  DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
594 
595  DERSequenceEncoder algorithm(privateKeyInfo);
596  GetAlgorithmID().DEREncode(algorithm);
597  DEREncodeAlgorithmParameters(algorithm);
598  algorithm.MessageEnd();
599 
600  DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
601  DEREncodePrivateKey(octetString);
602  octetString.MessageEnd();
603 
604  DEREncodeOptionalAttributes(privateKeyInfo);
605  privateKeyInfo.MessageEnd();
606 }
607 
609 {
610  DERReencode(bt, m_optionalAttributes);
611 }
612 
614 {
615  m_optionalAttributes.CopyTo(bt);
616 }
617 
618 NAMESPACE_END
619 
620 #endif
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:150
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const
encode optional attributes including context-specific tag
Definition: asn.cpp:613
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition: asn.cpp:538
bool SafeConvert(T1 from, T2 &to)
Tests whether a conversion from -> to is safe to perform.
Definition: misc.h:568
use this to make sure LazyPut is finalized in event of exception
Definition: queue.h:128
virtual size_t Peek(byte &outByte) const
Peek a 8-bit byte.
Definition: cryptlib.cpp:506
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:475
void resize(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:782
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:677
BufferedTransformation & TheBitBucket()
An input discarding BufferedTransformation.
Definition: cryptlib.cpp:53
Library configuration file.
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: asn.cpp:553
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:717
SecBlock<byte> typedef.
Definition: secblock.h:810
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition: asn.cpp:570
BER Sequence Decoder.
Definition: asn.h:303
Interface for buffered transformations.
Definition: cryptlib.h:1343
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:1637
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:1364
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:514
#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:19
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:545
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:468
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:608
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: asn.cpp:590
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:484
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:977
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:525
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:487
Crypto++ library namespace.
A ByteQueue iterator.
Definition: queue.h:78
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:700
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:570
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