]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/doc/ttab.tex
Security-54.1.tar.gz
[apple/security.git] / SecuritySNACCRuntime / doc / ttab.tex
1 % file: .../doc/ttab.tex
2
3 % $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/doc/ttab.tex,v 1.1.1.1 2001/05/18 23:14:10 mb Exp $
4 % $Log: ttab.tex,v $
5 % Revision 1.1.1.1 2001/05/18 23:14:10 mb
6 % Move from private repository to open source repository
7 %
8 % Revision 1.1.1.1 1999/03/16 18:05:55 aram
9 % Originals from SMIME Free Library.
10 %
11 % Revision 1.1 1997/01/01 22:47:43 rj
12 % first check-in
13 %
14
15 \chapter{\label{ttab-chapter}Type Tables}
16
17 Type tables are a flexible and compact way of dealing with ASN.1.
18 The type table data structure is included in the appendix. It was
19 defined in ASN.1 to provide a good storage format for the tables.
20
21 When snacc produces a type table it includes the useful types module
22 as well, if one was specified. If you are really trying to limit the
23 size of your type tables, put the only useful types that you need in
24 your ASN.1 module and compile it without using the useful types
25 module.
26
27 A generic buffer type (à la ISODE and XDR) was defined to allow type
28 table driven routines to read from a wide variety of buffer formats.
29 Currently slightly modified versions of the {\C ExpBuf} and the
30 {\C SBuf} are provided. It shouldn't be too hard for you to add
31 support for your own buffer formats. The generic buffers,
32 {\C GenBuf}s are described in more detail in a following section.
33
34 The general procedure for using type tables is to:
35 \begin{enumerate}
36 \item Use snacc to compile your ASN.1 modules into a type table.
37 \item Use {\ufn mkchdr} (make C header, not make cheddar) with the
38 type table to produce a friendly C type description of the types in
39 the type table.
40 \item Load the type table during runtime and use it to configure the table
41 encode, decode and other routines.
42 \end{enumerate}
43
44 Step two, making the C header file is not necessary but will make
45 dealing with the value easier and more type safe. Internally the
46 table driven encoders and decoders know nothing of these header file
47 and treat the types in a uniform, generic manner. This requires the
48 encoders and decoders to make assumptions about the way C represents
49 strucutures and values. Look in the {\ufn \dots/c-lib/src/tbl-enc.c} and
50 {\ufn \dots/c-lib/src/tbl-dec.c} files to see how this generic data
51 structure is manipulated.
52
53 On the down side, the compiler directives do not affect the data
54 structures generated by mkchdr and the generated C type definitions
55 will generally be different from those generated by the C backend.
56 This can be fixed, but time was lacking. Type tables also do not
57 support ANY DEFINED BY types. Someone could fix this without too much
58 difficulty. Only a C type table library is provided. I didn't have
59 time to deal with the complexities of creating C++ objects in a
60 generic way.
61
62 Currently the type tables are lacking subtyping information. It is
63 available in snacc's main parse tree but I didn't have time to add it
64 to the tables. If you want to add it, take the subtype related data
65 structures (in ASN.1) from asn1module.asn1 (quite a few), remove all
66 the cruft pertaining to linking and error checking etc, and add it to
67 the type table type definitions. Then change the
68 {\ufn \dots/compiler/core/gen-tbls.c} file to take the subtype information from
69 the parse tree and put it into the type table. See the appendix or
70 {\ufn \dots/asn1specs/} for the ASN.1 definitions of the parse tree
71 and type tables.
72
73 The parse tree itself was defined in ASN.1 so it could be the table
74 format. The extra complexity required for linking and error checking
75 made this very difficult. Cycles in the data structure and the many
76 links between the data elements made encoding in BER difficult.
77 [Maybe ASN.1 needs a type refernce type (i.e. pointer)].
78
79
80 \section{How Type Table See Values}
81
82 As mentioned in the last section, table driven encoding, decoding,
83 printing etc. routines see your values in a generic way. They do not
84 have abstract syntax specific header files like those created by
85 {\ufn mkchdr}.
86
87 The basic idea is that all of the standard primitive and list
88 (SEQUENCE OF and SET OF) types are used and some regular rules are
89 used for allocating and laying out structs for SEQUENCE, SET and
90 CHOICE types.
91
92 \begin{small}
93 \begin{verbatim}
94 /* values from table driver routines' point of view */
95 typedef void AVal;
96
97 /* SEQUENCE and SET type use AStructVal */
98 typedef AVal *AStructVal; /* an array of AVal ptrs */
99 \end{verbatim}
100 \end{small}
101
102 For SETs and SEQUENCEs, the {\C AStructVal} type is used. Its is
103 basically an array of pointers, one for each component of the
104 SET/SEQUENCE\@. Every component is referenced by pointer to simplify
105 allocations. OPTIONAL or DEFAULT components may be NULL\@. For
106 example, the type:
107
108 \begin{small}
109 \begin{verbatim}
110 Foo ::= SEQUENCE { a INTEGER, b BOOLEAN, c OCTET STRING }
111 \end{verbatim}
112 \end{small}
113
114 would be represented as an array of three pointers. The first pointer
115 would point to an {\C AsnInt} value, the second would point to an
116 {\C AsnBool} value, and the third would point to an {\C AsnOcts}
117 value. {\ufn mkchdr} would give you the following C typedef for Foo:
118
119 \begin{small}
120 \begin{verbatim}
121 typedef struct Foo
122 {
123 AsnInt *a;
124 AsnBool *b;
125 AsnOcts *c;
126 } Foo;
127 \end{verbatim}
128 \end{small}
129
130 \begin{small}
131 \begin{verbatim}
132 /* Internal representation for a CHOICE type */
133 typedef struct AChoiceVal
134 {
135 enum { achoiceval_notused } choiceId;
136 AVal *val;
137 } AChoiceVal;
138 \end{verbatim}
139 \end{small}
140
141
142 A CHOICE type is represented in a way similar to the C backend's
143 output. That is, an enum to hold the id of the CHOICE component
144 that is present and a pointer to the component itself. For example,
145 the type:
146
147 \begin{small}
148 \begin{verbatim}
149 Bar ::= CHOICE { a INTEGER, b BOOLEAN, c OCTET STRING }
150 \end{verbatim}
151 \end{small}
152
153 would internally be represented as AChoiceVal type. However,
154 {\ufn mkchdr} would give you the following:
155
156 \begin{small}
157 \begin{verbatim}
158 typedef struct Bar
159 {
160 enum
161 {
162 a_ID = 0,
163 b_ID = 1,
164 c_ID = 2
165 } choiceId;
166 union
167 {
168 AsnInt *a;
169 AsnBool *b;
170 AsnOcts *c;
171 } a;
172 } Bar;
173 \end{verbatim}
174 \end{small}
175
176
177 \section{Type Table Utilities}
178
179 There are a bunch of useful routines in {\ufn \dots/c-lib/src/tbl*.c}. Look
180 at the source code in {\ufn \dots/tbl-tools/*/} and
181 {\ufn \dots/tbl-example/} to see how to use some of them.
182
183 The {\C LoadTblFile} will decode a type table from a given file.
184 Notice that its definition of the {\C TBL} data structure has been
185 augmented to simplify encoding and decoding operations. (Look at the
186 patch in {\ufn \dots/c-lib/tbl.h.patch} that is applied through the makefile automatically.)
187 % The additional fields do not screw up the compiled encoder/decoder (in {\ufn \dots/c-lib/src/tbl.c}) provided they are recompiled.
188 The compiler uses unmodified {\ufn tbl.h} and {\ufn tbl.c} files.
189
190 I don't have time to document these routines. Look through the table
191 tools, examples and library code. Their usage should be fairly
192 obvious.
193
194
195 \section{Type Table Tools}
196
197 The {\ufn \dots/tbl-tools/} directory contains three tools, {\ufn mkchdr},
198 {\ufn pval} and {\ufn ptbl}. These are described in the following
199 sections.
200
201 \subsection{Making C Header Files with mkchdr}
202
203 {\ufn mkchdr} produces a C header file from a type table. This header
204 file shows the representation of the types that the table tools will
205 expect or return for the types in the given type table.
206
207 The main use is to provide you with an easy to use definition of the
208 ASN.1 types C representation. You do not need to use {\ufn mkchdr}
209 but it is definately recommended. Note that the table routines could
210 have used an even more generic data structure to represent values
211 (e.g. ISODE's Presentation Elements). If you have worked with these,
212 you know that they are cumbersome.
213
214 Its synopsis is:
215 \begin{small}
216 \begin{verbatim}
217 mkchdr <tbl-file> [output-file]
218 \end{verbatim}
219 \end{small}
220
221 If the output file is omitted, the header file is printed to {\C stdout}.
222
223 Here is an example of the output. Given the table that has the
224 following ASN.1 module in it:
225
226 \begin{small}
227 \begin{verbatim}
228 P-REC DEFINITIONS ::=
229 BEGIN
230 PersonnelRecord ::= [APPLICATION 0] IMPLICIT SET
231 {
232 Name,
233 title [0] IA5String,
234 EmployeeNumber,
235 dateOfHire [1] Date,
236 nameOfSpouse [2] Name,
237 children [3] IMPLICIT SEQUENCE OF ChildInformation DEFAULT {}
238 }
239
240 ChildInformation ::= SET
241 {
242 Name,
243 dateOfBirth [0] Date
244 }
245
246 Name ::= [APPLICATION 1] IMPLICIT SEQUENCE
247 {
248 givenName IA5String,
249 initial IA5String,
250 familyName IA5String
251 }
252
253 EmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER
254
255 Date ::= [APPLICATION 3] IMPLICIT IA5String -- YYYYMMDD
256
257 END
258 \end{verbatim}
259 \end{small}
260
261 {\ufn mkchdr} will produce:
262 \begin{small}
263 \begin{verbatim}
264 typedef AsnInt EmployeeNumber;
265
266 typedef struct Name
267 {
268 IA5String *givenName;
269 IA5String *initial;
270 IA5String *familyName;
271 } Name;
272
273 typedef IA5String Date;
274
275 typedef struct ChildInformation
276 {
277 Name *field0;
278 Date *dateOfBirth;
279 } ChildInformation;
280
281 typedef AsnList PersonnelRecordSeqOf;
282
283 typedef struct PersonnelRecord
284 {
285 Name *field0;
286 IA5String *title;
287 EmployeeNumber *field1;
288 Date *dateOfHire;
289 Name *nameOfSpouse;
290 PersonnelRecordSeqOf *children;
291 } PersonnelRecord;
292
293 \end{verbatim}
294 \end{small}
295
296
297 \subsection{Printing Tables with ptbl}
298
299 {\ufn ptbl} is a program that will show you the contents of a type
300 table. It can print a table in two modes:
301 \begin{itemize}
302 \item The value notation for the TBL ASN.1 data structure (see the appendix).
303 \item The ASN.1 text version
304 \end{itemize}
305
306 Its synopsis is:
307
308 \begin{small}
309 \begin{verbatim}
310 ptbl [-a] <tbl-file>
311 \end{verbatim}
312 \end{small}
313
314 For example, using {\ufn ptbl -a p-rec.tt} to print the
315 PersonnelRecord module used in the last section would yield:
316
317 \begin{small}
318 \begin{verbatim}
319 P-REC DEFINITIONS ::=
320 BEGIN
321 EmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER
322 Name ::= [APPLICATION 1] IMPLICIT SEQUENCE
323 {
324 givenName IA5String,
325 initial IA5String,
326 familyName IA5String
327 }
328 Date ::= [APPLICATION 3] IMPLICIT IA5String
329 ChildInformation ::= SET
330 {
331 Name,
332 dateOfBirth [0] Date
333 }
334 PersonnelRecordSeqOf ::= SEQUENCE OF ChildInformation
335 PersonnelRecord ::= [APPLICATION 0] IMPLICIT SET
336 {
337 Name,
338 title [0] IA5String,
339 EmployeeNumber,
340 dateOfHire [1] Date,
341 nameOfSpouse [2] Name,
342 children [3] IMPLICIT PersonnelRecordSeqOf
343 }
344 END
345 -- Definitions for ASN-USEFUL
346 ASN-USEFUL DEFINITIONS ::=
347 BEGIN
348 ObjectDescriptor ::= [UNIVERSAL 7] IMPLICIT OCTET STRING
349 NumericString ::= [UNIVERSAL 18] IMPLICIT OCTET STRING
350 PrintableString ::= [UNIVERSAL 19] IMPLICIT OCTET STRING
351 TeletexString ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
352 T61String ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
353 VideotexString ::= [UNIVERSAL 21] IMPLICIT OCTET STRING
354 IA5String ::= [UNIVERSAL 22] IMPLICIT OCTET STRING
355 GraphicString ::= [UNIVERSAL 25] IMPLICIT OCTET STRING
356 VisibleString ::= [UNIVERSAL 26] IMPLICIT OCTET STRING
357 ISO646String ::= [UNIVERSAL 26] IMPLICIT OCTET STRING
358 GeneralString ::= [UNIVERSAL 27] IMPLICIT OCTET STRING
359 UTCTime ::= [UNIVERSAL 23] IMPLICIT OCTET STRING
360 GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT OCTET STRING
361 EXTERNAL ::= [UNIVERSAL 8] IMPLICIT SEQUENCE
362 {
363 direct-reference OBJECT IDENTIFIER,
364 indirect-reference INTEGER,
365 data-value-descriptor ObjectDescriptor,
366 encoding CHOICE
367 {
368 single-ASN1-type [0] OCTET STRING,
369 octet-aligned [1] IMPLICIT OCTET STRING,
370 arbitrary [2] IMPLICIT BIT STRING
371 }
372 }
373 END
374 \end{verbatim}
375 \end{small}
376
377 Note that the useful type module is included in the table. As
378 mentioned before, to minimize the size of your tables, put the
379 definitions of the useful types (from {\ufn \dots/asn1specs/asn-useful.asn1})
380 into your ASN.1 module and do not compile with useful types module
381 (i.e. don't use the -u option). If your module doesn't use any
382 useful types, just don't use the -u option.
383
384 The other mode of {\ufn ptbl}, value notation for the TBL data
385 structure, produces a lot of output. It may be useful if you are
386 debugging one of the table drivers.
387
388
389 \subsection{Printing Values with pval}
390
391 The {\ufn pval} program will convert BER values into their value
392 notation. Its arguments are a type table file, a module and type name
393 and a list of BER files of that type.
394
395 Its synopsis is:
396
397 \begin{small}
398 \begin{verbatim}
399 pval -T <tt file name> [-m <module name>] -n <type name> <ber value file list>
400 \end{verbatim}
401 \end{small}
402
403 Running {\ufn pval} on a PersonnelRecord value produced the following:
404
405 \begin{small}
406 \begin{verbatim}
407 -- Contents of file "demo-tbls/p-rec.ber"--
408 -- module = ???, type = PersonnelRecord --
409
410 value P-REC.PersonnelRecord ::=
411 {
412 {
413 givenName '4a6f686e'H -- "John" --,
414 initial '45'H -- "E" --,
415 familyName '536d697468'H -- "Smith" --
416 },
417 title '5468652042696720436865657365'H -- "The Big Cheese" --,
418 99999,
419 dateOfHire '3139383230313034'H -- "19820104" --,
420 nameOfSpouse {
421 givenName '4d617279'H -- "Mary" --,
422 initial '4c'H -- "L" --,
423 familyName '536d697468'H -- "Smith" --
424 },
425 children {
426 {
427 {
428 givenName '4a616d6573'H -- "James" --,
429 initial '52'H -- "R" --,
430 familyName '536d697468'H -- "Smith" --
431 },
432 dateOfBirth '3139353730333130'H -- "19570310" --
433 },
434 {
435 {
436 givenName '4c697361'H -- "Lisa" --,
437 initial '4d'H -- "M" --,
438 familyName '536d697468'H -- "Smith" --
439 },
440 dateOfBirth '3139363130363231'H -- "19610621" --
441 }
442 }
443 }
444
445 -- decoded 143 bytes for the above value --
446 \end{verbatim}
447 \end{small}
448
449
450 \section{Using Tables in Your Own Applications}
451
452 The best way to get a handle on using tables is to look at the example
453 in {\ufn \dots/tbl-example/}. The general idea is to compile your
454 ASN.1 into a type table (use the snacc {\ufn -T} option). If you desire a
455 livable definition of the C data structures for the types in the type
456 table, run {\ufn mkchdr} and compile the generated header file with
457 your C code. During runtime, simply load your table file with
458 {\C LoadTblFile} (I use the {\ufn .tt} suffix naming convention for type table
459 files but it doesn't matter) and then use the {\C TblEncode},
460 {\C TblDecode}, {\C TblPrint} and {\C TblFree} routines with
461 your table. Quite simple. Seriously.
462
463 \section{Using GenBufs}
464
465 The {\C GenBuf} generic buffers are really a way of encapsulating
466 other buffer formats. A {\C GenBuf} contains a table of pointers to
467 the buffer functions (the standardized ones (see the buffer section)
468 plus ``Peek'' routines that the table drivers needed). They are
469 defined in {\ufn \dots/c-lib/inc/gen-buf.h}.
470
471 {\C GenBuf}s require functions for the standard buffer routines,
472 macros will not do since you cannot have a pointer to macro.
473
474 The benefit of the {\C GenBuf}s is that since they can support other
475 buffer types, only one set of library routines is needed. (Note that
476 there are 3 libraries in {\ufn \dots/c-lib/} for the backend model and only one for the type table model.
477
478 Here is most of {\ufn gen-buf.h} to give you an idea of how things work:
479
480 \begin{small}
481 \begin{verbatim}
482 typedef unsigned char (*BufGetByteFcn) PROTO ((void *b));
483 typedef unsigned char *(*BufGetSegFcn) PROTO ((void *b,
484 unsigned long int *lenPtr));
485 typedef long int (*BufCopyFcn) PROTO ((char *dst, void *b,
486 unsigned long int len));
487 typedef void (*BufSkipFcn) PROTO ((void *b, unsigned long int len));
488 typedef unsigned char (*BufPeekByteFcn) PROTO ((void *b));
489 typedef unsigned char *(*BufPeekSegFcn) PROTO ((void *b,
490 unsigned long int lenPtr));
491 typedef long int (*BufPeekCopyFcn) PROTO ((char *dst, void *b,
492 unsigned long int len));
493 typedef void (*BufPutByteRvsFcn) PROTO ((void *b, unsigned char byte));
494 typedef void (*BufPutSegRvsFcn) PROTO ((void *b, char *data,
495 unsigned long int len));
496 typedef int (*BufReadErrorFcn) PROTO ((void *b));
497 typedef int (*BufWriteErrorFcn) PROTO ((void *b));
498
499 typedef struct GenBuf
500 {
501 BufGetByteFcn getByte;
502 BufGetSegFcn getSeg;
503 BufCopyFcn copy;
504 BufSkipFcn skip;
505 BufPeekByteFcn peekByte;
506 BufPeekSegFcn peekSeg;
507 BufPeekCopyFcn peekCopy;
508 BufPutByteRvsFcn putByteRvs;
509 BufPutSegRvsFcn putSegRvs;
510 BufReadErrorFcn readError;
511 BufWriteErrorFcn writeError;
512 void *bufInfo;
513 void *spare; /* hack to save space for ExpBuf ** type */
514 } GenBuf;
515
516 #define GenBufGetByte( b) ((b)->getByte (b->bufInfo))
517 #define GenBufGetSeg( b, lenPtr) ((b)->getSeg (b->bufInfo, lenPtr))
518 #define GenBufCopy( dst, b, len) ((b)->copy (dst, b->bufInfo, len))
519 #define GenBufSkip( b, len) ((b)->skip (b->bufInfo,len))
520 #define GenBufPeekByte( b) ((b)->peekByte (b->bufInfo))
521 #define GenBufPeekSeg( b, lenPtr) ((b)->peekSeg (b->bufInfo, lenPtr))
522 #define GenBufPeekCopy( dst, b, len) ((b)->peekCopy (dst, b->bufInfo, len))
523 #define GenBufPutByteRvs( b, byte) ((b)->putByteRvs (b->bufInfo, byte))
524 #define GenBufPutSegRvs( b, data, len) ((b)->putSegRvs (b->bufInfo, data, len))
525 #define GenBufReadError( b) ((b)->readError (b->bufInfo))
526 #define GenBufWriteError( b) ((b)->writeError (b->bufInfo))
527 \end{verbatim}
528 \end{small}
529
530 \section{Type Tables Vs. Metacode}
531
532 Please refer to section~\ref{meta-ttab-comparison} on page~\pageref{meta-ttab-comparison}.