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

ghudson@MIT.EDU ghudson at MIT.EDU
Fri Jan 6 15:52:12 EST 2012


http://src.mit.edu/fisheye/changelog/krb5/?cs=25612
Commit By: ghudson
Log Message:
Use content-only ASN.1 primitives

As part of implicit tag support, rework ASN.1 encoding primitives so
that they encode only content, not tags.  Combine primitives which
become identical with this change.  The new atype_primitive type
invokes a primitive encoder and adds a tag.  atype_fn_len is split
into atype_string and atype_opaque, both of which are hardcoded to
use asn1_encode_bytestring.

For the encoders still using macros, create asn1_addprimitive,
asn1_addinteger, and asn1_addstring macros which call the primitive
encoder function and add a tag.


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-06 20:52:09 UTC (rev 25611)
+++ trunk/src/lib/krb5/asn.1/asn1_encode.c	2012-01-06 20:52:12 UTC (rev 25612)
@@ -32,28 +32,14 @@
 asn1_error_code
 asn1_encode_boolean(asn1buf *buf, asn1_intmax val, unsigned int *retlen)
 {
-    asn1_error_code retval;
-    unsigned int length = 0;
-    unsigned int partlen = 1;
-    asn1_octet bval;
+    asn1_octet bval = val ? 0xFF : 0x00;
 
-    bval = val ? 0xFF : 0x00;
-
-    retval = asn1buf_insert_octet(buf, bval);
-    if (retval) return retval;
-
-    length = partlen;
-    retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_BOOLEAN, length, &partlen);
-    if (retval) return retval;
-    length += partlen;
-
-    *retlen = length;
-    return 0;
+    *retlen = 1;
+    return asn1buf_insert_octet(buf, bval);
 }
 
-static asn1_error_code
-asn1_encode_integer_internal(asn1buf *buf, asn1_intmax val,
-                             unsigned int *retlen)
+asn1_error_code
+asn1_encode_integer(asn1buf *buf, asn1_intmax val, unsigned int *retlen)
 {
     asn1_error_code retval;
     unsigned int length = 0;
@@ -85,51 +71,11 @@
 }
 
 asn1_error_code
-asn1_encode_integer(asn1buf * buf, asn1_intmax val, unsigned int *retlen)
-{
-    asn1_error_code retval;
-    unsigned int length = 0;
-    unsigned  int partlen;
-    retval = asn1_encode_integer_internal(buf, val, &partlen);
-    if (retval) return retval;
-
-    length = partlen;
-    retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen);
-    if (retval) return retval;
-    length += partlen;
-
-    *retlen = length;
-    return 0;
-}
-
-#if 0
-asn1_error_code
-asn1_encode_enumerated(asn1buf * buf, long val,
-                       unsigned int *retlen)
-{
-    asn1_error_code retval;
-    unsigned int length = 0;
-    unsigned  int partlen;
-    retval = asn1_encode_integer_internal(buf, val, &partlen);
-    if (retval) return retval;
-
-    length = partlen;
-    retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_ENUMERATED,length, &partlen);
-    if (retval) return retval;
-    length += partlen;
-
-    *retlen = length;
-    return 0;
-}
-#endif
-
-asn1_error_code
 asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val,
                              unsigned int *retlen)
 {
     asn1_error_code retval;
     unsigned int length = 0;
-    unsigned int partlen;
     unsigned long valcopy;
     int digit;
 
@@ -148,79 +94,20 @@
         length++;
     }
 
-    retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen);
-    if (retval) return retval;
-    length += partlen;
-
     *retlen = length;
     return 0;
 }
 
-static asn1_error_code
-encode_bytestring_with_tag(asn1buf *buf, unsigned int len,
-                           const void *val, int tag,
-                           unsigned int *retlen)
-{
-    asn1_error_code retval;
-    unsigned int length;
-
-    if (len > 0 && val == 0) return ASN1_MISSING_FIELD;
-    retval = asn1buf_insert_octetstring(buf, len, val);
-    if (retval) return retval;
-    retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, tag,
-                           len, &length);
-    if (retval) return retval;
-
-    *retlen = len + length;
-    return 0;
-}
-
 asn1_error_code
-asn1_encode_oid(asn1buf *buf, unsigned int len, const void *val,
-                unsigned int *retlen)
+asn1_encode_bytestring(asn1buf *buf, unsigned int len, const void *val,
+                       unsigned int *retlen)
 {
-    return encode_bytestring_with_tag(buf, len, val, ASN1_OBJECTIDENTIFIER,
-                                      retlen);
+    if (len > 0 && val == NULL) return ASN1_MISSING_FIELD;
+    *retlen = len;
+    return asn1buf_insert_octetstring(buf, len, val);
 }
 
 asn1_error_code
