2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2N/A * Copyright 1994, 2008 by the Massachusetts Institute of Technology. 2N/A * All Rights Reserved. 2N/A * Export of this software from the United States of America may 2N/A * require a specific license from the United States Government. 2N/A * It is the responsibility of any person or organization contemplating 2N/A * export to obtain such a license before exporting. 2N/A * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 2N/A * distribute this software and its documentation for any purpose and 2N/A * without fee is hereby granted, provided that the above copyright 2N/A * notice appear in all copies and that both that copyright notice and 2N/A * this permission notice appear in supporting documentation, and that 2N/A * the name of M.I.T. not be used in advertising or publicity pertaining 2N/A * to distribution of the software without specific, written prior 2N/A * permission. Furthermore if you modify this software you must label 2N/A * your software as modified software and not distribute it in such a 2N/A * fashion that it might be confused with the original M.I.T. software. 2N/A * M.I.T. makes no representations about the suitability of 2N/A * this software for any purpose. It is provided "as is" without express 2N/A * or implied warranty. 2N/A * Each of these procedures inserts the encoding of an ASN.1 2N/A * primitive in a coding buffer. 2N/A * asn1_encode_boolean 2N/A * asn1_encode_integer 2N/A * asn1_encode_unsigned_integer 2N/A * asn1_encode_octetstring 2N/A * asn1_encode_generaltime 2N/A * asn1_encode_generalstring 2N/A * asn1_encode_bitstring 2N/A * requires *buf is allocated 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of NULL into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * Note: The encoding of GeneralizedTime is YYYYMMDDhhmmZ 2N/A * requires *buf is allocated, val has a length of len characters 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated, val has a length of len characters 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * requires *buf is allocated, val has a length of len characters 2N/A * modifies *buf, *retlen 2N/A * effects Inserts the encoding of val into *buf and returns 2N/A * the length of the encoding in *retlen. 2N/A * Returns ENOMEM to signal an unsuccesful attempt 2N/A * to expand the buffer. 2N/A * Type descriptor info. 2N/A * In this context, a "type" is a combination of a C data type 2N/A * and an ASN.1 encoding scheme for it. So we would have to define 2N/A * different "types" for: 2N/A * * unsigned char* encoded as octet string 2N/A * * char* encoded as octet string 2N/A * * char* encoded as generalstring 2N/A * * krb5_data encoded as octet string 2N/A * * krb5_data encoded as generalstring 2N/A * * int32_t encoded as integer 2N/A * * unsigned char encoded as integer 2N/A * Perhaps someday some kind of flags could be defined so that minor 2N/A * variations on the C types could be handled via common routines. 2N/A * The handling of strings is pretty messy. Currently, we have a 2N/A * separate kind of encoder function that takes an extra length 2N/A * parameter. Perhaps we should just give up on that, always deal 2N/A * with just a single location, and handle strings by via encoder 2N/A * functions for krb5_data, keyblock, etc. 2N/A * We wind up with a lot of load-time relocations being done, which is 2N/A * a bit annoying. Be careful about "fixing" that at the cost of too 2N/A * much run-time performance. It might work to have a master "module" 2N/A * descriptor with pointers to various arrays (type descriptors, 2N/A * strings, field descriptors, functions) most of which don't need 2N/A * relocation themselves, and replace most of the pointers with table 2N/A * It's a work in progress. 2N/A * For bounds checking only. By starting with values above 1, we 2N/A * guarantee that zero-initialized storage will be recognized as 2N/A /* Encoder function to be called with address of <thing>. */ 2N/A * Encoder function to be called with address of <thing> and a 2N/A * length (unsigned int). 2N/A * Pointer to actual thing to be encoded. 2N/A * Most of the fields are related only to the C type -- size, how 2N/A * to fetch a pointer in a type-safe fashion -- but since the base 2N/A * type descriptor encapsulates the encoding as well, different 2N/A * encodings for the same C type may require different pointer-to 2N/A * Must not refer to atype_fn_len. 2N/A /* Sequence, with pointer to sequence descriptor header. */ 2N/A * Sequence-of, with pointer to base type descriptor, represented 2N/A * as a null-terminated array of pointers (and thus the "base" 2N/A * type descriptor is actually an atype_ptr node). 2N/A * Encode this object using a single field descriptor. This may 2N/A * Main expected uses: Encode realm component of principal as a 2N/A * GENERALSTRING. Pluck data and length fields out of a structure 2N/A * and encode a counted SEQUENCE OF. 2N/A /* Tagged version of another type. */ 2N/A /* Integer types. */ 2N/A /* Unused except for bounds checking. */ 2N/A * Initialized structures could be a lot smaller if we could use C99 2N/A * designated initializers, and a union for all the type-specific 2N/A * stuff. Maybe use the hack we use for krb5int_access, where we use 2N/A * a run-time initialize if the compiler doesn't support designated 2N/A * initializers? That's a lot of work here, though, with so many 2N/A * little structures. Maybe if/when these get auto-generated. 2N/A /* used for sequence-of processing */ 2N/A /* atype_ptr, atype_fn_len */ 2N/A /* atype_ptr, atype_nullterm_sequence_of */ 2N/A /* atype_sequence */ 2N/A /* atype_tagged_thing */ 2N/A * The various DEF*TYPE macros must: 2N/A * + Define a type named aux_typedefname_##DESCNAME, for use in any 2N/A * types derived from the type being defined. 2N/A * + Define an atype_info struct named krb5int_asn1type_##DESCNAME. 2N/A * + Define any extra stuff needed in the type descriptor, like 2N/A * pointer-load functions. 2N/A * + Accept a following semicolon syntactically, to keep Emacs parsing 2N/A * (and indentation calculating) code happy. 2N/A * Nothing else should directly define the atype_info structures. 2N/A * Define a type for which we must use an explicit encoder function. 2N/A * The DEFFNTYPE variant uses a function taking a void*, the 2N/A * DEFFNXTYPE form wants a function taking a pointer to the actual C 2N/A * type to be encoded; you should use the latter unless you've already 2N/A * got the void* function supplied elsewhere. 2N/A * Of course, we need a single, consistent type for the descriptor 2N/A * structure field, so we use the function pointer type that uses 2N/A * void*, and create a wrapper function in DEFFNXTYPE. However, in 2N/A * all our cases so far, the supplied function is static and not used 2N/A * otherwise, so the compiler can merge it with the wrapper function 2N/A * if the optimizer is good enough. 2N/A * XXX The handling of data+length fields really needs reworking. 2N/A * A type descriptor probably isn't the right way. 2N/A * Also, the C type is likely to be one of char*, unsigned char*, 2N/A * or (maybe) void*. An enumerator or reference to an external 2N/A * function would be more compact. 2N/A * The supplied encoder function takes as an argument the data pointer 2N/A * loaded from the indicated location, not the address of the field. 2N/A * This isn't consistent with DEFFN[X]TYPE above, but all of the uses 2N/A * of DEFFNLENTYPE are for string encodings, and that's how our 2N/A * string-encoding primitives work. So be it. 2N/A * A sequence, defined by the indicated series of fields, and an 2N/A * optional function indicating which fields are present. 2N/A atype_int,
sizeof(
CTYPENAME), 0, 0, 0, 0, 0, 0, 0, 0, \
2N/A atype_uint,
sizeof(
CTYPENAME), 0, 0, 0, 0, 0, 0, 0, 0, \
2N/A/* Pointers to other types, to be encoded as those other types. */ 2N/A static const void * \
2N/A * This encodes a pointer-to-pointer-to-thing where the passed-in 2N/A * value points to a null-terminated list of pointers to objects to be 2N/A * encoded, and encodes a (possibly empty) SEQUENCE OF these objects. 2N/A * BASEDESCNAME is a descriptor name for the pointer-to-thing 2N/A * When dealing with a structure containing a 2N/A * pointer-to-pointer-to-thing field, make a DEFPTRTYPE of this type, 2N/A * and use that type for the structure field. 2N/A * Encode a thing (probably sub-fields within the structure) as a 2N/A/* Objects with an APPLICATION tag added. */ 2N/A * Declare an externally-defined type. This is a hack we should do 2N/A * away with once we move to generating code from a script. For now, 2N/A * this macro is unfortunately not compatible with the defining macros 2N/A * above, since you can't do the typedefs twice and we need the 2N/A * declarations to produce typedefs. (We could eliminate the typedefs 2N/A * from the DEF* macros, but then every DEF* macro use, even the ones 2N/A * for internal type nodes we only use to build other types, would 2N/A * need an accompanying declaration which explicitly lists the 2N/A * Create a partial-encoding function by the indicated name, for the 2N/A * indicated type. Should only be needed until we've converted all of 2N/A * the encoders, then everything should use descriptor tables. 2N/A * Sequence field descriptor. 2N/A * Currently we assume everything is a single object with a type 2N/A * descriptor, and then we bolt on some ugliness on the side for 2N/A * handling strings with length fields. 2N/A * Anything with "interesting" encoding handling, like a sequence-of 2N/A * or a pointer to the actual value to encode, is handled via opaque 2N/A * types with their own encoder functions. Most of that should 2N/A * eventually change. 2N/A /* Unused except for range checking. */ 2N/A /* Field ATYPE describes processing of field at DATAOFF. */ 2N/A * Encode an "immediate" integer value stored in DATAOFF, with no 2N/A * reference to the data structure. 2N/A * Encode some kind of string field encoded with pointer and 2N/A * length. (A GENERALSTRING represented as a null-terminated C 2N/A * string would be handled as field_normal.) 2N/A * LENOFF indicates a value describing the length of the array at 2N/A * DATAOFF, encoded as a sequence-of with the element type 2N/A * described by ATYPE. 2N/A /* Unused except for range checking. */ 2N/A/* To do: Consider using bitfields. */ 2N/A /* Type of the field. */ 2N/A unsigned int /* enum field_type */ ftype :
3;
2N/A * Use of DATAOFF and LENOFF are described by the value in FTYPE. 2N/A * Generally DATAOFF will be the offset from the supplied pointer 2N/A * at which we find the object to be encoded. 2N/A * If TAG is non-negative, a context tag with that value is added 2N/A * to the encoding of the thing. (XXX This would encode more 2N/A * compactly as an unsigned bitfield value tagnum+1, with 0=no 2N/A * tag.) The tag is omitted for optional fields that are not 2N/A * It's a bit illogical to combine the tag and other field info, 2N/A * since really a sequence field could have zero or several 2N/A * context tags, and of course a tag could be used elsewhere. But 2N/A * the normal mode in the Kerberos ASN.1 description is to use one 2N/A * context tag on each sequence field, so for now let's address 2N/A * that case primarily and work around the other cases (thus tag<0 2N/A * means skip tagging). 2N/A * If OPT is non-negative and the sequence header structure has a 2N/A * function pointer describing which fields are present, OPT is 2N/A * the bit position indicating whether the currently-described 2N/A * element is present. (XXX Similar encoding issue.) 2N/A * Note: Most of the time, I'm using the same number here as for 2N/A * the context tag. This is just because it's easier for me to 2N/A * keep track while working on the code by hand. The *only* 2N/A * meaningful correlation is of this value and the bits set by the 2N/A * "optional" function when examining the data structure. 2N/A * For some values of FTYPE, this describes the type of the 2N/A * object(s) to be encoded. 2N/A * We use different types for "length" fields in different places. 2N/A * So we need a good way to retrieve the various kinds of lengths 2N/A * in a compatible way. This may be a string length, or the 2N/A * length of an array of objects to encode in a SEQUENCE OF. 2N/A * In case the field is signed and negative, or larger than 2N/A * size_t, return SIZE_MAX as an error indication. We'll assume 2N/A * for now that we'll never have 4G-1 (or 2**64-1, or on tiny 2N/A * systems, 65535) sized values. On most if not all systems we 2N/A * care about, SIZE_MAX is equivalent to "all of addressable 2N/A * memory" minus one byte. That wouldn't leave enough extra room 2N/A * for the structure we're encoding, so it's pretty safe to assume 2N/A * SIZE_MAX won't legitimately come up on those systems. 2N/A * If this code gets ported to a segmented architecture or other 2N/A * system where it might be possible... figure it out then. 2N/A * Normal or optional sequence fields at a particular offset, encoded 2N/A * as indicated by the listed DESCRiptor. 2N/A * If encoding a subset of the fields of the current structure (for 2N/A * example, a flat structure describing data that gets encoded as a 2N/A * sequence containing one or more sequences), use ENCODEAS, no struct 2N/A * field name(s), and the indicated type descriptor must support the 2N/A * current struct type. 2N/A * Reinterpret some subset of the structure itself as something 2N/A * If present, returns a bitmask indicating which fields are 2N/A * present. See the "opt" field in struct field_info. 2N/A /* Indicates an array of sequence field descriptors. */ 2N/A /* Missing: Extensibility handling. (New field type?) */ 2N/A * Like "offsetof", but with type checking.