]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c-lib/src/tbl-dec.c
Security-54.1.3.tar.gz
[apple/security.git] / SecuritySNACCRuntime / c-lib / src / tbl-dec.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 #ifdef TTBL
20
21 /*
22 * tbl_dec.c - type table decoder.
23 *
24 *
25 * Mike Sample
26 *
27 * Copyright (C) 1993 Michael Sample
28 * and the University of British Columbia
29 *
30 * This library is free software; you can redistribute it and/or
31 * modify it provided that this copyright/license information is retained
32 * in original form.
33 *
34 * If you modify this file, you must clearly indicate your changes.
35 *
36 * This source code is distributed in the hope that it will be
37 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
38 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
39 */
40
41
42 #include <stdio.h>
43 #include "tbl-incl.h"
44
45 int TagsMatch PROTO ((TBLType *tblT, AsnTag asnTag));
46 void TblPopTagsAndLens PROTO ((TBLType *tblT, BUF_TYPE b, int implicit, unsigned long int *bytesDecoded, ENV_TYPE env));
47
48 void TblDecodeTagsAndLens PROTO ((TBLType *tblT, BUF_TYPE b, int implicit, ENV_TYPE env));
49
50 int CountMandatoryElmts PROTO ((TBLType *tblT));
51
52
53 typedef struct TagNLen
54 {
55 AsnTag tag;
56 AsnLen len;
57 unsigned int size; /* encoded len for this tag len pair */
58 } TagNLen;
59
60 #define TL_STK_SIZE 128
61 static TagNLen tlStkG[TL_STK_SIZE];
62 static int nextFreeTLG = 0;
63
64 #define PUSH_TL(t,l,sz, env)\
65 { if (nextFreeTLG >= TL_STK_SIZE)\
66 longjmp (env, -1000);\
67 tlStkG[nextFreeTLG].tag = t;\
68 tlStkG[nextFreeTLG].len = l;\
69 tlStkG[nextFreeTLG++].size = sz; }
70
71 #define POP_TL(env)\
72 { nextFreeTLG--;\
73 if (nextFreeTLG < 0)\
74 longjmp (env, -1001);}
75
76 #define LAST_TAG() (tlStkG[nextFreeTLG-1].tag)
77 #define LAST_LEN() (tlStkG[nextFreeTLG-1].len)
78 #define LAST_SIZE() (tlStkG[nextFreeTLG-1].size)
79
80
81
82 AVal*
83 TblDecode PARAMS ((tbl, modName, typeName, b, bytesDecoded),
84 TBL *tbl _AND_
85 char *modName _AND_
86 char *typeName _AND_
87 BUF_TYPE b _AND_
88 unsigned long int *bytesDecoded)
89 {
90 TBLModule *tblMod;
91 TBLTypeDef *tblTd;
92 ENV_TYPE env;
93 AVal *retVal;
94 int val;
95
96 tblTd = TblFindTypeDef (tbl, modName, typeName, &tblMod);
97 if (tblTd == NULL)
98 {
99 TblError ("TblDecode: Could not find a type definition with the given module and name");
100 return NULL;
101 }
102 *bytesDecoded = 0;
103
104 if ((val = setjmp (env)) == 0)
105 {
106 retVal = TblDecodeType (tblTd->type, b, FALSE, bytesDecoded, env);
107 }
108 else
109 retVal = NULL;
110
111 if (val != 0)
112 fprintf (stderr,"ack! longjmp error number: %d\n", val);
113
114 return retVal;
115 } /* TblDecode p*/
116
117
118 AVal*
119 TblDecodeType PARAMS ((tblT, b, implicit, bytesDecoded, env),
120 TBLType *tblT _AND_
121 BUF_TYPE b _AND_
122 int implicit _AND_
123 unsigned long int *bytesDecoded _AND_
124 ENV_TYPE env)
125 {
126 AVal *elmtVPtr;
127 unsigned long int tmpBytesDecoded = 0;
128 unsigned int currElmt;
129 TBLType *listElmtType;
130 TBLType *structElmtType;
131 TBLType *choiceElmtType;
132 AChoiceVal *cVal;
133 AStructVal *sVal;
134 AVal *retVal;
135 AVal **tmpHndl;
136 AsnTag asnTag;
137 int i, mandatoryCount, mandatoryElmts;
138 int implicitRef;
139 void *tmp;
140
141
142 TblDecodeTagsAndLens (tblT, b, implicit, env);
143
144 switch (tblT->typeId)
145 {
146 case TBL_TYPEREF:
147 /*
148 * carry over implicit ref if goes
149 * through typeref with no tags
150 */
151 implicitRef = tblT->content->a.typeRef->implicit ||
152 (implicit &&
153 ((tblT->tagList == NULL) || LIST_EMPTY (tblT->tagList)));
154
155 retVal = TblDecodeType (tblT->content->a.typeRef->typeDefPtr->type, b, implicitRef, &tmpBytesDecoded, env);
156 break;
157
158 case TBL_SEQUENCE:
159 /* go fwd though elmt type list */
160 currElmt = 0;
161 sVal = (AStructVal*) Asn1Alloc (sizeof (AVal*)*
162 LIST_COUNT (tblT->content->a.elmts));
163 tmp = CURR_LIST_NODE (tblT->content->a.elmts);
164 FOR_EACH_LIST_ELMT (structElmtType, tblT->content->a.elmts)
165 {
166 if (TagsMatch (structElmtType, PeekTag (b,env)))
167 {
168 sVal[currElmt] = TblDecodeType (structElmtType, b, FALSE, &tmpBytesDecoded, env);
169 }
170 else if (!structElmtType->optional)
171 longjmp (env,-1008);
172
173 currElmt++;
174 }
175 SET_CURR_LIST_NODE (tblT->content->a.elmts, tmp);
176 retVal = (AVal*) sVal;
177 break;
178
179 case TBL_SET:
180 sVal = (AStructVal*) Asn1Alloc (sizeof (AVal*)*
181 LIST_COUNT (tblT->content->a.elmts));
182 mandatoryCount = 0;
183 mandatoryElmts = CountMandatoryElmts (tblT);
184 if (LAST_LEN() == INDEFINITE_LEN)
185 while (!PeekEoc (b))
186 {
187 asnTag = PeekTag (b,env);
188 currElmt = 0;
189 /* find elmt that matches the peeked tag */
190 FOR_EACH_LIST_ELMT (structElmtType, tblT->content->a.elmts)
191 {
192 if (TagsMatch (structElmtType, asnTag))
193 break;
194 currElmt++;
195 }
196
197 /* didn't find a match */
198 if (currElmt >= LIST_COUNT (tblT->content->a.elmts))
199 longjmp (env,-1009);
200
201 if (!structElmtType->optional)
202 mandatoryCount++;
203
204 sVal[currElmt] = TblDecodeType (structElmtType, b, FALSE, &tmpBytesDecoded, env);
205 }
206 else
207 while (tmpBytesDecoded < LAST_LEN())
208 {
209 asnTag = PeekTag (b,env);
210 currElmt = 0;
211 /* find elmt that matches the peeked tag */
212 FOR_EACH_LIST_ELMT (structElmtType, tblT->content->a.elmts)
213 {
214 if (TagsMatch (structElmtType, asnTag))
215 break;
216 currElmt++;
217 }
218
219 if (currElmt >= LIST_COUNT (tblT->content->a.elmts))
220 longjmp (env, -1007);
221
222 if (!structElmtType->optional)
223 mandatoryCount++;
224
225 sVal[currElmt] = TblDecodeType (structElmtType, b, FALSE, &tmpBytesDecoded, env);
226 }
227 if (mandatoryCount != mandatoryElmts)
228 longjmp (env,-1006);
229 else
230 retVal = sVal;
231
232 break;
233
234
235 case TBL_SEQUENCEOF:
236 case TBL_SETOF:
237 retVal = (AsnList*)Asn1Alloc (sizeof (AsnList));
238 listElmtType = FIRST_LIST_ELMT (tblT->content->a.elmts);
239
240 if (LAST_LEN() == INDEFINITE_LEN)
241 while (!PeekEoc (b))
242 {
243 elmtVPtr = TblDecodeType (listElmtType, b, FALSE, &tmpBytesDecoded, env);
244 tmpHndl = AsnListAppend ((AsnList*)retVal);
245 *tmpHndl = elmtVPtr;
246 }
247 else
248 while (tmpBytesDecoded < LAST_LEN())
249 {
250 elmtVPtr = TblDecodeType (listElmtType, b, FALSE, &tmpBytesDecoded, env);
251 tmpHndl = AsnListAppend ((AsnList*)retVal);
252 *tmpHndl = elmtVPtr;
253 }
254
255 break;
256
257 case TBL_CHOICE:
258 retVal = cVal = (AChoiceVal*) Asn1Alloc (sizeof (AChoiceVal));
259 asnTag = PeekTag (b,env);
260 i = 0;
261 /* find elmt that matches the peeked tag */
262 tmp = CURR_LIST_NODE (tblT->content->a.elmts);
263 FOR_EACH_LIST_ELMT (choiceElmtType, tblT->content->a.elmts)
264 {
265 if (TagsMatch (choiceElmtType, asnTag))
266 {
267 cVal->choiceId = i;
268 break;
269 }
270 i++;
271 }
272 SET_CURR_LIST_NODE (tblT->content->a.elmts, tmp);
273 cVal->val = TblDecodeType (choiceElmtType, b, FALSE, &tmpBytesDecoded, env);
274 break;
275
276 case TBL_BOOLEAN:
277 retVal = Asn1Alloc (sizeof (AsnBool));
278 BDecAsnBoolContent (b, LAST_TAG(), LAST_LEN(), (AsnBool*) retVal, &tmpBytesDecoded, env);
279 break;
280
281 case TBL_INTEGER:
282 case TBL_ENUMERATED:
283 retVal = Asn1Alloc (sizeof (AsnInt));
284 BDecAsnIntContent (b, LAST_TAG(), LAST_LEN(), (AsnInt*) retVal, &tmpBytesDecoded, env);
285 break;
286
287 case TBL_BITSTRING:
288 retVal = Asn1Alloc (sizeof (AsnBits));
289 BDecAsnBitsContent (b, LAST_TAG(), LAST_LEN(), (AsnBits*) retVal, &tmpBytesDecoded, env);
290 break;
291
292 case TBL_OCTETSTRING:
293 retVal = Asn1Alloc (sizeof (AsnOcts));
294 BDecAsnOctsContent (b, LAST_TAG(), LAST_LEN(), (AsnOcts*) retVal, &tmpBytesDecoded, env);
295 break;
296
297 case TBL_NULL:
298 retVal = Asn1Alloc (sizeof (AsnNull));
299 BDecAsnNullContent (b, LAST_TAG(), LAST_LEN(), (AsnNull*) retVal, &tmpBytesDecoded, env);
300 break;
301
302 case TBL_OID:
303 retVal = Asn1Alloc (sizeof (AsnOid));
304 BDecAsnOidContent (b, LAST_TAG(), LAST_LEN(), (AsnOid*) retVal, &tmpBytesDecoded, env);
305 break;
306
307 case TBL_REAL:
308 retVal = Asn1Alloc (sizeof (AsnReal));
309 BDecAsnRealContent (b, LAST_TAG(), LAST_LEN(), (AsnReal*) retVal, &tmpBytesDecoded, env);
310 break;
311
312 default:
313 retVal = NULL;
314 break;
315 }
316
317 TblPopTagsAndLens (tblT, b, implicit, &tmpBytesDecoded, env);
318
319 (*bytesDecoded) += tmpBytesDecoded;
320
321 return retVal;
322
323 } /* TblDecodeType */
324
325
326 void
327 TblDecodeTagsAndLens PARAMS ((tblT, b, implicit, env),
328 TBLType *tblT _AND_
329 BUF_TYPE b _AND_
330 int implicit _AND_
331 ENV_TYPE env)
332 {
333 AsnTag tag;
334 AsnLen len;
335 AsnLen encSize;
336 TBLTag *tblTag;
337
338 if ((tblT->tagList == NULL) || (LIST_EMPTY (tblT->tagList)))
339 return;
340
341 SET_CURR_LIST_NODE (tblT->tagList, FIRST_LIST_NODE (tblT->tagList));
342 if (implicit)
343 {
344 SET_CURR_LIST_NODE (tblT->tagList, NEXT_LIST_NODE (tblT->tagList));
345 }
346
347
348 FOR_REST_LIST_ELMT (tblTag, tblT->tagList)
349 {
350 encSize = 0;
351 tag = BDecTag (b, &encSize, env);
352 len = BDecLen (b, &encSize, env);
353
354 if (!TagsEquiv (tag, tblTag))
355 longjmp (env, -1002);
356
357 PUSH_TL (tag, len, encSize, env);
358 }
359 } /* TblDecodeTagsAndLens */
360
361 /*
362 * bytesDecoded should hold the length of the content that
363 * was just decoded. This verifies the lengths as it pops
364 * them off the stack. Also decodes EOCs.
365 */
366 void
367 TblPopTagsAndLens PARAMS ((tblT, b, implicit, bytesDecoded, env),
368 TBLType *tblT _AND_
369 BUF_TYPE b _AND_
370 int implicit _AND_
371 unsigned long int *bytesDecoded _AND_
372 ENV_TYPE env)
373 {
374 TBLTag *tblTag;
375
376 FOR_EACH_LIST_ELMT_RVS (tblTag, tblT->tagList)
377 {
378 if (implicit && (tblTag == FIRST_LIST_ELMT (tblT->tagList)))
379 break;
380
381 if (LAST_LEN() == INDEFINITE_LEN)
382 BDecEoc (b, bytesDecoded, env);
383 else if (*bytesDecoded != LAST_LEN())
384 longjmp (env, -1003);
385
386 (*bytesDecoded) += LAST_SIZE();
387 POP_TL (env);
388 }
389 } /* TblPopTagsAndLens */
390
391
392 int TagsMatch PARAMS ((tblT, asnTag),
393 TBLType *tblT _AND_
394 AsnTag asnTag)
395 {
396 TBLType *tmpTblT;
397 TBLType *elmtTblT;
398 TBLTag *tblTag;
399 void *tmp;
400
401 /*
402 * skip through type refs until encounter first tag or
403 * untagged CHOICE (only TYPEREFs and CHOICEs can
404 * have empty tag lists).
405 */
406 for (tmpTblT = tblT; ((tmpTblT->typeId == TBL_TYPEREF) &&
407 ((tmpTblT->tagList == NULL) || LIST_EMPTY (tmpTblT->tagList)));
408 tmpTblT = tmpTblT->content->a.typeRef->typeDefPtr->type);
409
410
411 /*
412 * if untagged CHOICE must check for a match with the first tag
413 * of each component of the CHOICE
414 */
415 if ((tmpTblT->typeId == TBL_CHOICE) &&
416 ((tmpTblT->tagList == NULL) || LIST_EMPTY (tmpTblT->tagList)))
417 {
418 tmp = CURR_LIST_NODE (tmpTblT->content->a.elmts);
419 FOR_EACH_LIST_ELMT (elmtTblT, tmpTblT->content->a.elmts)
420 {
421 /*
422 * remember the elmt type can be an untagged choice too
423 * so call TagsMatch again.
424 */
425 if (TagsMatch (elmtTblT, asnTag))
426 {
427 SET_CURR_LIST_NODE (tmpTblT->content->a.elmts, tmp);
428 return TRUE; /* match in choice */
429 }
430 }
431 SET_CURR_LIST_NODE (tmpTblT->content->a.elmts, tmp);
432 return FALSE; /* no match in choice */
433 }
434 else /* is type other than untagged choice or type ref */
435 {
436 tblTag = FIRST_LIST_ELMT (tmpTblT->tagList);
437 return TagsEquiv (asnTag, tblTag);
438 }
439 } /* TagsMatch */
440
441
442 int
443 CountMandatoryElmts PARAMS ((tblT),
444 TBLType *tblT)
445 {
446 TBLType *tblElmtT;
447 int count = 0;
448 FOR_EACH_LIST_ELMT (tblElmtT, tblT->content->a.elmts)
449 {
450 if (!tblElmtT->optional)
451 count++;
452 }
453 return count;
454 } /* CountMandatoryElmts */
455
456 #endif /* TTBL */