-asn1_encode_octetstring(asn1buf *buf, unsigned int len, const void *val,
-                        unsigned int *retlen)
-{
-    return encode_bytestring_with_tag(buf, len, val, ASN1_OCTETSTRING,
-                                      retlen);
-}
-
-#if 0
-asn1_error_code asn1_encode_null(asn1buf *buf, int *retlen)
-{
-    asn1_error_code retval;
-
-    retval = asn1buf_insert_octet(buf,0x00);
-    if (retval) return retval;
-    retval = asn1buf_insert_octet(buf,0x05);
-    if (retval) return retval;
-
-    *retlen = 2;
-    return 0;
-}
-
-asn1_error_code asn1_encode_printablestring(asn1buf *buf, unsigned int len,
-                                            const char *val, int *retlen)
-{
-    return encode_bytestring_with_tag(buf, len, val, ASN1_PRINTABLESTRING,
-                                      retlen);
-}
-
-asn1_error_code asn1_encode_ia5string(asn1buf *buf, unsigned int len,
-                                      const char *val, int *retlen)
-{
-    return encode_bytestring_with_tag(buf, len, val, ASN1_IA5STRING,
-                                      retlen);
-}
-#endif
-
-asn1_error_code
 asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen)
 {
     struct tm *gtime, gtimebuf;
@@ -269,48 +156,21 @@
         sp = s;
     }
 
-    return encode_bytestring_with_tag(buf, 15, sp, ASN1_GENERALTIME,
-                                      retlen);
+    return asn1_encode_bytestring(buf, 15, sp, retlen);
 }
 
 asn1_error_code
-asn1_encode_generalstring(asn1buf *buf, unsigned int len, const void *val,
-                          unsigned int *retlen)
-{
-    return encode_bytestring_with_tag(buf, len, val, ASN1_GENERALSTRING,
-                                      retlen);
-}
-
-asn1_error_code
 asn1_encode_bitstring(asn1buf *buf, unsigned int len, const void *val,
                       unsigned int *retlen)
 {
     asn1_error_code retval;
-    unsigned int length;
 
     retval = asn1buf_insert_octetstring(buf, len, val);
     if (retval) return retval;
-    retval = asn1buf_insert_octet(buf, 0);
-    if (retval) return retval;
-    retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_BITSTRING,
-                           len+1, &length);
-    if (retval) return retval;
-    *retlen = len + 1 + length;
-    return 0;
+    *retlen = len + 1;
+    return asn1buf_insert_octet(buf, '\0');
 }
 
-asn1_error_code
-asn1_encode_opaque(asn1buf *buf, unsigned int len, const void *val,
-                   unsigned int *retlen)
-{
-    asn1_error_code retval;
-
-    retval = asn1buf_insert_octetstring(buf, len, val);
-    if (retval) return retval;
-    *retlen = len;
-    return 0;
-}
-
 /*
  * ASN.1 constructed type encoder engine
  *
@@ -383,12 +243,26 @@
 krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val,
                             const struct atype_info *a, unsigned int *retlen)
 {
+    asn1_error_code retval;
+    unsigned int length, sum = 0;
+
     switch (a->type) {
+    case atype_primitive:
     case atype_fn:
     {
-        const struct fn_info *fn = a->tinfo;
-        assert(fn->enc != NULL);
-        return fn->enc(buf, val, retlen);
+        const struct primitive_info *prim = a->tinfo;
+        assert(prim->enc != NULL);
+        retval = prim->enc(buf, val, &length);
+        if (retval) return retval;
+        sum += length;
+        if (a->type == atype_primitive) {
+            retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, prim->tagval,
+                                   sum, &length);
+            if (retval) return retval;
+            sum += length;
+        }
+        *retlen = sum;
+        return 0;
     }
     case atype_sequence:
         assert(a->tinfo != NULL);
@@ -411,8 +285,6 @@
                                            retlen);
     case atype_tagged_thing:
     {
-        asn1_error_code retval;
-        unsigned int length, sum = 0;
         const struct tagged_info *tag = a->tinfo;
         retval = krb5int_asn1_encode_a_thing(buf, val, tag->basetype, &length);
         if (retval) return retval;
@@ -428,21 +300,40 @@
     {
         const struct int_info *tinfo = a->tinfo;
         assert(tinfo->loadint != NULL);
-        return asn1_encode_integer(buf, tinfo->loadint(val), retlen);
+        retval = asn1_encode_integer(buf, tinfo->loadint(val), &length);
+        if (retval) return retval;
+        sum = length;
+        retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_INTEGER, sum,
+                               &length);
+        if (retval) return retval;
+        sum += length;
+        *retlen = sum;
+        return 0;
     }
     case atype_uint:
     {
         const struct uint_info *tinfo = a->tinfo;
         assert(tinfo->loaduint != NULL);
-        return asn1_encode_unsigned_integer(buf, tinfo->loaduint(val), retlen);
+        retval = asn1_encode_unsigned_integer(buf, tinfo->loaduint(val),
+                                              &length);
+        if (retval) return retval;
+        sum = length;
+        retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_INTEGER, sum,
+                               &length);
+        if (retval) return retval;
+        sum += length;
+        *retlen = sum;
+        return 0;
     }
     case atype_min:
     case atype_max:
-    case atype_fn_len:
+    case atype_string:          /* only usable with field_string */
+    case atype_opaque:          /* only usable with field_string */
     default:
         assert(a->type > atype_min);
         assert(a->type < atype_max);
