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