1 /*
2  * asnber.cxx
3  *
4  * Abstract Syntax Notation 1 Encoding Rules
5  *
6  * Portable Windows Library
7  *
8  */
9 
10 ///////////////////////////////////////////////////////////////////////
11 
NullDecode(PASN_Null & value)12 PBoolean PBER_Stream::NullDecode(PASN_Null & value)
13 {
14   unsigned len;
15   if (!HeaderDecode(value, len))
16     return PFalse;
17 
18   byteOffset += len;
19   return PTrue;
20 }
21 
22 
NullEncode(const PASN_Null & value)23 void PBER_Stream::NullEncode(const PASN_Null & value)
24 {
25   HeaderEncode(value);
26 }
27 
28 ///////////////////////////////////////////////////////////////////////
29 
BooleanDecode(PASN_Boolean & value)30 PBoolean PBER_Stream::BooleanDecode(PASN_Boolean & value)
31 {
32   unsigned len;
33   if (!HeaderDecode(value, len))
34     return PFalse;
35 
36   while (len-- > 0) {
37     if (IsAtEnd())
38       return PFalse;
39     value = (PBoolean)ByteDecode();
40   }
41 
42   return PTrue;
43 }
44 
45 
BooleanEncode(const PASN_Boolean & value)46 void PBER_Stream::BooleanEncode(const PASN_Boolean & value)
47 {
48   HeaderEncode(value);
49   ByteEncode((PBoolean)value);
50 }
51 
52 ///////////////////////////////////////////////////////////////////////
53 
IntegerDecode(PASN_Integer & value)54 PBoolean PBER_Stream::IntegerDecode(PASN_Integer & value)
55 {
56   unsigned len;
57   if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
58     return PFalse;
59 
60   int accumulator = (char)ByteDecode(); // sign extended first byte
61   while (--len > 0) {
62     if (IsAtEnd())
63       return PFalse;
64     accumulator = (accumulator << 8) | ByteDecode();
65   }
66 
67   value = accumulator;
68   return PTrue;
69 }
70 
71 
IntegerEncode(const PASN_Integer & value)72 void PBER_Stream::IntegerEncode(const PASN_Integer & value)
73 {
74   HeaderEncode(value);
75   // output the integer bits
76   for (int count = GetIntegerDataLength(value)-1; count >= 0; count--)
77     ByteEncode(value >> (count*8));
78 }
79 
80 ///////////////////////////////////////////////////////////////////////
81 
EnumerationDecode(PASN_Enumeration & value)82 PBoolean PBER_Stream::EnumerationDecode(PASN_Enumeration & value)
83 {
84   unsigned len;
85   if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
86     return PFalse;
87 
88   unsigned val = 0;
89   while (len-- > 0) {
90     if (IsAtEnd())
91       return PFalse;
92     val = (val << 8) | ByteDecode();
93   }
94 
95   value = val;
96   return PTrue;
97 }
98 
99 
EnumerationEncode(const PASN_Enumeration & value)100 void PBER_Stream::EnumerationEncode(const PASN_Enumeration & value)
101 {
102   HeaderEncode(value);
103   // output the integer bits
104   for (int count = GetIntegerDataLength(value)-1; count >= 0; count--)
105     ByteEncode(value >> (count*8));
106 }
107 
108 ///////////////////////////////////////////////////////////////////////
109 
RealDecode(PASN_Real & value)110 PBoolean PBER_Stream::RealDecode(PASN_Real & value)
111 {
112   unsigned len;
113   if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
114     return PFalse;
115 
116   PAssertAlways(PUnimplementedFunction);
117   byteOffset += len;
118 
119   return PTrue;
120 }
121 
122 
RealEncode(const PASN_Real &)123 void PBER_Stream::RealEncode(const PASN_Real &)
124 {
125   PAssertAlways(PUnimplementedFunction);
126 }
127 
128 ///////////////////////////////////////////////////////////////////////
129 
ObjectIdDecode(PASN_ObjectId & value)130 PBoolean PBER_Stream::ObjectIdDecode(PASN_ObjectId & value)
131 {
132   unsigned len;
133   if (!HeaderDecode(value, len))
134     return PFalse;
135 
136   return value.CommonDecode(*this, len);
137 }
138 
139 
ObjectIdEncode(const PASN_ObjectId & value)140 void PBER_Stream::ObjectIdEncode(const PASN_ObjectId & value)
141 {
142   HeaderEncode(value);
143   PBYTEArray data;
144   value.CommonEncode(data);
145   BlockEncode(data, data.GetSize());
146 }
147 
148 ///////////////////////////////////////////////////////////////////////
149 
DecodeBER(PBER_Stream & strm,unsigned len)150 PBoolean PASN_BitString::DecodeBER(PBER_Stream & strm, unsigned len)
151 {
152   totalBits = len*8 - strm.ByteDecode();
153   unsigned nBytes = (totalBits+7)/8;
154   return strm.BlockDecode(bitData.GetPointer(nBytes), nBytes) == nBytes;
155 }
156 
157 
EncodeBER(PBER_Stream & strm) const158 void PASN_BitString::EncodeBER(PBER_Stream & strm) const
159 {
160   if (totalBits == 0)
161     strm.ByteEncode(0);
162   else {
163     strm.ByteEncode(8-totalBits%8);
164     strm.BlockEncode(bitData, (totalBits+7)/8);
165   }
166 }
167 
168 ///////////////////////////////////////////////////////////////////////
169 
BitStringDecode(PASN_BitString & value)170 PBoolean PBER_Stream::BitStringDecode(PASN_BitString & value)
171 {
172   unsigned len;
173   if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
174     return PFalse;
175 
176   return value.DecodeBER(*this, len);
177 }
178 
179 
BitStringEncode(const PASN_BitString & value)180 void PBER_Stream::BitStringEncode(const PASN_BitString & value)
181 {
182   HeaderEncode(value);
183   value.EncodeBER(*this);
184 }
185 
186 ///////////////////////////////////////////////////////////////////////
187 
OctetStringDecode(PASN_OctetString & value)188 PBoolean PBER_Stream::OctetStringDecode(PASN_OctetString & value)
189 {
190   unsigned len;
191   if (!HeaderDecode(value, len))
192     return PFalse;
193 
194   return BlockDecode(value.GetPointer(len), len) == len;
195 }
196 
197 
OctetStringEncode(const PASN_OctetString & value)198 void PBER_Stream::OctetStringEncode(const PASN_OctetString & value)
199 {
200   HeaderEncode(value);
201   BlockEncode(value, value.GetSize());
202 }
203 
204 ///////////////////////////////////////////////////////////////////////
205 
DecodeBER(PBER_Stream & strm,unsigned len)206 PBoolean PASN_ConstrainedString::DecodeBER(PBER_Stream & strm, unsigned len)
207 {
208   return strm.BlockDecode((BYTE *)value.GetPointer(len+1), len) == len;
209 }
210 
211 
EncodeBER(PBER_Stream & strm) const212 void PASN_ConstrainedString::EncodeBER(PBER_Stream & strm) const
213 {
214   strm.BlockEncode(value, value.GetSize()-1);
215 }
216 
217 ///////////////////////////////////////////////////////////////////////
218 
ConstrainedStringDecode(PASN_ConstrainedString & value)219 PBoolean PBER_Stream::ConstrainedStringDecode(PASN_ConstrainedString & value)
220 {
221   unsigned len;
222   if (!HeaderDecode(value, len))
223     return PFalse;
224 
225   return value.DecodeBER(*this, len);
226 }
227 
228 
ConstrainedStringEncode(const PASN_ConstrainedString & value)229 void PBER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString & value)
230 {
231   HeaderEncode(value);
232   value.EncodeBER(*this);
233 }
234 
235 ///////////////////////////////////////////////////////////////////////
236 
DecodeBER(PBER_Stream & strm,unsigned len)237 PBoolean PASN_BMPString::DecodeBER(PBER_Stream & strm, unsigned len)
238 {
239   value.SetSize(len/2);
240   return strm.BlockDecode((BYTE *)value.GetPointer(len), len) == len;
241 }
242 
243 
EncodeBER(PBER_Stream & strm) const244 void PASN_BMPString::EncodeBER(PBER_Stream & strm) const
245 {
246   strm.BlockEncode((const BYTE *)(const wchar_t *)value, value.GetSize()*2);
247 }
248 
249 ///////////////////////////////////////////////////////////////////////
250 
BMPStringDecode(PASN_BMPString & value)251 PBoolean PBER_Stream::BMPStringDecode(PASN_BMPString & value)
252 {
253   unsigned len;
254   if (!HeaderDecode(value, len))
255     return PFalse;
256 
257   return value.DecodeBER(*this, len);
258 }
259 
260 
BMPStringEncode(const PASN_BMPString & value)261 void PBER_Stream::BMPStringEncode(const PASN_BMPString & value)
262 {
263   HeaderEncode(value);
264   value.EncodeBER(*this);
265 }
266 
267 ///////////////////////////////////////////////////////////////////////
268 
ChoiceDecode(PASN_Choice & value)269 PBoolean PBER_Stream::ChoiceDecode(PASN_Choice & value)
270 {
271   PINDEX savedPosition = GetPosition();
272 
273   unsigned tag;
274   PASN_Object::TagClass tagClass;
275   PBoolean primitive;
276   unsigned entryLen;
277   if (!HeaderDecode(tag, tagClass, primitive, entryLen))
278     return PFalse;
279 
280   SetPosition(savedPosition);
281 
282   value.SetTag(tag, tagClass);
283   if (value.IsValid())
284     return value.GetObject().Decode(*this);
285 
286   return PTrue;
287 }
288 
ChoiceEncode(const PASN_Choice & value)289 void PBER_Stream::ChoiceEncode(const PASN_Choice & value)
290 {
291   if (value.IsValid())
292     value.GetObject().Encode(*this);
293 }
294 
295 ///////////////////////////////////////////////////////////////////////
296 
PreambleDecodeBER(PBER_Stream & strm)297 PBoolean PASN_Sequence::PreambleDecodeBER(PBER_Stream & strm)
298 {
299   fields.RemoveAll();
300 
301   unsigned len;
302   if (!strm.HeaderDecode(*this, len))
303     return PFalse;
304 
305   endBasicEncoding = strm.GetPosition() + len;
306   return !strm.IsAtEnd();
307 }
308 
309 
PreambleEncodeBER(PBER_Stream & strm) const310 void PASN_Sequence::PreambleEncodeBER(PBER_Stream & strm) const
311 {
312   strm.HeaderEncode(*this);
313 }
314 
315 
KnownExtensionDecodeBER(PBER_Stream & strm,PINDEX,PASN_Object & field)316 PBoolean PASN_Sequence::KnownExtensionDecodeBER(PBER_Stream & strm, PINDEX, PASN_Object & field)
317 {
318   if (strm.GetPosition() >= endBasicEncoding)
319     return PFalse;
320 
321   return field.Decode(strm);
322 }
323 
324 
KnownExtensionEncodeBER(PBER_Stream & strm,PINDEX,const PASN_Object & field) const325 void PASN_Sequence::KnownExtensionEncodeBER(PBER_Stream & strm, PINDEX, const PASN_Object & field) const
326 {
327   field.Encode(strm);
328 }
329 
330 
UnknownExtensionsDecodeBER(PBER_Stream & strm)331 PBoolean PASN_Sequence::UnknownExtensionsDecodeBER(PBER_Stream & strm)
332 {
333   while (strm.GetPosition() < endBasicEncoding) {
334     PINDEX savedPosition = strm.GetPosition();
335 
336     unsigned tag;
337     PASN_Object::TagClass tagClass;
338     PBoolean primitive;
339     unsigned entryLen;
340     if (!strm.HeaderDecode(tag, tagClass, primitive, entryLen))
341       return PFalse;
342 
343     PINDEX nextEntryPosition = strm.GetPosition() + entryLen;
344     strm.SetPosition(savedPosition);
345 
346     PASN_Object * obj = strm.CreateObject(tag, tagClass, primitive);
347     if (obj == NULL)
348       strm.SetPosition(nextEntryPosition);
349     else {
350       if (!obj->Decode(strm))
351         return PFalse;
352 
353       fields.Append(obj);
354     }
355   }
356 
357   return PTrue;
358 }
359 
360 
UnknownExtensionsEncodeBER(PBER_Stream & strm) const361 void PASN_Sequence::UnknownExtensionsEncodeBER(PBER_Stream & strm) const
362 {
363   for (PINDEX i = 0; i < fields.GetSize(); i++)
364     fields[i].Encode(strm);
365 }
366 
367 ///////////////////////////////////////////////////////////////////////
368 
SequencePreambleDecode(PASN_Sequence & seq)369 PBoolean PBER_Stream::SequencePreambleDecode(PASN_Sequence & seq)
370 {
371   return seq.PreambleDecodeBER(*this);
372 }
373 
374 
SequencePreambleEncode(const PASN_Sequence & seq)375 void PBER_Stream::SequencePreambleEncode(const PASN_Sequence & seq)
376 {
377   seq.PreambleEncodeBER(*this);
378 }
379 
380 
SequenceKnownDecode(PASN_Sequence & seq,PINDEX fld,PASN_Object & field)381 PBoolean PBER_Stream::SequenceKnownDecode(PASN_Sequence & seq, PINDEX fld, PASN_Object & field)
382 {
383   return seq.KnownExtensionDecodeBER(*this, fld, field);
384 }
385 
386 
SequenceKnownEncode(const PASN_Sequence & seq,PINDEX fld,const PASN_Object & field)387 void PBER_Stream::SequenceKnownEncode(const PASN_Sequence & seq, PINDEX fld, const PASN_Object & field)
388 {
389   seq.KnownExtensionEncodeBER(*this, fld, field);
390 }
391 
392 
SequenceUnknownDecode(PASN_Sequence & seq)393 PBoolean PBER_Stream::SequenceUnknownDecode(PASN_Sequence & seq)
394 {
395   return seq.UnknownExtensionsDecodeBER(*this);
396 }
397 
398 
SequenceUnknownEncode(const PASN_Sequence & seq)399 void PBER_Stream::SequenceUnknownEncode(const PASN_Sequence & seq)
400 {
401   seq.UnknownExtensionsEncodeBER(*this);
402 }
403 
404 ///////////////////////////////////////////////////////////////////////
405 
ArrayDecode(PASN_Array & array)406 PBoolean PBER_Stream::ArrayDecode(PASN_Array & array)
407 {
408   array.RemoveAll();
409 
410   unsigned len;
411   if (!HeaderDecode(array, len))
412     return PFalse;
413 
414   PINDEX endOffset = byteOffset + len;
415   PINDEX count = 0;
416   while (byteOffset < endOffset) {
417     if (!array.SetSize(count+1))
418       return PFalse;
419     if (!array[count].Decode(*this))
420       return PFalse;
421     count++;
422   }
423 
424   byteOffset = endOffset;
425 
426   return PTrue;
427 }
428 
429 
ArrayEncode(const PASN_Array & array)430 void PBER_Stream::ArrayEncode(const PASN_Array & array)
431 {
432   HeaderEncode(array);
433   for (PINDEX i = 0; i < array.GetSize(); i++)
434     array[i].Encode(*this);
435 }
436 
437 ///////////////////////////////////////////////////////////////////////
438 
PBER_Stream()439 PBER_Stream::PBER_Stream()
440 {
441 }
442 
443 
PBER_Stream(const PBYTEArray & bytes)444 PBER_Stream::PBER_Stream(const PBYTEArray & bytes)
445   : PASN_Stream(bytes)
446 {
447 }
448 
449 
PBER_Stream(const BYTE * buf,PINDEX size)450 PBER_Stream::PBER_Stream(const BYTE * buf, PINDEX size)
451   : PASN_Stream(buf, size)
452 {
453 }
454 
455 
operator =(const PBYTEArray & bytes)456 PBER_Stream & PBER_Stream::operator=(const PBYTEArray & bytes)
457 {
458   PBYTEArray::operator=(bytes);
459   ResetDecoder();
460   return *this;
461 }
462 
Read(PChannel & chan)463 PBoolean PBER_Stream::Read(PChannel & chan)
464 {
465   SetSize(0);
466   PINDEX offset = 0;
467 
468   // read the sequence header
469   int b;
470   if ((b = chan.ReadChar()) < 0)
471     return PFalse;
472 
473   SetAt(offset++, (char)b);
474 
475   // only support direct read of simple sequences
476   if ((b&0x1f) == 0x1f) {
477     do {
478       if ((b = chan.ReadChar()) < 0)
479         return PFalse;
480       SetAt(offset++, (char)b);
481     } while ((b & 0x80) != 0);
482   }
483 
484   // read the first byte of the ASN length
485   if ((b = chan.ReadChar()) < 0)
486     return PFalse;
487 
488   SetAt(offset++, (char)b);
489 
490   // determine how many bytes in the length
491   PINDEX dataLen = 0;
492   if ((b & 0x80) == 0)
493     dataLen = b;
494   else {
495     PINDEX lenLen = b&0x7f;
496     SetSize(lenLen+2);
497     while (lenLen-- > 0) {
498       // read the length
499       if ((b = chan.ReadChar()) < 0)
500         return PFalse;
501       dataLen = (dataLen << 8) | b;
502       SetAt(offset++, (char)b);
503     }
504   }
505 
506   // read the data, all of it
507   BYTE * bufptr = GetPointer(dataLen+offset) + offset;
508   while (dataLen > 0) {
509     if (!chan.Read(bufptr, dataLen))
510       return PFalse;
511     PINDEX readbytes = chan.GetLastReadCount();
512     bufptr += readbytes;
513     dataLen -= readbytes;
514   }
515   return PTrue;
516 }
517 
518 
Write(PChannel & chan)519 PBoolean PBER_Stream::Write(PChannel & chan)
520 {
521   CompleteEncoding();
522   return chan.Write(theArray, GetSize());
523 }
524 
525 
CreateObject(unsigned tag,PASN_Object::TagClass tagClass,PBoolean primitive) const526 PASN_Object * PBER_Stream::CreateObject(unsigned tag,
527                                         PASN_Object::TagClass tagClass,
528                                         PBoolean primitive) const
529 {
530   if (tagClass == PASN_Object::UniversalTagClass) {
531     switch (tag) {
532       case PASN_Object::UniversalBoolean :
533         return new PASN_Boolean();
534 
535       case PASN_Object::UniversalInteger :
536         return new PASN_Integer();
537 
538       case PASN_Object::UniversalBitString :
539         return new PASN_BitString();
540 
541       case PASN_Object::UniversalOctetString :
542         return new PASN_OctetString();
543 
544       case PASN_Object::UniversalNull :
545         return new PASN_Null();
546 
547       case PASN_Object::UniversalObjectId :
548         return new PASN_ObjectId();
549 
550       case PASN_Object::UniversalReal :
551         return new PASN_Real();
552 
553       case PASN_Object::UniversalEnumeration :
554         return new PASN_Enumeration();
555 
556       case PASN_Object::UniversalSequence :
557         return new PASN_Sequence();
558 
559       case PASN_Object::UniversalSet :
560         return new PASN_Set();
561 
562       case PASN_Object::UniversalNumericString :
563         return new PASN_NumericString();
564 
565       case PASN_Object::UniversalPrintableString :
566         return new PASN_PrintableString();
567 
568       case PASN_Object::UniversalIA5String :
569         return new PASN_IA5String();
570 
571       case PASN_Object::UniversalVisibleString :
572         return new PASN_VisibleString();
573 
574       case PASN_Object::UniversalGeneralString :
575         return new PASN_GeneralString();
576 
577       case PASN_Object::UniversalBMPString :
578         return new PASN_BMPString();
579     }
580   }
581 
582   if (primitive)
583     return new PASN_OctetString(tag, tagClass);
584   else
585     return new PASN_Sequence(tag, tagClass, 0, PFalse, 0);
586 }
587 
HeaderDecode(unsigned & tagVal,PASN_Object::TagClass & tagClass,PBoolean & primitive,unsigned & len)588 PBoolean PBER_Stream::HeaderDecode(unsigned & tagVal,
589                                PASN_Object::TagClass & tagClass,
590                                PBoolean & primitive,
591                                unsigned & len)
592 {
593   BYTE ident = ByteDecode();
594   tagClass = (PASN_Object::TagClass)(ident>>6);
595   primitive = (ident&0x20) == 0;
596   tagVal = ident&31;
597   if (tagVal == 31) {
598     BYTE b;
599     tagVal = 0;
600     do {
601       if (IsAtEnd())
602         return PFalse;
603 
604       b = ByteDecode();
605       tagVal = (tagVal << 7) | (b&0x7f);
606     } while ((b&0x80) != 0);
607   }
608 
609   if (IsAtEnd())
610     return PFalse;
611 
612   BYTE len_len = ByteDecode();
613   if ((len_len & 0x80) == 0) {
614     len = len_len;
615     return PTrue;
616   }
617 
618   len_len &= 0x7f;
619 
620   len = 0;
621   while (len_len-- > 0) {
622     if (IsAtEnd())
623       return PFalse;
624 
625     len = (len << 8) | ByteDecode();
626   }
627 
628   return PTrue;
629 }
630 
631 
HeaderDecode(PASN_Object & obj,unsigned & len)632 PBoolean PBER_Stream::HeaderDecode(PASN_Object & obj, unsigned & len)
633 {
634   PINDEX pos = byteOffset;
635 
636   unsigned tagVal;
637   PASN_Object::TagClass tagClass;
638   PBoolean primitive;
639   if (HeaderDecode(tagVal, tagClass, primitive, len) &&
640               tagVal == obj.GetTag() && tagClass == obj.GetTagClass())
641     return PTrue;
642 
643   byteOffset = pos;
644   return PFalse;
645 }
646 
647 
HeaderEncode(const PASN_Object & obj)648 void PBER_Stream::HeaderEncode(const PASN_Object & obj)
649 {
650   BYTE ident = (BYTE)(obj.GetTagClass() << 6);
651   if (!obj.IsPrimitive())
652     ident |= 0x20;
653   unsigned tag = obj.GetTag();
654   if (tag < 31)
655     ByteEncode(ident|tag);
656   else {
657     ByteEncode(ident|31);
658     unsigned count = (CountBits(tag)+6)/7;
659     while (count-- > 1)
660       ByteEncode((tag >> (count*7))&0x7f);
661     ByteEncode(tag&0x7f);
662   }
663 
664   PINDEX len = obj.GetDataLength();
665   if (len < 128)
666     ByteEncode(len);
667   else {
668     PINDEX count = (CountBits(len+1)+7)/8;
669     ByteEncode(count|0x80);
670     while (count-- > 0)
671       ByteEncode(len >> (count*8));
672   }
673 }
674 
675 ///////////////////////////////////////////////////////////////////////
676