-        assert(a->type != atype_fn_len);
+        assert(a->type != atype_string);
+        assert(a->type != atype_opaque);
         abort();
     }
 }
@@ -466,6 +357,10 @@
                                      &length);
         if (retval) return retval;
         sum += length;
+        retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_INTEGER, sum,
+                               &length);
+        if (retval) return retval;
+        sum += length;
         break;
     }
     case field_sequenceof_len:
@@ -536,13 +431,13 @@
         const struct atype_info *a;
         size_t slen;
         unsigned int length;
-        const struct fn_len_info *fnlen;
+        const struct string_info *string;
 
         dataptr = (const char *)val + field->dataoff;
         lenptr = (const char *)val + field->lenoff;
 
         a = field->atype;
-        assert(a->type == atype_fn_len);
+        assert(a->type == atype_string || a->type == atype_opaque);
         assert(field->lentype != 0);
         assert(field->lentype->type == atype_int || field->lentype->type == atype_uint);
         assert(sizeof(int) <= sizeof(asn1_intmax));
@@ -563,25 +458,28 @@
             slen = (size_t) xlen;
         }
 
-        fnlen = a->tinfo;
-        dataptr = LOADPTR(dataptr, fnlen);
+        string = a->tinfo;
+        dataptr = LOADPTR(dataptr, string);
         if (slen == SIZE_MAX)
             /* Error - negative or out of size_t range.  */
             return EINVAL;
         if (dataptr == NULL && slen != 0)
             return ASN1_MISSING_FIELD;
-        /*
-         * Currently our string encoders want "unsigned int" for
-         * lengths.
-         */
-        if (slen != (unsigned int) slen)
+        /* Currently string encoders want "unsigned int" for length. */
+        if (slen != (unsigned int)slen)
             return EINVAL;
-        assert(fnlen->enclen != NULL);
-        retval = fnlen->enclen(buf, (unsigned int) slen, dataptr, &length);
-        if (retval) {
+        assert(string->enclen != NULL);
+        retval = string->enclen(buf, (unsigned int) slen, dataptr, &length);
+        if (retval)
             return retval;
-        }
         sum += length;
+        if (a->type == atype_string) {
+            retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, string->tagval,
+                                   sum, &length);
+            if (retval)
+                return retval;
+            sum += length;
+        }
         break;
     }
     default:

Modified: trunk/src/lib/krb5/asn.1/asn1_encode.h
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_encode.h	2012-01-06 20:52:09 UTC (rev 25611)
+++ trunk/src/lib/krb5/asn.1/asn1_encode.h	2012-01-06 20:52:12 UTC (rev 25612)
@@ -43,11 +43,9 @@
  *   asn1_encode_boolean
  *   asn1_encode_integer
  *   asn1_encode_unsigned_integer
- *   asn1_encode_octetstring
+ *   asn1_encode_bytestring
  *   asn1_encode_generaltime
- *   asn1_encode_generalstring
  *   asn1_encode_bitstring
- *   asn1_encode_oid
  */
 
 asn1_error_code asn1_encode_boolean(asn1buf *buf, asn1_intmax val,
@@ -63,9 +61,6 @@
  *            to expand the buffer.
  */
 
-asn1_error_code asn1_encode_enumerated(asn1buf *buf, long val,
-                                       unsigned int *retlen);
-
 asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val,
                                              unsigned int *retlen);
 /*
@@ -77,8 +72,8 @@
  *            to expand the buffer.
  */
 
-asn1_error_code asn1_encode_octetstring(asn1buf *buf, unsigned int len,
-                                        const void *val, unsigned int *retlen);
+asn1_error_code asn1_encode_bytestring(asn1buf *buf, unsigned int len,
+                                       const void *val, unsigned int *retlen);
 /*
  * requires  *buf is allocated
  * modifies  *buf, *retlen
@@ -87,23 +82,7 @@
  *           Returns ENOMEM to signal an unsuccesful attempt
  *            to expand the buffer.
  */
-#define asn1_encode_charstring asn1_encode_octetstring
 
