svn rev #25617: trunk/src/ include/ lib/krb5/asn.1/

ghudson@MIT.EDU ghudson at MIT.EDU
Fri Jan 6 16:17:14 EST 2012


http://src.mit.edu/fisheye/changelog/krb5/?cs=25617
Commit By: ghudson
Log Message:
Convert all remaining macro-coded ASN.1 encoders

Use data-driven encoders for all of the remaining types which still
used macros (primarily PKINIT types), and get rid of the macros.  Do
not change any encoding behavior, but add some comments where behavior
differs from the spec.

DEFFNTYPE is now unused except for the kdc_req_body hack.


Changed Files:
U   trunk/src/include/k5-int-pkinit.h
U   trunk/src/include/k5-int.h
U   trunk/src/lib/krb5/asn.1/Makefile.in
U   trunk/src/lib/krb5/asn.1/asn1_k_encode.c
D   trunk/src/lib/krb5/asn.1/asn1_k_encode.h
U   trunk/src/lib/krb5/asn.1/deps
D   trunk/src/lib/krb5/asn.1/krb5_encode.c
U   trunk/src/lib/krb5/asn.1/ldap_key_seq.c
Modified: trunk/src/include/k5-int-pkinit.h
===================================================================
--- trunk/src/include/k5-int-pkinit.h	2012-01-06 21:13:59 UTC (rev 25616)
+++ trunk/src/include/k5-int-pkinit.h	2012-01-06 21:17:14 UTC (rev 25617)
@@ -89,13 +89,13 @@
 
 /* TrustedCas */
 typedef struct _krb5_trusted_ca {
-    enum {
+    enum krb5_trusted_ca_selection {
         choice_trusted_cas_UNKNOWN = -1,
         choice_trusted_cas_principalName = 0,
         choice_trusted_cas_caName = 1,
         choice_trusted_cas_issuerAndSerial = 2
     } choice;
-    union {
+    union krb5_trusted_ca_choices {
         krb5_principal  principalName;
         krb5_data caName; /* fully-qualified X.500 "Name" as defined by X.509 (der-encoded) */
         krb5_data issuerAndSerial; /* Optional -- IssuerAndSerialNumber (der-encoded) */
@@ -151,12 +151,12 @@
 
 /* PA-PK-AS-REP (Draft 9 -- PA TYPE 15) */
 typedef struct _krb5_pa_pk_as_rep_draft9 {
-    enum {
+    enum krb5_pa_pk_as_rep_draft9_selection {
         choice_pa_pk_as_rep_draft9_UNKNOWN = -1,
         choice_pa_pk_as_rep_draft9_dhSignedData = 0,
         choice_pa_pk_as_rep_draft9_encKeyPack = 1
     } choice;
-    union {
+    union krb5_pa_pk_as_rep_draft9_choices {
         krb5_data dhSignedData;
         krb5_data encKeyPack;
     } u;
@@ -164,12 +164,12 @@
 
 /* PA-PK-AS-REP (rfc4556 -- PA TYPE 17) */
 typedef struct _krb5_pa_pk_as_rep {
-    enum {
+    enum krb5_pa_pk_as_rep_selection {
         choice_pa_pk_as_rep_UNKNOWN = -1,
         choice_pa_pk_as_rep_dhInfo = 0,
         choice_pa_pk_as_rep_encKeyPack = 1
     } choice;
-    union {
+    union krb5_pa_pk_as_rep_choices {
         krb5_dh_rep_info    dh_Info;
         krb5_data           encKeyPack;
     } u;
@@ -230,11 +230,11 @@
                                   krb5_data **code);
 
 krb5_error_code
-encode_krb5_td_trusted_certifiers(const krb5_external_principal_identifier **,
+encode_krb5_td_trusted_certifiers(krb5_external_principal_identifier *const *,
                                   krb5_data **code);
 
 krb5_error_code
-encode_krb5_td_dh_parameters(const krb5_algorithm_identifier **,
+encode_krb5_td_dh_parameters(krb5_algorithm_identifier *const *,
                              krb5_data **code);
 
 krb5_error_code

Modified: trunk/src/include/k5-int.h
===================================================================
--- trunk/src/include/k5-int.h	2012-01-06 21:13:59 UTC (rev 25616)
+++ trunk/src/include/k5-int.h	2012-01-06 21:17:14 UTC (rev 25617)
@@ -1677,7 +1677,7 @@
 encode_krb5_padata_sequence(krb5_pa_data *const *rep, krb5_data **code);
 
 krb5_error_code
-encode_krb5_typed_data(const krb5_pa_data *const *rep, krb5_data **code);
+encode_krb5_typed_data(krb5_pa_data *const *rep, krb5_data **code);
 
 krb5_error_code
 encode_krb5_alt_method(const krb5_alt_method *, krb5_data **code);

Modified: trunk/src/lib/krb5/asn.1/Makefile.in
===================================================================
--- trunk/src/lib/krb5/asn.1/Makefile.in	2012-01-06 21:13:59 UTC (rev 25616)
+++ trunk/src/lib/krb5/asn.1/Makefile.in	2012-01-06 21:17:14 UTC (rev 25617)
@@ -20,7 +20,6 @@
 	asn1buf.o\
 	krb5_decode.o\
 	krb5_decode_kdc.o\
-	krb5_encode.o\
 	asn1_k_encode.o\
 	ldap_key_seq.o\
 	asn1_misc.o
@@ -37,7 +36,6 @@
 	$(srcdir)/asn1buf.c\
 	$(srcdir)/krb5_decode.c\
 	$(srcdir)/krb5_decode_kdc.c\
-	$(srcdir)/krb5_encode.c\
 	$(srcdir)/asn1_k_encode.c\
 	$(srcdir)/ldap_key_seq.c\
 	$(srcdir)/asn1_misc.c
@@ -54,7 +52,6 @@
 	$(OUTPRE)asn1buf.$(OBJEXT)\
 	$(OUTPRE)krb5_decode.$(OBJEXT)\
 	$(OUTPRE)krb5_decode_kdc.$(OBJEXT)\
-	$(OUTPRE)krb5_encode.$(OBJEXT)\
 	$(OUTPRE)asn1_k_encode.$(OBJEXT)\
 	$(OUTPRE)ldap_key_seq.$(OBJEXT)\
 	$(OUTPRE)asn1_misc.$(OBJEXT)

Modified: trunk/src/lib/krb5/asn.1/asn1_k_encode.c
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_k_encode.c	2012-01-06 21:13:59 UTC (rev 25616)
+++ trunk/src/lib/krb5/asn.1/asn1_k_encode.c	2012-01-06 21:17:14 UTC (rev 25617)
@@ -24,53 +24,10 @@
  * or implied warranty.
  */
 
-#include "asn1_k_encode.h"
 #include "asn1_make.h"
 #include "asn1_encode.h"
 #include <assert.h>
 
-/*
- * helper macros
- *
- * These are mostly only needed for PKINIT, but there are three
- * basic-krb5 encoders not converted yet.
- */
-
-/*
- * setup() -- create and initialize bookkeeping variables
- *   retval: stores error codes returned from subroutines
- *   length: length of the most-recently produced encoding
- *   sum: cumulative length of the entire encoding
- */
-#define asn1_setup()                            \
-    asn1_error_code retval;                     \
-    unsigned int sum=0
-
-/* form a sequence (by adding a sequence header to the current encoding) */
-#define asn1_makeseq()                                  \
-    { unsigned int length;                              \
-        retval = asn1_make_sequence(buf,sum,&length);   \
-        if (retval) {                                   \
-            return retval; }                            \
-        sum += length; }
-
-/* produce the final output and clean up the workspace */
-#define asn1_cleanup()                          \
-    *retlen = sum;                              \
-    return 0
-
-/* asn1_addfield -- add a field, or component, to the encoding */
-#define asn1_addfield(value,tag,encoder)                                \
-    { unsigned int length;                                              \
-        retval = encoder(buf,value,&length);                            \
-        if (retval) {                                                   \
-            return retval; }                                            \
-        sum += length;                                                  \
-        retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length); \
-        if (retval) {                                                   \
-            return retval; }                                            \
-        sum += length; }
-
 DEFINTTYPE(int32, krb5_int32);
 DEFPTRTYPE(int32_ptr, int32);
 
@@ -546,39 +503,13 @@
 DEFSEQTYPE(sam_challenge,krb5_sam_challenge,sam_challenge_fields,
            optional_sam_challenge);
 
-MAKE_ENCFN(asn1_encode_sequence_of_checksum, seq_of_checksum);
-static asn1_error_code
-asn1_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val,
-                            unsigned int *retlen)
-{
-    asn1_setup();
-    if ( (!val) || (!val->sam_cksum) || (!val->sam_cksum[0]))
-        return ASN1_MISSING_FIELD;
+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, ptr_seqof_checksum, sam_cksum, 1, 0),
+};
+DEFSEQTYPE(sam_challenge_2, krb5_sam_challenge_2, sam_challenge_2_fields, 0);
 
-    asn1_addfield(val->sam_cksum, 1, asn1_encode_sequence_of_checksum);
-
-    {
-        unsigned int length;
-
-        retval = asn1buf_insert_octetstring(buf, val->sam_challenge_2_body.length,
-                                            (unsigned char *)val->sam_challenge_2_body.data);
-        if (retval) {
-            return retval;
-        }
-        sum += val->sam_challenge_2_body.length;
-        retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0,
-                                val->sam_challenge_2_body.length, &length);
-        if (retval) {
-            return retval;
-        }
-        sum += length;
-    }
-
-    asn1_makeseq();
-    asn1_cleanup();
-}
-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, 0),
     FIELDOF_NORM(krb5_sam_challenge_2_body, krb5_flags, sam_flags, 1, 0),
@@ -1543,151 +1474,8 @@
  * PKINIT
  */
 
-/*
- * This code hasn't been converted to use the above framework yet,
- * because we currently have no test cases to validate the new
- * version.  It *also* appears that some of the encodings may disagree
- * with the specifications, but that's a separate problem.
- */
-
-/**** asn1 macros ****/
-#if 0
-How to write an asn1 encoder function using these macros:
-
-asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf,
-                                              const krb5_type *val,
-                                              int *retlen)
-{
-    asn1_setup();
-
-    asn1_addfield(val->last_field, n, asn1_type);
-    asn1_addfield(rep->next_to_last_field, n-1, asn1_type);
-    ...
-
-        /* for OPTIONAL fields */
-        if (rep->field_i == should_not_be_omitted)
-            asn1_addfield(rep->field_i, i, asn1_type);
-
-        /*
-         * for string fields (these encoders take an additional argument,
-         * the length of the string)
-         */
-        addlenfield(rep->field_length, rep->field, i-1, asn1_type);
-
-        /* if you really have to do things yourself... */
-        retval = asn1_encode_asn1_type(buf,rep->field,&length);
-        if (retval) return retval;
-        sum += length;
-        retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length,
-                                &length);
-        if (retval) return retval;
-        sum += length;
-
-        ...
-            asn1_addfield(rep->second_field, 1, asn1_type);
-            asn1_addfield(rep->first_field, 0, asn1_type);
-            asn1_makeseq();
-
-            asn1_cleanup();
-}
-#endif
-
-/*
- * 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;                                                    \
-    }
-
-/*
- * asn1_addfield_implicit -- add an implicitly tagged field, or component,
- * to the encoding
- */
-#define asn1_addfield_implicit(value,tag,encoder)               \
-    { unsigned int length;                                      \
-        retval = encoder(buf,value,&length);                    \
-        if (retval) {                                           \
-            return retval; }                                    \
-        sum += length;                                          \
-        retval = asn1_make_tag(buf, CONTEXT_SPECIFIC,PRIMITIVE, \
-                               tag, length, &length);           \
-        if (retval) {                                           \
-            return retval; }                                    \
-        sum += length; }
-
-/*
- * asn1_insert_implicit_octetstring -- add an octet string with implicit
- * tagging
- */
-#define asn1_insert_implicit_octetstring(len,value,tag)                 \
-    { unsigned int length;                                              \
-        retval = asn1buf_insert_octetstring(buf,len,value);             \
-        if (retval) {                                                   \
-            return retval; }                                            \
-        sum += len;                                                     \
-        retval = asn1_make_tag(buf, CONTEXT_SPECIFIC, PRIMITIVE,        \
-                               tag, len, &length);                      \
-        if (retval) {                                                   \
-            return retval; }                                            \
-        sum += length; }
-
-/* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */
-/* needs "length" declared in enclosing context */
-#define asn1_insert_implicit_bitstring(len, value, tag)         \
-    {                                                           \
-        retval = asn1buf_insert_octetstring(buf, len, value);   \
-        if (retval) {                                           \
-            return retval; }                                    \
-        sum += len;                                             \
-        retval = asn1buf_insert_octet(buf, 0);                  \
-        if (retval) {                                           \
-            return retval; }                                    \
-        sum++;                                                  \
-        retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE,       \
-                               tag, len + 1, &length);          \
-        if (retval) {                                           \
-            return retval; }                                    \
-        sum += length;                                          \
-    }
-
 #ifndef DISABLE_PKINIT
 
-DEFFNTYPE(algorithm_identifier, krb5_algorithm_identifier, asn1_encode_algorithm_identifier);
 DEFSTRINGTYPE(object_identifier, char *, asn1_encode_bytestring,
               ASN1_OBJECTIDENTIFIER);
 DEFFIELDTYPE(oid_data, krb5_data,
@@ -1695,6 +1483,24 @@
                             -1, 0));
 DEFPTRTYPE(oid_data_ptr, oid_data);
 
+static unsigned int
+algorithm_identifier_optional(const void *p)
+{
+    unsigned int optional = 0;
+    const krb5_algorithm_identifier *val = p;
+    if (val->parameters.length > 0)
+        optional |= (1u << 1);
+    return optional;
+}
+
+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),
+};
+DEFSEQTYPE(algorithm_identifier, krb5_algorithm_identifier,
+           algorithm_identifier_fields, algorithm_identifier_optional);
+DEFPTRTYPE(algorithm_identifier_ptr, algorithm_identifier);
+
 static const struct field_info kdf_alg_id_fields[] = {
     FIELDOF_ENCODEAS(krb5_data, oid_data, 0, 0)
 };
