From 4e51ef754ee49ce6e48869df9aca47572ab1b4f8 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sun, 8 Jan 2012 02:10:47 +0000 Subject: [PATCH] Clean up the asn1 encoder design Now that the PKINIT types have been converted and atype_fn has only one use, we can more easily modify the encoder so that any object can be encoded without its tag, which makes for a cleaner design. The basic building block is now krb5int_asn1_encode_type, which encodes the contents of a function and returns its tag information to the caller. atype_fn now has its own structure, and the encoder function it references follows the semantics of krb5int_asn1_encode_type. atype_opaque is now atype_der and goes with a new corresponding field type (field_der); stored DER encodings are parsed to separate the tag from the content. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25622 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/asn.1/asn1_encode.c | 344 +++++++++++++++-------------- src/lib/krb5/asn.1/asn1_encode.h | 84 +++---- src/lib/krb5/asn.1/asn1_k_encode.c | 25 +-- 3 files changed, 227 insertions(+), 226 deletions(-) diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c index e654b7286..ba71add15 100644 --- a/src/lib/krb5/asn.1/asn1_encode.c +++ b/src/lib/krb5/asn.1/asn1_encode.c @@ -176,8 +176,9 @@ asn1_encode_bitstring(asn1buf *buf, unsigned int len, const void *val, * * Two entry points here: * - * krb5int_asn1_encode_a_thing: Incrementally adds the partial - * encoding of an object to an already-initialized asn1buf. + * krb5int_asn1_encode_type: Incrementally adds the contents-only encoding of + * an object to an already-initialized asn1buf, and returns its tag + * information. * * krb5int_asn1_do_full_encode: Returns a completed encoding, in the * correct byte order, in an allocated krb5_data. @@ -235,142 +236,143 @@ just_encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq, unsigned int *retlen); static asn1_error_code -encode_a_field(asn1buf *buf, const void *val, - const struct field_info *field, - unsigned int *retlen, asn1_construction *omit_tag); +encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, + taginfo *rettag); -/* Encode a value according to a type. If omit_tag is non-NULL, omit the - * outer tag and return its construction bit instead. */ -static asn1_error_code -encode_type(asn1buf *buf, const void *val, const struct atype_info *a, - unsigned int *retlen, asn1_construction *omit_tag) +/* Encode a value (contents only, no outer tag) according to a type, and return + * its encoded tag information. */ +asn1_error_code +krb5int_asn1_encode_type(asn1buf *buf, const void *val, + const struct atype_info *a, taginfo *rettag) { asn1_error_code retval; - asn1_class tagclass = UNIVERSAL; - asn1_construction construction = PRIMITIVE; - asn1_tagnum tagnum = -1; - unsigned int length, sum = 0; - /* - * In the switch statement, do one of the following: (1) encode the - * contents of val and set tagclass, construction, and tagnum to the - * appropriate values for the tag; (2) encode the contents and tag, leaving - * tagnum alone (won't work with implicit tagging); (3) delegate the whole - * process to a subcall. If not returning immediately, set length to the - * number of bytes encoded. - */ switch (a->type) { - case atype_primitive: - case atype_fn: - { + case atype_primitive: { const struct primitive_info *prim = a->tinfo; assert(prim->enc != NULL); - retval = prim->enc(buf, val, &length); + retval = prim->enc(buf, val, &rettag->length); if (retval) return retval; - if (a->type == atype_primitive) - tagnum = prim->tagval; + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = prim->tagval; break; } + case atype_fn: { + const struct fn_info *fn = a->tinfo; + assert(fn->enc != NULL); + return fn->enc(buf, val, rettag); + } case atype_sequence: assert(a->tinfo != NULL); - retval = just_encode_sequence(buf, val, a->tinfo, &length); + retval = just_encode_sequence(buf, val, a->tinfo, &rettag->length); if (retval) return retval; - construction = CONSTRUCTED; - tagnum = ASN1_SEQUENCE; + rettag->asn1class = UNIVERSAL; + rettag->construction = CONSTRUCTED; + rettag->tagnum = ASN1_SEQUENCE; break; - case atype_ptr: - { + case atype_ptr: { const struct ptr_info *ptr = a->tinfo; assert(ptr->basetype != NULL); - return encode_type(buf, LOADPTR(val, ptr), ptr->basetype, retlen, - omit_tag); + return krb5int_asn1_encode_type(buf, LOADPTR(val, ptr), ptr->basetype, + rettag); } case atype_field: assert(a->tinfo != NULL); - return encode_a_field(buf, val, a->tinfo, retlen, omit_tag); + return encode_a_field(buf, val, a->tinfo, rettag); case atype_nullterm_sequence_of: case atype_nonempty_nullterm_sequence_of: assert(a->tinfo != NULL); retval = encode_nullterm_sequence_of(buf, val, a->tinfo, a->type == atype_nullterm_sequence_of, - &length); + &rettag->length); if (retval) return retval; - construction = CONSTRUCTED; - tagnum = ASN1_SEQUENCE; + rettag->asn1class = UNIVERSAL; + rettag->construction = CONSTRUCTED; + rettag->tagnum = ASN1_SEQUENCE; break; - case atype_tagged_thing: - { + case atype_tagged_thing: { const struct tagged_info *tag = a->tinfo; - if (tag->implicit) { - retval = encode_type(buf, val, tag->basetype, &length, - &construction); - } else { - retval = encode_type(buf, val, tag->basetype, &length, NULL); - construction = tag->construction; + retval = krb5int_asn1_encode_type(buf, val, tag->basetype, rettag); + if (retval) + return retval; + if (!tag->implicit) { + unsigned int tlen; + retval = asn1_make_tag(buf, rettag->asn1class, + rettag->construction, rettag->tagnum, + rettag->length, &tlen); + if (retval) + return retval; + rettag->length += tlen; + rettag->construction = tag->construction; } - tagclass = tag->tagtype; - tagnum = tag->tagval; + rettag->asn1class = tag->tagtype; + rettag->tagnum = tag->tagval; break; } - case atype_int: - { + case atype_int: { const struct int_info *tinfo = a->tinfo; assert(tinfo->loadint != NULL); - retval = asn1_encode_integer(buf, tinfo->loadint(val), &length); + retval = asn1_encode_integer(buf, tinfo->loadint(val), + &rettag->length); if (retval) return retval; - tagnum = ASN1_INTEGER; + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = ASN1_INTEGER; break; } - case atype_uint: - { + case atype_uint: { const struct uint_info *tinfo = a->tinfo; assert(tinfo->loaduint != NULL); retval = asn1_encode_unsigned_integer(buf, tinfo->loaduint(val), - &length); + &rettag->length); if (retval) return retval; - tagnum = ASN1_INTEGER; + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = ASN1_INTEGER; break; } case atype_min: case atype_max: case atype_string: /* only usable with field_string */ - case atype_opaque: /* only usable with field_string */ + case atype_der: /* only usable with field_der */ + case atype_choice: /* only usable with field_choice */ default: assert(a->type > atype_min); assert(a->type < atype_max); assert(a->type != atype_string); - assert(a->type != atype_opaque); + assert(a->type != atype_der); + assert(a->type != atype_choice); abort(); } - sum += length; - assert(omit_tag == NULL || tagnum != -1); - if (omit_tag == NULL && tagnum >= 0) { - /* We have not yet encoded the outer tag and should do so. */ - retval = asn1_make_tag(buf, tagclass, construction, tagnum, sum, - &length); - if (retval) - return retval; - sum += length; - } else if (omit_tag != NULL) { - /* Don't encode the tag; report its construction bit to the caller. */ - *omit_tag = construction; - } + return 0; +} - *retlen = sum; +static asn1_error_code +encode_type_and_tag(asn1buf *buf, const void *val, const struct atype_info *a, + unsigned int *retlen) +{ + taginfo t; + asn1_error_code retval; + unsigned int tlen; + + retval = krb5int_asn1_encode_type(buf, val, a, &t); + if (retval) + return retval; + retval = asn1_make_tag(buf, t.asn1class, t.construction, t.tagnum, + t.length, &tlen); + if (retval) + return retval; + *retlen = t.length + tlen; return 0; } -/* - * Encode a value according to a field specification, adding a context tag if - * specified. If omit_tag is non-NULL, omit the outer tag and return its - * construction bit instead (only valid if the field has no context tag). - */ static asn1_error_code get_field_len(const void *val, const struct field_info *field, unsigned int *retlen) @@ -404,40 +406,51 @@ get_field_len(const void *val, const struct field_info *field, return 0; } +/* Split a DER encoding into tag and contents. Insert the contents into buf, + * then return the length of the contents and the tag. */ +static asn1_error_code +split_der(asn1buf *buf, const unsigned char *der, unsigned int len, + taginfo *rettag) +{ + asn1buf der_buf; + krb5_data der_data = make_data((unsigned char *)der, len); + asn1_error_code retval; + + retval = asn1buf_wrap_data(&der_buf, &der_data); + if (retval) + return retval; + retval = asn1_get_tag_2(&der_buf, rettag); + if (retval) + return retval; + if ((unsigned int)asn1buf_remains(&der_buf, 0) != rettag->length) + return EINVAL; + return asn1buf_insert_bytestring(buf, rettag->length, + der + len - rettag->length); +} + +/* Encode part of a value (contents only, no tag) according to a field + * descriptor and return its encoded length and tag. */ static asn1_error_code encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, - unsigned int *retlen, asn1_construction *omit_tag) + taginfo *rettag) { asn1_error_code retval; - asn1_class tagclass = UNIVERSAL; - asn1_construction construction = PRIMITIVE; - asn1_tagnum tagnum = -1; - unsigned int sum = 0, length; if (val == NULL) return ASN1_MISSING_FIELD; - assert(omit_tag == NULL || field->tag < 0); assert(!(field->tag_implicit && field->tag < 0)); - /* - * In the switch statement, either (1) encode the contents of the field and - * set tagclass, construction, and tagnum to the appropriate values for the - * tag; (2) encode the contents and tag, leaving tagnum alone; (3) delegate - * the whole process to a subcall (only an option if the field has no - * context tag). If not returning immediately, set length to the number of - * bytes encoded. - */ switch (field->ftype) { - case field_immediate: - { + case field_immediate: { retval = asn1_encode_integer(buf, (asn1_intmax) field->dataoff, - &length); + &rettag->length); if (retval) return retval; - tagnum = ASN1_INTEGER; + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = ASN1_INTEGER; break; } - case field_sequenceof_len: - { + case field_sequenceof_len: { const void *dataptr = (const char *)val + field->dataoff; unsigned int slen; const struct ptr_info *ptrinfo; @@ -456,37 +469,29 @@ encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, if (slen != 0 && dataptr == NULL) return ASN1_MISSING_FIELD; retval = encode_sequence_of(buf, slen, dataptr, ptrinfo->basetype, - &length); + &rettag->length); if (retval) return retval; - construction = CONSTRUCTED; - tagnum = ASN1_SEQUENCE; + rettag->asn1class = UNIVERSAL; + rettag->construction = CONSTRUCTED; + rettag->tagnum = ASN1_SEQUENCE; break; } - case field_normal: - { + case field_normal: { const void *dataptr = (const char *)val + field->dataoff; - if (omit_tag != NULL) - return encode_type(buf, dataptr, field->atype, retlen, omit_tag); - if (field->tag_implicit) { - retval = encode_type(buf, dataptr, field->atype, &length, - &construction); - } else - retval = encode_type(buf, dataptr, field->atype, &length, NULL); + retval = krb5int_asn1_encode_type(buf, dataptr, field->atype, rettag); if (retval) return retval; break; } - case field_string: - { + case field_string: { const void *dataptr = (const char *)val + field->dataoff; const struct atype_info *a; unsigned int slen; const struct string_info *string; a = field->atype; - assert(a->type == atype_string || a->type == atype_opaque); - assert(!(a->type == atype_opaque && field->tag_implicit)); + assert(a->type == atype_string); retval = get_field_len(val, field, &slen); if (retval) return retval; @@ -495,22 +500,39 @@ encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, if (dataptr == NULL && slen != 0) return ASN1_MISSING_FIELD; assert(string->enclen != NULL); - retval = string->enclen(buf, slen, dataptr, &length); + retval = string->enclen(buf, slen, dataptr, &rettag->length); if (retval) return retval; - if (a->type == atype_string) - tagnum = string->tagval; - else - assert(omit_tag == NULL && !field->tag_implicit); + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = string->tagval; break; } - case field_choice: - { + case field_der: { + const void *dataptr = (const char *)val + field->dataoff; + const struct atype_info *a; + unsigned int slen; + const struct ptr_info *ptr; + + a = field->atype; + assert(a->type == atype_der); + retval = get_field_len(val, field, &slen); + if (retval) + return retval; + ptr = a->tinfo; + dataptr = LOADPTR(dataptr, ptr); + if (dataptr == NULL && slen != 0) + return ASN1_MISSING_FIELD; + retval = split_der(buf, dataptr, slen, rettag); + if (retval) + return retval; + break; + } + case field_choice: { const void *dataptr = (const char *)val + field->dataoff; unsigned int choice; const struct seq_info *seq; - assert(omit_tag == NULL); assert(field->atype->type == atype_choice); seq = field->atype->tinfo; retval = get_field_len(val, field, &choice); @@ -518,8 +540,9 @@ encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, return retval; if (choice > seq->n_fields) return ASN1_MISSING_FIELD; - retval = encode_a_field(buf, dataptr, &seq->fields[choice], &length, - NULL); + retval = encode_a_field(buf, dataptr, &seq->fields[choice], rettag); + if (retval) + return retval; break; } default: @@ -529,31 +552,20 @@ encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, abort(); } - sum += length; - if (tagnum >= 0 && omit_tag == NULL && !field->tag_implicit) { - /* We have not yet encoded the field's outer tag and should do so. */ - retval = asn1_make_tag(buf, tagclass, construction, tagnum, sum, - &length); - if (retval) - return retval; - sum += length; - } else if (omit_tag != NULL) { - /* Don't encode the tag; report its construction bit to the caller. */ - *omit_tag = construction; - } - - /* Maybe add a context tag. Explicit tags are always constructed; implicit - * tags are primitive if the replaced outer tag would have been. */ if (field->tag >= 0) { - if (!field->tag_implicit) - construction = CONSTRUCTED; - retval = asn1_make_tag(buf, CONTEXT_SPECIFIC, construction, field->tag, - sum, &length); - if (retval) - return retval; - sum += length; + if (!field->tag_implicit) { + unsigned int tlen; + retval = asn1_make_tag(buf, rettag->asn1class, + rettag->construction, rettag->tagnum, + rettag->length, &tlen); + if (retval) + return retval; + rettag->length += tlen; + rettag->construction = CONSTRUCTED; + } + rettag->asn1class = CONTEXT_SPECIFIC; + rettag->tagnum = field->tag; } - *retlen = sum; return 0; } @@ -567,21 +579,20 @@ encode_fields(asn1buf *buf, const void *val, unsigned int sum = 0; for (i = nfields; i > 0; i--) { const struct field_info *f = fields+i-1; - unsigned int length; + taginfo t; asn1_error_code retval; - int present; - - if (f->opt == -1) - present = 1; - else if ((1u << f->opt) & optional) - present = 1; - else - present = 0; - if (present) { - retval = encode_a_field(buf, val, f, &length, NULL); - if (retval) return retval; - sum += length; - } + + if (f->opt != -1 && !((1u << f->opt) & optional)) + continue; + retval = encode_a_field(buf, val, f, &t); + if (retval) + return retval; + sum += t.length; + retval = asn1_make_tag(buf, t.asn1class, t.construction, t.tagnum, + t.length, &t.length); + if (retval) + return retval; + sum += t.length; } *retlen = sum; return 0; @@ -615,7 +626,7 @@ encode_sequence_of(asn1buf *buf, unsigned int seqlen, const void *val, assert(eltinfo->size != 0); eltptr = (const char *)val + (i - 1) * eltinfo->size; - retval = encode_type(buf, eltptr, a, &length, NULL); + retval = encode_type_and_tag(buf, eltptr, a, &length); if (retval) return retval; sum += length; @@ -624,13 +635,6 @@ encode_sequence_of(asn1buf *buf, unsigned int seqlen, const void *val, return 0; } -asn1_error_code -krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val, - const struct atype_info *a, unsigned int *retlen) -{ - return encode_type(buf, val, a, retlen, NULL); -} - krb5_error_code krb5int_asn1_do_full_encode(const void *rep, krb5_data **code, const struct atype_info *a) @@ -649,7 +653,7 @@ krb5int_asn1_do_full_encode(const void *rep, krb5_data **code, if (retval) return retval; - retval = encode_type(buf, rep, a, &length, NULL); + retval = encode_type_and_tag(buf, rep, a, &length); if (retval) goto cleanup; retval = asn12krb5_buf(buf, &d); diff --git a/src/lib/krb5/asn.1/asn1_encode.h b/src/lib/krb5/asn.1/asn1_encode.h index c1486d2be..77d34f425 100644 --- a/src/lib/krb5/asn.1/asn1_encode.h +++ b/src/lib/krb5/asn.1/asn1_encode.h @@ -30,6 +30,7 @@ #include "k5-int.h" #include "krbasn1.h" #include "asn1buf.h" +#include "asn1_get.h" #include /* @@ -163,9 +164,11 @@ enum atype_type { * 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 . tinfo - * is a struct primitive_info * with tagval ignored. Cannot be used - * with an implicit tag. */ + /* + * Encoder function to be called with address of . The encoder + * function must generate a sequence without the sequence tag. tinfo is a + * struct fn_info *. Used only by kdc_req_body. + */ atype_fn, /* * Encoder function (contents only) to be called with address of @@ -175,10 +178,11 @@ enum atype_type { */ atype_string, /* - * As above, but the encoder function produces the tag as well as the - * contents. Cannot be used with an implicit context tag. + * Pre-made DER encoding stored at the address of . tinfo is a + * struct ptr_info * with the basetype field ignored. Only usable with the + * field_der field type. */ - atype_opaque, + atype_der, /* * Pointer to actual thing to be encoded. tinfo is a struct ptr_info *. * @@ -209,8 +213,8 @@ enum atype_type { atype_nonempty_nullterm_sequence_of, /* * Encode this object using a single field descriptor. tinfo is a struct - * field_info *. Cannot be used with an implicit tag. The presence of - * this type may mean the atype/field breakdown needs revision.... + * field_info *. The presence of this type may mean the atype/field + * breakdown needs revision.... * * Main expected uses: Encode realm component of principal as a * GENERALSTRING. Pluck data and length fields out of a structure @@ -238,6 +242,10 @@ struct primitive_info { unsigned int tagval; }; +struct fn_info { + asn1_error_code (*enc)(asn1buf *, const void *, taginfo *); +}; + struct string_info { asn1_error_code (*enclen)(asn1buf *, unsigned int, const void *, unsigned int *); @@ -311,16 +319,8 @@ struct uint_info { /* 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, \ - unsigned int *retlen) \ - { \ - return ENCFN(buf, \ - (const aux_typedefname_##DESCNAME *)val, \ - retlen); \ - } \ - static const struct primitive_info aux_info_##DESCNAME = { \ - aux_encfn_##DESCNAME \ + static const struct fn_info aux_info_##DESCNAME = { \ + ENCFN \ }; \ const struct atype_info krb5int_asn1type_##DESCNAME = { \ atype_fn, sizeof(CTYPENAME), &aux_info_##DESCNAME \ @@ -364,18 +364,18 @@ struct uint_info { } #endif /* Not used enough to justify a POINTERS_ARE_ALL_THE_SAME version. */ -#define DEFOPAQUETYPE(DESCNAME, CTYPENAME, ENCFN) \ +#define DEFDERTYPE(DESCNAME, CTYPENAME) \ 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 \ + static const struct ptr_info aux_info_##DESCNAME = { \ + loadptr_for_##DESCNAME \ }; \ const struct atype_info krb5int_asn1type_##DESCNAME = { \ - atype_opaque, 0, &aux_info_##DESCNAME \ + atype_der, 0, &aux_info_##DESCNAME \ } /* * A sequence, defined by the indicated series of fields, and an @@ -431,7 +431,7 @@ struct uint_info { typedef aux_typedefname_##BASEDESCNAME * aux_typedefname_##DESCNAME; \ static const struct ptr_info aux_info_##DESCNAME = { \ NULL, &krb5int_asn1type_##BASEDESCNAME \ - }; + }; \ const struct atype_info krb5int_asn1type_##DESCNAME = { \ atype_ptr, sizeof(aux_typedefname_##DESCNAME), \ &aux_info_##DESCNAME \ @@ -535,24 +535,11 @@ struct uint_info { typedef CTYPENAME aux_typedefname_##DESCNAME; \ extern const struct atype_info krb5int_asn1type_##DESCNAME -/* - * Create a partial-encoding function by the indicated name, for the - * indicated type. Should only be needed until we've converted all of - * the encoders, then everything should use descriptor tables. - */ -extern asn1_error_code -krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val, - const struct atype_info *a, unsigned int *retlen); -#define MAKE_ENCFN(FNAME,DESC) \ - static asn1_error_code FNAME(asn1buf *buf, \ - const aux_typedefname_##DESC *val, \ - unsigned int *retlen) \ - { \ - return krb5int_asn1_encode_a_thing(buf, val, \ - &krb5int_asn1type_##DESC, \ - retlen); \ - } \ - extern int dummy /* gobble semicolon */ +/* Partially encode the contents of a type and return its tag information. + * Used only by asn1_encode_kdc_req_body. */ +asn1_error_code +krb5int_asn1_encode_type(asn1buf *buf, const void *val, + const struct atype_info *a, taginfo *rettag); /* * Sequence field descriptor. @@ -583,6 +570,8 @@ enum field_type { * string would be handled as field_normal.) */ field_string, + /* Insert a DER encoding given by the pointer and length. */ + field_der, /* * LENOFF indicates a value describing the length of the array at * DATAOFF, encoded as a sequence-of with the element type @@ -616,7 +605,8 @@ struct field_info { * compactly as an unsigned bitfield value tagnum+1, with 0=no * tag.) The tag is omitted for optional fields that are not * present. If tag_implicit is set, then the context tag replaces - * the outer tag of the field. + * the outer tag of the field, and uses the same construction bit + * as the outer tag would have used. * * It's a bit illogical to combine the tag and other field info, * since really a sequence field could have zero or several @@ -721,6 +711,16 @@ struct field_info { #define FIELD_INT_IMM(VALUE,TAG,IMPLICIT) \ { field_immediate, VALUE, 0, TAG, IMPLICIT, -1, 0, } +#define FIELDOF_OPTDER(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG,IMPLICIT,OPT) \ + { field_der, \ + OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC), \ + OFFOF(STYPE, LENFIELD, aux_typedefname_##LENTYPE), \ + TAG, IMPLICIT, OPT, \ + &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENTYPE \ + } +#define FIELDOF_DER(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG,IMPLICIT) \ + FIELDOF_OPTDER(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG,IMPLICIT,-1) + #define FIELDOF_SEQOF_LEN(STYPE,DESC,PTRFIELD,LENFIELD,LENTYPE,TAG,IMPLICIT) \ { \ field_sequenceof_len, \ diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index a3ed7835f..b23a3ef73 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -42,7 +42,7 @@ DEFSTRINGTYPE(generalstring, char *, asn1_encode_bytestring, ASN1_GENERALSTRING); DEFSTRINGTYPE(u_generalstring, unsigned char *, asn1_encode_bytestring, ASN1_GENERALSTRING); -DEFOPAQUETYPE(opaque, char *, asn1_encode_bytestring); +DEFDERTYPE(der, char *); DEFFIELDTYPE(gstring_data, krb5_data, FIELDOF_STRING(krb5_data, generalstring, data, length, -1, 0)); @@ -52,8 +52,8 @@ DEFFIELDTYPE(ostring_data, krb5_data, FIELDOF_STRING(krb5_data, s_octetstring, data, length, -1, 0)); DEFPTRTYPE(ostring_data_ptr,ostring_data); -DEFFIELDTYPE(opaque_data, krb5_data, - FIELDOF_STRING(krb5_data, opaque, data, length, -1, 0)); +DEFFIELDTYPE(der_data, krb5_data, + FIELDOF_DER(krb5_data, der, data, length, uint, -1, 0)); DEFFIELDTYPE(realm_of_principal_data, krb5_principal_data, FIELDOF_NORM(krb5_principal_data, gstring_data, realm, -1, 0)); @@ -298,13 +298,9 @@ optional_kdc_req_hack(const void *p) DEFSEQTYPE(kdc_req_body_hack, struct kdc_req_hack, kdc_req_hack_fields, optional_kdc_req_hack); static asn1_error_code -asn1_encode_kdc_req_hack(asn1buf *, const struct kdc_req_hack *, - unsigned int *); -MAKE_ENCFN(asn1_encode_kdc_req_hack, kdc_req_body_hack); -static asn1_error_code -asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *val, - unsigned int *retlen) +asn1_encode_kdc_req_body(asn1buf *buf, const void *ptr, taginfo *rettag) { + const krb5_kdc_req *val = ptr; struct kdc_req_hack val2; val2.v = *val; if (val->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { @@ -314,7 +310,9 @@ asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *val, } else if (val->server != NULL) { val2.server_realm = &val->server->realm; } else return ASN1_MISSING_FIELD; - return asn1_encode_kdc_req_hack(buf, &val2, retlen); + return krb5int_asn1_encode_type(buf, &val2, + &krb5int_asn1type_kdc_req_body_hack, + rettag); } DEFFNTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body); /* end ugly hack */ @@ -455,8 +453,7 @@ DEFPTRTYPE(etype_info2_entry_ptr, etype_info2_entry); DEFNULLTERMSEQOFTYPE(etype_info2, etype_info2_entry_ptr); static const struct field_info sam_challenge_2_fields[] = { - FIELDOF_NORM(krb5_sam_challenge_2, opaque_data, sam_challenge_2_body, - 0, 0), + FIELDOF_NORM(krb5_sam_challenge_2, der_data, sam_challenge_2_body, 0, 0), FIELDOF_NORM(krb5_sam_challenge_2, ptr_seqof_checksum, sam_cksum, 1, 0), }; DEFSEQTYPE(sam_challenge_2, krb5_sam_challenge_2, sam_challenge_2_fields, 0); @@ -790,7 +787,7 @@ static const struct field_info krb5_safe_fields[] = { DEFSEQTYPE(untagged_krb5_safe, krb5_safe, krb5_safe_fields, 0); DEFAPPTAGGEDTYPE(krb5_safe, 20, untagged_krb5_safe); -DEFPTRTYPE(krb_saved_safe_body_ptr, opaque_data); +DEFPTRTYPE(krb_saved_safe_body_ptr, der_data); DEFFIELDTYPE(krb5_safe_checksum_only, krb5_safe, FIELDOF_NORM(krb5_safe, checksum_ptr, checksum, -1, 0)); DEFPTRTYPE(krb5_safe_checksum_only_ptr, krb5_safe_checksum_only); @@ -1307,7 +1304,7 @@ algorithm_identifier_optional(const void *p) static const struct field_info algorithm_identifier_fields[] = { FIELDOF_NORM(krb5_algorithm_identifier, oid_data, algorithm, -1, 0), - FIELDOF_OPT(krb5_algorithm_identifier, opaque_data, parameters, -1, 0, 1), + FIELDOF_OPT(krb5_algorithm_identifier, der_data, parameters, -1, 0, 1), }; DEFSEQTYPE(algorithm_identifier, krb5_algorithm_identifier, algorithm_identifier_fields, algorithm_identifier_optional); -- 2.26.2