Crypto++
asn.cpp
1 // asn.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 
5 #ifndef CRYPTOPP_IMPORTS
6 
7 #include "asn.h"
8 
9 #include <iomanip>
10 #include <time.h>
11 
12 NAMESPACE_BEGIN(CryptoPP)
13 USING_NAMESPACE(std)
14 
15 /// DER Length
16 size_t DERLengthEncode(BufferedTransformation &bt, lword length)
17 {
18  size_t i=0;
19  if (length <= 0x7f)
20  {
21  bt.Put(byte(length));
22  i++;
23  }
24  else
25  {
26  bt.Put(byte(BytePrecision(length) | 0x80));
27  i++;
28  for (int j=BytePrecision(length); j; --j)
29  {
30  bt.Put(byte(length >> (j-1)*8));
31  i++;
32  }
33  }
34  return i;
35 }
36 
37 bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength)
38 {
39  byte b;
40 
41  if (!bt.Get(b))
42  return false;
43 
44  if (!(b & 0x80))
45  {
46  definiteLength = true;
47  length = b;
48  }
49  else
50  {
51  unsigned int lengthBytes = b & 0x7f;
52 
53  if (lengthBytes == 0)
54  {
55  definiteLength = false;
56  return true;
57  }
58 
59  definiteLength = true;
60  length = 0;
61  while (lengthBytes--)
62  {
63  if (length >> (8*(sizeof(length)-1)))
64  BERDecodeError(); // length about to overflow
65 
66  if (!bt.Get(b))
67  return false;
68 
69  length = (length << 8) | b;
70  }
71  }
72  return true;
73 }
74 
75 bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
76 {
77  lword lw;
78  bool definiteLength;
79  if (!BERLengthDecode(bt, lw, definiteLength))
80  BERDecodeError();
81  if (!SafeConvert(lw, length))
82  BERDecodeError();
83  return definiteLength;
84 }
85 
86 void DEREncodeNull(BufferedTransformation &out)
87 {
88  out.Put(TAG_NULL);
89  out.Put(0);
90 }
91 
92 void BERDecodeNull(BufferedTransformation &in)
93 {
94  byte b;
95  if (!in.Get(b) || b != TAG_NULL)
96  BERDecodeError();
97  size_t length;
98  if (!BERLengthDecode(in, length) || length != 0)
99  BERDecodeError();
100 }
101 
102 /// ASN Strings
103 size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
104 {
105  bt.Put(OCTET_STRING);
106  size_t lengthBytes = DERLengthEncode(bt, strLen);
107  bt.Put(str, strLen);
108  return 1+lengthBytes+strLen;
109 }
110 
111 size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)
112 {
113  return DEREncodeOctetString(bt, str.begin(), str.size());
114 }
115 
116 size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
117 {
118  byte b;
119  if (!bt.Get(b) || b != OCTET_STRING)
120  BERDecodeError();
121 
122  size_t bc;
123  if (!BERLengthDecode(bt, bc))
124  BERDecodeError();
125 
126  str.resize(bc);
127  if (bc != bt.Get(str, bc))
128  BERDecodeError();
129  return bc;
130 }
131 
132 size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)
133 {
134  byte b;
135  if (!bt.Get(b) || b != OCTET_STRING)
136  BERDecodeError();
137 
138  size_t bc;
139  if (!BERLengthDecode(bt, bc))
140  BERDecodeError();
141 
142  bt.TransferTo(str, bc);
143  return bc;
144 }
145 
146 size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
147 {
148  bt.Put(asnTag);
149  size_t lengthBytes = DERLengthEncode(bt, str.size());
150  bt.Put((const byte *)str.data(), str.size());
151  return 1+lengthBytes+str.size();
152 }
153 
154 size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
155 {
156  byte b;
157  if (!bt.Get(b) || b != asnTag)
158  BERDecodeError();
159 
160  size_t bc;
161  if (!BERLengthDecode(bt, bc))
162  BERDecodeError();
163 
164  SecByteBlock temp(bc);
165  if (bc != bt.Get(temp, bc))
166  BERDecodeError();
167  str.assign((char *)temp.begin(), bc);
168  return bc;
169 }
170 
171 /// ASN BitString
172 size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)
173 {
174  bt.Put(BIT_STRING);
175  size_t lengthBytes = DERLengthEncode(bt, strLen+1);
176  bt.Put((byte)unusedBits);
177  bt.Put(str, strLen);
178  return 2+lengthBytes+strLen;
179 }
180 
181 size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
182 {
183  byte b;
184  if (!bt.Get(b) || b != BIT_STRING)
185  BERDecodeError();
186 
187  size_t bc;
188  if (!BERLengthDecode(bt, bc))
189  BERDecodeError();
190 
191  byte unused;
192  if (!bt.Get(unused))
193  BERDecodeError();
194  unusedBits = unused;
195  str.resize(bc-1);
196  if ((bc-1) != bt.Get(str, bc-1))
197  BERDecodeError();
198  return bc-1;
199 }
200 
201 void DERReencode(BufferedTransformation &source, BufferedTransformation &dest)
202 {
203  byte tag;
204  source.Peek(tag);
205  BERGeneralDecoder decoder(source, tag);
206  DERGeneralEncoder encoder(dest, tag);
207  if (decoder.IsDefiniteLength())
208  decoder.TransferTo(encoder, decoder.RemainingLength());
209  else
210  {
211  while (!decoder.EndReached())
212  DERReencode(decoder, encoder);
213  }
214  decoder.MessageEnd();
215  encoder.MessageEnd();
216 }
217 
218 void OID::EncodeValue(BufferedTransformation &bt, word32 v)
219 {
220  for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
221  bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
222  bt.Put((byte)(v & 0x7f));
223 }
224 
225 size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)
226 {
227  byte b;
228  size_t i=0;
229  v = 0;
230  while (true)
231  {
232  if (!bt.Get(b))
233  BERDecodeError();
234  i++;
235  if (v >> (8*sizeof(v)-7)) // v about to overflow
236  BERDecodeError();
237  v <<= 7;
238  v += b & 0x7f;
239  if (!(b & 0x80))
240  return i;
241  }
242 }
243 
244 void OID::DEREncode(BufferedTransformation &bt) const
245 {
246  assert(m_values.size() >= 2);
247  ByteQueue temp;
248  temp.Put(byte(m_values[0] * 40 + m_values[1]));
249  for (size_t i=2; i<m_values.size(); i++)
250  EncodeValue(temp, m_values[i]);
251  bt.Put(OBJECT_IDENTIFIER);
252  DERLengthEncode(bt, temp.CurrentSize());
253  temp.TransferTo(bt);
254 }
255 
256 void OID::BERDecode(BufferedTransformation &bt)
257 {
258  byte b;
259  if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
260  BERDecodeError();
261 
262  size_t length;
263  if (!BERLengthDecode(bt, length) || length < 1)
264  BERDecodeError();
265 
266  if (!bt.Get(b))
267  BERDecodeError();
268 
269  length--;
270  m_values.resize(2);
271  m_values[0] = b / 40;
272  m_values[1] = b % 40;
273 
274  while (length > 0)
275  {
276  word32 v;
277  size_t valueLen = DecodeValue(bt, v);
278  if (valueLen > length)
279  BERDecodeError();
280  m_values.push_back(v);
281  length -= valueLen;
282  }
283 }
284 
285 void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
286 {
287  OID oid(bt);
288  if (*this != oid)
289  BERDecodeError();
290 }
291 
292 inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
293 {
294  if (m_flags & PUT_OBJECTS)
295  return *AttachedTransformation();
296  else
297  return TheBitBucket();
298 }
299 
300 void EncodedObjectFilter::Put(const byte *inString, size_t length)
301 {
302  if (m_nCurrentObject == m_nObjects)
303  {
304  AttachedTransformation()->Put(inString, length);
305  return;
306  }
307 
308  LazyPutter lazyPutter(m_queue, inString, length);
309 
310  while (m_queue.AnyRetrievable())
311  {
312  switch (m_state)
313  {
314  case IDENTIFIER:
315  if (!m_queue.Get(m_id))
316  return;
317  m_queue.TransferTo(CurrentTarget(), 1);
318  m_state = LENGTH; // fall through
319  case LENGTH:
320  {
321  byte b;
322  if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
323  {
324  m_queue.TransferTo(CurrentTarget(), 1);
325  m_level--;
326  m_state = IDENTIFIER;
327  break;
328  }
329  ByteQueue::Walker walker(m_queue);
330  bool definiteLength;
331  if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
332  return;
333  m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
334  if (!((m_id & CONSTRUCTED) || definiteLength))
335  BERDecodeError();
336  if (!definiteLength)
337  {
338  if (!(m_id & CONSTRUCTED))
339  BERDecodeError();
340  m_level++;
341  m_state = IDENTIFIER;
342  break;
343  }
344  m_state = BODY; // fall through
345  }
346  case BODY:
347  m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
348 
349  if (m_lengthRemaining == 0)
350  m_state = IDENTIFIER;
351  }
352 
353  if (m_state == IDENTIFIER && m_level == 0)
354  {
355  // just finished processing a level 0 object
356  ++m_nCurrentObject;
357 
358  if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
359  AttachedTransformation()->MessageEnd();
360 
361  if (m_nCurrentObject == m_nObjects)
362  {
363  if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
364  AttachedTransformation()->MessageEnd();
365 
366  if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
368 
369  m_queue.TransferAllTo(*AttachedTransformation());
370  return;
371  }
372  }
373  }
374 }
375 
376 BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
377  : m_inQueue(inQueue), m_finished(false)
378 {
379  Init(asnTag);
380 }
381 
382 BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
383  : m_inQueue(inQueue), m_finished(false)
384 {
385  Init(asnTag);
386 }
387 
388 void BERGeneralDecoder::Init(byte asnTag)
389 {
390  byte b;
391  if (!m_inQueue.Get(b) || b != asnTag)
392  BERDecodeError();
393 
394  if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
395  BERDecodeError();
396 
397  if (!m_definiteLength && !(asnTag & CONSTRUCTED))
398  BERDecodeError(); // cannot be primitive and have indefinite length
399 }
400 
401 BERGeneralDecoder::~BERGeneralDecoder()
402 {
403  try // avoid throwing in constructor
404  {
405  if (!m_finished)
406  MessageEnd();
407  }
408  catch (...)
409  {
410  }
411 }
412 
413 bool BERGeneralDecoder::EndReached() const
414 {
415  if (m_definiteLength)
416  return m_length == 0;
417  else
418  { // check end-of-content octets
419  word16 i;
420  return (m_inQueue.PeekWord16(i)==2 && i==0);
421  }
422 }
423 
424 byte BERGeneralDecoder::PeekByte() const
425 {
426  byte b;
427  if (!Peek(b))
428  BERDecodeError();
429  return b;
430 }
431 
432 void BERGeneralDecoder::CheckByte(byte check)
433 {
434  byte b;
435  if (!Get(b) || b != check)
436  BERDecodeError();
437 }
438 
439 void BERGeneralDecoder::MessageEnd()
440 {
441  m_finished = true;
442  if (m_definiteLength)
443  {
444  if (m_length != 0)
445  BERDecodeError();
446  }
447  else
448  { // remove end-of-content octets
449  word16 i;
450  if (m_inQueue.GetWord16(i) != 2 || i != 0)
451  BERDecodeError();
452  }
453 }
454 
455 size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
456 {
457  if (m_definiteLength && transferBytes > m_length)
458  transferBytes = m_length;
459  size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
460  ReduceLength(transferBytes);
461  return blockedBytes;
462 }
463 
464 size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
465 {
466  if (m_definiteLength)
467  end = STDMIN(m_length, end);
468  return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
469 }
470 
471 lword BERGeneralDecoder::ReduceLength(lword delta)
472 {
473  if (m_definiteLength)
474  {
475  if (m_length < delta)
476  BERDecodeError();
477  m_length -= delta;
478  }
479  return delta;
480 }
481 
482 DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
483  : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
484 {
485 }
486 
487 DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
488  : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
489 {
490 }
491 
492 DERGeneralEncoder::~DERGeneralEncoder()
493 {
494  try // avoid throwing in constructor
495  {
496  if (!m_finished)
497  MessageEnd();
498  }
499  catch (...)
500  {
501  }
502 }
503 
504 void DERGeneralEncoder::MessageEnd()
505 {
506  m_finished = true;
507  lword length = CurrentSize();
508  m_outQueue.Put(m_asnTag);
509  DERLengthEncode(m_outQueue, length);
510  TransferTo(m_outQueue);
511 }
512 
513 // *************************************************************
514 
516 {
517  BERSequenceDecoder subjectPublicKeyInfo(bt);
518  BERSequenceDecoder algorithm(subjectPublicKeyInfo);
519  GetAlgorithmID().BERDecodeAndCheck(algorithm);
520  bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
521  algorithm.MessageEnd();
522 
523  BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
524  subjectPublicKey.CheckByte(0); // unused bits
525  BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
526  subjectPublicKey.MessageEnd();
527  subjectPublicKeyInfo.MessageEnd();
528 }
529 
531 {
532  DERSequenceEncoder subjectPublicKeyInfo(bt);
533 
534  DERSequenceEncoder algorithm(subjectPublicKeyInfo);
535  GetAlgorithmID().DEREncode(algorithm);
536  DEREncodeAlgorithmParameters(algorithm);
537  algorithm.MessageEnd();
538 
539  DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
540  subjectPublicKey.Put(0); // unused bits
541  DEREncodePublicKey(subjectPublicKey);
542  subjectPublicKey.MessageEnd();
543 
544  subjectPublicKeyInfo.MessageEnd();
545 }
546 
548 {
549  BERSequenceDecoder privateKeyInfo(bt);
550  word32 version;
551  BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
552 
553  BERSequenceDecoder algorithm(privateKeyInfo);
554  GetAlgorithmID().BERDecodeAndCheck(algorithm);
555  bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
556  algorithm.MessageEnd();
557 
558  BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
559  BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
560  octetString.MessageEnd();
561 
562  if (!privateKeyInfo.EndReached())
563  BERDecodeOptionalAttributes(privateKeyInfo);
564  privateKeyInfo.MessageEnd();
565 }
566 
568 {
569  DERSequenceEncoder privateKeyInfo(bt);
570  DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
571 
572  DERSequenceEncoder algorithm(privateKeyInfo);
573  GetAlgorithmID().DEREncode(algorithm);
574  DEREncodeAlgorithmParameters(algorithm);
575  algorithm.MessageEnd();
576 
577  DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
578  DEREncodePrivateKey(octetString);
579  octetString.MessageEnd();
580 
581  DEREncodeOptionalAttributes(privateKeyInfo);
582  privateKeyInfo.MessageEnd();
583 }
584 
586 {
587  DERReencode(bt, m_optionalAttributes);
588 }
589 
591 {
592  m_optionalAttributes.CopyTo(bt);
593 }
594 
595 NAMESPACE_END
596 
597 #endif