-/**
- * Encode @a val, an object identifier in compressed DER form without a tag or
- * length. This function adds the OID tag and length.
- */
-asn1_error_code asn1_encode_oid(asn1buf *buf, unsigned int len,
-                                const void *val, unsigned int *retlen);
-/*
- * requires  *buf is allocated
- * modifies  *buf, *retlen
- * effects   Inserts the encoding of val into *buf and returns
- *            the length of the encoding in *retlen.
- *           Returns ENOMEM to signal an unsuccesful attempt
- *            to expand the buffer.
- */
-
 asn1_error_code asn1_encode_null(asn1buf *buf, int *retlen);
 /*
  * requires  *buf is allocated
@@ -114,28 +93,6 @@
  *            to expand the buffer.
  */
 
-asn1_error_code asn1_encode_printablestring(asn1buf *buf, unsigned int len,
-                                            const char *val, int *retlen);
-/*
- * requires  *buf is allocated
- * modifies  *buf, *retlen
- * effects   Inserts the encoding of val into *buf and returns
- *            the length of the encoding in *retlen.
- *           Returns ENOMEM to signal an unsuccesful attempt
- *            to expand the buffer.
- */
-
-asn1_error_code asn1_encode_ia5string(asn1buf *buf, unsigned int len,
-                                      const char *val, int *retlen);
-/*
- * requires  *buf is allocated
- * modifies  *buf, *retlen
- * effects   Inserts the encoding of val into *buf and returns
- *            the length of the encoding in *retlen.
- *           Returns ENOMEM to signal an unsuccesful attempt
- *            to expand the buffer.
- */
-
 asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val,
                                         unsigned int *retlen);
 /*
@@ -148,18 +105,6 @@
  * Note: The encoding of GeneralizedTime is YYYYMMDDhhmmZ
  */
 
-asn1_error_code asn1_encode_generalstring(asn1buf *buf,
-                                          unsigned int len, const void *val,
-                                          unsigned int *retlen);
-/*
- * requires  *buf is allocated,  val has a length of len characters
- * modifies  *buf, *retlen
- * effects   Inserts the encoding of val into *buf and returns
- *            the length of the encoding in *retlen.
- *           Returns ENOMEM to signal an unsuccesful attempt
- *            to expand the buffer.
- */
-
 asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len,
                                       const void *val,
                                       unsigned int *retlen);
@@ -172,19 +117,7 @@
  *            to expand the buffer.
  */
 
-asn1_error_code asn1_encode_opaque(asn1buf *buf, unsigned int len,
-                                   const void *val,
-                                   unsigned int *retlen);
 /*
- * requires  *buf is allocated,  val has a length of len characters
- * modifies  *buf, *retlen
- * effects   Inserts the encoding of val into *buf and returns
- *            the length of the encoding in *retlen.
- *           Returns ENOMEM to signal an unsuccesful attempt
- *            to expand the buffer.
- */
-
-/*
  * Type descriptor info.
  *
  * In this context, a "type" is a combination of a C data type
@@ -226,15 +159,26 @@
      * invalid.
      */
     atype_min = 1,
-    /* Encoder function to be called with address of <thing>.  tinfo is a
-     * struct fn_info *. */
+    /* Encoder function (contents-only) to be called with address of <thing>
+     * and wrapped with a universal primitive tag.  tinfo is a struct
+     * primitive_info *. */
+    atype_primitive,
+    /* Encoder function (with tag) to be called with address of <thing>.  tinfo
+     * is a struct primitive_info * with tagval ignored. */
     atype_fn,
     /*
-     * Encoder function to be called with address of <thing> and a
-     * length (unsigned int).  tinfo is a struct fn_len_info *.
+     * Encoder function (contents only) to be called with address of <thing>
+     * and a length (unsigned int), and wrapped with a universal primitive tag.
+     * tinfo is a struct string_info *.  Only usable with the field_string
+     * field type.
      */
-    atype_fn_len,
+    atype_string,
     /*
+     * As above, but the encoder function produces the tag as well as the
+     * contents.
+     */
+    atype_opaque,
+    /*
      * Pointer to actual thing to be encoded.  tinfo is a struct ptr_info *.
      *
      * Most of the fields are related only to the C type -- size, how
@@ -282,14 +226,16 @@
     const void *tinfo;          /* Points to type-specific structure */
 };
 