@@ -1702,11 +1508,7 @@
 DEFPTRTYPE(kdf_alg_id_ptr, kdf_alg_id);
 DEFNONEMPTYNULLTERMSEQOFTYPE(supported_kdfs, kdf_alg_id_ptr);
 DEFPTRTYPE(supported_kdfs_ptr, supported_kdfs);
-MAKE_ENCFN(asn1_encode_supported_kdfs,
-           supported_kdfs);
-MAKE_ENCFN(asn1_encode_kdf_alg_id, kdf_alg_id);
 
-
 /* Krb5PrincipalName is defined in RFC 4556 and is *not* PrincipalName from RFC 4120*/
 static const struct field_info pkinit_krb5_principal_name_fields[] = {
     FIELDOF_NORM(krb5_principal_data, gstring_data, realm, 0, 0),
@@ -1747,449 +1549,311 @@
 MAKE_FULL_ENCODER(encode_krb5_pkinit_supp_pub_info, pkinit_supp_pub_info);
 MAKE_FULL_ENCODER(encode_krb5_sp80056a_other_info, sp80056a_other_info);
 
-/* Callable encoders for the types defined above, until the PKINIT
-   encoders get converted.  */
-MAKE_ENCFN(asn1_encode_realm, realm_of_principal_data);
-MAKE_ENCFN(asn1_encode_principal_name, principal_data);
-MAKE_ENCFN(asn1_encode_encryption_key, encryption_key);
-MAKE_ENCFN(asn1_encode_checksum, checksum);
+/* A krb5_checksum encoded as an OCTET STRING, for PKAuthenticator. */
+DEFFIELDTYPE(ostring_checksum, krb5_checksum,
+             FIELDOF_STRING(krb5_checksum, octetstring, contents, length,
+                            -1, 0));
 
-static asn1_error_code
-asn1_encode_kerberos_time(asn1buf *buf, const krb5_timestamp val,
-                          unsigned int *retlen)
-{
-    return asn1_encode_kerberos_time_at(buf,&val,retlen);
-}
+static const struct field_info pk_authenticator_fields[] = {
+    FIELDOF_NORM(krb5_pk_authenticator, int32, cusec, 0, 0),
+    FIELDOF_NORM(krb5_pk_authenticator, kerberos_time, ctime, 1, 0),
+    FIELDOF_NORM(krb5_pk_authenticator, int32, nonce, 2, 0),
+    FIELDOF_NORM(krb5_pk_authenticator, ostring_checksum, paChecksum, 3, 0),
+};
+DEFSEQTYPE(pk_authenticator, krb5_pk_authenticator, pk_authenticator_fields,
+           0);
 
-/* Now the real PKINIT encoder functions.  */
-asn1_error_code
-asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val,
-                             unsigned int *retlen)
-{
-    asn1_setup();
-    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);
+static const struct field_info pk_authenticator_draft9_fields[] = {
+    FIELDOF_NORM(krb5_pk_authenticator_draft9, principal, kdcName, 0, 0),
+    FIELDOF_NORM(krb5_pk_authenticator_draft9, realm_of_principal, kdcName,
+                 1, 0),
+    FIELDOF_NORM(krb5_pk_authenticator_draft9, int32, cusec, 2, 0),
+    FIELDOF_NORM(krb5_pk_authenticator_draft9, kerberos_time, ctime, 3, 0),
+    FIELDOF_NORM(krb5_pk_authenticator_draft9, int32, nonce, 4, 0),
+};
+DEFSEQTYPE(pk_authenticator_draft9, krb5_pk_authenticator_draft9,
+           pk_authenticator_draft9_fields, 0);
 
