svn rev #25622: trunk/src/lib/krb5/asn.1/
ghudson@MIT.EDU
ghudson at MIT.EDU
Sat Jan 7 21:10:47 EST 2012
http://src.mit.edu/fisheye/changelog/krb5/?cs=25622
Commit By: ghudson
Log Message:
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.
Changed Files:
U trunk/src/lib/krb5/asn.1/asn1_encode.c
U trunk/src/lib/krb5/asn.1/asn1_encode.h
U trunk/src/lib/krb5/asn.1/asn1_k_encode.c
Modified: trunk/src/lib/krb5/asn.1/asn1_encode.c
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_encode.c 2012-01-07 20:57:36 UTC (rev 25621)
+++ trunk/src/lib/krb5/asn.1/asn1_encode.c 2012-01-08 02:10:47 UTC (rev 25622)
@@ -176,8 +176,9 @@
*
* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
Modified: trunk/src/lib/krb5/asn.1/asn1_encode.h
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_encode.h 2012-01-07 20:57:36 UTC (rev 25621)
+++ trunk/src/lib/krb5/asn.1/asn1_encode.h 2012-01-08 02:10:47 UTC (rev 25622)
@@ -30,6 +30,7 @@
#include "k5-int.h"
#include "krbasn1.h"
#include "asn1buf.h"
+#include "asn1_get.h"
#include <time.h>
/*
@@ -163,9 +164,11 @@
* 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. Cannot be used
- * with an implicit tag. */
+ /*
+ * Encoder function to be called with address of <thing>. 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 <thing>
@@ -175,10 +178,11 @@
*/
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 <thing>. 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 @@
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 @@
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 @@
/* 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 @@
}
#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 @@
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 @@
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 @@
* 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 @@
* 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 @@
#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, \
Modified: trunk/src/lib/krb5/asn.1/asn1_k_encode.c
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_k_encode.c 2012-01-07 20:57:36 UTC (rev 25621)
+++ trunk/src/lib/krb5/asn.1/asn1_k_encode.c 2012-01-08 02:10:47 UTC (rev 25622)
@@ -42,7 +42,7 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
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);
More information about the cvs-krb5
mailing list