1 /* -*- mode: c; indent-tabs-mode: nil -*- */
2 /*
3  * src/lib/krb5/asn.1/asn1_encode.h
4  *
5  * Copyright 1994, 2008 by the Massachusetts Institute of Technology.
6  * All Rights Reserved.
7  *
8  * Export of this software from the United States of America may
9  *   require a specific license from the United States Government.
10  *   It is the responsibility of any person or organization contemplating
11  *   export to obtain such a license before exporting.
12  *
13  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14  * distribute this software and its documentation for any purpose and
15  * without fee is hereby granted, provided that the above copyright
16  * notice appear in all copies and that both that copyright notice and
17  * this permission notice appear in supporting documentation, and that
18  * the name of M.I.T. not be used in advertising or publicity pertaining
19  * to distribution of the software without specific, written prior
20  * permission.  Furthermore if you modify this software you must label
21  * your software as modified software and not distribute it in such a
22  * fashion that it might be confused with the original M.I.T. software.
23  * M.I.T. makes no representations about the suitability of
24  * this software for any purpose.  It is provided "as is" without express
25  * or implied warranty.
26  */
27 
28 #ifndef __ASN1_ENCODE_H__
29 #define __ASN1_ENCODE_H__
30 
31 #include "k5-int.h"
32 #include "krbasn1.h"
33 #include "asn1buf.h"
34 #include <time.h>
35 
36 /*
37    Overview
38 
39      Each of these procedures inserts the encoding of an ASN.1
40      primitive in a coding buffer.
41 
42    Operations
43 
44      asn1_encode_boolean
45      asn1_encode_integer
46      asn1_encode_unsigned_integer
47      asn1_encode_octetstring
48      asn1_encode_generaltime
49      asn1_encode_generalstring
50      asn1_encode_bitstring
51      asn1_encode_oid
52 */
53 
54 asn1_error_code asn1_encode_boolean
55         (asn1buf *buf, asn1_intmax val, unsigned int *retlen);
56 asn1_error_code asn1_encode_integer
57         (asn1buf *buf, asn1_intmax val, unsigned int *retlen);
58 /* requires  *buf is allocated
59    modifies  *buf, *retlen
60    effects   Inserts the encoding of val into *buf and returns
61               the length of the encoding in *retlen.
62              Returns ENOMEM to signal an unsuccesful attempt
63               to expand the buffer. */
64 
65 asn1_error_code asn1_encode_enumerated
66 (asn1buf *buf, long val, unsigned int *retlen);
67 
68 asn1_error_code asn1_encode_unsigned_integer
69         (asn1buf *buf, asn1_uintmax val,
70                    unsigned int *retlen);
71 /* requires  *buf is allocated
72    modifies  *buf, *retlen
73    effects   Inserts the encoding of val into *buf and returns
74               the length of the encoding in *retlen.
75              Returns ENOMEM to signal an unsuccesful attempt
76               to expand the buffer. */
77 
78 asn1_error_code asn1_encode_octetstring
79         (asn1buf *buf,
80                    unsigned int len, const void *val,
81                    unsigned int *retlen);
82 /* requires  *buf is allocated
83    modifies  *buf, *retlen
84    effects   Inserts the encoding of val into *buf and returns
85               the length of the encoding in *retlen.
86              Returns ENOMEM to signal an unsuccesful attempt
87               to expand the buffer. */
88 #define asn1_encode_charstring asn1_encode_octetstring
89 
90 asn1_error_code asn1_encode_oid
91         (asn1buf *buf,
92                    unsigned int len, const asn1_octet *val,
93                    unsigned int *retlen);
94 /* requires  *buf is allocated
95    modifies  *buf, *retlen
96    effects   Inserts the encoding of val into *buf and returns
97               the length of the encoding in *retlen.
98              Returns ENOMEM to signal an unsuccesful attempt
99               to expand the buffer. */
100 
101 asn1_error_code asn1_encode_null
102         (asn1buf *buf, int *retlen);
103 /* requires  *buf is allocated
104    modifies  *buf, *retlen
105    effects   Inserts the encoding of NULL into *buf and returns
106               the length of the encoding in *retlen.
107              Returns ENOMEM to signal an unsuccesful attempt
108               to expand the buffer. */
109 
110 asn1_error_code asn1_encode_printablestring
111         (asn1buf *buf,
112                    unsigned int len, const char *val,
113                    int *retlen);
114 /* requires  *buf is allocated
115    modifies  *buf, *retlen
116    effects   Inserts the encoding of val into *buf and returns
117               the length of the encoding in *retlen.
118              Returns ENOMEM to signal an unsuccesful attempt
119               to expand the buffer. */
120 
121 asn1_error_code asn1_encode_ia5string
122         (asn1buf *buf,
123                    unsigned int len, const char *val,
124                    int *retlen);
125 /* requires  *buf is allocated
126    modifies  *buf, *retlen
127    effects   Inserts the encoding of val into *buf and returns
128               the length of the encoding in *retlen.
129              Returns ENOMEM to signal an unsuccesful attempt
130               to expand the buffer. */
131 
132 asn1_error_code asn1_encode_generaltime
133         (asn1buf *buf, time_t val, unsigned int *retlen);
134 /* requires  *buf is allocated
135    modifies  *buf, *retlen
136    effects   Inserts the encoding of val into *buf and returns
137               the length of the encoding in *retlen.
138              Returns ENOMEM to signal an unsuccesful attempt
139               to expand the buffer.
140    Note: The encoding of GeneralizedTime is YYYYMMDDhhmmZ */
141 
142 asn1_error_code asn1_encode_generalstring
143         (asn1buf *buf,
144                    unsigned int len, const void *val,
145                    unsigned int *retlen);
146 /* requires  *buf is allocated,  val has a length of len characters
147    modifies  *buf, *retlen
148    effects   Inserts the encoding of val into *buf and returns
149               the length of the encoding in *retlen.
150              Returns ENOMEM to signal an unsuccesful attempt
151               to expand the buffer. */
152 
153 asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len,
154                                       const void *val,
155                                       unsigned int *retlen);
156 /* requires  *buf is allocated,  val has a length of len characters
157    modifies  *buf, *retlen
158    effects   Inserts the encoding of val into *buf and returns
159               the length of the encoding in *retlen.
160              Returns ENOMEM to signal an unsuccesful attempt
161               to expand the buffer. */
162 
163 asn1_error_code asn1_encode_opaque(asn1buf *buf, unsigned int len,
164                                    const void *val,
165                                    unsigned int *retlen);
166 /* requires  *buf is allocated,  val has a length of len characters
167    modifies  *buf, *retlen
168    effects   Inserts the encoding of val into *buf and returns
169               the length of the encoding in *retlen.
170              Returns ENOMEM to signal an unsuccesful attempt
171               to expand the buffer. */
172 
173 /* Type descriptor info.
174 
175    In this context, a "type" is a combination of a C data type
176    and an ASN.1 encoding scheme for it.  So we would have to define
177    different "types" for:
178 
179    * unsigned char* encoded as octet string
180    * char* encoded as octet string
181    * char* encoded as generalstring
182    * krb5_data encoded as octet string
183    * krb5_data encoded as generalstring
184    * int32_t encoded as integer
185    * unsigned char encoded as integer
186 
187    Perhaps someday some kind of flags could be defined so that minor
188    variations on the C types could be handled via common routines.
189 
190    The handling of strings is pretty messy.  Currently, we have a
191    separate kind of encoder function that takes an extra length
192    parameter.  Perhaps we should just give up on that, always deal
193    with just a single location, and handle strings by via encoder
194    functions for krb5_data, keyblock, etc.
195 
196    We wind up with a lot of load-time relocations being done, which is
197    a bit annoying.  Be careful about "fixing" that at the cost of too
198    much run-time performance.  It might work to have a master "module"
199    descriptor with pointers to various arrays (type descriptors,
200    strings, field descriptors, functions) most of which don't need
201    relocation themselves, and replace most of the pointers with table
202    indices.
203 
204    It's a work in progress.  */
205 
206 enum atype_type {
207     /* For bounds checking only.  By starting with values above 1, we
208        guarantee that zero-initialized storage will be recognized as
209        invalid.  */
210     atype_min = 1,
211     /* Encoder function to be called with address of <thing>.  */
212     atype_fn,
213     /* Encoder function to be called with address of <thing> and a
214        length (unsigned int).  */
215     atype_fn_len,
216     /* Pointer to actual thing to be encoded.
217 
218        Most of the fields are related only to the C type -- size, how
219        to fetch a pointer in a type-safe fashion -- but since the base
220        type descriptor encapsulates the encoding as well, different
221        encodings for the same C type may require different pointer-to
222        types as well.
223 
224        Must not refer to atype_fn_len.  */
225     atype_ptr,
226     /* Sequence, with pointer to sequence descriptor header.  */
227     atype_sequence,
228     /* Sequence-of, with pointer to base type descriptor, represented
229        as a null-terminated array of pointers (and thus the "base"
230        type descriptor is actually an atype_ptr node).  */
231     atype_nullterm_sequence_of,
232     atype_nonempty_nullterm_sequence_of,
233     /* Encode this object using a single field descriptor.  This may
234        mean the atype/field breakdown needs revision....
235 
236        Main expected uses: Encode realm component of principal as a
237        GENERALSTRING.  Pluck data and length fields out of a structure
238        and encode a counted SEQUENCE OF.  */
239     atype_field,
240     /* Tagged version of another type.  */
241     atype_tagged_thing,
242     /* Integer types.  */
243     atype_int,
244     atype_uint,
245     /* Unused except for bounds checking.  */
246     atype_max
247 };
248 
249 /* Initialized structures could be a lot smaller if we could use C99
250    designated initializers, and a union for all the type-specific
251    stuff.  Maybe use the hack we use for krb5int_access, where we use
252    a run-time initialize if the compiler doesn't support designated
253    initializers?  That's a lot of work here, though, with so many
254    little structures.  Maybe if/when these get auto-generated.  */
255 struct atype_info {
256     enum atype_type type;
257     /* used for sequence-of processing */
258     unsigned int size;
259     /* atype_fn */
260     asn1_error_code (*enc)(asn1buf *, const void *, unsigned int *);
261     /* atype_fn_len */
262     asn1_error_code (*enclen)(asn1buf *, unsigned int, const void *,
263                               unsigned int *);
264     /* atype_ptr, atype_fn_len */
265     const void *(*loadptr)(const void *);
266     /* atype_ptr, atype_nullterm_sequence_of */
267     const struct atype_info *basetype;
268     /* atype_sequence */
269     const struct seq_info *seq;
270     /* atype_field */
271     const struct field_info *field;
272     /* atype_tagged_thing */
273     unsigned int tagval : 8, tagtype : 8;
274     /* atype_[u]int */
275     asn1_intmax (*loadint)(const void *);
276     asn1_uintmax (*loaduint)(const void *);
277 };
278 
279 /* The various DEF*TYPE macros must:
280 
281    + Define a type named aux_typedefname_##DESCNAME, for use in any
282      types derived from the type being defined.
283 
284    + Define an atype_info struct named krb5int_asn1type_##DESCNAME.
285 
286    + Define any extra stuff needed in the type descriptor, like
287      pointer-load functions.
288 
289    + Accept a following semicolon syntactically, to keep Emacs parsing
290      (and indentation calculating) code happy.
291 
292    Nothing else should directly define the atype_info structures.  */
293 
294 /* Define a type for which we must use an explicit encoder function.
295    The DEFFNTYPE variant uses a function taking a void*, the
296    DEFFNXTYPE form wants a function taking a pointer to the actual C
297    type to be encoded; you should use the latter unless you've already
298    got the void* function supplied elsewhere.
299 
300    Of course, we need a single, consistent type for the descriptor
301    structure field, so we use the function pointer type that uses
302    void*, and create a wrapper function in DEFFNXTYPE.  However, in
303    all our cases so far, the supplied function is static and not used
304    otherwise, so the compiler can merge it with the wrapper function
305    if the optimizer is good enough.  */
306 #define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN)                   \
307     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
308     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
309         atype_fn, sizeof(CTYPENAME), ENCFN,                     \
310     }
311 #define DEFFNXTYPE(DESCNAME, CTYPENAME, ENCFN)                  \
312     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
313     static asn1_error_code                                      \
314     aux_encfn_##DESCNAME(asn1buf *buf, const void *val,         \
315                          unsigned int *retlen)                  \
316     {                                                           \
317         return ENCFN(buf,                                       \
318                      (const aux_typedefname_##DESCNAME *)val,   \
319                      retlen);                                   \
320     }                                                           \
321     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
322         atype_fn, sizeof(CTYPENAME), aux_encfn_##DESCNAME,      \
323     }
324 /* XXX The handling of data+length fields really needs reworking.
325    A type descriptor probably isn't the right way.
326 
327    Also, the C type is likely to be one of char*, unsigned char*,
328    or (maybe) void*.  An enumerator or reference to an external
329    function would be more compact.
330 
331    The supplied encoder function takes as an argument the data pointer
332    loaded from the indicated location, not the address of the field.
333    This isn't consistent with DEFFN[X]TYPE above, but all of the uses
334    of DEFFNLENTYPE are for string encodings, and that's how our
335    string-encoding primitives work.  So be it.  */
336 #ifdef POINTERS_ARE_ALL_THE_SAME
337 #define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN)                \
338     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
339     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
340         atype_fn_len, 0, 0, ENCFN,                              \
341     }
342 #else
343 #define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN)                \
344     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
345     static const void *loadptr_for_##DESCNAME(const void *pv)   \
346     {                                                           \
347         const aux_typedefname_##DESCNAME *p = pv;               \
348         return *p;                                              \
349     }                                                           \
350     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
351         atype_fn_len, 0, 0, ENCFN,                              \
352         loadptr_for_##DESCNAME                                  \
353     }
354 #endif
355 /* A sequence, defined by the indicated series of fields, and an
356    optional function indicating which fields are present.  */
357 #define DEFSEQTYPE(DESCNAME, CTYPENAME, FIELDS, OPT)            \
358     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
359     static const struct seq_info aux_seqinfo_##DESCNAME = {     \
360         OPT, FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0])           \
361     };                                                          \
362     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
363         atype_sequence, sizeof(CTYPENAME), 0,0,0,0,             \
364         &aux_seqinfo_##DESCNAME,                                \
365     }
366 /* Integer types.  */
367 #define DEFINTTYPE(DESCNAME, CTYPENAME)                         \
368     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
369     static asn1_intmax loadint_##DESCNAME(const void *p)        \
370     {                                                           \
371         assert(sizeof(CTYPENAME) <= sizeof(asn1_intmax));       \
372         return *(const aux_typedefname_##DESCNAME *)p;          \
373     }                                                           \
374     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
375         atype_int, sizeof(CTYPENAME), 0, 0, 0, 0, 0, 0, 0, 0,   \
376         loadint_##DESCNAME, 0,                                  \
377     }
378 #define DEFUINTTYPE(DESCNAME, CTYPENAME)                        \
379     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
380     static asn1_uintmax loaduint_##DESCNAME(const void *p)      \
381     {                                                           \
382         assert(sizeof(CTYPENAME) <= sizeof(asn1_uintmax));      \
383         return *(const aux_typedefname_##DESCNAME *)p;          \
384     }                                                           \
385     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
386         atype_uint, sizeof(CTYPENAME), 0, 0, 0, 0, 0, 0, 0, 0,  \
387         0, loaduint_##DESCNAME,                                 \
388     }
389 /* Pointers to other types, to be encoded as those other types.  */
390 #ifdef POINTERS_ARE_ALL_THE_SAME
391 #define DEFPTRTYPE(DESCNAME,BASEDESCNAME)                               \
392     typedef aux_typedefname_##BASEDESCNAME * aux_typedefname_##DESCNAME; \
393     const struct atype_info krb5int_asn1type_##DESCNAME = {             \
394         atype_ptr, sizeof(aux_typedefname_##DESCNAME), 0, 0, 0,         \
395         &krb5int_asn1type_##BASEDESCNAME, 0                             \
396     }
397 #else
398 #define DEFPTRTYPE(DESCNAME,BASEDESCNAME)                               \
399     typedef aux_typedefname_##BASEDESCNAME * aux_typedefname_##DESCNAME; \
400     static const void *                                                 \
401     loadptr_for_##BASEDESCNAME##_from_##DESCNAME(const void *p)         \
402     {                                                                   \
403         const aux_typedefname_##DESCNAME *inptr = p;                    \
404         const aux_typedefname_##BASEDESCNAME *retptr;                   \
405         retptr = *inptr;                                                \
406         return retptr;                                                  \
407     }                                                                   \
408     const struct atype_info krb5int_asn1type_##DESCNAME = {             \
409         atype_ptr, sizeof(aux_typedefname_##DESCNAME), 0, 0,            \
410         loadptr_for_##BASEDESCNAME##_from_##DESCNAME,                   \
411         &krb5int_asn1type_##BASEDESCNAME, 0                             \
412     }
413 #endif
414 /* This encodes a pointer-to-pointer-to-thing where the passed-in
415    value points to a null-terminated list of pointers to objects to be
416    encoded, and encodes a (possibly empty) SEQUENCE OF these objects.
417 
418    BASEDESCNAME is a descriptor name for the pointer-to-thing
419    type.
420 
421    When dealing with a structure containing a
422    pointer-to-pointer-to-thing field, make a DEFPTRTYPE of this type,
423    and use that type for the structure field.  */
424 #define DEFNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME)                     \
425     typedef aux_typedefname_##BASEDESCNAME aux_typedefname_##DESCNAME;  \
426     const struct atype_info krb5int_asn1type_##DESCNAME = {             \
427         atype_nullterm_sequence_of, sizeof(aux_typedefname_##DESCNAME), \
428         0, 0,                                                           \
429         0 /* loadptr */,                                                \
430         &krb5int_asn1type_##BASEDESCNAME, 0                             \
431     }
432 #define DEFNONEMPTYNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME)             \
433     typedef aux_typedefname_##BASEDESCNAME aux_typedefname_##DESCNAME;  \
434     const struct atype_info krb5int_asn1type_##DESCNAME = {             \
435         atype_nonempty_nullterm_sequence_of,                            \
436         sizeof(aux_typedefname_##DESCNAME),                             \
437         0, 0,                                                           \
438         0 /* loadptr */,                                                \
439         &krb5int_asn1type_##BASEDESCNAME, 0                             \
440     }
441 /* Encode a thing (probably sub-fields within the structure) as a
442    single object.  */
443 #define DEFFIELDTYPE(DESCNAME, CTYPENAME, FIELDINFO)                    \
444     typedef CTYPENAME aux_typedefname_##DESCNAME;                       \
445     static const struct field_info aux_fieldinfo_##DESCNAME = FIELDINFO; \
446     const struct atype_info krb5int_asn1type_##DESCNAME = {             \
447         atype_field, sizeof(CTYPENAME), 0, 0, 0, 0, 0,                  \
448         &aux_fieldinfo_##DESCNAME                                       \
449     }
450 /* Objects with an APPLICATION tag added.  */
451 #define DEFAPPTAGGEDTYPE(DESCNAME, TAG, BASEDESC)                       \
452     typedef aux_typedefname_##BASEDESC aux_typedefname_##DESCNAME;      \
453     const struct atype_info krb5int_asn1type_##DESCNAME = {             \
454         atype_tagged_thing, sizeof(aux_typedefname_##DESCNAME),         \
455         0, 0, 0, &krb5int_asn1type_##BASEDESC, 0, 0, TAG, APPLICATION   \
456     }
457 
458 /* Declare an externally-defined type.  This is a hack we should do
459    away with once we move to generating code from a script.  For now,
460    this macro is unfortunately not compatible with the defining macros
461    above, since you can't do the typedefs twice and we need the
462    declarations to produce typedefs.  (We could eliminate the typedefs
463    from the DEF* macros, but then every DEF* macro use, even the ones
464    for internal type nodes we only use to build other types, would
465    need an accompanying declaration which explicitly lists the
466    type.)  */
467 #define IMPORT_TYPE(DESCNAME, CTYPENAME)                        \
468     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
469     extern const struct atype_info krb5int_asn1type_##DESCNAME
470 
471 /* Create a partial-encoding function by the indicated name, for the
472    indicated type.  Should only be needed until we've converted all of
473    the encoders, then everything should use descriptor tables.  */
474 extern asn1_error_code
475 krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val,
476                             const struct atype_info *a, unsigned int *retlen);
477 #define MAKE_ENCFN(FNAME,DESC)                                          \
478    static asn1_error_code FNAME (asn1buf *buf,                          \
479                            const aux_typedefname_##DESC *val,           \
480                            unsigned int *retlen)                        \
481     {                                                                   \
482         return krb5int_asn1_encode_a_thing(buf, val,                    \
483                                            &krb5int_asn1type_##DESC,    \
484                                            retlen);                     \
485     }                                                                   \
486     extern int dummy /* gobble semicolon */
487 
488 /* Sequence field descriptor.
489 
490    Currently we assume everything is a single object with a type
491    descriptor, and then we bolt on some ugliness on the side for
492    handling strings with length fields.
493 
494    Anything with "interesting" encoding handling, like a sequence-of
495    or a pointer to the actual value to encode, is handled via opaque
496    types with their own encoder functions.  Most of that should
497    eventually change.  */
498 
499 enum field_type {
500     /* Unused except for range checking.  */
501     field_min = 1,
502     /* Field ATYPE describes processing of field at DATAOFF.  */
503     field_normal,
504     /* Encode an "immediate" integer value stored in DATAOFF, with no
505        reference to the data structure.  */
506     field_immediate,
507     /* Encode some kind of string field encoded with pointer and
508        length.  (A GENERALSTRING represented as a null-terminated C
509        string would be handled as field_normal.)  */
510     field_string,
511     /* LENOFF indicates a value describing the length of the array at
512        DATAOFF, encoded as a sequence-of with the element type
513        described by ATYPE.  */
514     field_sequenceof_len,
515     /* Unused except for range checking.  */
516     field_max
517 };
518 /* To do: Consider using bitfields.  */
519 struct field_info {
520     /* Type of the field.  */
521     unsigned int /* enum field_type */ ftype : 3;
522 
523     /* Use of DATAOFF and LENOFF are described by the value in FTYPE.
524        Generally DATAOFF will be the offset from the supplied pointer
525        at which we find the object to be encoded.  */
526     unsigned int dataoff : 9, lenoff : 9;
527 
528     /* If TAG is non-negative, a context tag with that value is added
529        to the encoding of the thing.  (XXX This would encode more
530        compactly as an unsigned bitfield value tagnum+1, with 0=no
531        tag.)  The tag is omitted for optional fields that are not
532        present.
533 
534        It's a bit illogical to combine the tag and other field info,
535        since really a sequence field could have zero or several
536        context tags, and of course a tag could be used elsewhere.  But
537        the normal mode in the Kerberos ASN.1 description is to use one
538        context tag on each sequence field, so for now let's address
539        that case primarily and work around the other cases (thus tag<0
540        means skip tagging).  */
541     signed int tag : 5;
542 
543     /* If OPT is non-negative and the sequence header structure has a
544        function pointer describing which fields are present, OPT is
545        the bit position indicating whether the currently-described
546        element is present.  (XXX Similar encoding issue.)
547 
548        Note: Most of the time, I'm using the same number here as for
549        the context tag.  This is just because it's easier for me to
550        keep track while working on the code by hand.  The *only*
551        meaningful correlation is of this value and the bits set by the
552        "optional" function when examining the data structure.  */
553     signed int opt : 5;
554 
555     /* For some values of FTYPE, this describes the type of the
556        object(s) to be encoded.  */
557     const struct atype_info *atype;
558 
559     /* We use different types for "length" fields in different places.
560        So we need a good way to retrieve the various kinds of lengths
561        in a compatible way.  This may be a string length, or the
562        length of an array of objects to encode in a SEQUENCE OF.
563 
564        In case the field is signed and negative, or larger than
565        size_t, return SIZE_MAX as an error indication.  We'll assume
566        for now that we'll never have 4G-1 (or 2**64-1, or on tiny
567        systems, 65535) sized values.  On most if not all systems we
568        care about, SIZE_MAX is equivalent to "all of addressable
569        memory" minus one byte.  That wouldn't leave enough extra room
570        for the structure we're encoding, so it's pretty safe to assume
571        SIZE_MAX won't legitimately come up on those systems.
572 
573        If this code gets ported to a segmented architecture or other
574        system where it might be possible... figure it out then.  */
575     const struct atype_info *lentype;
576 };
577 
578 /* Normal or optional sequence fields at a particular offset, encoded
579    as indicated by the listed DESCRiptor.  */
580 #define FIELDOF_OPT(TYPE,DESCR,FIELDNAME,TAG,OPT)                       \
581     {                                                                   \
582         field_normal, OFFOF(TYPE, FIELDNAME, aux_typedefname_##DESCR),  \
583         0, TAG, OPT, &krb5int_asn1type_##DESCR                          \
584     }
585 #define FIELDOF_NORM(TYPE,DESCR,FIELDNAME,TAG)  \
586     FIELDOF_OPT(TYPE,DESCR,FIELDNAME,TAG,-1)
587 /* If encoding a subset of the fields of the current structure (for
588    example, a flat structure describing data that gets encoded as a
589    sequence containing one or more sequences), use ENCODEAS, no struct
590    field name(s), and the indicated type descriptor must support the
591    current struct type.  */
592 #define FIELDOF_ENCODEAS(TYPE,DESCR,TAG) \
593     FIELDOF_ENCODEAS_OPT(TYPE,DESCR,TAG,-1)
594 #define FIELDOF_ENCODEAS_OPT(TYPE,DESCR,TAG,OPT)                        \
595     {                                                                   \
596         field_normal,                                                   \
597         0 * sizeof(0 ? (TYPE *)0 : (aux_typedefname_##DESCR *) 0),      \
598         0, TAG, OPT, &krb5int_asn1type_##DESCR                          \
599     }
600 
601 /* Reinterpret some subset of the structure itself as something
602    else.  */
603 #define FIELD_SELF(DESCR, TAG) \
604     { field_normal, 0, 0, TAG, -1, &krb5int_asn1type_##DESCR }
605 
606 #define FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG,OPT) \
607    {                                                                    \
608        field_string,                                                    \
609        OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC),                  \
610        OFFOF(STYPE, LENFIELD, aux_typedefname_##LENDESC),               \
611        TAG, OPT, &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENDESC  \
612    }
613 #define FIELDOF_OPTSTRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG,OPT)         \
614     FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,uint,LENFIELD,TAG,OPT)
615 #define FIELDOF_STRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG)       \
616     FIELDOF_OPTSTRINGL(STYPE,DESC,PTRFIELD,LENDESC,LENFIELD,TAG,-1)
617 #define FIELDOF_STRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG) \
618     FIELDOF_OPTSTRING(STYPE,DESC,PTRFIELD,LENFIELD,TAG,-1)
619 #define FIELD_INT_IMM(VALUE,TAG)   \
620     { field_immediate, VALUE, 0, TAG, -1, 0, }
621 
622 #define FIELDOF_SEQOF_LEN(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG)     \
623     {                                                                   \
624         field_sequenceof_len,                                           \
625         OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC),                 \
626         OFFOF(STYPE, LENFIELD, aux_typedefname_##LENTYPE),              \
627         TAG, -1, &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENTYPE  \
628     }
629 #define FIELDOF_SEQOF_INT32(STYPE,DESC,PTRFIELD,LENFIELD,TAG)   \
630     FIELDOF_SEQOF_LEN(STYPE,DESC,PTRFIELD,LENFIELD,int32,TAG)
631 
632 struct seq_info {
633     /* If present, returns a bitmask indicating which fields are
634        present.  See the "opt" field in struct field_info.  */
635     unsigned int (*optional)(const void *);
636     /* Indicates an array of sequence field descriptors.  */
637     const struct field_info *fields;
638     size_t n_fields;
639     /* Missing: Extensibility handling.  (New field type?)  */
640 };
641 
642 extern krb5_error_code
643 krb5int_asn1_do_full_encode(const void *rep, krb5_data **code,
644                             const struct atype_info *a);
645 
646 #define MAKE_FULL_ENCODER(FNAME, DESC)                                  \
647     krb5_error_code FNAME(const aux_typedefname_##DESC *rep,            \
648                           krb5_data **code)                             \
649     {                                                                   \
650         return krb5int_asn1_do_full_encode(rep, code,                   \
651                                            &krb5int_asn1type_##DESC);   \
652     }                                                                   \
653     extern int dummy /* gobble semicolon */
654 
655 #include <stddef.h>
656 /* Ugly hack!
657    Like "offsetof", but with type checking.  */
658 #define WARN_IF_TYPE_MISMATCH(LVALUE, TYPE)  \
659     (sizeof(0 ? (TYPE *) 0 : &(LVALUE)))
660 #define OFFOF(TYPE,FIELD,FTYPE)                                 \
661     (offsetof(TYPE, FIELD)                                      \
662      + 0 * WARN_IF_TYPE_MISMATCH(((TYPE*)0)->FIELD, FTYPE))
663 
664 #endif
665