-    asn1_makeseq();
-    asn1_cleanup();
-}
+DEFSTRINGTYPE(s_bitstring, char *, asn1_encode_bitstring, ASN1_BITSTRING);
+DEFFIELDTYPE(bitstring_data, krb5_data,
+             FIELDOF_STRING(krb5_data, s_bitstring, data, length, -1, 0));
 
-asn1_error_code
-asn1_encode_pk_authenticator_draft9(asn1buf *buf,
-                                    const krb5_pk_authenticator_draft9 *val,
-                                    unsigned int *retlen)
-{
-    asn1_setup();
+static const struct field_info subject_pk_info_fields[] = {
+    FIELDOF_NORM(krb5_subject_pk_info, algorithm_identifier, algorithm, -1, 0),
+    FIELDOF_NORM(krb5_subject_pk_info, bitstring_data, subjectPublicKey, -1, 0)
+};
+DEFSEQTYPE(subject_pk_info, krb5_subject_pk_info, subject_pk_info_fields, 0);
+DEFPTRTYPE(subject_pk_info_ptr, subject_pk_info);
 
-    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);
+DEFNULLTERMSEQOFTYPE(seq_of_algorithm_identifier, algorithm_identifier_ptr);
+DEFPTRTYPE(ptr_seqof_algorithm_identifier, seq_of_algorithm_identifier);
 