-struct fn_info {
+struct primitive_info {
     asn1_error_code (*enc)(asn1buf *, const void *, unsigned int *);
+    unsigned int tagval;
 };
 
-struct fn_len_info {
+struct string_info {
     asn1_error_code (*enclen)(asn1buf *, unsigned int, const void *,
                               unsigned int *);
     const void *(*loadptr)(const void *);
+    unsigned int tagval;
 };
 
 struct ptr_info {
@@ -331,26 +277,32 @@
  */
 
 /*
- * Define a type for which we must use an explicit encoder function.
- * The DEFFNTYPE variant uses a function taking a void*, the
- * DEFFNXTYPE form wants a function taking a pointer to the actual C
- * type to be encoded; you should use the latter unless you've already
- * got the void* function supplied elsewhere.
+ * Define a type using a primitive (content-only) encoder function.
  *
- * Of course, we need a single, consistent type for the descriptor
- * structure field, so we use the function pointer type that uses
- * void*, and create a wrapper function in DEFFNXTYPE.  However, in
- * all our cases so far, the supplied function is static and not used
- * otherwise, so the compiler can merge it with the wrapper function
- * if the optimizer is good enough.
+ * Because we need a single, consistent type for the descriptor structure
+ * field, we use the function pointer type that uses void*, and create a
+ * wrapper function in DEFFNXTYPE.  The supplied function is static and not
+ * used otherwise, so the compiler can merge it with the wrapper function if
+ * the optimizer is good enough.
  */
-#define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN)                           \
+#define DEFPRIMITIVETYPE(DESCNAME, CTYPENAME, ENCFN, TAG)               \
     typedef CTYPENAME aux_typedefname_##DESCNAME;                       \
-    static const struct fn_info aux_info_##DESCNAME = { ENCFN };        \
+    static asn1_error_code                                              \
+    aux_encfn_##DESCNAME(asn1buf *buf, const void *val,                 \
+                         unsigned int *retlen)                          \
+    {                                                                   \
+        return ENCFN(buf,                                               \
+                     (const aux_typedefname_##DESCNAME *)val,           \
+                     retlen);                                           \
+    }                                                                   \
+    static const struct primitive_info aux_info_##DESCNAME = {          \
+        aux_encfn_##DESCNAME, TAG                                       \
+    };                                                                  \
     const struct atype_info krb5int_asn1type_##DESCNAME = {             \
-        atype_fn, sizeof(CTYPENAME), &aux_info_##DESCNAME               \
+        atype_primitive, sizeof(CTYPENAME), &aux_info_##DESCNAME        \
     }
-#define DEFFNXTYPE(DESCNAME, CTYPENAME, ENCFN)                          \
+/* Define a type using an explicit (with tag) encoder function. */
+#define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN)                           \
     typedef CTYPENAME aux_typedefname_##DESCNAME;                       \
     static asn1_error_code                                              \
     aux_encfn_##DESCNAME(asn1buf *buf, const void *val,                 \
@@ -360,7 +312,7 @@
                      (const aux_typedefname_##DESCNAME *)val,           \
                      retlen);                                           \
     }                                                                   \
-    static const struct fn_info aux_info_##DESCNAME = {                 \
+    static const struct primitive_info aux_info_##DESCNAME = {          \
         aux_encfn_##DESCNAME                                            \
     };                                                                  \
     const struct atype_info krb5int_asn1type_##DESCNAME = {             \
@@ -381,29 +333,43 @@
  * string-encoding primitives work.  So be it.
  */
 #ifdef POINTERS_ARE_ALL_THE_SAME
-#define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN)                \
+#define DEFSTRINGTYPE(DESCNAME, CTYPENAME, ENCFN, TAGVAL)       \
     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
-    static const struct fn_len_info aux_info_##DESCNAME = {     \
-        ENCFN, NULL                                             \
+    static const struct string_info aux_info_##DESCNAME = {     \
+        ENCFN, NULL, TAGVAL                                     \
     }                                                           \
     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
-        atype_fn_len, 0, &aux_info_##DESCNAME                   \
+        atype_string, 0, &aux_info_##DESCNAME                   \
     }
 #else
-#define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN)                \
+#define DEFSTRINGTYPE(DESCNAME, CTYPENAME, ENCFN, TAGVAL)       \
     typedef CTYPENAME aux_typedefname_##DESCNAME;               \
     static const void *loadptr_for_##DESCNAME(const void *pv)   \
     {                                                           \
         const aux_typedefname_##DESCNAME *p = pv;               \
         return *p;                                              \
     }                                                           \
-    static const struct fn_len_info aux_info_##DESCNAME = {     \
-        ENCFN, loadptr_for_##DESCNAME                           \
+    static const struct string_info aux_info_##DESCNAME = {     \
+        ENCFN, loadptr_for_##DESCNAME, TAGVAL                   \
     };                                                          \
     const struct atype_info krb5int_asn1type_##DESCNAME = {     \
-        atype_fn_len, 0, &aux_info_##DESCNAME                   \
+        atype_string, 0, &aux_info_##DESCNAME                   \
     }
 #endif
