summaryrefslogtreecommitdiffstats
path: root/src/lib/krb5/asn.1
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/krb5/asn.1')
-rw-r--r--src/lib/krb5/asn.1/asn1_encode.c248
-rw-r--r--src/lib/krb5/asn.1/asn1_encode.h168
-rw-r--r--src/lib/krb5/asn.1/asn1_k_encode.c168
3 files changed, 245 insertions, 339 deletions
diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c
index 5ecd82f59..f222423e9 100644
--- a/src/lib/krb5/asn.1/asn1_encode.c
+++ b/src/lib/krb5/asn.1/asn1_encode.c
@@ -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;
-
- 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;
+ asn1_octet bval = val ? 0xFF : 0x00;
- *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_encode_integer_internal(asn1buf *buf, asn1_intmax val,
}
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,77 +94,18 @@ asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val,
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)
-{
- return encode_bytestring_with_tag(buf, len, val, ASN1_OBJECTIDENTIFIER,
- retlen);
-}
-
-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)
+asn1_encode_bytestring(asn1buf *buf, unsigned int len, const void *val,
+ unsigned int *retlen)
{
- return encode_bytestring_with_tag(buf, len, val, ASN1_IA5STRING,
- retlen);
+ if (len > 0 && val == NULL) return ASN1_MISSING_FIELD;
+ *retlen = len;
+ return asn1buf_insert_octetstring(buf, len, val);
}
-#endif
asn1_error_code
asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen)
@@ -269,16 +156,7 @@ asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen)
sp = s;
}
- return encode_bytestring_with_tag(buf, 15, sp, ASN1_GENERALTIME,
- 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);
+ return asn1_encode_bytestring(buf, 15, sp, retlen);
}
asn1_error_code
@@ -286,29 +164,11 @@ 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;
-}
-
-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;
+ *retlen = len + 1;
+ return asn1buf_insert_octet(buf, '\0');
}
/*
@@ -383,12 +243,26 @@ asn1_error_code
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 @@ krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val,
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 @@ krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val,
{
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 @@ encode_a_field(asn1buf *buf, const void *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;
break;
}
case field_sequenceof_len:
@@ -536,13 +431,13 @@ encode_a_field(asn1buf *buf, const void *val,
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 @@ encode_a_field(asn1buf *buf, const void *val,
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:
diff --git a/src/lib/krb5/asn.1/asn1_encode.h b/src/lib/krb5/asn.1/asn1_encode.h
index 8a7c9f073..ed2eb18e9 100644
--- a/src/lib/krb5/asn.1/asn1_encode.h
+++ b/src/lib/krb5/asn.1/asn1_encode.h
@@ -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 @@ asn1_error_code asn1_encode_integer(asn1buf *buf, asn1_intmax val,
* 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,24 +72,8 @@ asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val,
* to expand the buffer.
*/
-asn1_error_code asn1_encode_octetstring(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.
- */
-#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);
+asn1_error_code asn1_encode_bytestring(asn1buf *buf, unsigned int len,
+ const void *val, unsigned int *retlen);
/*
* requires *buf is allocated
* modifies *buf, *retlen
@@ -114,28 +93,6 @@ asn1_error_code asn1_encode_null(asn1buf *buf, int *retlen);
* 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 @@ asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val,
* 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,18 +117,6 @@ asn1_error_code asn1_encode_bitstring(asn1buf *buf, unsigned int len,
* 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.
*
@@ -226,14 +159,25 @@ enum atype_type {
* 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 *.
*
@@ -282,14 +226,16 @@ struct atype_info {
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 @@ struct uint_info {
*/
/*
- * 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 @@ struct uint_info {
(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 @@ struct uint_info {
* 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.
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
index 8aecfdf56..56b98022b 100644
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
@@ -78,12 +78,14 @@ DEFUINTTYPE(uint, unsigned int);
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 @@ asn1_encode_kerberos_time_at(asn1buf *buf, const krb5_timestamp *val,
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 @@ asn1_encode_krb5_flags_at(asn1buf *buf, const krb5_flags *val,
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 @@ asn1_encode_kdc_req_body(asn1buf *buf, const krb5_kdc_req *val,
} 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_encode_sam_challenge_2(asn1buf *buf, const krb5_sam_challenge_2 *val,
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 @@ asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf,
}
#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 @@ asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf,
#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 @@ DEFSEQTYPE(sp80056a_other_info, krb5_sp80056a_other_info, sp80056a_other_info_fi
/* 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 @@ asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val,
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_encode_pk_authenticator_draft9(asn1buf *buf,
{
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 @@ asn1_encode_algorithm_identifier(asn1buf *buf,
{
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 @@ asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val,
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,29 +1809,25 @@ asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val,
val->algorithm.parameters.data);
if (retval)
return retval;
- sum += val->algorithm.parameters.length;
+ alen += val->algorithm.parameters.length;
}
- {
- unsigned int length;
-
- retval = asn1_encode_oid(buf, val->algorithm.algorithm.length,
- val->algorithm.algorithm.data,
- &length);
-
- if (retval)
- return retval;
- sum += length;
-
+ retval = asn1_encode_bytestring(buf, val->algorithm.algorithm.length,
+ val->algorithm.algorithm.data, &len);
+ if (retval)
+ return retval;
+ alen += len;
- retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE,
- val->algorithm.parameters.length + length,
- &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;
asn1_makeseq();
asn1_cleanup();
@@ -1825,7 +1864,8 @@ asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val,
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_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_info *val,
{
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_encode_reply_key_pack_draft9(asn1buf *buf,
{
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 @@ asn1_encode_typed_data(asn1buf *buf, const krb5_pa_data *val,
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();
}