-    asn1_makeseq();
-    asn1_cleanup();
-}
-
-
-asn1_error_code
-asn1_encode_algorithm_identifier(asn1buf *buf,
-                                 const krb5_algorithm_identifier *val,
-                                 unsigned int *retlen)
+static unsigned int
+auth_pack_optional(const void *p)
 {
-    asn1_setup();
-
-    if (val->parameters.length != 0) {
-        retval = asn1buf_insert_octetstring(buf, val->parameters.length,
-                                            val->parameters.data);
-        if (retval)
-            return retval;
-        sum += val->parameters.length;
-    }
-
-    {
-        unsigned int 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();
-    asn1_cleanup();
+    unsigned int optional = 0;
+    const krb5_auth_pack *val = p;
+    if (val->clientPublicValue != NULL)
+        optional |= (1u << 1);
+    if (val->supportedCMSTypes != NULL)
+        optional |= (1u << 2);
+    if (val->clientDHNonce.length != 0)
+        optional |= (1u << 3);
+    if (val->supportedKDFs != NULL)
+        optional |= (1u << 4);
+    return optional;
 }
 
-asn1_error_code
-asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val,
-                            unsigned int *retlen)
-{
-    asn1_setup();
-    unsigned int len, alen = 0;
+static const struct field_info auth_pack_fields[] = {
+    FIELDOF_NORM(krb5_auth_pack, pk_authenticator, pkAuthenticator, 0, 0),
+    FIELDOF_OPT(krb5_auth_pack, subject_pk_info_ptr, clientPublicValue,
+                1, 0, 1),
+    FIELDOF_OPT(krb5_auth_pack, ptr_seqof_algorithm_identifier,
+                supportedCMSTypes, 2, 0, 2),
+    FIELDOF_OPT(krb5_auth_pack, ostring_data, clientDHNonce, 3, 0, 3),
+    FIELDOF_OPT(krb5_auth_pack, supported_kdfs_ptr, supportedKDFs, 4, 0, 4),
+};
+DEFSEQTYPE(auth_pack, krb5_auth_pack, auth_pack_fields, auth_pack_optional);
 
-    {
-        unsigned int length;
-
-        asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING);
-    }
-
-    if (val->algorithm.parameters.length != 0) {
-        retval = asn1buf_insert_octetstring(buf, val->algorithm.parameters.length,
-                                            val->algorithm.parameters.data);
-        if (retval)
-            return retval;
-        alen += val->algorithm.parameters.length;
-    }
-
-    retval = asn1_encode_bytestring(buf, val->algorithm.algorithm.length,
-                                    val->algorithm.algorithm.data, &len);
-    if (retval)
-        return retval;
-    alen += len;
-
-    retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE,
-                           ASN1_OBJECTIDENTIFIER, len, &len);
-    if (retval)
-        return retval;
-    alen += len;
-
-    retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, alen, &len);
-    if (retval)
-        return retval;
-    sum += alen + len;
-
-    asn1_makeseq();
-    asn1_cleanup();
-}
-
-asn1_error_code
-asn1_encode_sequence_of_algorithm_identifier(
-    asn1buf *buf, const krb5_algorithm_identifier **val,
-    unsigned int *retlen)
+static unsigned int
+auth_pack_draft9_optional(const void *p)
 {
-    asn1_setup();
-    int i;
-
-    if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
-
-    for (i=0; val[i] != NULL; i++);
-    for (i--; i>=0; i--) {
-        unsigned int length;
-        retval = asn1_encode_algorithm_identifier(buf,val[i],&length);
-        if (retval) return retval;
-        sum += length;
-    }
-    asn1_makeseq();
-
-    asn1_cleanup();
-}
-
-asn1_error_code
-asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val,
-                      unsigned int *retlen)
-{
-    asn1_setup();
-
-    if (val->supportedKDFs != NULL)
-        asn1_addfield(val->supportedKDFs, 4, asn1_encode_supported_kdfs);
-    if (val->clientDHNonce.length != 0)
-        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);
+    unsigned int optional = 0;
+    const krb5_auth_pack *val = p;
     if (val->clientPublicValue != NULL)
-        asn1_addfield(val->clientPublicValue,1,asn1_encode_subject_pk_info);
-    asn1_addfield(&(val->pkAuthenticator),0,asn1_encode_pk_authenticator);
-
-    asn1_makeseq();
-    asn1_cleanup();
+        optional |= (1u << 1);
+    return optional;
 }
 
-asn1_error_code
-asn1_encode_auth_pack_draft9(asn1buf *buf, const krb5_auth_pack_draft9 *val,
-                             unsigned int *retlen)
-{
-    asn1_setup();
+static const struct field_info auth_pack_draft9_fields[] = {
+    FIELDOF_NORM(krb5_auth_pack_draft9, pk_authenticator_draft9,
+                 pkAuthenticator, 0, 0),
+    FIELDOF_OPT(krb5_auth_pack_draft9, subject_pk_info_ptr,
+                clientPublicValue, 1, 0, 1),
+};
+DEFSEQTYPE(auth_pack_draft9, krb5_auth_pack_draft9, auth_pack_draft9_fields,
+           auth_pack_draft9_optional);
 
-    if (val->clientPublicValue != NULL)
-        asn1_addfield(val->clientPublicValue, 1, asn1_encode_subject_pk_info);
-    asn1_addfield(&(val->pkAuthenticator), 0, asn1_encode_pk_authenticator_draft9);
-
-    asn1_makeseq();
-    asn1_cleanup();
-}
-
-asn1_error_code
-asn1_encode_external_principal_identifier(
-    asn1buf *buf, const krb5_external_principal_identifier *val,
-    unsigned int *retlen)
+static unsigned int
+external_principal_identifier_optional(const void *p)
 {
-    asn1_setup();
-
-    /* Verify there is something to encode */
-    if (val->subjectKeyIdentifier.length == 0 && val->issuerAndSerialNumber.length == 0 && val->subjectName.length == 0)
-        return ASN1_MISSING_FIELD;
-
-    if (val->subjectKeyIdentifier.length != 0)
-        asn1_insert_implicit_octetstring(val->subjectKeyIdentifier.length,val->subjectKeyIdentifier.data,2);
-
-    if (val->issuerAndSerialNumber.length != 0)
-        asn1_insert_implicit_octetstring(val->issuerAndSerialNumber.length,val->issuerAndSerialNumber.data,1);
-
-    if (val->subjectName.length != 0)
-        asn1_insert_implicit_octetstring(val->subjectName.length,val->subjectName.data,0);
-
-    asn1_makeseq();
-    asn1_cleanup();
+    unsigned int optional = 0;
+    const krb5_external_principal_identifier *val = p;
+    if (val->subjectName.length > 0)
+        optional |= (1u << 0);
+    if (val->issuerAndSerialNumber.length > 0)
+        optional |= (1u << 1);
+    if (val->subjectKeyIdentifier.length > 0)
+        optional |= (1u << 2);
+    return optional;
 }
 
