diff options
Diffstat (limited to 'src/lib/krb5/asn.1')
-rw-r--r-- | src/lib/krb5/asn.1/asn1_encode.c | 248 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/asn1_encode.h | 168 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_encode.c | 168 |
3 files changed, 245 insertions, 339 deletions
diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c index 5ecd82f59..f222423e9 100644 --- a/src/lib/krb5/asn.1/asn1_encode.c +++ b/src/lib/krb5/asn.1/asn1_encode.c @@ -32,28 +32,14 @@ asn1_error_code asn1_encode_boolean(asn1buf *buf, asn1_intmax val, unsigned int *retlen) { - asn1_error_code retval; - unsigned int length = 0; - unsigned int partlen = 1; - asn1_octet bval; - - bval = val ? 0xFF : 0x00; - - retval = asn1buf_insert_octet(buf, bval); - if (retval) return retval; - - length = partlen; - retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_BOOLEAN, length, &partlen); - if (retval) return retval; - length += partlen; + asn1_octet bval = val ? 0xFF : 0x00; - *retlen = length; - return 0; + *retlen = 1; + return asn1buf_insert_octet(buf, bval); } -static asn1_error_code -asn1_encode_integer_internal(asn1buf *buf, asn1_intmax val, - unsigned int *retlen) +asn1_error_code +asn1_encode_integer(asn1buf *buf, asn1_intmax val, unsigned int *retlen) { asn1_error_code retval; unsigned int length = 0; @@ -85,51 +71,11 @@ asn1_encode_integer_internal(asn1buf *buf, asn1_intmax val, } asn1_error_code -asn1_encode_integer(asn1buf * buf, asn1_intmax val, unsigned int *retlen) -{ - asn1_error_code retval; - unsigned int length = 0; - unsigned int partlen; - retval = asn1_encode_integer_internal(buf, val, &partlen); - if (retval) return retval; - - length = partlen; - retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen); - if (retval) return retval; - length += partlen; - - *retlen = length; - return 0; -} - -#if 0 -asn1_error_code -asn1_encode_enumerated(asn1buf * buf, long val, - unsigned int *retlen) -{ - asn1_error_code retval; - unsigned int length = 0; - unsigned int partlen; - retval = asn1_encode_integer_internal(buf, val, &partlen); - if (retval) return retval; - - length = partlen; - retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_ENUMERATED,length, &partlen); - if (retval) return retval; - length += partlen; - - *retlen = length; - return 0; -} -#endif - -asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val, unsigned int *retlen) { asn1_error_code retval; unsigned int length = 0; - unsigned int partlen; unsigned long valcopy; int digit; @@ -148,77 +94,18 @@ asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val, length++; } - retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen); - if (retval) return retval; - length += partlen; - *retlen = length; return 0; } -static asn1_error_code -encode_bytestring_with_tag(asn1buf *buf, unsigned int len, - const void *val, int tag, - unsigned int *retlen) -{ - asn1_error_code retval; - unsigned int length; - - if (len > 0 && val == 0) return ASN1_MISSING_FIELD; - retval = asn1buf_insert_octetstring(buf, len, val); - if (retval) return retval; - retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, tag, - len, &length); - if (retval) return retval; - - *retlen = len + length; - return 0; -} - asn1_error_code -asn1_encode_oid(asn1buf *buf, unsigned int len, const void *val, - unsigned int *retlen) -{ - return encode_bytestring_with_tag(buf, len, val, ASN1_OBJECTIDENTIFIER, - retlen); -} - -asn1_error_code -asn1_encode_octetstring(asn1buf *buf, unsigned int len, const void *val, - unsigned int *retlen) -{ - return encode_bytestring_with_tag(buf, len, val, ASN1_OCTETSTRING, - retlen); -} - -#if 0 -asn1_error_code asn1_encode_null(asn1buf *buf, int *retlen) -{ - asn1_error_code retval; - - retval = asn1buf_insert_octet(buf,0x00); - if (retval) return retval; - retval = asn1buf_insert_octet(buf,0x05); - if (retval) return retval; - - *retlen = 2; - return 0; -} - -asn1_error_code asn1_encode_printablestring(asn1buf *buf, unsigned int len, - const char *val, int *retlen) -{ - return encode_bytestring_with_tag(buf, len, val, ASN1_PRINTABLESTRING, - retlen); -} - -asn1_error_code asn1_encode_ia5string(asn1buf *buf, unsigned int len, - const char *val, int *retlen) +asn1_encode_bytestring(asn1buf *buf, unsigned int len, const void *val, + unsigned int *retlen) { - return encode_bytestring_with_tag(buf, len, val, ASN1_IA5STRING, - retlen); + if (len > 0 && val == NULL) return ASN1_MISSING_FIELD; + *retlen = len; + return asn1buf_insert_octetstring(buf, len, val); } -#endif asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen) @@ -269,16 +156,7 @@ asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen) sp = s; } - return encode_bytestring_with_tag(buf, 15, sp, ASN1_GENERALTIME, - retlen); -} - -asn1_error_code -asn1_encode_generalstring(asn1buf *buf, unsigned int len, const void *val, - unsigned int *retlen) -{ - return encode_bytestring_with_tag(buf, len, val, ASN1_GENERALSTRING, - retlen); + return asn1_encode_bytestring(buf, 15, sp, retlen); } asn1_error_code @@ -286,29 +164,11 @@ asn1_encode_bitstring(asn1buf *buf, unsigned int len, const void *val, unsigned int *retlen) { asn1_error_code retval; - unsigned int length; retval = asn1buf_insert_octetstring(buf, len, val); if (retval) return retval; - retval = asn1buf_insert_octet(buf, 0); - if (retval) return retval; - retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_BITSTRING, - len+1, &length); - if (retval) return retval; - *retlen = len + 1 + length; - return 0; -} - -asn1_error_code -asn1_encode_opaque(asn1buf *buf, unsigned int len, const void *val, - unsigned int *retlen) -{ - asn1_error_code retval; - - retval = asn1buf_insert_octetstring(buf, len, val); - if (retval) return retval; - *retlen = len; - return 0; + *retlen = len + 1; + return asn1buf_insert_octet(buf, '\0'); } /* @@ -383,12 +243,26 @@ asn1_error_code krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val, const struct atype_info *a, unsigned int *retlen) { + asn1_error_code retval; + unsigned int length, sum = 0; + switch (a->type) { + case atype_primitive: case atype_fn: { - const struct fn_info *fn = a->tinfo; - assert(fn->enc != NULL); - return fn->enc(buf, val, retlen); + const struct primitive_info *prim = a->tinfo; + assert(prim->enc != NULL); + retval = prim->enc(buf, val, &length); + if (retval) return retval; + sum += length; + if (a->type == atype_primitive) { + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, prim->tagval, + sum, &length); + if (retval) return retval; + sum += length; + } + *retlen = sum; + return 0; } case atype_sequence: assert(a->tinfo != NULL); @@ -411,8 +285,6 @@ krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val, retlen); case atype_tagged_thing: { - asn1_error_code retval; - unsigned int length, sum = 0; const struct tagged_info *tag = a->tinfo; retval = krb5int_asn1_encode_a_thing(buf, val, tag->basetype, &length); if (retval) return retval; @@ -428,21 +300,40 @@ krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val, { const struct int_info *tinfo = a->tinfo; assert(tinfo->loadint != NULL); - return asn1_encode_integer(buf, tinfo->loadint(val), retlen); + retval = asn1_encode_integer(buf, tinfo->loadint(val), &length); + if (retval) return retval; + sum = length; + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_INTEGER, sum, + &length); + if (retval) return retval; + sum += length; + *retlen = sum; + return 0; } case atype_uint: { const struct uint_info *tinfo = a->tinfo; assert(tinfo->loaduint != NULL); - return asn1_encode_unsigned_integer(buf, tinfo->loaduint(val), retlen); + retval = asn1_encode_unsigned_integer(buf, tinfo->loaduint(val), + &length); + if (retval) return retval; + sum = length; + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_INTEGER, sum, + &length); + if (retval) return retval; + sum += length; + *retlen = sum; + return 0; } case atype_min: case atype_max: - case atype_fn_len: + case atype_string: /* only usable with field_string */ + case atype_opaque: /* only usable with field_string */ default: assert(a->type > atype_min); assert(a->type < atype_max); - assert(a->type != atype_fn_len); + assert(a->type != atype_string); + assert(a->type != atype_opaque); abort(); } } @@ -466,6 +357,10 @@ encode_a_field(asn1buf *buf, const void *val, &length); if (retval) return retval; sum += length; + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_INTEGER, sum, + &length); + if (retval) return retval; + sum += length; break; } case field_sequenceof_len: @@ -536,13 +431,13 @@ encode_a_field(asn1buf *buf, const void *val, const struct atype_info *a; size_t slen; unsigned int length; - const struct fn_len_info *fnlen; + const struct string_info *string; dataptr = (const char *)val + field->dataoff; lenptr = (const char *)val + field->lenoff; a = field->atype; - assert(a->type == atype_fn_len); + assert(a->type == atype_string || a->type == atype_opaque); assert(field->lentype != 0); assert(field->lentype->type == atype_int || field->lentype->type == atype_uint); assert(sizeof(int) <= sizeof(asn1_intmax)); @@ -563,25 +458,28 @@ encode_a_field(asn1buf *buf, const void *val, slen = (size_t) xlen; } - fnlen = a->tinfo; - dataptr = LOADPTR(dataptr, fnlen); + string = a->tinfo; + dataptr = LOADPTR(dataptr, string); if (slen == SIZE_MAX) /* Error - negative or out of size_t range. */ return EINVAL; if (dataptr == NULL && slen != 0) return ASN1_MISSING_FIELD; - /* - * Currently our string encoders want "unsigned int" for - * lengths. - */ - if (slen != (unsigned int) slen) + /* Currently string encoders want "unsigned int" for length. */ + if (slen != (unsigned int)slen) return EINVAL; - assert(fnlen->enclen != NULL); - retval = fnlen->enclen(buf, (unsigned int) slen, dataptr, &length); - if (retval) { + assert(string->enclen != NULL); + retval = string->enclen(buf, (unsigned int) slen, dataptr, &length); + if (retval) return retval; - } sum += length; + if (a->type == atype_string) { + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, string->tagval, + sum, &length); + if (retval) + return retval; + sum += length; + } break; } default: diff --git a/src/lib/krb5/asn.1/asn1_encode.h b/src/lib/krb5/asn.1/asn1_encode.h index 8a7c9f073..ed2eb18e9 100644 --- a/src/lib/krb5/asn.1/asn1_encode.h +++ b/src/lib/krb5/asn.1/asn1_encode.h @@ -43,11 +43,9 @@ * asn1_encode_boolean * asn1_encode_integer * asn1_encode_unsigned_integer - * asn1_encode_octetstring + * asn1_encode_bytestring * asn1_encode_generaltime - * asn1_encode_generalstring * asn1_encode_bitstring - * asn1_encode_oid */ asn1_error_code asn1_encode_boolean(asn1buf *buf, asn1_intmax val, @@ -63,9 +61,6 @@ asn1_error_code asn1_encode_integer(asn1buf *buf, asn1_intmax val, * to expand the buffer. */ -asn1_error_code asn1_encode_enumerated(asn1buf *buf, long val, - unsigned int *retlen); - asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val, unsigned int *retlen); /* @@ -77,24 +72,8 @@ asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val, * to expand the buffer. */ -asn1_error_code asn1_encode_octetstring(asn1buf *buf, unsigned int len, - const void *val, unsigned int *retlen); -/* - * requires *buf is allocated - * modifies *buf, *retlen - * effects Inserts the encoding of val into *buf and returns - * the length of the encoding in *retlen. - * Returns ENOMEM to signal an unsuccesful attempt - * to expand the buffer. - */ -#define asn1_encode_charstring asn1_encode_octetstring - -/** - * Encode @a val, an object identifier in compressed DER form without a tag or - * length. This function adds the OID tag and length. - */ -asn1_error_code asn1_encode_oid(asn1buf *buf, unsigned int len, - const void *val, unsigned int *retlen); +asn1_error_code asn1_encode_bytestring(asn1buf *buf, unsigned int len, + const void *val, unsigned int *retlen); /* * requires *buf is allocated * modifies *buf, *retlen @@ -114,28 +93,6 @@ asn1_error_code asn1_encode_null(asn1buf *buf, int *retlen); * to expand the buffer. */ -asn1_error_code asn1_encode_printablestring(asn1buf *buf, unsigned int len, - const char *val, int *retlen); -/* - * requires *buf is allocated - * modifies *buf, *retlen - * effects Inserts the encoding of val into *buf and returns - * the length of the encoding in *retlen. - * Returns ENOMEM to signal an unsuccesful attempt - * to expand the buffer. - */ - -asn1_error_code asn1_encode_ia5string(asn1buf *buf, unsigned int len, - const char *val, int *retlen); -/* - * requires *buf is allocated - * modifies *buf, *retlen - * effects Inserts the encoding of val into *buf and returns - * the length of the encoding in *retlen. - * Returns ENOMEM to signal an unsuccesful attempt - * to expand the buffer. - */ - asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen); /* @@ -148,18 +105,6 @@ asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val, * Note: The encoding of GeneralizedTime is YYYYMMDDhhmmZ */ -asn1_error_code asn1_encode_generalstring(asn1buf *buf, - unsigned int len, const void *val, - unsigned int *retlen); -/* - * requires *buf is allocated, val has a length of len characters - * modifies *buf, *retlen - * effects Inserts the encoding of val into *buf and returns - * the length of the encoding in *retlen. - * Returns ENOMEM to signal an unsuccesful attempt - * to expand the buffer. - */ - asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len, const void *val, unsigned int *retlen); @@ -172,18 +117,6 @@ asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len, * to expand the buffer. */ -asn1_error_code asn1_encode_opaque(asn1buf *buf, unsigned int len, - const void *val, - unsigned int *retlen); -/* - * requires *buf is allocated, val has a length of len characters - * modifies *buf, *retlen - * effects Inserts the encoding of val into *buf and returns - * the length of the encoding in *retlen. - * Returns ENOMEM to signal an unsuccesful attempt - * to expand the buffer. - */ - /* * Type descriptor info. * @@ -226,14 +159,25 @@ enum atype_type { * invalid. */ atype_min = 1, - /* Encoder function to be called with address of <thing>. tinfo is a - * struct fn_info *. */ + /* Encoder function (contents-only) to be called with address of <thing> + * and wrapped with a universal primitive tag. tinfo is a struct + * primitive_info *. */ + atype_primitive, + /* Encoder function (with tag) to be called with address of <thing>. tinfo + * is a struct primitive_info * with tagval ignored. */ atype_fn, /* - * Encoder function to be called with address of <thing> and a - * length (unsigned int). tinfo is a struct fn_len_info *. + * Encoder function (contents only) to be called with address of <thing> + * and a length (unsigned int), and wrapped with a universal primitive tag. + * tinfo is a struct string_info *. Only usable with the field_string + * field type. */ - atype_fn_len, + atype_string, + /* + * As above, but the encoder function produces the tag as well as the + * contents. + */ + atype_opaque, /* * Pointer to actual thing to be encoded. tinfo is a struct ptr_info *. * @@ -282,14 +226,16 @@ struct atype_info { const void *tinfo; /* Points to type-specific structure */ }; -struct fn_info { +struct primitive_info { asn1_error_code (*enc)(asn1buf *, const void *, unsigned int *); + unsigned int tagval; }; -struct fn_len_info { +struct string_info { asn1_error_code (*enclen)(asn1buf *, unsigned int, const void *, unsigned int *); const void *(*loadptr)(const void *); + unsigned int tagval; }; struct ptr_info { @@ -331,26 +277,32 @@ struct uint_info { */ /* - * Define a type for which we must use an explicit encoder function. - * The DEFFNTYPE variant uses a function taking a void*, the - * DEFFNXTYPE form wants a function taking a pointer to the actual C - * type to be encoded; you should use the latter unless you've already - * got the void* function supplied elsewhere. + * Define a type using a primitive (content-only) encoder function. * - * Of course, we need a single, consistent type for the descriptor - * structure field, so we use the function pointer type that uses - * void*, and create a wrapper function in DEFFNXTYPE. However, in - * all our cases so far, the supplied function is static and not used - * otherwise, so the compiler can merge it with the wrapper function - * if the optimizer is good enough. + * Because we need a single, consistent type for the descriptor structure + * field, we use the function pointer type that uses void*, and create a + * wrapper function in DEFFNXTYPE. The supplied function is static and not + * used otherwise, so the compiler can merge it with the wrapper function if + * the optimizer is good enough. */ -#define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN) \ +#define DEFPRIMITIVETYPE(DESCNAME, CTYPENAME, ENCFN, TAG) \ typedef CTYPENAME aux_typedefname_##DESCNAME; \ - static const struct fn_info aux_info_##DESCNAME = { ENCFN }; \ + static asn1_error_code \ + aux_encfn_##DESCNAME(asn1buf *buf, const void *val, \ + unsigned int *retlen) \ + { \ + return ENCFN(buf, \ + (const aux_typedefname_##DESCNAME *)val, \ + retlen); \ + } \ + static const struct primitive_info aux_info_##DESCNAME = { \ + aux_encfn_##DESCNAME, TAG \ + }; \ const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_fn, sizeof(CTYPENAME), &aux_info_##DESCNAME \ + atype_primitive, sizeof(CTYPENAME), &aux_info_##DESCNAME \ } -#define DEFFNXTYPE(DESCNAME, CTYPENAME, ENCFN) \ +/* Define a type using an explicit (with tag) encoder function. */ +#define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN) \ typedef CTYPENAME aux_typedefname_##DESCNAME; \ static asn1_error_code \ aux_encfn_##DESCNAME(asn1buf *buf, const void *val, \ @@ -360,7 +312,7 @@ struct uint_info { (const aux_typedefname_##DESCNAME *)val, \ retlen); \ } \ - static const struct fn_info aux_info_##DESCNAME = { \ + static const struct primitive_info aux_info_##DESCNAME = { \ aux_encfn_##DESCNAME \ }; \ const struct atype_info krb5int_asn1type_##DESCNAME = { \ @@ -381,29 +333,43 @@ struct uint_info { * string-encoding primitives work. So be it. */ #ifdef POINTERS_ARE_ALL_THE_SAME -#define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN) \ +#define DEFSTRINGTYPE(DESCNAME, CTYPENAME, ENCFN, TAGVAL) \ typedef CTYPENAME aux_typedefname_##DESCNAME; \ - static const struct fn_len_info aux_info_##DESCNAME = { \ - ENCFN, NULL \ + static const struct string_info aux_info_##DESCNAME = { \ + ENCFN, NULL, TAGVAL \ } \ const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_fn_len, 0, &aux_info_##DESCNAME \ + atype_string, 0, &aux_info_##DESCNAME \ } #else -#define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN) \ +#define DEFSTRINGTYPE(DESCNAME, CTYPENAME, ENCFN, TAGVAL) \ typedef CTYPENAME aux_typedefname_##DESCNAME; \ static const void *loadptr_for_##DESCNAME(const void *pv) \ { \ const aux_typedefname_##DESCNAME *p = pv; \ return *p; \ } \ - static const struct fn_len_info aux_info_##DESCNAME = { \ - ENCFN, loadptr_for_##DESCNAME \ + static const struct string_info aux_info_##DESCNAME = { \ + ENCFN, loadptr_for_##DESCNAME, TAGVAL \ }; \ const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_fn_len, 0, &aux_info_##DESCNAME \ + atype_string, 0, &aux_info_##DESCNAME \ } #endif +/* Not used enough to justify a POINTERS_ARE_ALL_THE_SAME version. */ +#define DEFOPAQUETYPE(DESCNAME, CTYPENAME, ENCFN) \ + typedef CTYPENAME aux_typedefname_##DESCNAME; \ + static const void *loadptr_for_##DESCNAME(const void *pv) \ + { \ + const aux_typedefname_##DESCNAME *p = pv; \ + return *p; \ + } \ + static const struct string_info aux_info_##DESCNAME = { \ + ENCFN, loadptr_for_##DESCNAME \ + }; \ + const struct atype_info krb5int_asn1type_##DESCNAME = { \ + atype_opaque, 0, &aux_info_##DESCNAME \ + } /* * A sequence, defined by the indicated series of fields, and an * optional function indicating which fields are present. diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index 8aecfdf56..56b98022b 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -78,12 +78,14 @@ DEFUINTTYPE(uint, unsigned int); DEFUINTTYPE(octet, krb5_octet); DEFUINTTYPE(ui_4, krb5_ui_4); -DEFFNLENTYPE(octetstring, unsigned char *, asn1_encode_octetstring); -DEFFNLENTYPE(s_octetstring, char *, asn1_encode_octetstring); -DEFFNLENTYPE(charstring, char *, asn1_encode_charstring); -DEFFNLENTYPE(generalstring, char *, asn1_encode_generalstring); -DEFFNLENTYPE(u_generalstring, unsigned char *, asn1_encode_generalstring); -DEFFNLENTYPE(opaque, char *, asn1_encode_opaque); +DEFSTRINGTYPE(octetstring, unsigned char *, asn1_encode_bytestring, + ASN1_OCTETSTRING); +DEFSTRINGTYPE(s_octetstring, char *, asn1_encode_bytestring, ASN1_OCTETSTRING); +DEFSTRINGTYPE(generalstring, char *, asn1_encode_bytestring, + ASN1_GENERALSTRING); +DEFSTRINGTYPE(u_generalstring, unsigned char *, asn1_encode_bytestring, + ASN1_GENERALSTRING); +DEFOPAQUETYPE(opaque, char *, asn1_encode_bytestring); DEFFIELDTYPE(gstring_data, krb5_data, FIELDOF_STRING(krb5_data, generalstring, data, length, -1)); @@ -119,7 +121,8 @@ asn1_encode_kerberos_time_at(asn1buf *buf, const krb5_timestamp *val, time_t tval = *val; return asn1_encode_generaltime(buf, tval, retlen); } -DEFFNXTYPE(kerberos_time, krb5_timestamp, asn1_encode_kerberos_time_at); +DEFPRIMITIVETYPE(kerberos_time, krb5_timestamp, asn1_encode_kerberos_time_at, + ASN1_GENERALTIME); const static struct field_info address_fields[] = { FIELDOF_NORM(krb5_address, int32, addrtype, 0), @@ -164,7 +167,8 @@ asn1_encode_krb5_flags_at(asn1buf *buf, const krb5_flags *val, store_32_be((krb5_ui_4) *val, cbuf); return asn1_encode_bitstring(buf, 4, cbuf, retlen); } -DEFFNXTYPE(krb5_flags, krb5_flags, asn1_encode_krb5_flags_at); +DEFPRIMITIVETYPE(krb5_flags, krb5_flags, asn1_encode_krb5_flags_at, + ASN1_BITSTRING); const static struct field_info authdata_elt_fields[] = { /* ad-type[0] INTEGER */ @@ -347,7 +351,7 @@ asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *val, } else return ASN1_MISSING_FIELD; return asn1_encode_kdc_req_hack(buf, &val2, retlen); } -DEFFNXTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body); +DEFFNTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body); /* end ugly hack */ DEFPTRTYPE(ptr_kdc_req_body,kdc_req_body); @@ -562,7 +566,7 @@ asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val, asn1_makeseq(); asn1_cleanup(); } -DEFFNXTYPE(sam_challenge_2, krb5_sam_challenge_2, asn1_encode_sam_challenge_2); +DEFFNTYPE(sam_challenge_2, krb5_sam_challenge_2, asn1_encode_sam_challenge_2); static const struct field_info sam_challenge_2_body_fields[] = { FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_type, 0), @@ -1553,19 +1557,46 @@ asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf, } #endif -/* asn1_addlenfield -- add a field whose length must be separately specified */ -#define asn1_addlenfield(len, value, tag, encoder) \ - { \ - unsigned int length; \ - retval = encoder(buf, len, value, &length); \ - if (retval) { \ - return retval; } \ - sum += length; \ - retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, \ - tag, length, &length); \ - if (retval) { \ - return retval; } \ - sum += length; \ +/* + * asn1_addprimitive -- add a primitive field and universal primitive tag to + * the encoding, wrapped in a context tag. encoder must encode only the + * contents, not the tag. + */ +#define asn1_addprimitive(value,tag,encoder,ptag) \ + { unsigned int enclen, tlen; \ + retval = encoder(buf, value, &enclen); \ + if (retval) { \ + return retval; } \ + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ptag, \ + enclen, &tlen); \ + sum += enclen + tlen; \ + retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag, \ + enclen + tlen, &tlen); \ + if (retval) { \ + return retval; } \ + sum += tlen; } + +#define asn1_addinteger(value, tag) \ + asn1_addprimitive(value, tag, asn1_encode_integer, ASN1_INTEGER) + +/* asn1_addstring -- add a string field whose length must be separately + * specified, wrapped in a universal primitive tag. */ +#define asn1_addstring(len, value, tag, ptag) \ + { \ + unsigned int enclen, tlen; \ + retval = asn1_encode_bytestring(buf, len, value, &enclen); \ + if (retval) { \ + return retval; } \ + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ptag, \ + enclen, &tlen); \ + if (retval) { \ + return retval; } \ + sum += enclen + tlen; \ + retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag, \ + enclen + tlen, &tlen); \ + if (retval) { \ + return retval; } \ + sum += tlen; \ } /* @@ -1621,8 +1652,9 @@ asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf, #ifndef DISABLE_PKINIT -DEFFNXTYPE(algorithm_identifier, krb5_algorithm_identifier, asn1_encode_algorithm_identifier); -DEFFNLENTYPE(object_identifier, char *, asn1_encode_oid); +DEFFNTYPE(algorithm_identifier, krb5_algorithm_identifier, asn1_encode_algorithm_identifier); +DEFSTRINGTYPE(object_identifier, char *, asn1_encode_bytestring, + ASN1_OBJECTIDENTIFIER); DEFFIELDTYPE(oid_data, krb5_data, FIELDOF_STRING(krb5_data, object_identifier, data, length, -1)); DEFPTRTYPE(oid_data_ptr, oid_data); @@ -1664,8 +1696,10 @@ DEFSEQTYPE(sp80056a_other_info, krb5_sp80056a_other_info, sp80056a_other_info_fi /* For PkinitSuppPubInfo, for pkinit agility */ static const struct field_info pkinit_supp_pub_info_fields[] = { FIELDOF_NORM(krb5_pkinit_supp_pub_info, int32, enctype, 0), - FIELDOF_STRING(krb5_pkinit_supp_pub_info, charstring, as_req.data, as_req.length, 1), - FIELDOF_STRING(krb5_pkinit_supp_pub_info, charstring, pk_as_rep.data, pk_as_rep.length, 2), + FIELDOF_STRING(krb5_pkinit_supp_pub_info, s_octetstring, as_req.data, + as_req.length, 1), + FIELDOF_STRING(krb5_pkinit_supp_pub_info, s_octetstring, pk_as_rep.data, + pk_as_rep.length, 2), }; DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info, pkinit_supp_pub_info_fields, NULL); @@ -1693,10 +1727,12 @@ asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen) { asn1_setup(); - asn1_addlenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_encode_octetstring); - asn1_addfield(val->nonce, 2, asn1_encode_integer); - asn1_addfield(val->ctime, 1, asn1_encode_kerberos_time); - asn1_addfield(val->cusec, 0, asn1_encode_integer); + asn1_addstring(val->paChecksum.length, val->paChecksum.contents, 3, + ASN1_OCTETSTRING); + asn1_addinteger(val->nonce, 2); + asn1_addprimitive(val->ctime, 1, asn1_encode_kerberos_time, + ASN1_GENERALTIME); + asn1_addinteger(val->cusec, 0); asn1_makeseq(); asn1_cleanup(); @@ -1709,9 +1745,10 @@ asn1_encode_pk_authenticator_draft9(asn1buf *buf, { asn1_setup(); - asn1_addfield(val->nonce, 4, asn1_encode_integer); - asn1_addfield(val->ctime, 3, asn1_encode_kerberos_time); - asn1_addfield(val->cusec, 2, asn1_encode_integer); + asn1_addinteger(val->nonce, 4); + asn1_addprimitive(val->ctime, 3, asn1_encode_kerberos_time, + ASN1_GENERALTIME); + asn1_addinteger(val->cusec, 2); asn1_addfield(val->kdcName, 1, asn1_encode_realm); asn1_addfield(val->kdcName, 0, asn1_encode_principal_name); @@ -1737,13 +1774,17 @@ asn1_encode_algorithm_identifier(asn1buf *buf, { unsigned int length; - retval = asn1_encode_oid(buf, val->algorithm.length, - val->algorithm.data, - &length); + retval = asn1_encode_bytestring(buf, val->algorithm.length, + val->algorithm.data, &length); if (retval) return retval; sum += length; + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, + ASN1_OBJECTIDENTIFIER, length, &length); + if (retval) + return retval; + sum += length; } asn1_makeseq(); @@ -1755,9 +1796,11 @@ asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen) { asn1_setup(); + unsigned int len, alen = 0; { unsigned int length; + asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING); } @@ -1766,29 +1809,25 @@ asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val, val->algorithm.parameters.data); if (retval) return retval; - sum += val->algorithm.parameters.length; + alen += val->algorithm.parameters.length; } - { - unsigned int length; - - retval = asn1_encode_oid(buf, val->algorithm.algorithm.length, - val->algorithm.algorithm.data, - &length); - - if (retval) - return retval; - sum += length; - + retval = asn1_encode_bytestring(buf, val->algorithm.algorithm.length, + val->algorithm.algorithm.data, &len); + if (retval) + return retval; + alen += len; - retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, - val->algorithm.parameters.length + length, - &length); + retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, + ASN1_OBJECTIDENTIFIER, len, &len); + if (retval) + return retval; + alen += len; - if (retval) - return retval; - sum += length; - } + retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, alen, &len); + if (retval) + return retval; + sum += alen + len; asn1_makeseq(); asn1_cleanup(); @@ -1825,7 +1864,8 @@ asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val, if (val->supportedKDFs != NULL) asn1_addfield(val->supportedKDFs, 4, asn1_encode_supported_kdfs); if (val->clientDHNonce.length != 0) - asn1_addlenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_encode_octetstring); + asn1_addstring(val->clientDHNonce.length, val->clientDHNonce.data, 3, + ASN1_OCTETSTRING); if (val->supportedCMSTypes != NULL) asn1_addfield((const krb5_algorithm_identifier **)val->supportedCMSTypes,2,asn1_encode_sequence_of_algorithm_identifier); if (val->clientPublicValue != NULL) @@ -2003,9 +2043,11 @@ asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_info *val, { asn1_setup(); - if (val->dhKeyExpiration != 0) - asn1_addfield(val->dhKeyExpiration, 2, asn1_encode_kerberos_time); - asn1_addfield(val->nonce, 1, asn1_encode_integer); + if (val->dhKeyExpiration != 0) { + asn1_addprimitive(val->dhKeyExpiration, 2, asn1_encode_kerberos_time, + ASN1_GENERALTIME); + } + asn1_addinteger(val->nonce, 1); { unsigned int length; @@ -2043,7 +2085,7 @@ asn1_encode_reply_key_pack_draft9(asn1buf *buf, { asn1_setup(); - asn1_addfield(val->nonce, 1, asn1_encode_integer); + asn1_addinteger(val->nonce, 1); asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key); asn1_makeseq(); @@ -2157,8 +2199,8 @@ asn1_encode_typed_data(asn1buf *buf, const krb5_pa_data *val, unsigned int *retlen) { asn1_setup(); - asn1_addlenfield(val->length, val->contents, 1, asn1_encode_octetstring); - asn1_addfield(val->pa_type, 0, asn1_encode_integer); + asn1_addstring(val->length, val->contents, 1, ASN1_OCTETSTRING); + asn1_addinteger(val->pa_type, 0); asn1_makeseq(); asn1_cleanup(); } |