summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2012-01-06 21:13:59 +0000
committerGreg Hudson <ghudson@mit.edu>2012-01-06 21:13:59 +0000
commitb5143ff810a937e12491ba678575c09948d78300 (patch)
treeb59920c5f3687cd1c70186f001e930d39045c1e5 /src
parentfff0545bfbe58930c71c4ccb280447d0d335d499 (diff)
downloadkrb5-b5143ff810a937e12491ba678575c09948d78300.tar.gz
krb5-b5143ff810a937e12491ba678575c09948d78300.tar.xz
krb5-b5143ff810a937e12491ba678575c09948d78300.zip
Add support for CHOICE in ASN.1 encoder
Add a new field type where the length offset indicates a distinguisher and the data offset indicates a union address. The field's type is an atype_choice containing a seq_info indexed by the distinguisher. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25616 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/lib/krb5/asn.1/asn1_encode.c18
-rw-r--r--src/lib/krb5/asn.1/asn1_encode.h32
2 files changed, 50 insertions, 0 deletions
diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c
index 5fc1efdfd3..e654b72866 100644
--- a/src/lib/krb5/asn.1/asn1_encode.c
+++ b/src/lib/krb5/asn.1/asn1_encode.c
@@ -504,6 +504,24 @@ encode_a_field(asn1buf *buf, const void *val, const struct field_info *field,
assert(omit_tag == NULL && !field->tag_implicit);
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);
+ if (retval)
+ return retval;
+ if (choice > seq->n_fields)
+ return ASN1_MISSING_FIELD;
+ retval = encode_a_field(buf, dataptr, &seq->fields[choice], &length,
+ NULL);
+ break;
+ }
default:
assert(field->ftype > field_min);
assert(field->ftype < field_max);
diff --git a/src/lib/krb5/asn.1/asn1_encode.h b/src/lib/krb5/asn.1/asn1_encode.h
index 85e4861a53..c1486d2be0 100644
--- a/src/lib/krb5/asn.1/asn1_encode.h
+++ b/src/lib/krb5/asn.1/asn1_encode.h
@@ -194,6 +194,12 @@ enum atype_type {
/* Sequence. tinfo is a struct seq_info *. */
atype_sequence,
/*
+ * Choice. tinfo is a struct seq_info *, with the optional field ignored.
+ * Only usable with the field_choice field type. Cannot be used with an
+ * implicit context tag.
+ */
+ atype_choice,
+ /*
* Sequence-of, with pointer to base type descriptor, represented
* as a null-terminated array of pointers (and thus the "base"
* type descriptor is actually an atype_ptr node). tinfo is a
@@ -383,6 +389,15 @@ struct uint_info {
const struct atype_info krb5int_asn1type_##DESCNAME = { \
atype_sequence, sizeof(CTYPENAME), &aux_seqinfo_##DESCNAME \
}
+/* A choice, selected from the indicated series of fields. */
+#define DEFCHOICETYPE(DESCNAME, CTYPENAME, FIELDS) \
+ typedef CTYPENAME aux_typedefname_##DESCNAME; \
+ static const struct seq_info aux_seqinfo_##DESCNAME = { \
+ NULL, FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0]) \
+ }; \
+ const struct atype_info krb5int_asn1type_##DESCNAME = { \
+ atype_choice, sizeof(CTYPENAME), &aux_seqinfo_##DESCNAME \
+ }
/* Integer types. */
#define DEFINTTYPE(DESCNAME, CTYPENAME) \
typedef CTYPENAME aux_typedefname_##DESCNAME; \
@@ -574,6 +589,12 @@ enum field_type {
* described by ATYPE.
*/
field_sequenceof_len,
+ /*
+ * LENOFF indicates a distinguisher and DATAOFF indicates a union base
+ * address. ATYPE is an atype_choice type pointing to a seq_info
+ * containing a field type for each choice element.
+ */
+ field_choice,
/* Unused except for range checking. */
field_max
};
@@ -711,6 +732,17 @@ struct field_info {
#define FIELDOF_SEQOF_INT32(STYPE,DESC,PTRFIELD,LENFIELD,TAG,IMPLICIT) \
FIELDOF_SEQOF_LEN(STYPE,DESC,PTRFIELD,LENFIELD,int32,TAG,IMPLICIT)
+#define FIELDOF_OPTCHOICE(STYPE,DESC,PTRFIELD,CHOICEFIELD,LENTYPE,TAG,OPT) \
+ { \
+ field_choice, \
+ OFFOF(STYPE, PTRFIELD, aux_typedefname_##DESC), \
+ OFFOF(STYPE, CHOICEFIELD, aux_typedefname_##LENTYPE), \
+ TAG, 0, OPT, \
+ &krb5int_asn1type_##DESC, &krb5int_asn1type_##LENTYPE \
+ }
+#define FIELDOF_CHOICE(STYPE,DESC,PTRFIELD,CHOICEFIELD,LENTYPE,TAG) \
+ FIELDOF_OPTCHOICE(STYPE,DESC,PTRFIELD,CHOICEFIELD,LENTYPE,TAG,-1)
+
struct seq_info {
/*
* If present, returns a bitmask indicating which fields are