-asn1_error_code
-asn1_encode_sequence_of_external_principal_identifier(
-    asn1buf *buf,
-    const krb5_external_principal_identifier **val,
-    unsigned int *retlen)
-{
-    asn1_setup();
-    int i;
+static const struct field_info external_principal_identifier_fields[] = {
+    FIELDOF_OPT(krb5_external_principal_identifier, ostring_data, subjectName,
+                0, 1, 0),
+    FIELDOF_OPT(krb5_external_principal_identifier, ostring_data,
+                issuerAndSerialNumber, 1, 1, 1),
+    FIELDOF_OPT(krb5_external_principal_identifier, ostring_data,
+                subjectKeyIdentifier, 2, 1, 2),
+};
+DEFSEQTYPE(external_principal_identifier, krb5_external_principal_identifier,
+           external_principal_identifier_fields,
+           external_principal_identifier_optional);
+DEFPTRTYPE(external_principal_identifier_ptr, external_principal_identifier);
 
-    if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+DEFNULLTERMSEQOFTYPE(seq_of_external_principal_identifier,
+                     external_principal_identifier_ptr);
+DEFPTRTYPE(ptr_seqof_external_principal_identifier,
+           seq_of_external_principal_identifier);
 
-    for (i=0; val[i] != NULL; i++);
-    for (i--; i>=0; i--) {
-        unsigned int length;
-        retval = asn1_encode_external_principal_identifier(buf,val[i],&length);
-        if (retval) return retval;
-        sum += length;
-    }
-    asn1_makeseq();
-
-    asn1_cleanup();
-}
-
-asn1_error_code
-asn1_encode_pa_pk_as_req(asn1buf *buf, const krb5_pa_pk_as_req *val,
-                         unsigned int *retlen)
+static unsigned int
+pa_pk_as_req_optional(const void *p)
 {
-    asn1_setup();
-
-    if (val->kdcPkId.length != 0)
-        asn1_insert_implicit_octetstring(val->kdcPkId.length,val->kdcPkId.data,2);
-
+    unsigned int optional = 0;
+    const krb5_pa_pk_as_req *val = p;
     if (val->trustedCertifiers != NULL)
-        asn1_addfield((const krb5_external_principal_identifier **)val->trustedCertifiers,1,asn1_encode_sequence_of_external_principal_identifier);
-
-    asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0);
-
-    asn1_makeseq();
-    asn1_cleanup();
+        optional |= (1u << 1);
+    if (val->kdcPkId.length > 0)
+        optional |= (1u << 2);
+    return optional;
 }
 
-asn1_error_code
-asn1_encode_trusted_ca(asn1buf *buf, const krb5_trusted_ca *val,
-                       unsigned int *retlen)
-{
-    asn1_setup();
+static const struct field_info pa_pk_as_req_fields[] = {
+    FIELDOF_NORM(krb5_pa_pk_as_req, ostring_data, signedAuthPack, 0, 1),
+    FIELDOF_OPT(krb5_pa_pk_as_req, ptr_seqof_external_principal_identifier,
+                trustedCertifiers, 1, 0, 1),
+    FIELDOF_OPT(krb5_pa_pk_as_req, ostring_data, kdcPkId, 2, 1, 2),
+};
+DEFSEQTYPE(pa_pk_as_req, krb5_pa_pk_as_req, pa_pk_as_req_fields,
+           pa_pk_as_req_optional);
 
-    switch (val->choice) {
-    case choice_trusted_cas_issuerAndSerial:
-        asn1_insert_implicit_octetstring(val->u.issuerAndSerial.length,val->u.issuerAndSerial.data,2);
-        break;
-    case choice_trusted_cas_caName:
-        asn1_insert_implicit_octetstring(val->u.caName.length,val->u.caName.data,1);
-        break;
-    case choice_trusted_cas_principalName:
-        asn1_addfield_implicit(val->u.principalName,0,asn1_encode_principal_name);
-        break;
-    default:
-        return ASN1_MISSING_FIELD;
-    }
+/*
+ * draft-ietf-cat-kerberos-pk-init-09 specifies these fields as explicitly
+ * tagged KerberosName, Name, and IssuerAndSerialNumber respectively, which
+ * means they should have constructed context tags.  However, our historical
+ * behavior is to use primitive context-specific tags, and we don't want to
+ * change that behavior without interop testing.  For the principal name, which
+ * we encode ourselves, use a DEFTAGGEDTYPE to wrap the principal encoding in a
+ * primitive [0] tag.  For the other two types, we have the encoding in a
+ * krb5_data object; pretend that they are wrapped in IMPLICIT OCTET STRING in
+ * order to wrap them in primitive [1] and [2] tags.
+ */
+DEFTAGGEDTYPE(princ_0_primitive, CONTEXT_SPECIFIC, PRIMITIVE, 0, 0, principal);
+typedef union krb5_trusted_ca_choices krb5_trusted_ca_choices;
+typedef enum krb5_trusted_ca_selection krb5_trusted_ca_selection;
+static const struct field_info trusted_ca_alternatives[] = {
+    FIELDOF_NORM(krb5_trusted_ca_choices, princ_0_primitive, principalName,
+                 -1, 0),
+    FIELDOF_NORM(krb5_trusted_ca_choices, ostring_data, caName, 1, 1),
+    FIELDOF_NORM(krb5_trusted_ca_choices, ostring_data, issuerAndSerial, 2, 1),
+};
+DEFCHOICETYPE(trusted_ca_choice, krb5_trusted_ca_choices,
+              trusted_ca_alternatives);
+DEFINTTYPE(trusted_ca_selection, krb5_trusted_ca_selection);
+DEFFIELDTYPE(trusted_ca, krb5_trusted_ca,
+             FIELDOF_CHOICE(krb5_trusted_ca, trusted_ca_choice, u, choice,
+                            trusted_ca_selection, -1));
+DEFPTRTYPE(trusted_ca_ptr, trusted_ca);
 
-    asn1_cleanup();
-}
+DEFNULLTERMSEQOFTYPE(seq_of_trusted_ca, trusted_ca_ptr);
+DEFPTRTYPE(ptr_seqof_trusted_ca, seq_of_trusted_ca);
 
