Use "local" instead of "system" header file inclusion.
[asterisk/asterisk.git] / addons / ooh323c / src / decode.c
1 /*
2  * Copyright (C) 1997-2005 by Objective Systems, Inc.
3  *
4  * This software is furnished under an open source license and may be 
5  * used and copied only in accordance with the terms of this license. 
6  * The text of the license may generally be found in the root 
7  * directory of this installation in the COPYING file.  It 
8  * can also be viewed online at the following URL:
9  *
10  *   http://www.obj-sys.com/open/license.html
11  *
12  * Any redistributions of this file including modified versions must 
13  * maintain this copyright notice.
14  *
15  *****************************************************************************/
16
17 #include "asterisk.h"
18 #include "asterisk/lock.h"
19
20 #include "ooasn1.h"
21
22 static int decode16BitConstrainedString 
23 (OOCTXT* pctxt, Asn116BitCharString* pString, Asn116BitCharSet* pCharSet);
24
25 static int decodeOctets 
26 (OOCTXT* pctxt, ASN1OCTET* pbuffer, ASN1UINT bufsiz, ASN1UINT nbits);
27
28 static int getComponentLength (OOCTXT* pctxt, ASN1UINT itemBits);
29
30 int decodeBits (OOCTXT* pctxt, ASN1UINT* pvalue, ASN1UINT nbits)
31
32    unsigned char mask;
33
34    if (nbits == 0) {
35       *pvalue = 0;
36       return ASN_OK;
37    }
38
39    /* If the number of bits is less than the current bit offset, mask   */
40    /* off the required number of bits and return..                      */
41
42    if (nbits < (unsigned)pctxt->buffer.bitOffset) {
43       /* Check if buffer contains number of bits requested */
44
45       if (pctxt->buffer.byteIndex >= pctxt->buffer.size)
46          return LOG_ASN1ERR (pctxt, ASN_E_ENDOFBUF);
47
48       pctxt->buffer.bitOffset -= nbits;
49
50       *pvalue = ((pctxt->buffer.data[pctxt->buffer.byteIndex]) >> 
51                  pctxt->buffer.bitOffset) & ((1 << nbits) - 1);
52
53       return ASN_OK;
54    }
55
56    /* Otherwise, we first need to mask off the remaining bits in the    */
57    /* current byte, followed by a loop to extract bits from full bytes, */
58    /* followed by logic to mask of remaining bits from the start of     */
59    /* of the last byte..                                                */
60
61    else {
62       /* Check if buffer contains number of bits requested */
63
64       int nbytes = (((nbits - pctxt->buffer.bitOffset) + 7) / 8);
65       
66       if ((pctxt->buffer.byteIndex + nbytes) >= pctxt->buffer.size) {
67          return LOG_ASN1ERR (pctxt, ASN_E_ENDOFBUF);
68       }
69
70       /* first read current byte remaining bits */
71       mask = ((1 << pctxt->buffer.bitOffset) - 1);
72
73       *pvalue = (pctxt->buffer.data[pctxt->buffer.byteIndex]) & mask;
74
75       nbits -= pctxt->buffer.bitOffset;
76       pctxt->buffer.bitOffset = 8;
77       pctxt->buffer.byteIndex++;
78
79       /* second read bytes from next byteIndex */
80       while (nbits >= 8) {
81          *pvalue = (*pvalue << 8) | 
82             (pctxt->buffer.data[pctxt->buffer.byteIndex]);
83          pctxt->buffer.byteIndex++;
84          nbits -= 8;
85       }
86
87       /* third read bits & set bitoffset of the byteIndex */
88       if (nbits > 0) {
89          pctxt->buffer.bitOffset = 8 - nbits;
90          *pvalue = (*pvalue << nbits) | 
91             ((pctxt->buffer.data[pctxt->buffer.byteIndex]) >> 
92              pctxt->buffer.bitOffset);
93       }
94
95       return ASN_OK;
96    }
97 }
98
99 int decodeBitString 
100 (OOCTXT* pctxt, ASN1UINT* numbits_p, ASN1OCTET* buffer, ASN1UINT bufsiz)
101 {
102    ASN1UINT bitcnt;
103    int lstat, octidx = 0, stat;
104    Asn1SizeCnst* pSizeList = pctxt->pSizeConstraint;
105    ASN1BOOL doAlign;
106
107    for (*numbits_p = 0;;) {
108       lstat = decodeLength (pctxt, &bitcnt);
109       if (lstat < 0) return LOG_ASN1ERR (pctxt, lstat);
110
111       if (bitcnt > 0) {
112          *numbits_p += bitcnt;
113
114          stat = bitAndOctetStringAlignmentTest 
115             (pSizeList, bitcnt, TRUE, &doAlign);
116          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
117
118          if (doAlign) {
119             stat = decodeByteAlign (pctxt);
120             if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
121          }
122
123          stat = decodeOctets (pctxt, &buffer[octidx], bufsiz - octidx, bitcnt);
124          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
125       }
126
127       if (lstat == ASN_OK_FRAG) {
128          octidx += (bitcnt / 8);
129       }
130       else break;
131    }
132
133    return ASN_OK;
134 }
135
136 int decodeBMPString 
137 (OOCTXT* pctxt, ASN1BMPString* pvalue, Asn116BitCharSet* permCharSet)
138 {
139    Asn116BitCharSet charSet;
140    int stat;
141
142    /* Set character set */
143
144    init16BitCharSet (&charSet, BMP_FIRST, BMP_LAST, BMP_ABITS, BMP_UBITS);
145
146    if (permCharSet) {
147       set16BitCharSet (pctxt, &charSet, permCharSet);
148    }
149
150    /* Decode constrained string */
151
152    stat = decode16BitConstrainedString (pctxt, pvalue, &charSet);
153    if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
154
155    return (stat);
156 }
157
158 int decodeByteAlign (OOCTXT* pctxt)
159 {
160    if (pctxt->buffer.bitOffset != 8) {
161       pctxt->buffer.byteIndex++;
162       pctxt->buffer.bitOffset = 8;
163    }
164    return ASN_OK;
165 }
166
167 int decodeConstrainedStringEx 
168 (OOCTXT* pctxt, const char** string, const char* charSet,
169  ASN1UINT abits, ASN1UINT ubits, ASN1UINT canSetBits)
170 {
171    int   stat;
172    char* tmpstr;
173
174    ASN1UINT i, idx, len, nbits = abits;
175
176    /* note: need to save size constraint for use in alignCharStr     */
177    /* because it will be cleared in decodeLength from the context..        */
178    Asn1SizeCnst* psize = pctxt->pSizeConstraint;
179
180    /* Decode length */
181
182    stat = decodeLength (pctxt, &len);
183    if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
184
185    /* Byte-align */
186
187    if (alignCharStr (pctxt, len, nbits, psize)) {
188       stat = decodeByteAlign (pctxt);
189       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
190    }
191
192    /* Decode data */
193
194    tmpstr = (char*) ASN1MALLOC (pctxt, len+1);
195    if (0 != tmpstr) {
196       if (nbits >= canSetBits && canSetBits > 4) {
197          for (i = 0; i < len; i++) {
198             if ((stat = decodeBits (pctxt, &idx, nbits)) == ASN_OK) {
199                tmpstr[i] = (char) idx;
200             }
201             else break;
202          }
203       }
204       else if (0 != charSet) {
205          ASN1UINT nchars = strlen (charSet);
206          for (i = 0; i < len; i++) {
207             if ((stat = decodeBits (pctxt, &idx, nbits)) == ASN_OK) {
208                if (idx < nchars) {
209                   tmpstr[i] = charSet[idx];
210                }
211                else return LOG_ASN1ERR (pctxt, ASN_E_CONSVIO);
212             }
213             else break;
214          }
215       }
216       else stat = ASN_E_INVPARAM;
217
218       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
219
220       tmpstr[i] = '\0';  /* add null-terminator */
221    }
222    else
223       return LOG_ASN1ERR (pctxt, ASN_E_NOMEM);
224
225    *string = tmpstr;
226
227    return ASN_OK;
228 }
229
230 int decodeConsInteger 
231 (OOCTXT* pctxt, ASN1INT* pvalue, ASN1INT lower, ASN1INT upper)
232
233    ASN1UINT range_value = upper - lower;
234    ASN1UINT adjusted_value;
235    int stat = ASN_OK;
236
237    if (range_value != ASN1UINT_MAX) { range_value += 1; }
238
239    if (lower > upper)
240       return ASN_E_RANGERR;
241    else if (lower != upper) {
242       stat = decodeConsWholeNumber (pctxt, &adjusted_value, range_value);
243       if (stat == ASN_OK) {
244          *pvalue = adjusted_value + lower;
245
246          if (*pvalue < lower || *pvalue > upper)
247             stat = ASN_E_CONSVIO;
248       }
249    }
250    else {
251       *pvalue = lower;
252    }
253
254    return stat;
255 }
256
257 int decodeConsUInt8 
258 (OOCTXT* pctxt, ASN1UINT8* pvalue, ASN1UINT lower, ASN1UINT upper)
259
260    ASN1UINT range_value, value;
261    ASN1UINT adjusted_value;
262    int stat = ASN_OK;
263
264    /* Check for special case: if lower is 0 and upper is ASN1UINT_MAX,  */
265    /* set range to ASN1UINT_MAX; otherwise to upper - lower + 1         */
266
267    range_value = (lower == 0 && upper == ASN1UINT_MAX) ?
268       ASN1UINT_MAX : upper - lower + 1;
269
270    if (lower != upper) {
271       ASN1UINT range_bitcnt = 0;
272
273       /* If range is <= 255, bit-field case (10.5.7a) */
274
275       if (range_value <= 255) {
276          range_bitcnt = getUIntBitCount (range_value - 1);
277       }
278
279       /* If range is exactly 256, one-octet case (10.5.7b) */
280
281       else if (range_value == 256) {
282          stat = decodeByteAlign (pctxt);
283          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
284
285          range_bitcnt = 8;
286       }
287       stat = decodeBits (pctxt, &adjusted_value, range_bitcnt);
288       if (stat == ASN_OK) {
289          value = adjusted_value + lower;
290
291          if (value < lower || value > upper)
292             stat = ASN_E_CONSVIO;
293
294          *pvalue = (ASN1OCTET)value;
295       }
296    }
297    else *pvalue = (ASN1OCTET)lower;
298
299    return stat;
300 }
301
302 int decodeConsUInt16 
303 (OOCTXT* pctxt, ASN1USINT* pvalue, ASN1UINT lower, ASN1UINT upper)
304
305    ASN1UINT range_value, value;
306    ASN1UINT adjusted_value;
307    int stat = ASN_OK;
308
309    /* Check for special case: if lower is 0 and upper is ASN1UINT_MAX,  */
310    /* set range to ASN1UINT_MAX; otherwise to upper - lower + 1         */
311
312    range_value = (lower == 0 && upper == ASN1UINT_MAX) ?
313       ASN1UINT_MAX : upper - lower + 1;
314
315    if (lower != upper) {
316       stat = decodeConsWholeNumber (pctxt, &adjusted_value, range_value);
317       if (stat == ASN_OK) {
318          value = adjusted_value + lower;
319
320          /* Verify value is within given range (ED, 1/15/2002) */
321          if (value < lower || value > upper)
322             stat = ASN_E_CONSVIO;
323          *pvalue = (ASN1USINT) value;
324       }
325    }
326    else *pvalue = (ASN1USINT) lower;
327
328    return stat;
329 }
330
331 int decodeConsUnsigned 
332 (OOCTXT* pctxt, ASN1UINT* pvalue, ASN1UINT lower, ASN1UINT upper)
333
334    ASN1UINT range_value;
335    ASN1UINT adjusted_value;
336    int stat = ASN_OK;
337
338    /* Check for special case: if lower is 0 and upper is ASN1UINT_MAX,  */
339    /* set range to ASN1UINT_MAX; otherwise to upper - lower + 1         */
340
341    range_value = (lower == 0 && upper == ASN1UINT_MAX) ?
342       ASN1UINT_MAX : upper - lower + 1;
343
344    if (lower != upper) {
345       stat = decodeConsWholeNumber (pctxt, &adjusted_value, range_value);
346       if (stat == ASN_OK) {
347          *pvalue = adjusted_value + lower;
348          if (*pvalue < lower || *pvalue > upper)
349             stat = ASN_E_CONSVIO;
350       }
351    }
352    else *pvalue = lower;
353
354    return stat;
355 }
356
357 int decodeConsWholeNumber 
358 (OOCTXT* pctxt, ASN1UINT* padjusted_value, ASN1UINT range_value)
359
360    ASN1UINT nocts, range_bitcnt;
361    int stat;
362
363    /* If unaligned, decode non-negative binary integer in the minimum   */
364    /* number of bits necessary to represent the range (10.5.6)          */
365
366    if (!TRUE) {
367       range_bitcnt = getUIntBitCount (range_value - 1);
368    }
369
370    /* If aligned, encoding depended on range value (10.5.7) */
371
372    else {  /* aligned */
373
374       /* If range is <= 255, bit-field case (10.5.7a) */
375
376       if (range_value <= 255) {
377          range_bitcnt = getUIntBitCount (range_value - 1);
378       }
379
380       /* If range is exactly 256, one-octet case (10.5.7b) */
381
382       else if (range_value == 256) {
383          stat = decodeByteAlign (pctxt);
384          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
385
386          range_bitcnt = 8;
387       }
388
389       /* If range > 256 and <= 64k (65535), two-octet case (10.5.7c) */
390
391       else if (range_value <= 65536) {
392          stat = decodeByteAlign (pctxt);
393          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
394
395          range_bitcnt = 16;
396       }
397
398       /* If range > 64k, indefinite-length case (10.5.7d) */
399
400       else {
401          stat = decodeBits (pctxt, &nocts, 2);
402          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
403
404          stat = decodeByteAlign (pctxt);
405          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
406
407          range_bitcnt = (nocts + 1) * 8;
408       }
409    }
410
411    return decodeBits (pctxt, padjusted_value, range_bitcnt);
412 }
413
414 int decodeDynBitString (OOCTXT* pctxt, ASN1DynBitStr* pBitStr)
415 {
416    ASN1UINT nocts;
417    ASN1OCTET* ptmp;
418    int nbits, stat = ASN_OK;
419
420    /* If "fast copy" option is not set (ASN1FATSCOPY) or if constructed,
421     * copy the bit string value into a dynamic memory buffer;
422     * otherwise, store the pointer to the value in the decode 
423     * buffer in the data pointer argument. */
424    
425    if (pctxt->flags & ASN1FASTCOPY) {
426       /* check is it possible to do optimized decoding */
427
428       ASN1OCTET bit;
429       ASN1UINT byteIndex = pctxt->buffer.byteIndex;  /* save byte index */
430       ASN1USINT bitOffset = pctxt->buffer.bitOffset; /* save bit offset */
431
432       stat = decodeByteAlign (pctxt);
433       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
434
435       stat = DECODEBIT (pctxt, &bit); /* read first bit of length determinant */
436       if (bit == 1 && stat == ASN_OK) 
437          stat = DECODEBIT (pctxt, &bit); /* read second bit */
438
439       pctxt->buffer.byteIndex = byteIndex;  /* restore byte index */
440       pctxt->buffer.bitOffset = bitOffset;  /* restore bit offset */
441
442       /* if either first or second bit != 0 - not fragmented */
443
444       if (bit == 0 && stat == ASN_OK) { 
445          ASN1UINT bitcnt;
446          
447          stat = decodeLength (pctxt, &bitcnt);
448          if (stat != 0) return LOG_ASN1ERR (pctxt, stat);
449
450          pBitStr->numbits = bitcnt;
451          if (bitcnt > 0) {
452             pBitStr->data = ASN1BUFPTR (pctxt);
453
454             stat = moveBitCursor (pctxt, bitcnt);
455             if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
456          }
457          else 
458             pBitStr->data = 0;
459    
460          return stat;
461       }
462    }
463
464    nbits = getComponentLength (pctxt, 1);
465
466    if (nbits < 0) return LOG_ASN1ERR (pctxt, nbits);
467    else if (nbits == 0) {
468       pBitStr->numbits = 0;
469       ptmp = 0;
470    }
471
472    nocts = (nbits + 7) / 8;
473       
474    /* Allocate memory for the target string */
475
476    if (nocts > 0) {
477       ptmp = (ASN1OCTET*) ASN1MALLOC (pctxt, nocts);
478       if (0 == ptmp) return LOG_ASN1ERR (pctxt, ASN_E_NOMEM);
479       
480       /* Call static bit string decode function */
481
482       stat = decodeBitString (pctxt, &pBitStr->numbits, ptmp, nocts);
483    }
484    pBitStr->data = ptmp;
485
486    return stat;
487 }
488
489 int decodeDynOctetString (OOCTXT* pctxt, ASN1DynOctStr* pOctStr)
490 {
491    ASN1OCTET* ptmp;
492    int nocts, stat;
493
494    /* If "fast copy" option is not set (ASN1FASTCOPY) or if constructed,
495     * copy the octet string value into a dynamic memory buffer;
496     * otherwise, store the pointer to the value in the decode 
497     * buffer in the data pointer argument. */
498
499    if (pctxt->flags & ASN1FASTCOPY) {
500       /* check if it is possible to do optimized decoding */
501
502       ASN1OCTET bit;
503       ASN1UINT byteIndex = pctxt->buffer.byteIndex;  /* save byte index */
504       ASN1USINT bitOffset = pctxt->buffer.bitOffset; /* save bit offset */
505
506       stat = decodeByteAlign (pctxt);
507       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
508
509       stat = DECODEBIT (pctxt, &bit); /* read first bit of length determinant */
510       if (bit == 1 && stat == ASN_OK) 
511          stat = DECODEBIT (pctxt, &bit); /* read second bit */
512
513       pctxt->buffer.byteIndex = byteIndex;  /* restore byte index */
514       pctxt->buffer.bitOffset = bitOffset;  /* restore bit offset */
515
516       /* if either first or second bit != 0 - not fragmented */
517
518       if (bit == 0 && stat == ASN_OK) { 
519          ASN1UINT octcnt;
520          
521          stat = decodeLength (pctxt, &octcnt);
522          if (stat != 0) return LOG_ASN1ERR (pctxt, stat);
523
524          pOctStr->numocts = octcnt;
525          if (octcnt > 0) {
526             pOctStr->data = ASN1BUFPTR (pctxt);
527
528             stat = moveBitCursor (pctxt, octcnt * 8);
529             if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
530          }
531          else 
532             pOctStr->data = 0;
533          
534          return stat;
535       }
536    }
537    
538    nocts = getComponentLength (pctxt, 8);
539
540    if (nocts < 0) return LOG_ASN1ERR (pctxt, nocts);
541    else if (nocts == 0) {
542       pOctStr->numocts = 0;
543       ptmp = 0;
544    }
545
546    /* Allocate memory for the target string */
547
548    else {
549       ptmp = (ASN1OCTET*) ASN1MALLOC (pctxt, nocts);
550       if (0 == ptmp) return LOG_ASN1ERR (pctxt, ASN_E_NOMEM);
551    }
552
553    /* Call static octet string decode function */
554
555    stat = decodeOctetString (pctxt, &pOctStr->numocts, ptmp, nocts);
556
557    pOctStr->data = ptmp;
558
559    return stat;
560 }
561
562 int decodeLength (OOCTXT* pctxt, ASN1UINT* pvalue)
563 {
564    Asn1SizeCnst* pSize;
565    ASN1UINT lower, upper;
566    ASN1BOOL bitValue, extbit;
567    int      stat;
568
569    /* If size constraint is present and extendable, decode extension    */
570    /* bit..                                                             */
571
572    if (isExtendableSize(pctxt->pSizeConstraint)) {
573       stat = DECODEBIT (pctxt, &extbit);
574       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
575    }
576    else extbit = 0;
577
578    /* Now use the value of the extension bit to select the proper       */
579    /* size constraint range specification..                             */
580
581    pSize = getSizeConstraint (pctxt, extbit);
582
583    lower = (pSize) ? pSize->lower : 0;
584    upper = (pSize) ? pSize->upper : ASN1UINT_MAX;
585
586    /* Reset the size constraint in the context block structure */
587
588    pctxt->pSizeConstraint = 0;
589
590    /* If upper limit is less than 64k, constrained case */
591
592    if (upper < 65536) {
593       if (lower == upper) {
594          *pvalue = 0;
595          stat = ASN_OK;
596       }
597       else
598          stat = decodeConsWholeNumber (pctxt, pvalue, (upper - lower + 1));
599
600       if (stat == ASN_OK) *pvalue += lower;
601    }
602    else {
603       /* unconstrained case OR constrained with upper bound >= 64K*/
604
605       stat = decodeByteAlign (pctxt);
606       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
607
608       stat = DECODEBIT (pctxt, &bitValue);
609       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
610
611       if (bitValue == 0) {
612          stat = decodeBits (pctxt, pvalue, 7);   /* 10.9.3.6 */
613          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
614       }
615       else {
616          stat = DECODEBIT (pctxt, &bitValue);
617          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
618
619          if (bitValue == 0) {
620             stat = decodeBits (pctxt, pvalue, 14);  /* 10.9.3.7 */
621             if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
622          }
623          else {
624             ASN1UINT multiplier;
625
626             stat = decodeBits (pctxt, &multiplier, 6);
627             if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
628
629             *pvalue = 16384 * multiplier;
630
631             stat = ASN_OK_FRAG;
632          }
633       }
634    }
635
636    return stat;
637 }
638
639 int decodeObjectIdentifier (OOCTXT* pctxt, ASN1OBJID* pvalue)
640 {
641    ASN1UINT  len;
642    int       stat, j;
643    unsigned  subid;
644    ASN1UINT  b;
645
646    /* Decode unconstrained length */
647
648    if ((stat = decodeLength (pctxt, &len)) < 0) {
649       return LOG_ASN1ERR (pctxt, stat);
650    }
651
652    /* Copy contents to a byte-aligned local buffer */
653
654    j = 0;
655    while (len > 0 && stat == ASN_OK) {
656       if (j < ASN_K_MAXSUBIDS) {
657
658          /* Parse a subidentifier out of the contents field */
659
660          pvalue->subid[j] = 0;
661          do {
662             if ((stat = decodeBits (pctxt, &b, 8)) == ASN_OK) {
663                pvalue->subid[j] = (pvalue->subid[j] * 128) + (b & 0x7F);
664                len--;
665             }
666          } while (b & 0x80 && stat == ASN_OK);
667
668          /* Handle the first subidentifier special case: the first two   */
669          /* sub-id's are encoded into one using the formula (x * 40) + y */
670
671          if (j == 0) {
672             subid = pvalue->subid[0];
673             pvalue->subid[0] = ((subid / 40) >= 2) ? 2 : subid / 40;
674             pvalue->subid[1] = (pvalue->subid[0] == 2) ? 
675                subid - 80 : subid % 40;
676             j = 2;
677          }
678          else j++;
679       }
680       else
681          stat = ASN_E_INVOBJID; 
682    }
683
684    pvalue->numids = j;
685    if (stat == ASN_OK && len != 0) stat = ASN_E_INVLEN;
686
687    return (stat);
688 }
689
690 static int decodeOctets 
691 (OOCTXT* pctxt, ASN1OCTET* pbuffer, ASN1UINT bufsiz, ASN1UINT nbits)
692
693    ASN1UINT nbytes = (nbits + 7) / 8 ;
694    ASN1UINT i = 0, j;
695    ASN1UINT rshift = pctxt->buffer.bitOffset;
696    ASN1UINT lshift = 8 - rshift;
697    ASN1UINT nbitsInLastOctet;
698    ASN1OCTET mask;
699    int stat;
700
701    /* Check to make sure buffer contains number of bits requested */
702
703    if ((pctxt->buffer.byteIndex + nbytes) > pctxt->buffer.size) {
704       return LOG_ASN1ERR (pctxt, ASN_E_ENDOFBUF);
705    }
706
707    /* Check to make sure buffer is big enough to hold requested         */
708    /* number of bits..                                                  */
709
710    if (nbytes > bufsiz) {
711       return LOG_ASN1ERR (pctxt, ASN_E_STROVFLW);
712    }
713
714    /* If on a byte boundary, can do a direct memcpy to target buffer */
715
716    if (pctxt->buffer.bitOffset == 8) {
717       memcpy (pbuffer, &pctxt->buffer.data[pctxt->buffer.byteIndex], nbytes);
718       stat = moveBitCursor (pctxt, nbits);
719       if (stat != ASN_OK) return stat;
720       i = nbytes - 1; nbits %= 8;
721    }
722    else {
723       while (nbits >= 8) {
724
725          /* Transfer lower bits from stream octet to upper bits of      */
726          /* target octet..                                              */
727
728          pbuffer[i] = pctxt->buffer.data[pctxt->buffer.byteIndex++]
729             << lshift;
730
731          /* Transfer upper bits from next stream octet to lower bits    */
732          /* target octet..                                              */
733
734          pbuffer[i++] |= pctxt->buffer.data[pctxt->buffer.byteIndex]
735             >> rshift;
736
737          nbits -= 8;
738       }
739
740       /* Copy last partial byte */
741
742       if (nbits >= rshift) {
743          pbuffer[i] = 
744             pctxt->buffer.data[pctxt->buffer.byteIndex++] << lshift;
745
746          nbitsInLastOctet = nbits - rshift;
747
748          if (nbitsInLastOctet > 0) {
749             pbuffer[i] |= 
750                pctxt->buffer.data[pctxt->buffer.byteIndex] >> rshift;
751          }
752
753          pctxt->buffer.bitOffset = 8 - nbitsInLastOctet;
754       }
755       else if (nbits > 0) {  /* nbits < rshift */
756          pbuffer[i] = 
757             pctxt->buffer.data[pctxt->buffer.byteIndex] << lshift;
758          pctxt->buffer.bitOffset = rshift - nbits;
759       }
760    }
761
762    /* Mask unused bits off of last byte */
763
764    if (nbits > 0) {
765       mask = 0;
766       for (j = 0; j < nbits; j++) {
767          mask >>= 1;
768          mask |= 0x80;
769       }
770       pbuffer[i] &= mask;
771    }
772
773    return ASN_OK;
774 }
775
776 int decodeOctetString 
777 (OOCTXT* pctxt, ASN1UINT* numocts_p, ASN1OCTET* buffer, ASN1UINT bufsiz)
778 {
779    ASN1UINT octcnt;
780    int lstat, octidx = 0, stat;
781    Asn1SizeCnst* pSizeList = pctxt->pSizeConstraint;
782
783    for (*numocts_p = 0;;) {
784       lstat = decodeLength (pctxt, &octcnt);
785       if (lstat < 0) return LOG_ASN1ERR (pctxt, lstat);
786
787       if (octcnt > 0) {
788          *numocts_p += octcnt;
789
790          if (TRUE) {
791             ASN1BOOL doAlign;
792
793             stat = bitAndOctetStringAlignmentTest 
794                (pSizeList, octcnt, FALSE, &doAlign);
795             if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
796
797             if (doAlign) {
798                stat = decodeByteAlign (pctxt);
799                if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
800             }
801          }
802
803          stat = decodeOctets (pctxt, &buffer[octidx], 
804                            bufsiz - octidx, (octcnt * 8));
805
806          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
807       }
808
809       if (lstat == ASN_OK_FRAG) {
810          octidx += octcnt;
811       }
812       else break;
813    }
814
815    return ASN_OK;
816 }
817
818 int decodeOpenType 
819 (OOCTXT* pctxt, const ASN1OCTET** object_p2, ASN1UINT* numocts_p)
820 {
821    ASN1DynOctStr octStr;
822    int stat;
823
824    stat = decodeDynOctetString (pctxt, &octStr);
825    if (stat == ASN_OK) {
826       *numocts_p = octStr.numocts;
827       *object_p2 = octStr.data;
828    }
829
830    return stat;
831 }
832
833 int decodeSemiConsInteger (OOCTXT* pctxt, ASN1INT* pvalue, ASN1INT lower)
834 {
835    signed char b;
836    unsigned char ub;
837    ASN1UINT nbytes;
838    int stat;
839
840    stat = decodeLength (pctxt, &nbytes);
841    if (stat < 0) return LOG_ASN1ERR (pctxt, stat);
842
843    if (nbytes > 0) {
844
845       /* Align buffer */
846
847       stat = decodeByteAlign (pctxt);
848       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
849
850       /* Decode first byte into a signed byte value and assign to integer. */
851       /* This should handle sign extension..                               */
852
853       stat = decodeOctets (pctxt, (ASN1OCTET*)&b, 1, 8);
854       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
855
856       *pvalue = b;
857       nbytes--;
858
859       /* Decode remaining bytes and add to result */
860
861       while (nbytes > 0) {
862          stat = decodeOctets (pctxt, (ASN1OCTET*)&ub, 1, 8);
863          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
864
865          *pvalue = (*pvalue * 256) + ub;
866          nbytes--;
867       }
868    }
869    else {  /* nbytes == 0 */
870       *pvalue = 0;
871    }
872    if (lower > ASN1INT_MIN)
873       *pvalue += lower;
874
875    return ASN_OK;
876 }
877
878 int decodeSemiConsUnsigned (OOCTXT* pctxt, ASN1UINT* pvalue, ASN1UINT lower)
879 {
880    ASN1UINT nbytes;
881    int stat;
882
883    stat = decodeLength (pctxt, &nbytes);
884    if (stat < 0) return LOG_ASN1ERR (pctxt, stat);
885
886    
887    if (nbytes > 0) {
888       stat = decodeByteAlign (pctxt);
889       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
890
891       stat = decodeBits (pctxt, pvalue, nbytes * 8);
892    }
893    else
894       *pvalue = 0;
895    *pvalue += lower;
896
897    return stat;
898 }
899
900 int decodeSmallNonNegWholeNumber (OOCTXT* pctxt, ASN1UINT* pvalue)
901
902    ASN1BOOL bitValue;
903    ASN1UINT len;
904    int ret;
905
906    if ((ret = DECODEBIT (pctxt, &bitValue)) != ASN_OK)
907       return ret;
908
909    if (bitValue == 0) {
910       return decodeBits (pctxt, pvalue, 6);   /* 10.6.1 */
911    }
912    else {
913       if ((ret = decodeLength (pctxt, &len)) < 0)
914          return ret;
915
916       if ((ret = decodeByteAlign (pctxt)) != ASN_OK)
917          return ret;
918
919       return decodeBits (pctxt, pvalue, len*8);
920    }
921 }
922
923 int decodeVarWidthCharString (OOCTXT* pctxt, const char** pvalue)
924 {
925    int        stat;
926    ASN1OCTET* tmpstr;
927    ASN1UINT   len;
928
929    /* note: need to save size constraint for use in alignCharStr     */
930    /* because it will be cleared in decodeLength from the context..        */
931    Asn1SizeCnst* psize = pctxt->pSizeConstraint;
932
933    /* Decode length */
934
935    stat = decodeLength (pctxt, &len);
936    if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
937
938    /* Byte-align */
939
940    if (alignCharStr (pctxt, len, 8, psize)) {
941       stat = decodeByteAlign (pctxt);
942       if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
943    }
944
945    /* Decode data */
946
947    tmpstr = (ASN1OCTET*) ASN1MALLOC (pctxt, len + 1);
948    if (0 != tmpstr) {
949       if ((stat = decodeOctets (pctxt, tmpstr, len, len * 8)) != ASN_OK)
950          return LOG_ASN1ERR (pctxt, stat);
951
952       tmpstr[len] = '\0';  /* add null-terminator */
953    }
954    else
955       return LOG_ASN1ERR (pctxt, ASN_E_NOMEM);
956
957    *pvalue = (char*)tmpstr;
958
959    return ASN_OK;
960 }
961
962 static int decode16BitConstrainedString 
963 (OOCTXT* pctxt, Asn116BitCharString* pString, Asn116BitCharSet* pCharSet)
964 {
965    ASN1UINT i, idx, nbits = pCharSet->alignedBits;
966    int stat;
967
968    /* Decode length */
969
970    stat = decodeLength (pctxt, &pString->nchars);
971    if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
972
973    /* Byte-align */
974
975    stat = decodeByteAlign (pctxt);
976    if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
977
978    /* Decode data */
979
980    pString->data = (ASN116BITCHAR*)
981       ASN1MALLOC (pctxt, pString->nchars*sizeof(ASN116BITCHAR));
982
983    if (pString->data) {
984       for (i = 0; i < pString->nchars; i++) {
985          stat = decodeBits (pctxt, &idx, nbits);
986          if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
987
988          pString->data[i] = (pCharSet->charSet.data == 0) ? 
989             idx + pCharSet->firstChar : pCharSet->charSet.data[idx];
990       }
991    }
992    else
993       return LOG_ASN1ERR (pctxt, ASN_E_NOMEM);
994
995    return ASN_OK;
996 }
997
998 static int getComponentLength (OOCTXT* pctxt, ASN1UINT itemBits)
999 {
1000    OOCTXT lctxt;
1001    ASN1UINT len, totalLen = 0;
1002    int stat;
1003
1004    stat = initSubContext (&lctxt, pctxt);
1005    if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);
1006
1007    stat = setPERBufferUsingCtxt (&lctxt, pctxt);
1008    if (stat != ASN_OK) {
1009       freeContext (&lctxt);
1010       return LOG_ASN1ERR (pctxt, stat);
1011    }
1012    lctxt.pSizeConstraint = pctxt->pSizeConstraint;
1013
1014    for (;;) {
1015       stat = decodeLength (&lctxt, &len);
1016       if (stat < 0) {
1017          freeContext (&lctxt);
1018          return LOG_ASN1ERR (pctxt, stat);
1019       }
1020
1021       totalLen += len;
1022
1023       if (stat == ASN_OK_FRAG) {
1024          stat = moveBitCursor (&lctxt, len * itemBits);
1025          if (stat != ASN_OK) {
1026             freeContext (&lctxt);
1027             return LOG_ASN1ERR (pctxt, stat);
1028          }
1029       }
1030       else break;
1031    }
1032
1033    freeContext (&lctxt);
1034
1035    return totalLen;
1036 }
1037
1038 int moveBitCursor (OOCTXT* pctxt, int bitOffset)
1039 {
1040    int currBitOffset =
1041       (pctxt->buffer.byteIndex * 8) + (8 - pctxt->buffer.bitOffset);
1042
1043    currBitOffset += bitOffset;
1044
1045    pctxt->buffer.byteIndex = (currBitOffset / 8);
1046    pctxt->buffer.bitOffset = 8 - (currBitOffset % 8);
1047
1048    if (pctxt->buffer.byteIndex > pctxt->buffer.size) {
1049       return (ASN_E_ENDOFBUF);
1050    }
1051       
1052    return ASN_OK;
1053 }