+/* Not used enough to justify a POINTERS_ARE_ALL_THE_SAME version. */
+#define DEFOPAQUETYPE(DESCNAME, CTYPENAME, ENCFN)               \
+    typedef CTYPENAME aux_typedefname_##DESCNAME;               \
+    static const void *loadptr_for_##DESCNAME(const void *pv)   \
+    {                                                           \
+        const aux_typedefname_##DESCNAME *p = pv;               \
+        return *p;                                              \
+    }                                                           \
+    static const struct string_info aux_info_##DESCNAME = {     \
+        ENCFN, loadptr_for_##DESCNAME                           \
+    };                                                          \
+    const struct atype_info krb5int_asn1type_##DESCNAME = {     \
+        atype_opaque, 0, &aux_info_##DESCNAME                   \
+    }
 /*
  * A sequence, defined by the indicated series of fields, and an
  * optional function indicating which fields are present.

Modified: trunk/src/lib/krb5/asn.1/asn1_k_encode.c
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_k_encode.c	2012-01-06 20:52:09 UTC (rev 25611)
+++ trunk/src/lib/krb5/asn.1/asn1_k_encode.c	2012-01-06 20:52:12 UTC (rev 25612)
@@ -78,12 +78,14 @@
 DEFUINTTYPE(octet, krb5_octet);
 DEFUINTTYPE(ui_4, krb5_ui_4);
 
-DEFFNLENTYPE(octetstring, unsigned char *, asn1_encode_octetstring);
-DEFFNLENTYPE(s_octetstring, char *, asn1_encode_octetstring);
-DEFFNLENTYPE(charstring, char *, asn1_encode_charstring);
-DEFFNLENTYPE(generalstring, char *, asn1_encode_generalstring);
-DEFFNLENTYPE(u_generalstring, unsigned char *, asn1_encode_generalstring);
-DEFFNLENTYPE(opaque, char *, asn1_encode_opaque);
+DEFSTRINGTYPE(octetstring, unsigned char *, asn1_encode_bytestring,
+              ASN1_OCTETSTRING);
+DEFSTRINGTYPE(s_octetstring, char *, asn1_encode_bytestring, ASN1_OCTETSTRING);
+DEFSTRINGTYPE(generalstring, char *, asn1_encode_bytestring,
+              ASN1_GENERALSTRING);
+DEFSTRINGTYPE(u_generalstring, unsigned char *, asn1_encode_bytestring,
+              ASN1_GENERALSTRING);
+DEFOPAQUETYPE(opaque, char *, asn1_encode_bytestring);
 
 DEFFIELDTYPE(gstring_data, krb5_data,
              FIELDOF_STRING(krb5_data, generalstring, data, length, -1));
@@ -119,7 +121,8 @@
     time_t tval = *val;
     return asn1_encode_generaltime(buf, tval, retlen);
 }
-DEFFNXTYPE(kerberos_time, krb5_timestamp, asn1_encode_kerberos_time_at);
+DEFPRIMITIVETYPE(kerberos_time, krb5_timestamp, asn1_encode_kerberos_time_at,
+                 ASN1_GENERALTIME);
 
 const static struct field_info address_fields[] = {
     FIELDOF_NORM(krb5_address, int32, addrtype, 0),
@@ -164,7 +167,8 @@
     store_32_be((krb5_ui_4) *val, cbuf);
     return asn1_encode_bitstring(buf, 4, cbuf, retlen);
 }
-DEFFNXTYPE(krb5_flags, krb5_flags, asn1_encode_krb5_flags_at);
+DEFPRIMITIVETYPE(krb5_flags, krb5_flags, asn1_encode_krb5_flags_at,
+                 ASN1_BITSTRING);
 
 const static struct field_info authdata_elt_fields[] = {
     /* ad-type[0]               INTEGER */
@@ -347,7 +351,7 @@
     } else return ASN1_MISSING_FIELD;
     return asn1_encode_kdc_req_hack(buf, &val2, retlen);
 }
-DEFFNXTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body);
+DEFFNTYPE(kdc_req_body, krb5_kdc_req, asn1_encode_kdc_req_body);
 /* end ugly hack */
 
 DEFPTRTYPE(ptr_kdc_req_body,kdc_req_body);
@@ -562,7 +566,7 @@
     asn1_makeseq();
     asn1_cleanup();
 }
-DEFFNXTYPE(sam_challenge_2, krb5_sam_challenge_2, asn1_encode_sam_challenge_2);
+DEFFNTYPE(sam_challenge_2, krb5_sam_challenge_2, asn1_encode_sam_challenge_2);
 
 static const struct field_info sam_challenge_2_body_fields[] = {
     FIELDOF_NORM(krb5_sam_challenge_2_body, int32, sam_type, 0),
@@ -1553,19 +1557,46 @@
 }
 #endif
 