-asn1_error_code
-asn1_encode_sequence_of_trusted_ca(asn1buf *buf, const krb5_trusted_ca **val,
-                                   unsigned int *retlen)
+static unsigned int
+pa_pk_as_req_draft9_optional(const void *p)
 {
-    asn1_setup();
-    int i;
-
-    if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
-
-    for (i=0; val[i] != NULL; i++);
-    for (i--; i>=0; i--) {
-        unsigned int length;
-        retval = asn1_encode_trusted_ca(buf,val[i],&length);
-        if (retval) return retval;
-        sum += length;
-    }
-    asn1_makeseq();
-    asn1_cleanup();
-}
-
-asn1_error_code
-asn1_encode_pa_pk_as_req_draft9(asn1buf *buf,
-                                const krb5_pa_pk_as_req_draft9 *val,
-                                unsigned int *retlen)
-{
-    asn1_setup();
-
-    if (val->encryptionCert.length != 0)
-        asn1_insert_implicit_octetstring(val->encryptionCert.length,val->encryptionCert.data,3);
-
-    if (val->kdcCert.length != 0)
-        asn1_insert_implicit_octetstring(val->kdcCert.length,val->kdcCert.data,2);
-
+    unsigned int optional = 0;
+    const krb5_pa_pk_as_req_draft9 *val = p;
     if (val->trustedCertifiers != NULL)
-        asn1_addfield((const krb5_trusted_ca **)val->trustedCertifiers,1,asn1_encode_sequence_of_trusted_ca);
-
-    asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0);
-
-    asn1_makeseq();
-    asn1_cleanup();
+        optional |= (1u << 1);
+    if (val->kdcCert.length > 0)
+        optional |= (1u << 2);
+    if (val->encryptionCert.length > 0)
+        optional |= (1u << 3);
+    return optional;
 }
 
-asn1_error_code
-asn1_encode_dh_rep_info(asn1buf *buf, const krb5_dh_rep_info *val,
-                        unsigned int *retlen)
-{
-    asn1_setup();
+/*
+ * draft-ietf-cat-kerberos-pk-init-09 specifies signedAuthPack, kdcCert, and
+ * EncryptionCert as explictly tagged SignedData, IssuerAndSerialNumber, and
+ * IssuerAndSerialNumber, which means they should have constructed context
+ * tags.  However, our historical behavior is to use a primitive context tag,
+ * and we don't want to change that without interop testing.  We have the DER
+ * encodings of these fields in krb5_data objects; pretend that they are
+ * wrapped in IMPLICIT OCTET STRING in order to generate primitive context
+ * tags.
+ */
+static const struct field_info pa_pk_as_req_draft9_fields[] = {
+    FIELDOF_NORM(krb5_pa_pk_as_req_draft9, ostring_data, signedAuthPack, 0, 1),
+    FIELDOF_OPT(krb5_pa_pk_as_req_draft9, ptr_seqof_trusted_ca,
+                trustedCertifiers, 1, 0, 1),
+    FIELDOF_OPT(krb5_pa_pk_as_req_draft9, ostring_data, kdcCert, 2, 1, 2),
+    FIELDOF_OPT(krb5_pa_pk_as_req_draft9, ostring_data, encryptionCert,
+                3, 1, 3),
+};
+DEFSEQTYPE(pa_pk_as_req_draft9, krb5_pa_pk_as_req_draft9,
+           pa_pk_as_req_draft9_fields, pa_pk_as_req_draft9_optional);
 
-    if (val->kdfID)
-        asn1_addfield(val->kdfID, 2, asn1_encode_kdf_alg_id);
-    if (val->serverDHNonce.length != 0)
-        asn1_insert_implicit_octetstring(val->serverDHNonce.length,val->serverDHNonce.data,1);
-
-    asn1_insert_implicit_octetstring(val->dhSignedData.length,val->dhSignedData.data,0);
-
-    asn1_makeseq();
-    asn1_cleanup();
-}
-
-asn1_error_code
-asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_info *val,
-                            unsigned int *retlen)
+static unsigned int
+dh_rep_info_optional(const void *p)
 {
-    asn1_setup();
-
-    if (val->dhKeyExpiration != 0) {
-        asn1_addprimitive(val->dhKeyExpiration, 2, asn1_encode_kerberos_time,
-                          ASN1_GENERALTIME);
-    }
-    asn1_addinteger(val->nonce, 1);
-
-    {
-        unsigned int length;
-
-        asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,3);
-        retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0,
-                                val->subjectPublicKey.length + 1 + length,
-                                &length);
-        if (retval)
-            return retval;
-        sum += length;
-    }
-
-    asn1_makeseq();
-    asn1_cleanup();
+    unsigned int optional = 0;
+    const krb5_dh_rep_info *val = p;
+    if (val->serverDHNonce.length > 0)
+        optional |= (1u << 1);
+    if (val->kdfID != NULL)
+        optional |= (1u << 2);
+    return optional;
 }
 
