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