-/* asn1_addlenfield -- add a field whose length must be separately specified */
-#define asn1_addlenfield(len, value, tag, encoder)      \
-    {                                                   \
-        unsigned int length;                            \
-        retval = encoder(buf, len, value, &length);     \
-        if (retval) {                                   \
-            return retval; }                            \
-        sum += length;                                  \
-        retval = asn1_make_etag(buf, CONTEXT_SPECIFIC,  \
-                                tag, length, &length);  \
-        if (retval) {                                   \
-            return retval; }                            \
-        sum += length;                                  \
+/*
+ * asn1_addprimitive -- add a primitive field and universal primitive tag to
+ * the encoding, wrapped in a context tag.  encoder must encode only the
+ * contents, not the tag.
+ */
+#define asn1_addprimitive(value,tag,encoder,ptag)                       \
+    { unsigned int enclen, tlen;                                        \
+        retval = encoder(buf, value, &enclen);                          \
+        if (retval) {                                                   \
+            return retval; }                                            \
+        retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ptag,         \
+                               enclen, &tlen);                          \
+        sum += enclen + tlen;                                           \
+        retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag,             \
+                                enclen + tlen, &tlen);                  \
+        if (retval) {                                                   \
+            return retval; }                                            \
+        sum += tlen; }
+
+#define asn1_addinteger(value, tag) \
+    asn1_addprimitive(value, tag, asn1_encode_integer, ASN1_INTEGER)
+
+/* asn1_addstring -- add a string field whose length must be separately
+ * specified, wrapped in a universal primitive tag. */
+#define asn1_addstring(len, value, tag, ptag)                           \
+    {                                                                   \
+        unsigned int enclen, tlen;                                      \
+        retval = asn1_encode_bytestring(buf, len, value, &enclen);      \
+        if (retval) {                                                   \
+            return retval; }                                            \
+        retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ptag,         \
+                               enclen, &tlen);                          \
+        if (retval) {                                                   \
+            return retval; }                                            \
+        sum += enclen + tlen;                                           \
+        retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag,             \
+                                enclen + tlen, &tlen);                  \
+        if (retval) {                                                   \
+            return retval; }                                            \
+        sum += tlen;                                                    \
     }
 
 /*
@@ -1621,8 +1652,9 @@
 
 #ifndef DISABLE_PKINIT
 
-DEFFNXTYPE(algorithm_identifier, krb5_algorithm_identifier, asn1_encode_algorithm_identifier);
-DEFFNLENTYPE(object_identifier, char *, asn1_encode_oid);
+DEFFNTYPE(algorithm_identifier, krb5_algorithm_identifier, asn1_encode_algorithm_identifier);
+DEFSTRINGTYPE(object_identifier, char *, asn1_encode_bytestring,
+              ASN1_OBJECTIDENTIFIER);
 DEFFIELDTYPE(oid_data, krb5_data,
              FIELDOF_STRING(krb5_data, object_identifier, data, length, -1));
 DEFPTRTYPE(oid_data_ptr, oid_data);
@@ -1664,8 +1696,10 @@
 /* For PkinitSuppPubInfo, for pkinit agility */
 static const struct field_info pkinit_supp_pub_info_fields[] = {
     FIELDOF_NORM(krb5_pkinit_supp_pub_info, int32, enctype, 0),
-    FIELDOF_STRING(krb5_pkinit_supp_pub_info, charstring, as_req.data, as_req.length, 1),
-    FIELDOF_STRING(krb5_pkinit_supp_pub_info, charstring, pk_as_rep.data, pk_as_rep.length, 2),
+    FIELDOF_STRING(krb5_pkinit_supp_pub_info, s_octetstring, as_req.data,
+                   as_req.length, 1),
+    FIELDOF_STRING(krb5_pkinit_supp_pub_info, s_octetstring, pk_as_rep.data,
+                   pk_as_rep.length, 2),
 };
 
 DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info, pkinit_supp_pub_info_fields, NULL);
@@ -1693,10 +1727,12 @@
                              unsigned int *retlen)
 {
     asn1_setup();
-    asn1_addlenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_encode_octetstring);
-    asn1_addfield(val->nonce, 2, asn1_encode_integer);
-    asn1_addfield(val->ctime, 1, asn1_encode_kerberos_time);
-    asn1_addfield(val->cusec, 0, asn1_encode_integer);
+    asn1_addstring(val->paChecksum.length, val->paChecksum.contents, 3,
+                   ASN1_OCTETSTRING);
+    asn1_addinteger(val->nonce, 2);
+    asn1_addprimitive(val->ctime, 1, asn1_encode_kerberos_time,
+                      ASN1_GENERALTIME);
+    asn1_addinteger(val->cusec, 0);
 
     asn1_makeseq();
     asn1_cleanup();