-asn1_error_code
-asn1_encode_reply_key_pack(asn1buf *buf, const krb5_reply_key_pack *val,
-                           unsigned int *retlen)
-{
-    asn1_setup();
+/*
+ * RFC 4556 specifies serverDHNonce as an explicitly tagged octet string.
+ * Historically we encode it as an implicitly tagged octet string.  This may be
+ * harmless (and fixable) since we don't appear to include a serverDHNonce in
+ * our PKINIT server code, but we would want to change this carefully.
+ */
+static const struct field_info dh_rep_info_fields[] = {
+    FIELDOF_NORM(krb5_dh_rep_info, ostring_data, dhSignedData, 0, 1),
+    FIELDOF_OPT(krb5_dh_rep_info, ostring_data, serverDHNonce, 1, 1, 1),
+    FIELDOF_OPT(krb5_dh_rep_info, kdf_alg_id_ptr, kdfID, 2, 0, 2),
+};
+DEFSEQTYPE(dh_rep_info, krb5_dh_rep_info,
+           dh_rep_info_fields, dh_rep_info_optional);
 
-    asn1_addfield(&(val->asChecksum), 1, asn1_encode_checksum);
-    asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
-
-    asn1_makeseq();
-    asn1_cleanup();
-}
-
-asn1_error_code
-asn1_encode_reply_key_pack_draft9(asn1buf *buf,
-                                  const krb5_reply_key_pack_draft9 *val,
-                                  unsigned int *retlen)
+static unsigned int
+kdc_dh_key_info_optional(const void *p)
 {
-    asn1_setup();
-
-    asn1_addinteger(val->nonce, 1);
-    asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
-
-    asn1_makeseq();
-    asn1_cleanup();
+    unsigned int optional = 0;
+    const krb5_kdc_dh_key_info *val = p;
+    if (val->dhKeyExpiration != 0)
+        optional |= (1u << 2);
+    return optional;
 }
 
-asn1_error_code
-asn1_encode_pa_pk_as_rep(asn1buf *buf, const krb5_pa_pk_as_rep *val,
-                         unsigned int *retlen)
-{
-    asn1_setup();
+static const struct field_info kdc_dh_key_info_fields[] = {
+    FIELDOF_NORM(krb5_kdc_dh_key_info, bitstring_data, subjectPublicKey, 0, 0),
+    FIELDOF_NORM(krb5_kdc_dh_key_info, int32, nonce, 1, 0),
+    FIELDOF_OPT(krb5_kdc_dh_key_info, kerberos_time, dhKeyExpiration, 2, 0, 2),
+};
+DEFSEQTYPE(kdc_dh_key_info, krb5_kdc_dh_key_info, kdc_dh_key_info_fields,
+           kdc_dh_key_info_optional);
 
-    switch (val->choice)
-    {
-    case choice_pa_pk_as_rep_dhInfo:
-        asn1_addfield(&(val->u.dh_Info), choice_pa_pk_as_rep_dhInfo, asn1_encode_dh_rep_info);
-        break;
-    case choice_pa_pk_as_rep_encKeyPack:
-        asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1);
-        break;
-    default:
-        return ASN1_MISSING_FIELD;
-    }
 
-    asn1_cleanup();
-}
+static const struct field_info reply_key_pack_fields[] = {
+    FIELDOF_NORM(krb5_reply_key_pack, encryption_key, replyKey, 0, 0),
+    FIELDOF_NORM(krb5_reply_key_pack, checksum, asChecksum, 1, 0),
+};
+DEFSEQTYPE(reply_key_pack, krb5_reply_key_pack, reply_key_pack_fields, 0);
 
-asn1_error_code
-asn1_encode_pa_pk_as_rep_draft9(asn1buf *buf,
-                                const krb5_pa_pk_as_rep_draft9 *val,
-                                unsigned int *retlen)
-{
-    asn1_setup();
+static const struct field_info reply_key_pack_draft9_fields[] = {
+    FIELDOF_NORM(krb5_reply_key_pack_draft9, encryption_key, replyKey, 0, 0),
+    FIELDOF_NORM(krb5_reply_key_pack_draft9, int32, nonce, 1, 0),
+};
+DEFSEQTYPE(reply_key_pack_draft9, krb5_reply_key_pack_draft9,
+           reply_key_pack_draft9_fields, 0);
 
-    switch (val->choice)
-    {
-    case choice_pa_pk_as_rep_draft9_dhSignedData:
-        asn1_insert_implicit_octetstring(val->u.dhSignedData.length,val->u.dhSignedData.data,0);
-        break;
-    case choice_pa_pk_as_rep_encKeyPack:
-        asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1);
-        break;
-    default:
-        return ASN1_MISSING_FIELD;
-    }
+typedef union krb5_pa_pk_as_rep_choices krb5_pa_pk_as_rep_choices;
+typedef enum krb5_pa_pk_as_rep_selection krb5_pa_pk_as_rep_selection;
+static const struct field_info pa_pk_as_rep_alternatives[] = {
+    FIELDOF_NORM(krb5_pa_pk_as_rep_choices, dh_rep_info, dh_Info, 0, 0),
+    FIELDOF_NORM(krb5_pa_pk_as_rep_choices, ostring_data, encKeyPack, 1, 1),
+};
+DEFCHOICETYPE(pa_pk_as_rep_choice, krb5_pa_pk_as_rep_choices,
+              pa_pk_as_rep_alternatives);
+DEFINTTYPE(pa_pk_as_rep_selection, krb5_pa_pk_as_rep_selection);
+DEFFIELDTYPE(pa_pk_as_rep, krb5_pa_pk_as_rep,
+             FIELDOF_CHOICE(krb5_pa_pk_as_rep, pa_pk_as_rep_choice, u, choice,
+                            pa_pk_as_rep_selection, -1));
 
-    asn1_cleanup();
-}
+typedef union krb5_pa_pk_as_rep_draft9_choices
+krb5_pa_pk_as_rep_draft9_choices;
+typedef enum krb5_pa_pk_as_rep_draft9_selection
+krb5_pa_pk_as_rep_draft9_selection;
+static const struct field_info pa_pk_as_rep_draft9_alternatives[] = {
+    FIELDOF_NORM(krb5_pa_pk_as_rep_draft9_choices, ostring_data, dhSignedData,
+                 0, 1),
+    FIELDOF_NORM(krb5_pa_pk_as_rep_draft9_choices, ostring_data, encKeyPack,
+                 1, 1),
+};
+DEFCHOICETYPE(pa_pk_as_rep_draft9_choice, krb5_pa_pk_as_rep_draft9_choices,
+              pa_pk_as_rep_draft9_alternatives);
+DEFINTTYPE(pa_pk_as_rep_draft9_selection, krb5_pa_pk_as_rep_draft9_selection);
+DEFFIELDTYPE(pa_pk_as_rep_draft9, krb5_pa_pk_as_rep_draft9,
+             FIELDOF_CHOICE(krb5_pa_pk_as_rep_draft9,
+                            pa_pk_as_rep_draft9_choice, u, choice,
+                            pa_pk_as_rep_draft9_selection, -1));
 
