• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 // ----------------------------------------------------------------------
19 //
20 // This Software is an original work of authorship of PacketVideo Corporation.
21 // Portions of the Software were developed in collaboration with NTT  DoCoMo,
22 // Inc. or were derived from the public domain or materials licensed from
23 // third parties.  Title and ownership, including all intellectual property
24 // rights in and to the Software shall remain with PacketVideo Corporation
25 // and NTT DoCoMo, Inc.
26 //
27 // -----------------------------------------------------------------------
28 // ============================================================
29 // FILE: GenericPER.c
30 //
31 // DESCRIPTION: Generic PER encode/decode routines.  These are
32 //   called by the automatically generated MiniParser code.
33 //
34 // Written by Ralph Neff, PacketVideo, 2/8/2000
35 // (c) 2000 PacketVideo Corp.
36 // ============================================================
37 
38 #include "per_headers.h"
39 #include "analyzeper.h"
40 #include "genericper.h"
41 #include "oscl_error_codes.h"
42 #include "oscl_mem.h"
43 #include "oscl_stdstring.h"
44 #include "pvlogger.h"
45 
46 #define STREAM_ADDITION 64      /* Output stream grows in increments */
47 /*   of this many bytes.             */
48 
49 const uint8 MaskBit[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
50 
51 /***********************************************************/
52 /*=========================================================*/
53 /*============ DECODING ROUTINES (Generic PER) ============*/
54 /*=========================================================*/
55 /***********************************************************/
56 
57 /* --------------------------------------------- */
58 /* ------------- LOW LEVEL STREAM -------------- */
59 /* --------------------------------------------- */
60 
61 // =========================================================
62 // ErrorMessage()
63 //
64 // This function is a generic error call for PER routines.
65 //
66 // NOTE: Removed the MessageBox called and replaced with a
67 //   call to the analyzer via Show245().  Since tag informaion
68 //   isn't easy to get (encoder/decoder autogen routines don't
69 //   provide tags, and deleter autogen routines don't even have
70 //   a tag defined!), we will fix to the "PER Decoder" tag for
71 //   now.  The proper thing to do would be to use a newly
72 //   defined "PER Error" tag.  But it's not so important to
73 //   do this, since the source of the error is always defined
74 //   in the message itself.  (RAN-MessageBox)  10/5/01
75 // =========================================================
ErrorMessage(const char * msg)76 void ErrorMessage(const char *msg)
77 {
78     OSCL_UNUSED_ARG(msg);
79 
80     PVLogger *logger = PVLogger::GetLoggerObject("3g324m.h245.per");
81     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, logger, PVLOGMSG_ERR, (0, "GenericPer::ErrorMessage - %s", msg));
82 }
83 
ErrorMessageAndLeave(const char * msg)84 void ErrorMessageAndLeave(const char *msg)
85 {
86     ErrorMessage(msg);
87     PVLogger *logger = PVLogger::GetLoggerObject("3g324m.h245.per");
88     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, logger, PVLOGMSG_ERR, (0, "GenericPer::ErrorMessageAndLeave - LEAVE"));
89     OSCL_LEAVE(OsclErrCorrupt);
90 }
91 
92 // =========================================================
93 // ReadBits()
94 //
95 // This function reads some number of bits from the
96 // input stream.
97 // =========================================================
ReadBits(uint32 number,PS_InStream stream)98 uint8 ReadBits(uint32 number, PS_InStream stream)
99 {
100     uint8 x;
101     uint8 NextBit, BitSize;
102 
103     if (number > 8)
104     {
105         ErrorMessageAndLeave("ReadBits(): Max number (8) exceeded");
106     }
107 
108     BitSize = (uint8)(stream->bitIndex + number);
109     x = (uint8)(stream->data[0] & MaskBit[(int)stream->bitIndex ]);
110     if (BitSize > 8)
111     {
112         NextBit = (uint8)(BitSize - 8);
113         x <<= NextBit;
114         ++stream->data;
115         x |= ((stream->data[0]) & ~MaskBit[(int)stream->bitIndex ]) >> (8 - NextBit);
116     }
117     else if (BitSize < 8)
118     {
119         NextBit = BitSize;
120         x >>= (8 - NextBit);
121     }
122     else
123     {
124         NextBit = 0;
125         ++stream->data;
126     }
127 
128     stream->bitIndex = NextBit;
129     return(x);
130 }
131 
132 // =========================================================
133 // ReadRemainingBits()
134 //
135 // This function advances to the next octet boundary in
136 // the input stream.  If the stream already points to
137 // an octet boundary, no action is taken.
138 // =========================================================
ReadRemainingBits(PS_InStream stream)139 void  ReadRemainingBits(PS_InStream stream)
140 {
141     if (stream->bitIndex)
142     {
143         stream->bitIndex = 0;
144         ++stream->data;
145     }
146 }
147 
148 // =========================================================
149 // ReadOctets()
150 //
151 // This function reads one or more octets from the input
152 // stream.  Input arguments are:
153 //   uint32 number;        /* Number of octets to read */
154 //   uint8* octets;      /* Destination for octets */
155 //   uint8 reorder;      /* Reorder for little-endian machine? */
156 //   PS_InStream stream; /* Input stream */
157 // =========================================================
ReadOctets(uint32 number,uint8 * octets,uint8 reorder,PS_InStream stream)158 void  ReadOctets(uint32 number, uint8* octets, uint8 reorder, PS_InStream stream)
159 {
160     ReadRemainingBits(stream);  /* Octet alignment */
161 
162     if (number == 0)   /* No action */
163     {
164         return;
165     }
166     else if (number <= 4 && reorder)   /* Apply reordering */
167     {
168         switch (number)
169         {
170             case 1:
171                 octets[0] = stream->data[0];
172                 break;
173             case 2:
174                 octets[0] = stream->data[1];
175                 octets[1] = stream->data[0];
176                 break;
177             case 3:
178                 octets[0] = stream->data[2];
179                 octets[1] = stream->data[1];
180                 octets[2] = stream->data[0];
181                 break;
182             case 4:
183                 octets[0] = stream->data[3];
184                 octets[1] = stream->data[2];
185                 octets[2] = stream->data[1];
186                 octets[3] = stream->data[0];
187                 break;
188         }
189     }
190     else
191     {
192         oscl_memcpy(octets, stream->data, number);  /* Straight copy */
193     }
194 
195     stream->data += number;
196 }
197 
198 
199 /* --------------------------------------------- */
200 /* ------------ HIGH LEVEL ASN DATA ------------ */
201 /* --------------------------------------------- */
202 
203 
204 // =========================================================
205 // GetBoolean()
206 //
207 // This function reads a boolean from the input stream.
208 // =========================================================
GetBoolean(PS_InStream stream)209 uint8 GetBoolean(PS_InStream stream)
210 {
211     return(ReadBits(1, stream));
212 }
213 
214 // =========================================================
215 // GetInteger()                           X.691 Section 10.5
216 //
217 // This function decodes a constrained integer, given the
218 // lower/upper bounds.  Note that bounds are uint32, which
219 // means min>=0, max<=4294967295.
220 // Assumes ALIGNED variant of PER.
221 // =========================================================
GetInteger(uint32 lower,uint32 upper,PS_InStream stream)222 uint32  GetInteger(uint32 lower, uint32 upper, PS_InStream stream)
223 {
224     uint32 value = 0, range;
225     uint8 nbits, nbytes = 0;
226 
227     if (lower > upper)
228     {
229         ErrorMessageAndLeave("GetInteger(): Range is negative.");
230         return(lower);
231     }
232     range = upper - lower + 1;
233 
234     if (range == 0)     /* Special case: int32EGER(0..4294967295) */
235     {
236         nbytes = (uint8)(ReadBits(2, stream) + 1);
237         ReadOctets(nbytes, (uint8*)&value, 1, stream);
238         return(value);
239     }
240     else if (range == 1)            /* 0-bits */
241         return(lower);
242     else if (range < 256)           /* Bit-field cases */
243     {
244         if (range <= 2) nbits = 1;
245         else if (range <= 4) nbits = 2;
246         else if (range <= 8) nbits = 3;
247         else if (range <= 16) nbits = 4;
248         else if (range <= 32) nbits = 5;
249         else if (range <= 64) nbits = 6;
250         else if (range <= 128) nbits = 7;
251         else nbits = 8;
252         value = ReadBits(nbits, stream);
253         if (lower + value > upper)
254         {
255             ErrorMessageAndLeave("GetInteger(): Integer exceeds range");
256         }
257         return(lower + value);
258     }
259     else                            /* One or more octets */
260     {
261         if (range == 256) nbytes = 1;
262         else if (range <= 65536) nbytes = 2;
263         else nbytes = (uint8)(ReadBits(2, stream) + 1);
264         ReadOctets(nbytes, (uint8*)&value, 1, stream);
265         if (lower + value > upper)
266         {
267             ErrorMessageAndLeave("GetInteger(): exceeds range");
268         }
269         return(lower + value);
270     }
271 }
272 
273 // =========================================================
274 // GetSignedInteger()                     X.691 Section 10.5
275 //
276 // This function decodes a constrained integer, given the
277 // lower/upper bounds.  The only difference from GetInteger()
278 // is that the bounds and returned values are int32, and
279 // so may be negative.
280 // Assumes ALIGNED variant of PER.
281 // =========================================================
GetSignedInteger(int32 lower,int32 upper,PS_InStream stream)282 int32   GetSignedInteger(int32 lower, int32 upper, PS_InStream stream)
283 {
284     int32 value = 0, range;
285     uint8 nbits, nbytes = 0;
286 
287     if (lower > upper)
288     {
289         ErrorMessageAndLeave("GetSignedInteger(): Range is negative.");
290         return(lower);
291     }
292     range = upper - lower + 1;
293 
294     if (range == 0)
295     {
296         ErrorMessageAndLeave("GetSignedInteger(): Range is zero.");
297         return(lower);
298     }
299     else if (range == 1)            /* 0-bits */
300         return(lower);
301     else if (range < 256)           /* Bit-field cases */
302     {
303         if (range <= 2) nbits = 1;
304         else if (range <= 4) nbits = 2;
305         else if (range <= 8) nbits = 3;
306         else if (range <= 16) nbits = 4;
307         else if (range <= 32) nbits = 5;
308         else if (range <= 64) nbits = 6;
309         else if (range <= 128) nbits = 7;
310         else nbits = 8;
311         value = ReadBits(nbits, stream);
312         if (lower + value > upper)
313         {
314             ErrorMessageAndLeave("GetSignedInteger(): Integer exceeds range");
315         }
316         return(lower + value);
317     }
318     else                            /* One or more octets */
319     {
320         if (range == 256) nbytes = 1;
321         else if (range <= 65536) nbytes = 2;
322         else nbytes = (uint8)(ReadBits(2, stream) + 1);
323         ReadOctets(nbytes, (uint8*)&value, 1, stream);
324         if (lower + value > upper)
325         {
326             ErrorMessageAndLeave("GetSignedInteger(): GetInteger exceeds range");
327         }
328         return(lower + value);
329     }
330 }
331 
332 // =========================================================
333 // GetUnboundedInteger()                   X.691 Section 12
334 //                                         and also 10.4, 10.9.
335 //
336 // This function decodes an unbounded integer.  The structure
337 // definition can only accomodate a uint32 return type, so if
338 // the decoded value is negative, we signal an error.
339 // Assumes ALIGNED variant of PER.
340 // =========================================================
GetUnboundedInteger(PS_InStream stream)341 uint32  GetUnboundedInteger(PS_InStream stream)
342 {
343     uint32 nbytes, value = 0;
344 
345     nbytes = GetLengthDet(stream);               // Length Det (10.9)
346     ReadOctets(nbytes, (uint8*)&value, 1, stream);  // Value (10.4)
347 
348     // Check for negative value
349     if ((nbytes == 1 && value >= 0x7f) ||
350             (nbytes == 2 && value >= 0x8000) ||
351             (nbytes == 3 && value >= 0x800000) ||
352             (nbytes == 4 && value >= 0x80000000))
353     {
354         ErrorMessageAndLeave("GetUnboundedInteger: Found a negative value!");
355     }
356 
357     return(value);
358 }
359 
360 // =========================================================
361 // GetExtendedInteger()                   X.691 Section 12.1
362 //
363 // This function decodes a constrained integer with an
364 // extended range.  We assume the value is unsigned, and
365 // that the ALIGNED variant of PER is used.
366 // =========================================================
GetExtendedInteger(uint32 lower,uint32 upper,PS_InStream stream)367 uint32  GetExtendedInteger(uint32 lower, uint32 upper, PS_InStream stream)
368 {
369     uint32 extension_bit, value;
370 
371     extension_bit = ReadBits(1, stream);
372     if (extension_bit)
373     {
374         value = GetUnboundedInteger(stream);
375     }
376     else
377     {
378         value = GetInteger(lower, upper, stream);
379     }
380 
381     return(value);
382 }
383 
384 // =========================================================
385 // GetOctetString()                      X.691 Section 16
386 //
387 // This function reads an OCTET STRING from the input stream.
388 // Bounds on the size, if any, are included in the input
389 // arguments.
390 // =========================================================
GetOctetString(uint8 unbounded,uint32 min,uint32 max,PS_OCTETSTRING x,PS_InStream stream)391 void GetOctetString(uint8 unbounded, uint32 min, uint32 max,
392                     PS_OCTETSTRING x, PS_InStream stream)
393 {
394     if (unbounded)         /* ====Size is unbounded==== */
395     {
396         x->size = (uint16) GetLengthDet(stream);
397         if (x->size)
398         {
399             x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8));
400             ReadOctets(x->size, x->data, 0, stream);
401         }
402         else
403         {
404             x->data = NULL;
405         }
406     }
407     else                   /* ====Size is bounded==== */
408     {
409 
410         if (min > max)            /* Error handling */
411         {
412             ErrorMessageAndLeave("GetOctetString(): Constraint error (min>max)");
413         }
414 
415         if (min == max)           /* Fixed size (no length det!) */
416         {
417             x->size = (uint16) min;
418             if (x->size)
419             {
420                 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8));
421                 if (x->size > 2)
422                 {
423                     ReadOctets(x->size, x->data, 0, stream);
424                 }
425                 else if (x->size == 2)
426                 {
427                     x->data[0] = ReadBits(8, stream);
428                     x->data[1] = ReadBits(8, stream);
429                 }
430                 else if (x->size == 1)
431                 {
432                     x->data[0] = ReadBits(8, stream);
433                 }
434             }
435             else
436             {
437                 x->data = NULL;
438             }
439         }
440         else                      /* Constrained size */
441         {
442             x->size = (uint16) GetInteger(min, max, stream);
443             if (x->size)
444             {
445                 x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8));
446                 ReadOctets(x->size, x->data, 0, stream);
447             }
448             else
449             {
450                 x->data = NULL;
451             }
452         }
453     }
454 }
455 
456 // =========================================================
457 // GetBitString()                      X.691 Section 16
458 //
459 // This function reads a BIT STRING from the input stream.
460 // Bounds on the size, if any, are included in the input
461 // arguments.  The BITSTRING structure (x) is returned.
462 // =========================================================
GetBitString(uint8 unbounded,uint32 min,uint32 max,PS_BITSTRING x,PS_InStream stream)463 void GetBitString(uint8 unbounded, uint32 min, uint32 max,
464                   PS_BITSTRING x, PS_InStream stream)
465 {
466     uint32 count;
467     uint8* temp;
468 
469     if (unbounded)         /* ====Size is unbounded==== */
470     {
471         count = GetLengthDet(stream);
472         x->size = (uint16) count;
473         temp = x->data = (uint8*) OSCL_DEFAULT_MALLOC((1 + x->size / 8) * sizeof(uint8));
474         while (count >= 8)
475         {
476             temp[0] = ReadBits(8, stream);
477             ++temp;
478             count -= 8;
479         }
480         temp[0] = (uint8)(ReadBits(count, stream) << (8 - count));
481     }
482     else                   /* ====Size is bounded==== */
483     {
484 
485         if (min > max)            /* Error handling */
486         {
487             ErrorMessageAndLeave("GetBitString(): Constraint error (min>max)");
488         }
489 
490         if (min == max)           /* Fixed size (no length det!) */
491         {
492             count = min;
493             x->size = (uint16) count;
494             temp = x->data = (uint8*) OSCL_DEFAULT_MALLOC((1 + x->size / 8) * sizeof(uint8));
495             if (x->size > 16)
496             {
497                 ReadRemainingBits(stream);  /* Octet align */
498             }
499             while (count >= 8)
500             {
501                 temp[0] = ReadBits(8, stream);
502                 ++temp;
503                 count -= 8;
504             }
505             temp[0] = (uint8)(ReadBits(count, stream) << (8 - count));
506         }
507         else                      /* Constrained size */
508         {
509             count = GetInteger(min, max, stream);
510             x->size = (uint16) count;
511             temp = x->data = (uint8*) OSCL_DEFAULT_MALLOC((1 + x->size / 8) * sizeof(uint8));
512             ReadRemainingBits(stream);
513             while (count >= 8)
514             {
515                 temp[0] = ReadBits(8, stream);
516                 ++temp;
517                 count -= 8;
518             }
519         }
520     }
521 }
522 
523 // =========================================================
524 // GetCharString()                             (RAN-UII)
525 //
526 // This function decodes a character string from a stream.
527 // Currently it only handles the special case of DTMF user
528 //   input (that is, signalType in UserInputIndication).
529 // However, it should be straightforward to extend this
530 //   to handle generic restrictions on the four common
531 //   types (IA5String, NumericString, PrintableString,
532 //   and VisibleString).  See X.691 Clause 26.5 for details.
533 // NOTE: For now I'm adding NULL string termination so that
534 //   the analyzer (ShowPERCharString() ) will correctly display
535 //   it on the decode side.  Should correct this at some point,
536 //   since x->data should really only contain characters that
537 //   were pulled from the input stream.
538 // =========================================================
GetCharString(const char * stringName,uint8 unbounded,uint32 min,uint32 max,const char * from,PS_int8STRING x,PS_InStream stream)539 void GetCharString(const char *stringName,
540                    uint8 unbounded, uint32 min, uint32 max, const char *from,
541                    PS_int8STRING x, PS_InStream stream)
542 {
543     if (oscl_strncmp(stringName, "IA5String", oscl_strlen("IA5String")) == 0 &&    // Validate DTMF UII case
544             unbounded == 0 &&
545             min == 1 &&
546             max == 1 &&
547             oscl_strncmp(from, "0123456789#*ABCD!", oscl_strlen("0123456789#*ABCD!")) == 0)
548     {
549         x->size = 2;
550         x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8));
551         x->data[0] = ReadBits(8, stream);     // Read single character,
552         // Normal ascii value, not octet aligned
553         x->data[1] = 0;  // NULL terminate
554     }
555     else if (oscl_strncmp(stringName, "GeneralString", oscl_strlen("GeneralString")) == 0)   // Validate GeneralString case  (RAN-ALPHA)
556     {
557         x->size = (uint16)(1 + GetLengthDet(stream)); // (leave extra space for NULL)
558         x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8));
559         ReadOctets(x->size - 1, x->data, 1, stream);
560         x->data[x->size-1] = 0;  // NULL terminate
561     }
562     else
563     {
564         x->size = 0;
565         x->data = NULL;
566         ErrorMessageAndLeave("GetCharString(): Not yet implemented.");
567     }
568 }
569 
570 // =========================================================
571 // GetObjectID()                        X.691 Section 23
572 //
573 // This function reads an OBJECT IDENTIFIER from the input
574 // stream.  This is just a length determinant, followed by
575 // a variable number of octets.
576 // =========================================================
GetObjectID(PS_OBJECTIDENT x,PS_InStream stream)577 void GetObjectID(PS_OBJECTIDENT x, PS_InStream stream)
578 {
579     x->size = (uint16) GetLengthDet(stream);
580     if (x->size)
581     {
582         x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8));
583         ReadOctets(x->size, x->data, 0, stream);
584     }
585     else
586     {
587         x->data = NULL;
588     }
589 }
590 
591 
592 /* --------------------------------------------- */
593 /* --------------- OTHER CALLS ------------------*/
594 /* --------------------------------------------- */
595 
596 // =========================================================
597 // GetLengthDet()                        X.691 Section 10.9
598 //
599 // Decodes a general length determinant from the input
600 // stream.  Assumes ALIGNED variant of PER.
601 // =========================================================
GetLengthDet(PS_InStream stream)602 uint32 GetLengthDet(PS_InStream stream)
603 {
604     uint32 length;
605     uint8 byte1, byte2;
606     uint8 mask1 = 0x80;   /* 10000000 */
607     uint8 mask2 = 0x40;   /* 01000000 */
608     uint8 mask3 = 0x3f;   /* 00111111 */
609 
610     ReadOctets(1, (uint8*)&byte1, 0, stream);  /* Get first byte */
611     if (!(byte1&mask1))       /* 0xxxxxxx ==>Single octet case */
612     {
613         length = (uint32) byte1;
614     }
615     else if (!(byte1&mask2))  /* 10xxxxxx ==>Dual octet case */
616     {
617         ReadOctets(1, (uint8*)&byte2, 0, stream); /* Second byte */
618         length = (((uint32)(byte1 & mask3)) << 8) + (int32)byte2;
619     }
620     else
621     {
622         ErrorMessageAndLeave("GetLengthDet(): Fragmented Length Dets Not Supported.");
623         return(0);
624     }
625     return(length);
626 }
627 
628 // =========================================================
629 // GetNormSmallLength()              X.691 Section 10.9.3.4
630 //
631 // Decodes a Normally Small length determinant from the
632 // input stream.  (In SEQUENCE, this gets the size of an
633 // unknown extensions map).
634 // Assumes ALIGNED variant of PER.
635 // =========================================================
GetNormSmallLength(PS_InStream stream)636 uint32 GetNormSmallLength(PS_InStream stream)
637 {
638     uint8 value = 0;
639     uint8 mask = 0x40;  /* 01000000 */
640 
641     value = ReadBits(7, stream);
642     if (value&mask)
643     {
644         ErrorMessageAndLeave("GetNormSmallLength(): Range exceeded.");
645         return(0);
646     }
647     return((uint32)value + 1); /* Valid range is 1...64 */
648 }
649 
650 // =========================================================
651 // GetNormSmallValue()                     X.691 Section 10.6
652 //
653 // Decodes a Normally Small Nonnegative Whole Number from
654 // the input stream.
655 // (In CHOICE, gets choice index when extension is ON.)
656 // Assumes ALIGNED variant of PER.
657 // =========================================================
GetNormSmallValue(PS_InStream stream)658 uint32 GetNormSmallValue(PS_InStream stream)
659 {
660     uint8 value = 0;
661     uint8 mask = 0x40;  /* 01000000 */
662 
663     value = ReadBits(7, stream);
664     if (value&mask)
665     {
666         ErrorMessageAndLeave("GetNormSmallValue(): range exceeded.");
667         return(0);
668     }
669     return((uint32)value);    /* Valid range is 0...63 */
670 }
671 
672 // =========================================================
673 // SkipOneExtension()                X.691 Section 18.9
674 //
675 // The general length is first read, and that number of
676 // octets are then skipped.
677 // (In SEQUENCE, this skips over a single unknown extension.
678 //  In CHOICE, this skips an item that has been chosen from
679 //  the extension, assuming the choice index has already
680 //  been read).
681 // Assumes aligned variant of PER.
682 // =========================================================
SkipOneExtension(PS_InStream stream)683 void SkipOneExtension(PS_InStream stream)
684 {
685     uint16 length;
686     uint8 buffer[32];
687 
688     length = (uint16) GetLengthDet(stream);
689     while (length > 32)      /* Pieces of at most 32 bytes */
690     {
691         ReadOctets(32, buffer, 0, stream);
692         length -= 32;
693     }
694     ReadOctets(length, buffer, 0, stream);  /* Leftovers */
695 }
696 
697 // =========================================================
698 // SkipAllExtensions()                X.691 Section 18.9
699 //
700 // For SEQUENCE, this skips over all unknown extensions.
701 // This includes reading the SigMap, including size.
702 // Call this routine at the location of the ext marker [...].
703 //
704 // NOTE: This routine may be obsolete.  Miniparser code
705 // instead uses a combination of GetUnknownSigMap() and
706 // SkipUnreadExtensions().
707 // =========================================================
SkipAllExtensions(PS_InStream stream)708 void SkipAllExtensions(PS_InStream stream)
709 {
710     uint32 size, i, num_to_skip = 0;
711 
712     size = GetNormSmallLength(stream);  /* Length of SigMap */
713     /* Read sigmap, counting number of significant extensions */
714     for (i = 0; i < size; ++i)
715     {
716         num_to_skip += ReadBits(1, stream);
717     }
718     for (i = 0; i < num_to_skip; ++i)
719     {
720         SkipOneExtension(stream);
721     }
722 }
723 
724 // =========================================================
725 // GetChoiceIndex()              X.691 Sections 22.4 - 22.8
726 //
727 // Reads the extension bit and choice index from the input
728 // stream, and constructs a (possibly extended) choice index.
729 // Assumes ALIGNED variant of PER.
730 // ---------------------------------------------------------
731 // Inputs: rootnum   (number of objects in root)
732 //         extmarker (0 if no extension marker, 1 otherwise)
733 // =========================================================
GetChoiceIndex(uint32 rootnum,uint8 extmarker,PS_InStream stream)734 uint16 GetChoiceIndex(uint32 rootnum, uint8 extmarker, PS_InStream stream)
735 {
736     uint8 extension;
737     uint16 index;
738 
739     extension = 0;
740     if (extmarker)          /* Get extension bit */
741     {
742         extension = ReadBits(1, stream);
743     }
744 
745     if (!extension)      /* ---Item in root--- */
746     {
747         if (rootnum == 1)     /* Trivial index */
748         {
749             return(0);
750         }
751         else                  /* Standard index */
752         {
753             index = (uint16) GetInteger(0, rootnum - 1, stream);
754         }               /* ---Item in extension--- */
755     }
756     else                    /* Extended index */
757     {
758         index = (uint16)(GetNormSmallValue(stream) + rootnum);
759     }
760 
761     return(index);
762 }
763 
764 // =========================================================
765 // GetUnknownSigMap()           X.691 Sections 18.7 - 18.8
766 //
767 // This function reads an unknown significance map from
768 // the input stream.  This includes the length of the
769 // significance map, and an options bit corresponding to
770 // each of the possible extension items.  The completed
771 // map is returned in a special structure.
772 // =========================================================
GetUnknownSigMap(PS_InStream stream)773 PS_UnknownSigMap GetUnknownSigMap(PS_InStream stream)
774 {
775     int32 i;
776     PS_UnknownSigMap x;
777 
778     x = (PS_UnknownSigMap) OSCL_DEFAULT_MALLOC(sizeof(S_UnknownSigMap));
779 
780     x->size = (uint16) GetNormSmallLength(stream);
781     x->optionFlags = (uint8*) OSCL_DEFAULT_MALLOC(x->size * sizeof(uint8));
782     for (i = 0; i < x->size; ++i)
783     {
784         x->optionFlags[i] = ReadBits(1, stream);
785     }
786     x->extensionsRead = 0;
787 
788     return(x);
789 }
790 
791 // =========================================================
792 // SigMapValue()
793 //
794 // This function reads a single options flag from an
795 // unknown significance map (UnknownSigMap).  If the
796 // index of the desired value exceeds the size of the
797 // map, the return value is zero.
798 // =========================================================
SigMapValue(uint32 index,PS_UnknownSigMap map)799 uint8 SigMapValue(uint32 index, PS_UnknownSigMap map)
800 {
801     if (index < map->size)
802     {
803         return(map->optionFlags[index]);
804     }
805     else
806     {
807         return(0);
808     }
809 }
810 
811 // =========================================================
812 // ExtensionPrep()
813 //
814 // This function is called immediately before reading each
815 // unknown extension item in a SEQUENCE.  It performs two
816 // actions:
817 //    1. Records within the unknown sigmap that another
818 //       extension is being read (++map->extensionsRead).
819 //       This is so SkipUnreadExtensions() later knows
820 //       how many extensions should be skipped.
821 //    2. Reads and discards the length wrapper from the
822 //       input stream.
823 // =========================================================
ExtensionPrep(PS_UnknownSigMap map,PS_InStream stream)824 void ExtensionPrep(PS_UnknownSigMap map, PS_InStream stream)
825 {
826     ++map->extensionsRead;
827     GetLengthDet(stream);
828 }
829 
830 // =========================================================
831 // SkipUnreadExtensions()
832 //
833 // This function skips any unread (and possibly unknown) items
834 // in the extension of a SEQUENCE.  In order for this to work,
835 // previously read extension items must have been counted in
836 // map->extensionsRead; see ExtensionPrep() for details.
837 //
838 // This routine takes the following actions:
839 //    1. Uses map->extensionsRead to determine how many
840 //       extension items remain in the input stream.
841 //    2. Skips remaining extension items.
842 //    3. Frees the UnknownSigMap.
843 //    4. Returns the number of extensions skipped.
844 // =========================================================
SkipUnreadExtensions(PS_UnknownSigMap map,PS_InStream stream)845 uint32 SkipUnreadExtensions(PS_UnknownSigMap map, PS_InStream stream)
846 {
847     uint32 i, numExtensions;
848 
849     /* Compute the number of extensions to skip */
850     numExtensions = 0;
851     for (i = 0; i < map->size; ++i)
852     {
853         numExtensions += map->optionFlags[i];
854     }
855     numExtensions -= map->extensionsRead;
856 
857     /* Skip remaining extensions */
858     for (i = 0; i < numExtensions; ++i)
859     {
860         SkipOneExtension(stream);
861     }
862 
863     /* Free map, return number skipped */
864     OSCL_DEFAULT_FREE(map->optionFlags);
865     OSCL_DEFAULT_FREE(map);
866 
867     return(numExtensions);
868 }
869 
870 // =========================================================
871 // SkipOneOctet()
872 //
873 // Skip a single octet.  This is used when a NULL is
874 // read from the extension of a CHOICE (since an empty
875 // octet is present)
876 // =========================================================
SkipOneOctet(PS_InStream stream)877 void SkipOneOctet(PS_InStream stream)
878 {
879     uint8 temp;
880 
881     ReadOctets(1, &temp, 0, stream);
882 }
883 
884 /***********************************************************/
885 /*=========================================================*/
886 /*============ ENCODING ROUTINES (Generic PER) ============*/
887 /*=========================================================*/
888 /***********************************************************/
889 
890 
891 /* --------------------------------------------- */
892 /* ------------- LOW LEVEL STREAM -------------- */
893 /* --------------------------------------------- */
894 
895 // =========================================================
896 // WriteBits()
897 //
898 // This function writes some number of bits to the
899 // output stream.
900 // =========================================================
WriteBits(uint32 number,uint8 bits,PS_OutStream stream)901 void WriteBits(uint32 number, uint8 bits, PS_OutStream stream)
902 {
903     uint8 BitSize;
904     uint8 temp;
905 
906     BitSize = (uint8)((stream->bitIndex) + number);
907     temp = (uint8)(bits << (8 - number));
908     (stream->buildByte) |= (temp >> (stream->bitIndex));
909 
910     if (BitSize > 8)                          /* Appended size > 8 bits */
911     {
912         stream->bitIndex = 8;
913         WriteRemainingBits(stream);
914         stream->buildByte = (uint8)((bits) << (16 - BitSize));
915         stream->bitIndex = (uint16)(BitSize - 8);
916         return;
917     }
918     else if (BitSize < 8)                 /* Appended size < 8 bits */
919     {
920         stream->bitIndex = BitSize;
921         return;
922     }
923     else                                     /* Appended size == 8 bits */
924     {
925         stream->bitIndex = 8;
926         WriteRemainingBits(stream);
927         return;
928     }
929 
930 }
931 
932 // =========================================================
933 // WriteRemainingBits()
934 //
935 // This function advances to the next octet boundary in
936 // the output stream.  Zero-bit padding is done, if needed.
937 // If the stream already points to an octet boundary, no
938 // action is taken.
939 // =========================================================
WriteRemainingBits(PS_OutStream stream)940 void WriteRemainingBits(PS_OutStream stream)
941 {
942     if (stream->bitIndex)
943     {
944         if (stream->byteIndex + 1 > stream->size)
945         {
946             ExpandOutStream(stream);
947         }
948         stream->data[stream->byteIndex] = stream->buildByte;
949         ++stream->byteIndex;
950         stream->bitIndex = 0;
951         stream->buildByte = 0;
952     }
953 }
954 
955 // =========================================================
956 // WriteOctets()
957 //
958 // This function writes one or more octets to the output
959 // stream.  Input arguments are:
960 //   uint32 number;         /* Number of octets to write */
961 //   uint8* octets;       /* Source for octets */
962 //   uint8 reorder;       /* Reorder for little-endian machine? */
963 //   PS_OutStream stream; /* Output stream */
964 // =========================================================
WriteOctets(uint32 number,uint8 * octets,uint8 reorder,PS_OutStream stream)965 void WriteOctets(uint32 number, uint8* octets, uint8 reorder, PS_OutStream stream)
966 {
967     uint8* destination;
968 
969     WriteRemainingBits(stream);  /* Octet alignment */
970 
971     /* Expand the stream, if needed */
972     while (stream->byteIndex + number > stream->size)
973     {
974         ExpandOutStream(stream);
975     }
976 
977     /* Write the octets to stream */
978     destination = stream->data + stream->byteIndex;
979     if (number == 0)   /* No action */
980     {
981         return;
982     }
983     else if (number <= 4 && reorder)   /* Apply reordering */
984     {
985         switch (number)
986         {
987             case 1:
988                 destination[0] = octets[0];
989                 break;
990             case 2:
991                 destination[0] = octets[1];
992                 destination[1] = octets[0];
993                 break;
994             case 3:
995                 destination[0] = octets[2];
996                 destination[1] = octets[1];
997                 destination[2] = octets[0];
998                 break;
999             case 4:
1000                 destination[0] = octets[3];
1001                 destination[1] = octets[2];
1002                 destination[2] = octets[1];
1003                 destination[3] = octets[0];
1004                 break;
1005         }
1006     }
1007     else
1008     {
1009         oscl_memcpy(destination, octets, number);  /* Straight copy */
1010     }
1011 
1012     stream->byteIndex = (uint16)(number + stream->byteIndex);
1013 }
1014 
1015 // =========================================================
1016 // NewOutStream()
1017 //
1018 // This function creates a new, empty output stream.
1019 // =========================================================
NewOutStream(void)1020 PS_OutStream NewOutStream(void)
1021 {
1022     PS_OutStream x;
1023 
1024     x = (PS_OutStream) OSCL_DEFAULT_MALLOC(sizeof(S_OutStream));
1025     x->data = NULL;
1026     x->size = 0;
1027     x->byteIndex = 0;
1028     x->bitIndex = 0;
1029     x->buildByte = 0;
1030 
1031     return(x);
1032 }
1033 
1034 // =========================================================
1035 // ExpandOutStream()
1036 //
1037 // This function expands an output stream by some number
1038 // of bytes, as defined by STREAM_ADDITION.
1039 // =========================================================
ExpandOutStream(PS_OutStream x)1040 void ExpandOutStream(PS_OutStream x)
1041 {
1042     uint8* tmp = x->data;
1043 
1044     x->data = (uint8*) OSCL_DEFAULT_MALLOC(x->size + STREAM_ADDITION);
1045     oscl_memcpy(x->data, tmp, x->size);
1046     if (tmp)
1047         OSCL_DEFAULT_FREE(tmp);
1048 
1049     x->size += STREAM_ADDITION;
1050 }
1051 
1052 // =========================================================
1053 // FreeOutStream()
1054 //
1055 // This function frees an existing output stream.
1056 // =========================================================
FreeOutStream(PS_OutStream x)1057 void FreeOutStream(PS_OutStream x)
1058 {
1059     OSCL_DEFAULT_FREE(x->data);
1060     OSCL_DEFAULT_FREE(x);
1061 }
1062 
1063 /* ----------------------------------------------- */
1064 /* ------------- HIGH LEVEL ASN DATA ------------- */
1065 /* ----------------------------------------------- */
1066 
1067 // =========================================================
1068 // PutBoolean()
1069 //
1070 // This function writes a boolean to the output stream.
1071 // =========================================================
PutBoolean(uint32 value,PS_OutStream stream)1072 void PutBoolean(uint32 value, PS_OutStream stream)
1073 {
1074     WriteBits(1, (uint8)value, stream);
1075 }
1076 
1077 // =========================================================
1078 // PutInteger()                           X.691 Section 10.5
1079 //
1080 // This function encodes a constrained integer, given the
1081 // lower/upper bounds.  Note that bounds and value must be
1082 // uint32.  This means 0<= {lower,upper,value} <=4294967295.
1083 // Assumes ALIGNED variant of PER.
1084 // =========================================================
PutInteger(uint32 lower,uint32 upper,uint32 value,PS_OutStream stream)1085 void PutInteger(uint32 lower, uint32 upper, uint32 value, PS_OutStream stream)
1086 {
1087     uint32 range, offset;
1088     uint8 nbits, nbytes = 0;
1089     uint8 code_nbytes;
1090 
1091     if (lower > upper)
1092     {
1093         ErrorMessageAndLeave("PutInteger(): Negative range.");
1094         return;
1095     }
1096     if (value < lower)
1097     {
1098         ErrorMessageAndLeave("PutInteger(): Value too small.");
1099         return;
1100     }
1101     if (value > upper)
1102     {
1103         ErrorMessageAndLeave("PutInteger(): Value too large.");
1104         return;
1105     }
1106 
1107     range = upper - lower + 1;
1108     offset = value - lower;
1109 
1110     if (range == 0 || range > 65536)     /* Range exceeds 2-octets */
1111     {
1112         /* (Range==0 means [0,2^32-1] case) */
1113         if (offset < 256) nbytes = 1; /* Send using minimum #octets */
1114         else if (offset < 65536) nbytes = 2;
1115         else if (offset < 16777216) nbytes = 3;
1116         else nbytes = 4;
1117         code_nbytes = (uint8)(nbytes - 1);
1118         WriteBits(2, code_nbytes, stream);              /* Send #octets */
1119         WriteOctets(nbytes, (uint8*)&offset, 1, stream);  /* Offset value */
1120         return;
1121     }
1122     else if (range == 1)            /* 0-bits */
1123         return;
1124     else if (range < 256)           /* Bit-field cases */
1125     {
1126         if (range <= 2) nbits = 1;
1127         else if (range <= 4) nbits = 2;
1128         else if (range <= 8) nbits = 3;
1129         else if (range <= 16) nbits = 4;
1130         else if (range <= 32) nbits = 5;
1131         else if (range <= 64) nbits = 6;
1132         else if (range <= 128) nbits = 7;
1133         else nbits = 8;
1134         WriteBits(nbits, (uint8)offset, stream);
1135         return;
1136     }
1137     else if (range == 256)          /* One octet */
1138     {
1139         WriteOctets(1, (uint8*)(&offset), 1, stream);
1140         return;
1141     }
1142     else                            /* range<=65536; Two octet */
1143     {
1144         WriteOctets(2, (uint8*)(&offset), 1, stream);
1145         return;
1146     }
1147 }
1148 
1149 // =========================================================
1150 // PutSignedInteger()                   X.691 Section 10.5
1151 //
1152 // This function encodes a constrained integer, given the
1153 // lower/upper bounds.  The only difference from
1154 // PutInteger() is that the bounds and the values are
1155 // of type int32, and so may be negative.
1156 // Assumes ALIGNED variant of PER.
1157 // =========================================================
PutSignedInteger(int32 lower,int32 upper,int32 value,PS_OutStream stream)1158 void PutSignedInteger(int32 lower, int32 upper, int32 value, PS_OutStream stream)
1159 {
1160     int32 range, offset;
1161     uint8 nbits, nbytes = 0;
1162     uint8 code_nbytes;
1163 
1164     if (lower > upper)
1165     {
1166         ErrorMessageAndLeave("PutSignedInteger(): Negative range.");
1167         return;
1168     }
1169     if (value < lower)
1170     {
1171         ErrorMessageAndLeave("PutSignedInteger(): Value too small.");
1172         return;
1173     }
1174     if (value > upper)
1175     {
1176         ErrorMessageAndLeave("PutSignedInteger(): Value too large.");
1177         return;
1178     }
1179 
1180     range = upper - lower + 1;
1181     offset = value - lower;
1182 
1183     if (range == 0 || range > 65536)     /* Range exceeds 2-octets */
1184     {
1185         /* (Range==0 means [0,2^32-1] case) */
1186         if (offset < 256) nbytes = 1; /* Send using minimum #octets */
1187         else if (offset < 65536) nbytes = 2;
1188         else if (offset < 16777216) nbytes = 3;
1189         else nbytes = 4;
1190         code_nbytes = (uint8)(nbytes - 1);
1191         WriteBits(2, code_nbytes, stream);              /* Send #octets */
1192         WriteOctets(nbytes, (uint8*)&offset, 1, stream);  /* Offset value */
1193         return;
1194     }
1195     else if (range == 1)            /* 0-bits */
1196         return;
1197     else if (range < 256)           /* Bit-field cases */
1198     {
1199         if (range <= 2) nbits = 1;
1200         else if (range <= 4) nbits = 2;
1201         else if (range <= 8) nbits = 3;
1202         else if (range <= 16) nbits = 4;
1203         else if (range <= 32) nbits = 5;
1204         else if (range <= 64) nbits = 6;
1205         else if (range <= 128) nbits = 7;
1206         else nbits = 8;
1207         WriteBits(nbits, (uint8)offset, stream);
1208         return;
1209     }
1210     else if (range == 256)          /* One octet */
1211     {
1212         WriteOctets(1, (uint8*)(&offset), 1, stream);
1213         return;
1214     }
1215     else                            /* range<=65536; Two octet */
1216     {
1217         WriteOctets(2, (uint8*)(&offset), 1, stream);
1218         return;
1219     }
1220 }
1221 
1222 // =========================================================
1223 // PutUnboundedInteger()                   X.691 Section 12
1224 //                                         and also 10.4, 10.9.
1225 //
1226 // This function encodes an unbounded integer, which we
1227 // currently assume has type uint32.  We'd need to make
1228 // special arrangements if negative values are allowed.
1229 // Assumes ALIGNED variant of PER.
1230 // =========================================================
PutUnboundedInteger(uint32 value,PS_OutStream stream)1231 void PutUnboundedInteger(uint32 value, PS_OutStream stream)
1232 {
1233     uint32 nbytes;
1234 
1235     /* The encoding is min-octets, and so depends on value */
1236     if (value < 128)
1237         nbytes = 1;
1238     else if (value < 32768)
1239         nbytes = 2;
1240     else if (value < 8388608)
1241         nbytes = 3;
1242     else
1243         nbytes = 4;
1244 
1245     /* Send length det, followed by 2's complement encoding */
1246     PutLengthDet(nbytes, stream);
1247     WriteOctets(nbytes, (uint8*)(&value), 1, stream);
1248 }
1249 
1250 // =========================================================
1251 // PutExtendedInteger()                   X.691 Section 12.1
1252 //
1253 // This function encodes a constrained integer with an
1254 // extended range.  We assume the value is unsigned, and
1255 // that the ALIGNED variant of PER is used.
1256 // =========================================================
PutExtendedInteger(uint32 lower,uint32 upper,uint32 value,PS_OutStream stream)1257 void PutExtendedInteger(uint32 lower, uint32 upper, uint32 value, PS_OutStream stream)
1258 {
1259     if (value > upper)              // Extension ON
1260     {
1261         WriteBits(1, 1, stream);
1262         PutUnboundedInteger(value, stream);
1263     }
1264     else                            // Extension OFF
1265     {
1266         WriteBits(1, 0, stream);
1267         PutInteger(lower, upper, value, stream);
1268     }
1269 }
1270 
1271 // =========================================================
1272 // PutOctetString()                      X.691 Section 16
1273 //
1274 // This function writes an OCTET STRING to the output stream.
1275 // Bounds on the size, if any, are included in the input
1276 // arguments.  The OCTETSTRING structure (x) is freed at
1277 // the end.
1278 // =========================================================
PutOctetString(uint8 unbounded,uint32 min,uint32 max,PS_OCTETSTRING x,PS_OutStream stream)1279 void PutOctetString(uint8 unbounded, uint32 min, uint32 max,
1280                     PS_OCTETSTRING x, PS_OutStream stream)
1281 {
1282     if (unbounded)         /* ====Size is unbounded==== */
1283     {
1284         PutLengthDet(x->size, stream);
1285         WriteOctets(x->size, x->data, 0, stream);
1286     }
1287     else                   /* ====Size is bounded==== */
1288     {
1289 
1290         if (min > max)            /* Error handling */
1291         {
1292             ErrorMessageAndLeave("PutOctetString(): Constraint error (min>max)");
1293         }
1294         else if ((x->size < min) || (x->size > max))
1295         {
1296             ErrorMessageAndLeave("PutOctetString(): Size out of bounds");
1297         }
1298 
1299         if (min == max)           /* Fixed size (no length det!) */
1300         {
1301             if (x->size > 2)
1302             {
1303                 WriteOctets(x->size, x->data, 0, stream);
1304             }
1305             else if (x->size == 2)
1306             {
1307                 WriteBits(8, x->data[0], stream);
1308                 WriteBits(8, x->data[1], stream);
1309             }
1310             else if (x->size == 1)
1311             {
1312                 WriteBits(8, x->data[0], stream);
1313             }
1314         }
1315         else                      /* Constrained size */
1316         {
1317             PutInteger(min, max, x->size, stream);
1318             WriteOctets(x->size, x->data, 0, stream);
1319         }
1320     }
1321 }
1322 
1323 // =========================================================
1324 // PutBitString()                      X.691 Section 16
1325 //
1326 // This function writes a BIT STRING to the output stream.
1327 // Bounds on the size, if any, are included in the input
1328 // arguments.  The BITSTRING structure (x) is freed at
1329 // the end.
1330 // =========================================================
PutBitString(uint8 unbounded,uint32 min,uint32 max,PS_BITSTRING x,PS_OutStream stream)1331 void PutBitString(uint8 unbounded, uint32 min, uint32 max,
1332                   PS_BITSTRING x, PS_OutStream stream)
1333 {
1334     uint32 count;
1335     uint8* temp;
1336 
1337     count = x->size;
1338     temp = x->data;
1339 
1340     if (unbounded)         /* ====Size is unbounded==== */
1341     {
1342         PutLengthDet(x->size, stream);
1343         while (count >= 8)
1344         {
1345             WriteBits(8, temp[0], stream);
1346             ++temp;
1347             count -= 8;
1348         }
1349         WriteBits(count, (uint8)(temp[0] >> (8 - count)), stream);
1350     }
1351     else                   /* ====Size is bounded==== */
1352     {
1353 
1354         if (min > max)            /* Error handling */
1355         {
1356             ErrorMessageAndLeave("PutBitString(): Constraint error (min>max)");
1357         }
1358         else if ((x->size < min) || (x->size > max))
1359         {
1360             ErrorMessageAndLeave("PutBitString(): Size out of bounds");
1361         }
1362 
1363         if (min == max)           /* Fixed size (no length det!) */
1364         {
1365             if (x->size > 16)
1366             {
1367                 WriteRemainingBits(stream);  /* Octet align */
1368             }
1369             while (count >= 8)
1370             {
1371                 WriteBits(8, temp[0], stream);
1372                 ++temp;
1373                 count -= 8;
1374             }
1375             WriteBits(count, (uint8)(temp[0] >> (8 - count)), stream);
1376         }
1377         else                      /* Constrained size */
1378         {
1379             PutInteger(min, max, x->size, stream);
1380             WriteRemainingBits(stream);
1381             while (count >= 8)
1382             {
1383                 WriteBits(8, temp[0], stream);
1384                 ++temp;
1385                 count -= 8;
1386             }
1387             WriteBits(count, (uint8)(temp[0] >> (8 - count)), stream);
1388         }
1389     }
1390 }
1391 
1392 // =========================================================
1393 // PutCharString()                             (RAN-UII)
1394 //
1395 // This function encodes a character string to a stream.
1396 // Currently it only handles the special case of DTMF user
1397 //   input (that is, signalType in UserInputIndication).
1398 // However, it should be straightforward to extend this
1399 //   to handle generic restrictions on the four common
1400 //   types (IA5String, NumericString, PrintableString,
1401 //   and VisibleString).  See X.691 Clause 26.5 for details.
1402 // =========================================================
PutCharString(const char * stringName,uint8 unbounded,uint32 min,uint32 max,const char * from,PS_int8STRING x,PS_OutStream stream)1403 void PutCharString(const char *stringName,
1404                    uint8 unbounded, uint32 min, uint32 max, const char *from,
1405                    PS_int8STRING x, PS_OutStream stream)
1406 {
1407     if (oscl_strncmp(stringName, "IA5String", oscl_strlen("IA5String")) == 0 &&    // Validate DTMF UII case
1408             unbounded == 0 &&
1409             min == 1 &&
1410             max == 1 &&
1411             oscl_strncmp(from, "0123456789#*ABCD!", oscl_strlen("0123456789#*ABCD!")) == 0)
1412     {
1413         WriteBits(8, x->data[0], stream);     // Write single character,
1414         // Normal ascii value, not octet aligned
1415     }
1416     else if (oscl_strncmp(stringName, "GeneralString", oscl_strlen("GeneralString")) == 0)   // Validate GeneralString case (RAN-ALPHA)
1417         // ------------------------------------------------------------------------
1418         // Note on GeneralString: as far as I can tell this is treated as a
1419         // restricted character string type which is not a known-multiplier character
1420         // string.  As such it falls under clause 26.6 of X.691.  In this case, any
1421         // constraints passed from the PER encoder are not considered 'PER-visible'
1422         // and so they are not used.  Because of this, the following should be a
1423         // complete implementation of GeneralString (regardless of constraints).
1424         // It should work for alphanumeric, and anything else that would use
1425         // GeneralString.
1426         // ------------------------------------------------------------------------
1427         // Note also: I assume you need to install the primary graphic character
1428         // set described in T.51, i.e. that there is no default character set.
1429         // Invoking a character set means sending an escape code.  Whether you NEED
1430         // this to get the primary character set wasn't made clear in T.51
1431         // itself, though I found a hint elsewhere that suggested you have to send
1432         // the escape code.  The escape code is 27 40 66 15 (or in T.51 lingo,
1433         // "ESC 2/8 4/2 0/15").  Sending this code shouldn't hurt anything if the
1434         // receiving end is compliant to T.51, but if it doesn't work on the first
1435         // try, then one thing you guys might try is removing the escape code, in
1436         // case maybe the VIG is choking on it.  Comment out the relevant four lines
1437         // below, and also get rid of the extra '4+' in the length calculation.
1438         // BTW, the escape sequence breaks down into:
1439         //   "Designate primary T.51 character set as G0" -- 27 40 66
1440         //   "Invoke G0 as the current character set" -- 15
1441         // ------------------------------------------------------------------------
1442     {
1443         // Encode length of string, in octets
1444         PutLengthDet((x->size), stream);  // Assumes 4-byte T.51 escape sequence
1445         // Remove the '4+' if the escape sequence is removed.
1446         // Note: PutLengthDet() does octet alignment for us
1447         // Send the T.51 encoded character data
1448         WriteOctets(x->size, x->data, 1, stream);
1449     }
1450     else
1451     {
1452         ErrorMessageAndLeave("PutCharString(): Not fully implemented.");
1453     }
1454 }
1455 
1456 // =========================================================
1457 // PutObjectID()                        X.691 Section 23
1458 //
1459 // This function writes an OBJECT IDENTIFIER to the output
1460 // stream.  This is just a length determinant, followed by
1461 // a variable number of octets.  The OBJECTID structure is
1462 // freed at the end.
1463 // =========================================================
PutObjectID(PS_OBJECTIDENT x,PS_OutStream stream)1464 void PutObjectID(PS_OBJECTIDENT x, PS_OutStream stream)
1465 {
1466     PutLengthDet(x->size, stream);
1467     WriteOctets(x->size, x->data, 0, stream);
1468 }
1469 
1470 // =========================================================
1471 // PutExtensionNull()
1472 //
1473 // This function encodes a NULL object as an extension.
1474 // =========================================================
PutExtensionNull(PS_OutStream stream)1475 void PutExtensionNull(PS_OutStream stream)
1476 {
1477     uint8 temp = 0;
1478 
1479     PutLengthDet(1, stream);        /* Length wrapper */
1480     WriteOctets(1, &temp, 0, stream);  /* Empty octet */
1481 }
1482 
1483 // =========================================================
1484 // PutExtensionBoolean()
1485 //
1486 // This function encodes a boolean as an extension.
1487 // =========================================================
PutExtensionBoolean(uint32 value,PS_OutStream stream)1488 void PutExtensionBoolean(uint32 value, PS_OutStream stream)
1489 {
1490     PutLengthDet(1, stream);        /* Length wrapper */
1491     PutBoolean(value, stream);      /* Boolean */
1492     WriteRemainingBits(stream);     /* Complete the octet */
1493 }
1494 
1495 // =========================================================
1496 // PutExtensionInteger()
1497 //
1498 // This function encodes an integer as an extension.
1499 // =========================================================
PutExtensionInteger(uint32 lower,uint32 upper,uint32 value,PS_OutStream stream)1500 void PutExtensionInteger(uint32 lower, uint32 upper, uint32 value, PS_OutStream stream)
1501 {
1502     PS_OutStream tempStream;
1503 
1504     tempStream = NewOutStream();              /* Create a temp stream */
1505     PutInteger(lower, upper, value, tempStream); /* Write integer to temp */
1506     PutTempStream(tempStream, stream); /* Transmit contents of tempStream */
1507 }
1508 
1509 // =========================================================
1510 // PutExtensionOctetString()
1511 //
1512 // This function encodes an octet string as an extension.
1513 // =========================================================
PutExtensionOctetString(uint8 unbounded,uint32 min,uint32 max,PS_OCTETSTRING x,PS_OutStream stream)1514 void PutExtensionOctetString(uint8 unbounded,
1515                              uint32 min, uint32 max, PS_OCTETSTRING x, PS_OutStream stream)
1516 {
1517     PS_OutStream tempStream;
1518 
1519     tempStream = NewOutStream();                  /* Create a temp stream */
1520     PutOctetString(unbounded, min, max, x, tempStream);  /* Write to temp */
1521     PutTempStream(tempStream, stream); /* Transmit contents of tempStream */
1522 }
1523 
1524 
1525 /* --------------------------------------------- */
1526 /* ---------------- OTHER CALLS -----------------*/
1527 /* --------------------------------------------- */
1528 
1529 // =========================================================
1530 // PutNormSmallValue()                  X.691 Section 10.6
1531 //
1532 // Sends a normally small nonnegative value.  Range is
1533 // [0,infinity].  (In CHOICE, this sends the choice index
1534 // when extension is ON).
1535 // Assumes ALIGNED variant of PER.
1536 // =========================================================
PutNormSmallValue(uint32 value,PS_OutStream stream)1537 void PutNormSmallValue(uint32 value, PS_OutStream stream)
1538 {
1539     uint8 sendval;
1540     if (value < 64)
1541     {
1542         sendval = (uint8) value;
1543         WriteBits(7, sendval, stream);
1544     }
1545     else
1546     {
1547         ErrorMessageAndLeave("PutNormSmallValue(): range exceeded.");
1548     }
1549 }
1550 
1551 // =========================================================
1552 // PutChoiceIndex()              X.691 Sections 22.4 - 22.8
1553 //
1554 // Writes the extension bit (if needed) and the choice index
1555 // to the bitstream.  Assumes ALIGNED variant of PER.
1556 //
1557 // Inputs: rootnum      (number of items in root)
1558 //         extmarker    (0 if no extension marker, 1 otherwise)
1559 //         index        (choice index, possibly extended)
1560 // =========================================================
PutChoiceIndex(uint32 rootnum,uint8 extmarker,uint32 index,PS_OutStream stream)1561 void PutChoiceIndex(uint32 rootnum, uint8 extmarker, uint32 index,
1562                     PS_OutStream stream)
1563 {
1564     if (!extmarker)    /* ---Extension marker NOT present --- */
1565     {
1566         PutInteger(0, rootnum - 1, (uint32)index, stream);
1567     }
1568     else               /* ---Extension marker present --- */
1569     {
1570         if (index < rootnum)
1571         {
1572             WriteBits(1, 0, stream); /* Extension bit OFF */
1573             PutInteger(0, rootnum - 1, (uint32)index, stream);
1574         }
1575         else
1576         {
1577             WriteBits(1, 1, stream); /* Extension bit ON */
1578             PutNormSmallValue((uint32)(index - rootnum), stream);
1579         }
1580     }
1581 }
1582 
1583 // =========================================================
1584 // PutNormSmallLength()              X.691 Section 10.9.3.4
1585 //
1586 // Sends a normally small length determinant.  Range is
1587 // [1,infinity].  (For SEQUENCE, this sends the size of
1588 // the SigMap for unknown extensions.)
1589 // Assumes ALIGNED variant of PER.
1590 // =========================================================
PutNormSmallLength(uint32 value,PS_OutStream stream)1591 void PutNormSmallLength(uint32 value, PS_OutStream stream)
1592 {
1593     uint8 sendval;
1594     if (value < 65)
1595     {
1596         sendval = (uint8)(value - 1);
1597         WriteBits(7, sendval, stream);
1598     }
1599     else
1600     {
1601         ErrorMessageAndLeave("PutNormSmallLength(): range exceeded.");
1602     }
1603 }
1604 
1605 // =========================================================
1606 // PutLengthDet()                        X.691 Section 10.9
1607 //
1608 // Encodes a general length determinant to the output stream.
1609 // (e.g. for extension wrapper).
1610 // Assumes ALIGNED variant of PER.
1611 // =========================================================
PutLengthDet(uint32 value,PS_OutStream stream)1612 void PutLengthDet(uint32 value, PS_OutStream stream)
1613 {
1614     uint8 byte;
1615     uint16 bytes;
1616     uint16 mask = 0x8000;   /* 10000000 00000000 */
1617 
1618     if (value < 128)       /* One octet with leading '0' */
1619     {
1620         byte = (uint8) value;
1621         WriteOctets(1, &byte, 0, stream);
1622     }
1623     else if (value < 16384)   /* Two octets with leading '10' */
1624     {
1625         bytes = (uint16)(value | mask);
1626         WriteOctets(2, (uint8*)&bytes, 0, stream);
1627     }
1628     else
1629     {
1630         ErrorMessageAndLeave("PutLengthDet(): Fragmented Length Dets Not Supported.");
1631     }
1632 }
1633 
1634 // =========================================================
1635 // PutExtensionItem()
1636 //
1637 // This function writes an extension item, including the
1638 // length wrapper.  It makes a generic call to one of the
1639 // H.245-defined PER Encoder routines.
1640 // =========================================================
PutExtensionItem(void (* Func)(uint8 * data,PS_OutStream stream),uint8 * x,PS_OutStream stream)1641 void PutExtensionItem(
1642     void (*Func)(uint8* data, PS_OutStream stream),
1643     uint8* x, PS_OutStream stream)
1644 {
1645     PS_OutStream tempStream;
1646 
1647     tempStream = NewOutStream();                  /* Create a temp stream */
1648     Func(x, tempStream);               /* Encode x, writing to tempStream */
1649     PutTempStream(tempStream, stream); /* Transmit contents of tempStream */
1650 }
1651 
1652 // =========================================================
1653 // PutTempStream()
1654 //
1655 // This function copies the contents of a temporary output
1656 // stream (tempStream) to the main output stream (stream),
1657 // preceeded by a generial length determinant.
1658 // It also frees tempStream at the end.
1659 // =========================================================
PutTempStream(PS_OutStream tempStream,PS_OutStream stream)1660 void PutTempStream(PS_OutStream tempStream, PS_OutStream stream)
1661 {
1662     WriteRemainingBits(tempStream);
1663     PutLengthDet(tempStream->byteIndex, stream); /* Copy to real stream */
1664     WriteOctets(tempStream->byteIndex, tempStream->data, 0, stream);
1665     FreeOutStream(tempStream);
1666 }
1667 
1668 /********************************************************/
1669 /*======================================================*/
1670 /*============ OTHER ROUTINES (Generic PER) ============*/
1671 /*======================================================*/
1672 /********************************************************/
1673 
1674 // =========================================================
1675 // ConvertOutstreamToInstream()
1676 //
1677 // This function creates a new InStream and copies into
1678 // it the contents of an old OutStream.  This is useful
1679 // for internal testing.
1680 // Note that the outstream is destroyed in the process.
1681 // =========================================================
ConvertOutstreamToInstream(PS_OutStream outstream)1682 PS_InStream ConvertOutstreamToInstream(PS_OutStream outstream)
1683 {
1684     PS_InStream instream;
1685 
1686     WriteRemainingBits(outstream);
1687     instream = (PS_InStream) OSCL_DEFAULT_MALLOC(sizeof(S_InStream));
1688     instream->data = outstream->data;
1689     instream->bitIndex = 0;
1690 
1691     OSCL_DEFAULT_FREE(outstream);
1692     return(instream);
1693 }
1694 
1695 // =========================================================
1696 // NewOctetString()
1697 //
1698 // This function creates a new OCTETSTRING.
1699 // For now, the data field just contains the string
1700 // "OctetString".
1701 // Later, I'll add input parameters and construct the
1702 // real thing.
1703 // THIS ROUTINE NEEDS ATTENTION!
1704 // =========================================================
NewOctetString(void)1705 PS_OCTETSTRING NewOctetString(void)
1706 {
1707     PS_OCTETSTRING x;
1708 
1709     x = (PS_OCTETSTRING) OSCL_DEFAULT_MALLOC(sizeof(S_OCTETSTRING));
1710     x->size = 12;
1711     x->data = (uint8*) OSCL_DEFAULT_MALLOC(12 * sizeof(uint8));
1712     oscl_strncpy((char *) x->data, "OctetString", x->size);
1713 
1714     return(x);
1715 }
1716 
1717 // =========================================================
1718 // NewBitString()
1719 //
1720 // This function creates a new BITSTRING.
1721 // For now, the data field just contains the string
1722 // "BitString".
1723 // Later, I'll add input parameters and construct the
1724 // real thing.
1725 // THIS ROUTINE NEEDS ATTENTION!
1726 // =========================================================
NewBitString(void)1727 PS_BITSTRING NewBitString(void)
1728 {
1729     PS_BITSTRING x;
1730 
1731     x = (PS_BITSTRING) OSCL_DEFAULT_MALLOC(sizeof(S_BITSTRING));
1732     x->size = 10;
1733     x->data = (uint8*) OSCL_DEFAULT_MALLOC(10 * sizeof(uint8));
1734     oscl_strncpy((char *) x->data, "BitString", x->size);
1735 
1736     return(x);
1737 }
1738 
1739 // =========================================================
1740 // NewCharString()
1741 //
1742 // This function creates a new int8STRING.
1743 // For now, the data field just contains the string
1744 // "CharString".
1745 // Later, I'll add input parameters and construct the
1746 // real thing.
1747 // THIS ROUTINE NEEDS ATTENTION!
1748 // =========================================================
NewCharString(void)1749 PS_int8STRING NewCharString(void)
1750 {
1751     PS_int8STRING x;
1752 
1753     x = (PS_int8STRING) OSCL_DEFAULT_MALLOC(sizeof(S_int8STRING));
1754     x->size = 11;
1755     x->data = (uint8*) OSCL_DEFAULT_MALLOC(11 * sizeof(uint8));
1756     oscl_strncpy((char *) x->data, "CharString", x->size);
1757 
1758     return(x);
1759 }
1760 
1761 // =========================================================
1762 // NewObjectID()
1763 //
1764 // This function creates a new OBJECTID.
1765 // For now, the ID just contains the string "Object ID".
1766 // Later, I'll add input parameters and construct the
1767 // real thing.
1768 // THIS ROUTINE NEEDS ATTENTION!
1769 // =========================================================
NewObjectID(void)1770 PS_OBJECTIDENT NewObjectID(void)
1771 {
1772     PS_OBJECTIDENT x;
1773 
1774     x = (PS_OBJECTIDENT) OSCL_DEFAULT_MALLOC(sizeof(S_OBJECTIDENT));
1775     x->size = 10;
1776     x->data = (uint8*) OSCL_DEFAULT_MALLOC(10 * sizeof(uint8));
1777     oscl_strncpy((char *) x->data, "Object ID", x->size);
1778 
1779     return(x);
1780 }
1781 
1782 // =========================================================
1783 // InitOctetString()
1784 //
1785 // This function inits a previously allocated OCTET STRING.
1786 // For now, the data field just contains the string
1787 // "OctetString".
1788 // Later, I'll add input parameters and construct the
1789 // real thing.
1790 // THIS ROUTINE NEEDS ATTENTION!
1791 // =========================================================
InitOctetString(PS_OCTETSTRING x)1792 void InitOctetString(PS_OCTETSTRING x)
1793 {
1794     x->size = 12;
1795     x->data = (uint8*) OSCL_DEFAULT_MALLOC(12 * sizeof(uint8));
1796     oscl_strncpy((char *) x->data, "OctetString", x->size);
1797 }
1798 
1799 // =========================================================
1800 // InitBitString()
1801 //
1802 // This function inits a previously allocated BIT STRING.
1803 // For now, the data field just contains the string
1804 // "BitString".
1805 // Later, I'll add input parameters and construct the
1806 // real thing.
1807 // THIS ROUTINE NEEDS ATTENTION!
1808 // =========================================================
InitBitString(PS_BITSTRING x)1809 void InitBitString(PS_BITSTRING x)
1810 {
1811     x->size = 10;
1812     x->data = (uint8*) OSCL_DEFAULT_MALLOC(10 * sizeof(uint8));
1813     oscl_strncpy((char *) x->data, "BitString", x->size);
1814 }
1815 
1816 // =========================================================
1817 // InitCharString()
1818 //
1819 // This function inits a previously allocated int8 STRING.
1820 // For now, the data field just contains the string
1821 // "CharString".
1822 // Later, I'll add input parameters and construct the
1823 // real thing.
1824 // THIS ROUTINE NEEDS ATTENTION!
1825 // =========================================================
InitCharString(PS_int8STRING x)1826 void InitCharString(PS_int8STRING x)
1827 {
1828     x->size = 11;
1829     x->data = (uint8*) OSCL_DEFAULT_MALLOC(11 * sizeof(uint8));
1830     oscl_strncpy((char *) x->data, "CharString", x->size);
1831 }
1832 
1833 // =========================================================
1834 // InitObjectid()
1835 //
1836 // This function inits a previously allocated OBJECT IDENTIFIER.
1837 // For now, the data field just contains the string
1838 // "ObjectID".
1839 // Later, I'll add input parameters and construct the
1840 // real thing.
1841 // THIS ROUTINE NEEDS ATTENTION!
1842 // =========================================================
InitObjectid(PS_OBJECTIDENT x)1843 void InitObjectid(PS_OBJECTIDENT x)
1844 {
1845     x->size = 9;
1846     x->data = (uint8*) OSCL_DEFAULT_MALLOC(9 * sizeof(uint8));
1847     oscl_strncpy((char *) x->data, "ObjectID", x->size);
1848 }
1849 
1850 // =========================================================
1851 // FreeOctetString()
1852 //
1853 // This frees an OCTET STRING.
1854 // =========================================================
FreeOctetString(PS_OCTETSTRING x)1855 void FreeOctetString(PS_OCTETSTRING x)
1856 {
1857     if (x->size > 0)
1858     {
1859         OSCL_DEFAULT_FREE(x->data);
1860     }
1861     OSCL_DEFAULT_FREE(x);
1862 }
1863 
1864 // =========================================================
1865 // FreeBitString()
1866 //
1867 // This frees a BIT STRING.
1868 // =========================================================
FreeBitString(PS_BITSTRING x)1869 void FreeBitString(PS_BITSTRING x)
1870 {
1871     OSCL_DEFAULT_FREE(x->data);
1872     OSCL_DEFAULT_FREE(x);
1873 }
1874 
1875 // =========================================================
1876 // FreeCharString()
1877 //
1878 // This frees a int8 STRING.
1879 // =========================================================
FreeCharString(PS_int8STRING x)1880 void FreeCharString(PS_int8STRING x)
1881 {
1882     if (x->data)
1883     {
1884         OSCL_DEFAULT_FREE(x->data);
1885     }
1886     OSCL_DEFAULT_FREE(x);
1887 }
1888 
1889 // =========================================================
1890 // FreeObjectID()
1891 //
1892 // This frees an OBJECT IDENTIFIER.
1893 // =========================================================
FreeObjectID(PS_OBJECTIDENT x)1894 void FreeObjectID(PS_OBJECTIDENT x)
1895 {
1896     if (x->data)
1897         OSCL_DEFAULT_FREE(x->data);
1898     OSCL_DEFAULT_FREE(x);
1899 }
1900 
1901 
1902