xref: /freebsd/crypto/krb5/src/lib/krb5/asn.1/asn1_encode.h (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/asn.1/asn1_encode.h */
3 /*
4  * Copyright 1994, 2008 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 #ifndef __ASN1_ENCODE_H__
28 #define __ASN1_ENCODE_H__
29 
30 #include "k5-int.h"
31 #include "krbasn1.h"
32 #include <time.h>
33 
34 typedef struct asn1buf_st asn1buf;
35 
36 typedef struct {
37     asn1_class asn1class;
38     asn1_construction construction;
39     asn1_tagnum tagnum;
40 
41     /* When decoding, stores the leading length of a tag.  Used by
42      * store_der(). */
43     size_t tag_len;
44 } taginfo;
45 
46 /* These functions are referenced by encoder structures.  They handle the
47  * encoding of primitive ASN.1 types. */
48 void k5_asn1_encode_bool(asn1buf *buf, intmax_t val);
49 void k5_asn1_encode_int(asn1buf *buf, intmax_t val);
50 void k5_asn1_encode_uint(asn1buf *buf, uintmax_t val);
51 krb5_error_code k5_asn1_encode_bytestring(asn1buf *buf, uint8_t *const *val,
52                                           size_t len);
53 krb5_error_code k5_asn1_encode_bitstring(asn1buf *buf, uint8_t *const *val,
54                                          size_t len);
55 krb5_error_code k5_asn1_encode_generaltime(asn1buf *buf, time_t val);
56 
57 /* These functions are referenced by encoder structures.  They handle the
58  * decoding of primitive ASN.1 types. */
59 krb5_error_code k5_asn1_decode_bool(const uint8_t *asn1, size_t len,
60                                     intmax_t *val);
61 krb5_error_code k5_asn1_decode_int(const uint8_t *asn1, size_t len,
62                                    intmax_t *val);
63 krb5_error_code k5_asn1_decode_uint(const uint8_t *asn1, size_t len,
64                                     uintmax_t *val);
65 krb5_error_code k5_asn1_decode_generaltime(const uint8_t *asn1, size_t len,
66                                            time_t *time_out);
67 krb5_error_code k5_asn1_decode_bytestring(const uint8_t *asn1, size_t len,
68                                           uint8_t **str_out, size_t *len_out);
69 krb5_error_code k5_asn1_decode_bitstring(const uint8_t *asn1, size_t len,
70                                          uint8_t **bits_out, size_t *len_out);
71 
72 /*
73  * An atype_info structure specifies how to map a C object to an ASN.1 value.
74  *
75  * We wind up with a lot of load-time relocations being done, which is
76  * a bit annoying.  Be careful about "fixing" that at the cost of too
77  * much run-time performance.  It might work to have a master "module"
78  * descriptor with pointers to various arrays (type descriptors,
79  * strings, field descriptors, functions) most of which don't need
80  * relocation themselves, and replace most of the pointers with table
81  * indices.
82  *
83  * It's a work in progress.
84  */
85 
86 enum atype_type {
87     /* For bounds checking only.  By starting with 2, we guarantee that
88      * zero-initialized storage will be recognized as invalid. */
89     atype_min = 1,
90     /* Use a function table to handle encoding or decoding.  tinfo is a struct
91      * fn_info *. */
92     atype_fn,
93     /* C object is a pointer to the object to be encoded or decoded.  tinfo is
94      * a struct ptr_info *. */
95     atype_ptr,
96     /* C object to be encoded or decoded is at an offset from the original
97      * pointer.  tinfo is a struct offset_info *. */
98     atype_offset,
99     /*
100      * Indicates a sequence field which may or may not be present in the C
101      * object or ASN.1 sequence.  tinfo is a struct optional_info *.  Must be
102      * used within a sequence, although the optional type may be nested within
103      * offset, ptr, and/or tag types.
104      */
105     atype_optional,
106     /*
107      * C object contains an integer and another C object at specified offsets,
108      * to be combined and encoded or decoded as specified by a cntype_info
109      * structure.  tinfo is a struct counted_info *.
110      */
111     atype_counted,
112     /* Sequence.  tinfo is a struct seq_info *. */
113     atype_sequence,
114     /*
115      * Sequence-of, with pointer to base type descriptor, represented as a
116      * null-terminated array of pointers (and thus the "base" type descriptor
117      * is actually an atype_ptr node).  tinfo is a struct atype_info * giving
118      * the base type.
119      */
120     atype_nullterm_sequence_of,
121     atype_nonempty_nullterm_sequence_of,
122     /* Tagged version of another type.  tinfo is a struct tagged_info *. */
123     atype_tagged_thing,
124     /* Boolean value.  tinfo is NULL (size field determines C type width). */
125     atype_bool,
126     /* Signed or unsigned integer.  tinfo is NULL. */
127     atype_int,
128     atype_uint,
129     /*
130      * Integer value taken from the type info, not from the object being
131      * encoded.  tinfo is a struct immediate_info * giving the integer value
132      * and error code to return if a decoded object doesn't match it (or 0 if
133      * the value shouldn't be checked on decode).
134      */
135     atype_int_immediate,
136     /* Unused except for bounds checking.  */
137     atype_max
138 };
139 
140 struct atype_info {
141     enum atype_type type;
142     size_t size;                /* Used for sequence-of processing */
143     const void *tinfo;          /* Points to type-specific structure */
144 };
145 
146 struct fn_info {
147     krb5_error_code (*enc)(asn1buf *, const void *, taginfo *);
148     krb5_error_code (*dec)(const taginfo *, const uint8_t *, size_t, void *);
149     int (*check_tag)(const taginfo *);
150     void (*free_func)(void *);
151 };
152 
153 struct ptr_info {
154     void *(*loadptr)(const void *);
155     void (*storeptr)(void *, void *);
156     const struct atype_info *basetype;
157 };
158 
159 struct offset_info {
160     unsigned int dataoff : 9;
161     const struct atype_info *basetype;
162 };
163 
164 struct optional_info {
165     int (*is_present)(const void *);
166     void (*init)(void *);
167     const struct atype_info *basetype;
168 };
169 
170 struct counted_info {
171     unsigned int dataoff : 9;
172     unsigned int lenoff : 9;
173     unsigned int lensigned : 1;
174     unsigned int lensize : 5;
175     const struct cntype_info *basetype;
176 };
177 
178 struct tagged_info {
179     unsigned int tagval : 16, tagtype : 8, construction : 6, implicit : 1;
180     const struct atype_info *basetype;
181 };
182 
183 struct immediate_info {
184     intmax_t val;
185     krb5_error_code err;
186 };
187 
188 /* A cntype_info structure specifies how to map a C object and count (length or
189  * union distinguisher) to an ASN.1 value. */
190 
191 enum cntype_type {
192     cntype_min = 1,
193 
194     /*
195      * Apply an encoder function (contents only) and wrap it in a universal
196      * primitive tag.  The C object must be a char * or uint8_t *.  tinfo
197      * is a struct string_info *.
198      */
199     cntype_string,
200 
201     /*
202      * The C object is a DER encoding (with tag), to be simply inserted on
203      * encode or stored on decode.  The C object must be a char * or unsigned
204      * char *.  tinfo is NULL.
205      */
206     cntype_der,
207 
208     /* An ASN.1 sequence-of value, represtened in C as a counted array.  struct
209      * atype_info * giving the base type, which must be of type atype_ptr. */
210     cntype_seqof,
211 
212     /* An ASN.1 choice, represented in C as a distinguisher and union.  tinfo
213      * is a struct choice_info *. */
214     cntype_choice,
215 
216     cntype_max
217 };
218 
219 struct cntype_info {
220     enum cntype_type type;
221     const void *tinfo;
222 };
223 
224 struct string_info {
225     krb5_error_code (*enc)(asn1buf *, uint8_t *const *, size_t);
226     krb5_error_code (*dec)(const uint8_t *, size_t, uint8_t **, size_t *);
227     unsigned int tagval : 5;
228 };
229 
230 struct choice_info {
231     const struct atype_info **options;
232     size_t n_options;
233 };
234 
235 struct seq_info {
236     const struct atype_info **fields;
237     size_t n_fields;
238     /* Currently all sequences are assumed to be extensible. */
239 };
240 
241 /*
242  * The various DEF*TYPE macros must:
243  *
244  * + Define a type named aux_type_##DESCNAME, for use in any types derived from
245  *   the type being defined.
246  *
247  * + Define an atype_info struct named k5_atype_##DESCNAME
248  *
249  * + Define a type-specific structure, referenced by the tinfo field
250  *   of the atype_info structure.
251  *
252  * + Define any extra stuff needed in the type descriptor, like
253  *   pointer-load functions.
254  *
255  * + Accept a following semicolon syntactically, to keep Emacs parsing
256  *   (and indentation calculating) code happy.
257  *
258  * Nothing else should directly define the atype_info structures.
259  */
260 
261 /* Define a type using a function table. */
262 #define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN, DECFN, CHECKFN, FREEFN)   \
263     typedef CTYPENAME aux_type_##DESCNAME;                              \
264     static const struct fn_info aux_info_##DESCNAME = {                 \
265         ENCFN, DECFN, CHECKFN, FREEFN                                   \
266     };                                                                  \
267     const struct atype_info k5_atype_##DESCNAME = {                     \
268         atype_fn, sizeof(CTYPENAME), &aux_info_##DESCNAME               \
269     }
270 /* A sequence, defined by the indicated series of types, and an optional
271  * function indicating which fields are not present. */
272 #define DEFSEQTYPE(DESCNAME, CTYPENAME, FIELDS)                         \
273     typedef CTYPENAME aux_type_##DESCNAME;                              \
274     static const struct seq_info aux_seqinfo_##DESCNAME = {             \
275         FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0])                        \
276     };                                                                  \
277     const struct atype_info k5_atype_##DESCNAME = {                     \
278         atype_sequence, sizeof(CTYPENAME), &aux_seqinfo_##DESCNAME      \
279     }
280 /* A boolean type. */
281 #define DEFBOOLTYPE(DESCNAME, CTYPENAME)                        \
282     typedef CTYPENAME aux_type_##DESCNAME;                      \
283     const struct atype_info k5_atype_##DESCNAME = {             \
284         atype_bool, sizeof(CTYPENAME), NULL                     \
285     }
286 /* Integer types.  */
287 #define DEFINTTYPE(DESCNAME, CTYPENAME)                         \
288     typedef CTYPENAME aux_type_##DESCNAME;                      \
289     const struct atype_info k5_atype_##DESCNAME = {             \
290         atype_int, sizeof(CTYPENAME), NULL                      \
291     }
292 #define DEFUINTTYPE(DESCNAME, CTYPENAME)                        \
293     typedef CTYPENAME aux_type_##DESCNAME;                      \
294     const struct atype_info k5_atype_##DESCNAME = {             \
295         atype_uint, sizeof(CTYPENAME), NULL                     \
296     }
297 #define DEFINT_IMMEDIATE(DESCNAME, VAL, ERR)                    \
298     typedef int aux_type_##DESCNAME;                            \
299     static const struct immediate_info aux_info_##DESCNAME = {  \
300         VAL, ERR                                                \
301     };                                                          \
302     const struct atype_info k5_atype_##DESCNAME = {             \
303         atype_int_immediate, 0, &aux_info_##DESCNAME            \
304     }
305 
306 /* Pointers to other types, to be encoded as those other types.  */
307 #ifdef POINTERS_ARE_ALL_THE_SAME
308 #define DEFPTRTYPE(DESCNAME,BASEDESCNAME)                       \
309     typedef aux_type_##BASEDESCNAME *aux_type_##DESCNAME;       \
310     static const struct ptr_info aux_info_##DESCNAME = {        \
311         NULL, NULL, &k5_atype_##BASEDESCNAME                    \
312     };                                                          \
313     const struct atype_info k5_atype_##DESCNAME = {             \
314         atype_ptr, sizeof(aux_type_##DESCNAME),                 \
315         &aux_info_##DESCNAME                                    \
316     }
317 #else
318 #define DEFPTRTYPE(DESCNAME,BASEDESCNAME)                       \
319     typedef aux_type_##BASEDESCNAME *aux_type_##DESCNAME;       \
320     static void *                                               \
321     aux_loadptr_##DESCNAME(const void *p)                       \
322     {                                                           \
323         return *(aux_type_##DESCNAME *)p;                       \
324     }                                                           \
325     static void                                                 \
326     aux_storeptr_##DESCNAME(void *ptr, void *val)               \
327     {                                                           \
328         *(aux_type_##DESCNAME *)val = ptr;                      \
329     }                                                           \
330     static const struct ptr_info aux_info_##DESCNAME = {        \
331         aux_loadptr_##DESCNAME, aux_storeptr_##DESCNAME,        \
332         &k5_atype_##BASEDESCNAME                                \
333     };                                                          \
334     const struct atype_info k5_atype_##DESCNAME = {             \
335         atype_ptr, sizeof(aux_type_##DESCNAME),                 \
336         &aux_info_##DESCNAME                                    \
337     }
338 #endif
339 #define DEFOFFSETTYPE(DESCNAME, STYPE, FIELDNAME, BASEDESC)     \
340     typedef STYPE aux_type_##DESCNAME;                          \
341     static const struct offset_info aux_info_##DESCNAME = {     \
342         OFFOF(STYPE, FIELDNAME, aux_type_##BASEDESC),           \
343         &k5_atype_##BASEDESC                                    \
344     };                                                          \
345     const struct atype_info k5_atype_##DESCNAME = {             \
346         atype_offset, sizeof(aux_type_##DESCNAME),              \
347         &aux_info_##DESCNAME                                    \
348     }
349 #define DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, SIGNED, \
350                             CDESC)                                      \
351     typedef STYPE aux_type_##DESCNAME;                                  \
352     const struct counted_info aux_info_##DESCNAME = {                   \
353         OFFOF(STYPE, DATAFIELD, aux_ptrtype_##CDESC),                   \
354         OFFOF(STYPE, COUNTFIELD, aux_counttype_##CDESC),                \
355         SIGNED, sizeof(((STYPE*)0)->COUNTFIELD),                        \
356         &k5_cntype_##CDESC                                              \
357     };                                                                  \
358     const struct atype_info k5_atype_##DESCNAME = {                     \
359         atype_counted, sizeof(STYPE),                                   \
360         &aux_info_##DESCNAME                                            \
361     }
362 #define DEFCOUNTEDTYPE(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, CDESC) \
363     DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, 0, CDESC)
364 #define DEFCOUNTEDTYPE_SIGNED(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, CDESC) \
365     DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, 1, CDESC)
366 
367 /* Optional sequence fields.  The basic form allows arbitrary test and
368  * initializer functions to be used.  INIT may be null. */
369 #define DEFOPTIONALTYPE(DESCNAME, PRESENT, INIT, BASEDESC)       \
370     typedef aux_type_##BASEDESC aux_type_##DESCNAME;             \
371     static const struct optional_info aux_info_##DESCNAME = {   \
372         PRESENT, INIT, &k5_atype_##BASEDESC                     \
373     };                                                          \
374     const struct atype_info k5_atype_##DESCNAME = {             \
375         atype_optional, sizeof(aux_type_##DESCNAME),            \
376         &aux_info_##DESCNAME                                    \
377     }
378 /* This form defines an is_present function for a zero-valued integer or null
379  * pointer of the base type's C type. */
380 #define DEFOPTIONALZEROTYPE(DESCNAME, BASEDESC)                         \
381     static int                                                          \
382     aux_present_##DESCNAME(const void *p)                               \
383     {                                                                   \
384         return *(aux_type_##BASEDESC *)p != 0;                          \
385     }                                                                   \
386     DEFOPTIONALTYPE(DESCNAME, aux_present_##DESCNAME, NULL, BASEDESC)
387 /* This form defines an is_present function for a null or empty null-terminated
388  * array of the base type's C type. */
389 #define DEFOPTIONALEMPTYTYPE(DESCNAME, BASEDESC)                        \
390     static int                                                          \
391     aux_present_##DESCNAME(const void *p)                               \
392     {                                                                   \
393         const aux_type_##BASEDESC *val = p;                             \
394         return (*val != NULL && **val != NULL);                         \
395     }                                                                   \
396     DEFOPTIONALTYPE(DESCNAME, aux_present_##DESCNAME, NULL, BASEDESC)
397 
398 /*
399  * This encodes a pointer-to-pointer-to-thing where the passed-in
400  * value points to a null-terminated list of pointers to objects to be
401  * encoded, and encodes a (possibly empty) SEQUENCE OF these objects.
402  *
403  * BASEDESCNAME is a descriptor name for the pointer-to-thing
404  * type.
405  *
406  * When dealing with a structure containing a
407  * pointer-to-pointer-to-thing field, make a DEFPTRTYPE of this type,
408  * and use that type for the structure field.
409  */
410 #define DEFNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME)                     \
411     typedef aux_type_##BASEDESCNAME aux_type_##DESCNAME;                \
412     const struct atype_info k5_atype_##DESCNAME = {                     \
413         atype_nullterm_sequence_of, sizeof(aux_type_##DESCNAME),        \
414         &k5_atype_##BASEDESCNAME                                        \
415     }
416 #define DEFNONEMPTYNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME)     \
417     typedef aux_type_##BASEDESCNAME aux_type_##DESCNAME;        \
418     const struct atype_info k5_atype_##DESCNAME = {             \
419         atype_nonempty_nullterm_sequence_of,                    \
420         sizeof(aux_type_##DESCNAME),                            \
421         &k5_atype_##BASEDESCNAME                                \
422     }
423 
424 /* Objects with an explicit or implicit tag.  (Implicit tags will ignore the
425  * construction field.) */
426 #define DEFTAGGEDTYPE(DESCNAME, CLASS, CONSTRUCTION, TAG, IMPLICIT, BASEDESC) \
427     typedef aux_type_##BASEDESC aux_type_##DESCNAME;                    \
428     static const struct tagged_info aux_info_##DESCNAME = {             \
429         TAG, CLASS, CONSTRUCTION, IMPLICIT, &k5_atype_##BASEDESC        \
430     };                                                                  \
431     const struct atype_info k5_atype_##DESCNAME = {                     \
432         atype_tagged_thing, sizeof(aux_type_##DESCNAME),                \
433         &aux_info_##DESCNAME                                            \
434     }
435 /* Objects with an explicit APPLICATION tag added.  */
436 #define DEFAPPTAGGEDTYPE(DESCNAME, TAG, BASEDESC)                       \
437     DEFTAGGEDTYPE(DESCNAME, APPLICATION, CONSTRUCTED, TAG, 0, BASEDESC)
438 /* Object with a context-specific tag added */
439 #define DEFCTAGGEDTYPE(DESCNAME, TAG, BASEDESC)                         \
440     DEFTAGGEDTYPE(DESCNAME, CONTEXT_SPECIFIC, CONSTRUCTED, TAG, 0, BASEDESC)
441 #define DEFCTAGGEDTYPE_IMPLICIT(DESCNAME, TAG, BASEDESC)                \
442     DEFTAGGEDTYPE(DESCNAME, CONTEXT_SPECIFIC, CONSTRUCTED, TAG, 1, BASEDESC)
443 
444 /* Define an offset type with an explicit context tag wrapper (the usual case
445  * for an RFC 4120 sequence field). */
446 #define DEFFIELD(NAME, STYPE, FIELDNAME, TAG, DESC)                     \
447     DEFOFFSETTYPE(NAME##_untagged, STYPE, FIELDNAME, DESC);             \
448     DEFCTAGGEDTYPE(NAME, TAG, NAME##_untagged)
449 /* Define a counted type with an explicit context tag wrapper. */
450 #define DEFCNFIELD(NAME, STYPE, DATAFIELD, LENFIELD, TAG, CDESC)        \
451     DEFCOUNTEDTYPE(NAME##_untagged, STYPE, DATAFIELD, LENFIELD, CDESC); \
452     DEFCTAGGEDTYPE(NAME, TAG, NAME##_untagged)
453 /* Like DEFFIELD but with an implicit context tag. */
454 #define DEFFIELD_IMPLICIT(NAME, STYPE, FIELDNAME, TAG, DESC)            \
455     DEFOFFSETTYPE(NAME##_untagged, STYPE, FIELDNAME, DESC);             \
456     DEFCTAGGEDTYPE_IMPLICIT(NAME, TAG, NAME##_untagged)
457 
458 /*
459  * DEFCOUNTED*TYPE macros must:
460  *
461  * + Define types named aux_ptrtype_##DESCNAME and aux_counttype_##DESCNAME, to
462  *   allow type checking when the counted type is referenced with structure
463  *   field offsets in DEFCOUNTEDTYPE.
464  *
465  * + Define a cntype_info struct named k5_cntype_##DESCNAME
466  *
467  * + Define a type-specific structure, referenced by the tinfo field of the
468  *   cntype_info structure.
469  *
470  * + Accept a following semicolon syntactically.
471  */
472 
473 #define DEFCOUNTEDSTRINGTYPE(DESCNAME, DTYPE, LTYPE, ENCFN, DECFN, TAGVAL) \
474     typedef DTYPE aux_ptrtype_##DESCNAME;                               \
475     typedef LTYPE aux_counttype_##DESCNAME;                             \
476     static const struct string_info aux_info_##DESCNAME = {             \
477         ENCFN, DECFN, TAGVAL                                            \
478     };                                                                  \
479     const struct cntype_info k5_cntype_##DESCNAME = {                   \
480         cntype_string, &aux_info_##DESCNAME                             \
481     }
482 
483 #define DEFCOUNTEDDERTYPE(DESCNAME, DTYPE, LTYPE)               \
484     typedef DTYPE aux_ptrtype_##DESCNAME;                       \
485     typedef LTYPE aux_counttype_##DESCNAME;                     \
486     const struct cntype_info k5_cntype_##DESCNAME = {           \
487         cntype_der, NULL                                        \
488     }
489 
490 #define DEFCOUNTEDSEQOFTYPE(DESCNAME, LTYPE, BASEDESC)          \
491     typedef aux_type_##BASEDESC aux_ptrtype_##DESCNAME;         \
492     typedef LTYPE aux_counttype_##DESCNAME;                     \
493     const struct cntype_info k5_cntype_##DESCNAME = {           \
494         cntype_seqof, &k5_atype_##BASEDESC                      \
495     }
496 
497 #define DEFCHOICETYPE(DESCNAME, UTYPE, DTYPE, FIELDS)           \
498     typedef UTYPE aux_ptrtype_##DESCNAME;                       \
499     typedef DTYPE aux_counttype_##DESCNAME;                     \
500     static const struct choice_info aux_info_##DESCNAME = {     \
501         FIELDS, sizeof(FIELDS) / sizeof(FIELDS[0])              \
502     };                                                          \
503     const struct cntype_info k5_cntype_##DESCNAME = {           \
504         cntype_choice, &aux_info_##DESCNAME                     \
505     }
506 
507 /*
508  * Declare an externally-defined type.  This is a hack we should do
509  * away with once we move to generating code from a script.  For now,
510  * this macro is unfortunately not compatible with the defining macros
511  * above, since you can't do the typedefs twice and we need the
512  * declarations to produce typedefs.  (We could eliminate the typedefs
513  * from the DEF* macros, but then every DEF* macro use, even the ones
514  * for internal type nodes we only use to build other types, would
515  * need an accompanying declaration which explicitly lists the
516  * type.)
517  */
518 #define IMPORT_TYPE(DESCNAME, CTYPENAME)                        \
519     typedef CTYPENAME aux_type_##DESCNAME;                      \
520     extern const struct atype_info k5_atype_##DESCNAME
521 
522 /* Partially encode the contents of a type and return its tag information.
523  * Used only by kdc_req_body. */
524 krb5_error_code
525 k5_asn1_encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
526                      taginfo *tag_out);
527 
528 /* Decode the tag and contents of a type, storing the result in the
529  * caller-allocated C object val.  Used only by kdc_req_body. */
530 krb5_error_code
531 k5_asn1_decode_atype(const taginfo *t, const uint8_t *asn1, size_t len,
532                      const struct atype_info *a, void *val);
533 
534 /* Returns a completed encoding, with tag and in the correct byte order, in an
535  * allocated krb5_data. */
536 extern krb5_error_code
537 k5_asn1_full_encode(const void *rep, const struct atype_info *a,
538                     krb5_data **code_out);
539 krb5_error_code
540 k5_asn1_full_decode(const krb5_data *code, const struct atype_info *a,
541                     void **rep_out);
542 
543 #define MAKE_ENCODER(FNAME, DESC)                                       \
544     krb5_error_code                                                     \
545     FNAME(const aux_type_##DESC *rep, krb5_data **code_out)             \
546     {                                                                   \
547         return k5_asn1_full_encode(rep, &k5_atype_##DESC, code_out);    \
548     }                                                                   \
549     extern int dummy /* gobble semicolon */
550 
551 #define MAKE_DECODER(FNAME, DESC)                                       \
552     krb5_error_code                                                     \
553     FNAME(const krb5_data *code, aux_type_##DESC **rep_out)             \
554     {                                                                   \
555         krb5_error_code ret;                                            \
556         void *rep;                                                      \
557         *rep_out = NULL;                                                \
558         ret = k5_asn1_full_decode(code, &k5_atype_##DESC, &rep);        \
559         if (ret)                                                        \
560             return ret;                                                 \
561         *rep_out = rep;                                                 \
562         return 0;                                                       \
563     }                                                                   \
564     extern int dummy /* gobble semicolon */
565 
566 #include <stddef.h>
567 /*
568  * Ugly hack!
569  * Like "offsetof", but with type checking.
570  */
571 #define WARN_IF_TYPE_MISMATCH(LVALUE, TYPE)     \
572     (sizeof(0 ? (TYPE *) 0 : &(LVALUE)))
573 #define OFFOF(TYPE,FIELD,FTYPE)                                 \
574     (offsetof(TYPE, FIELD)                                      \
575      + 0 * WARN_IF_TYPE_MISMATCH(((TYPE*)0)->FIELD, FTYPE))
576 
577 #endif
578