-asn1_error_code
-asn1_encode_td_trusted_certifiers(
-    asn1buf *buf, const krb5_external_principal_identifier **val,
-    unsigned int *retlen)
-{
-    asn1_setup();
-    {
-        unsigned int length;
-        retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length);
-        if (retval)
-            return retval;
-        /* length set but ignored?  sum not updated?  */
-    }
-    asn1_cleanup();
-}
+MAKE_FULL_ENCODER(encode_krb5_pa_pk_as_req, pa_pk_as_req);
+MAKE_FULL_ENCODER(encode_krb5_pa_pk_as_req_draft9, pa_pk_as_req_draft9);
+MAKE_FULL_ENCODER(encode_krb5_pa_pk_as_rep, pa_pk_as_rep);
+MAKE_FULL_ENCODER(encode_krb5_pa_pk_as_rep_draft9, pa_pk_as_rep_draft9);
+MAKE_FULL_ENCODER(encode_krb5_auth_pack, auth_pack);
+MAKE_FULL_ENCODER(encode_krb5_auth_pack_draft9, auth_pack_draft9);
+MAKE_FULL_ENCODER(encode_krb5_kdc_dh_key_info, kdc_dh_key_info);
+MAKE_FULL_ENCODER(encode_krb5_reply_key_pack, reply_key_pack);
+MAKE_FULL_ENCODER(encode_krb5_reply_key_pack_draft9, reply_key_pack_draft9);
+MAKE_FULL_ENCODER(encode_krb5_td_trusted_certifiers,
+                  seq_of_external_principal_identifier);
+MAKE_FULL_ENCODER(encode_krb5_td_dh_parameters, seq_of_algorithm_identifier);
 
 #else /* DISABLE_PKINIT */
 
@@ -2211,36 +1875,12 @@
 
 #endif /* not DISABLE_PKINIT */
 
-asn1_error_code
-asn1_encode_sequence_of_typed_data(asn1buf *buf,
-                                   const krb5_pa_data *const *val,
-                                   unsigned int *retlen)
-{
-    asn1_setup();
-    int i;
+static const struct field_info typed_data_fields[] = {
+    FIELDOF_NORM(krb5_pa_data, int32, pa_type, 0, 0),
+    FIELDOF_STRING(krb5_pa_data, octetstring, contents, length, 1, 0),
+};
+DEFSEQTYPE(typed_data, krb5_pa_data, typed_data_fields, 0);
+DEFPTRTYPE(typed_data_ptr, typed_data);
 
-    if (val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
-
-    for (i=0; val[i] != NULL; i++);
-    for (i--; i>=0; i--) {
-        unsigned int length;
-
-        retval = asn1_encode_typed_data(buf,val[i],&length);
-        if (retval) return retval;
-        sum += length;
-    }
-    asn1_makeseq();
-
-    asn1_cleanup();
-}
-
-asn1_error_code
-asn1_encode_typed_data(asn1buf *buf, const krb5_pa_data *val,
-                       unsigned int *retlen)
-{
-    asn1_setup();
-    asn1_addstring(val->length, val->contents, 1, ASN1_OCTETSTRING);
-    asn1_addinteger(val->pa_type, 0);
-    asn1_makeseq();
-    asn1_cleanup();
-}
+DEFNULLTERMSEQOFTYPE(seq_of_typed_data, typed_data_ptr);
+MAKE_FULL_ENCODER(encode_krb5_typed_data, seq_of_typed_data);

Modified: trunk/src/lib/krb5/asn.1/deps
===================================================================
--- trunk/src/lib/krb5/asn.1/deps	2012-01-06 21:13:59 UTC (rev 25616)
+++ trunk/src/lib/krb5/asn.1/deps	2012-01-06 21:17:14 UTC (rev 25617)
@@ -138,19 +138,6 @@
   $(top_srcdir)/include/socket-utils.h asn1_decode.h \
   asn1_get.h asn1_k_decode.h asn1_misc.h asn1buf.h krb5_decode_kdc.c \
   krb5_decode_macros.h krbasn1.h
-krb5_encode.so krb5_encode.po $(OUTPRE)krb5_encode.$(OBJEXT): \
-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
-  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
-  $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
-  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
-  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h asn1_encode.h \
-  asn1_k_encode.h asn1_make.h asn1buf.h krb5_encode.c \
-  krbasn1.h
 asn1_k_encode.so asn1_k_encode.po $(OUTPRE)asn1_k_encode.$(OBJEXT): \
   $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
   $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
@@ -162,8 +149,7 @@
   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
   $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
   $(top_srcdir)/include/socket-utils.h asn1_encode.h \
-  asn1_k_encode.c asn1_k_encode.h asn1_make.h asn1buf.h \
-  krbasn1.h
+  asn1_k_encode.c asn1_make.h asn1buf.h krbasn1.h
 ldap_key_seq.so ldap_key_seq.po $(OUTPRE)ldap_key_seq.$(OBJEXT): \
   $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
   $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
@@ -175,8 +161,8 @@
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
   $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
   $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-  asn1_decode.h asn1_encode.h asn1_get.h asn1_k_encode.h \
-  asn1_make.h asn1buf.h krbasn1.h ldap_key_seq.c
+  asn1_decode.h asn1_encode.h asn1_get.h asn1_make.h \
+  asn1buf.h krbasn1.h ldap_key_seq.c
 asn1_misc.so asn1_misc.po $(OUTPRE)asn1_misc.$(OBJEXT): \
   $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
   $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \

Modified: trunk/src/lib/krb5/asn.1/ldap_key_seq.c
===================================================================
--- trunk/src/lib/krb5/asn.1/ldap_key_seq.c	2012-01-06 21:13:59 UTC (rev 25616)
+++ trunk/src/lib/krb5/asn.1/ldap_key_seq.c	2012-01-06 21:17:14 UTC (rev 25617)
@@ -40,7 +40,6 @@
 #include "asn1_decode.h"
 #include "asn1_make.h"
 #include "asn1_get.h"
-#include "asn1_k_encode.h"
 
 #ifdef ENABLE_LDAP
 



More information about the cvs-krb5 mailing list