@@ -1709,9 +1745,10 @@
 {
     asn1_setup();
 
-    asn1_addfield(val->nonce, 4, asn1_encode_integer);
-    asn1_addfield(val->ctime, 3, asn1_encode_kerberos_time);
-    asn1_addfield(val->cusec, 2, asn1_encode_integer);
+    asn1_addinteger(val->nonce, 4);
+    asn1_addprimitive(val->ctime, 3, asn1_encode_kerberos_time,
+                      ASN1_GENERALTIME);
+    asn1_addinteger(val->cusec, 2);
     asn1_addfield(val->kdcName, 1, asn1_encode_realm);
     asn1_addfield(val->kdcName, 0, asn1_encode_principal_name);
 
@@ -1737,13 +1774,17 @@
 
     {
         unsigned int length;
-        retval = asn1_encode_oid(buf, val->algorithm.length,
-                                 val->algorithm.data,
-                                 &length);
+        retval = asn1_encode_bytestring(buf, val->algorithm.length,
+                                        val->algorithm.data, &length);
 
         if (retval)
             return retval;
         sum += length;
+        retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE,
+                               ASN1_OBJECTIDENTIFIER, length, &length);
+        if (retval)
+            return retval;
+        sum += length;
     }
 
     asn1_makeseq();
@@ -1755,9 +1796,11 @@
                             unsigned int *retlen)
 {
     asn1_setup();
+    unsigned int len, alen = 0;
 
     {
         unsigned int length;
+
         asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING);
     }
 
@@ -1766,30 +1809,26 @@
                                             val->algorithm.parameters.data);
         if (retval)
             return retval;
-        sum += val->algorithm.parameters.length;
+        alen += val->algorithm.parameters.length;
     }
 
-    {
-        unsigned int length;
+    retval = asn1_encode_bytestring(buf, val->algorithm.algorithm.length,
+                                    val->algorithm.algorithm.data, &len);
+    if (retval)
+        return retval;
+    alen += len;
 
-        retval = asn1_encode_oid(buf, val->algorithm.algorithm.length,
-                                 val->algorithm.algorithm.data,
-                                 &length);
+    retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE,
+                           ASN1_OBJECTIDENTIFIER, len, &len);
+    if (retval)
+        return retval;
+    alen += len;
 
-        if (retval)
-            return retval;
-        sum += length;
+    retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, alen, &len);
+    if (retval)
+        return retval;
+    sum += alen + len;
 
-
-        retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE,
-                                val->algorithm.parameters.length + length,
-                                &length);
-
-        if (retval)
-            return retval;
-        sum += length;
-    }
-
     asn1_makeseq();
     asn1_cleanup();
 }
@@ -1825,7 +1864,8 @@
     if (val->supportedKDFs != NULL)
         asn1_addfield(val->supportedKDFs, 4, asn1_encode_supported_kdfs);
     if (val->clientDHNonce.length != 0)
-        asn1_addlenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_encode_octetstring);
+        asn1_addstring(val->clientDHNonce.length, val->clientDHNonce.data, 3,
+                       ASN1_OCTETSTRING);
     if (val->supportedCMSTypes != NULL)
         asn1_addfield((const krb5_algorithm_identifier **)val->supportedCMSTypes,2,asn1_encode_sequence_of_algorithm_identifier);
     if (val->clientPublicValue != NULL)
@@ -2003,9 +2043,11 @@
 {
     asn1_setup();
 
-    if (val->dhKeyExpiration != 0)
-        asn1_addfield(val->dhKeyExpiration, 2, asn1_encode_kerberos_time);
-    asn1_addfield(val->nonce, 1, asn1_encode_integer);
+    if (val->dhKeyExpiration != 0) {
+        asn1_addprimitive(val->dhKeyExpiration, 2, asn1_encode_kerberos_time,
+                          ASN1_GENERALTIME);
+    }
+    asn1_addinteger(val->nonce, 1);
 
     {
         unsigned int length;
@@ -2043,7 +2085,7 @@
 {
     asn1_setup();
 
-    asn1_addfield(val->nonce, 1, asn1_encode_integer);
+    asn1_addinteger(val->nonce, 1);
     asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
 
     asn1_makeseq();
@@ -2157,8 +2199,8 @@
                        unsigned int *retlen)
 {
     asn1_setup();
-    asn1_addlenfield(val->length, val->contents, 1, asn1_encode_octetstring);
-    asn1_addfield(val->pa_type, 0, asn1_encode_integer);
+    asn1_addstring(val->length, val->contents, 1, ASN1_OCTETSTRING);
+    asn1_addinteger(val->pa_type, 0);
     asn1_makeseq();
     asn1_cleanup();
 }



More information about the cvs-krb5 mailing list