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