krb5 commit: Simplify ASN.1 encoding
Greg Hudson
ghudson at mit.edu
Tue Mar 27 14:55:45 EDT 2018
https://github.com/krb5/krb5/commit/5dd2f6877bb88aa57e6650b26daf0864ae732ae8
commit 5dd2f6877bb88aa57e6650b26daf0864ae732ae8
Author: Greg Hudson <ghudson at mit.edu>
Date: Wed Mar 21 18:17:08 2018 -0400
Simplify ASN.1 encoding
Like most ASN.1 DER implementations, we encode backwards. The
existing asn1buf implementation inserts bytes forward into a
resizeable buffer, then reallocates the number of bytes inserted and
reverses them.
Throw out this implementation and replace it with two simple inline
functions in asn1_encode.c, which conditionally insert bytes in
reverse order and unconditionally increment a count. Make two passes
over the input representation, once to count the encoding size and
once to actually encode it into a precisely allocated buffer. Remove
all of the explicit length counting from encoding functions; in the
places where we need intermediate lengths, compute them from the
difference in buffer byte count. Make a few encoding functions return
void as they no longer have error cases.
src/lib/krb5/asn.1/Makefile.in | 3 -
src/lib/krb5/asn.1/asn1_encode.c | 323 ++++++++++++++++--------------------
src/lib/krb5/asn.1/asn1_encode.h | 25 ++--
src/lib/krb5/asn.1/asn1_k_encode.c | 26 ++--
src/lib/krb5/asn.1/asn1buf.c | 208 -----------------------
src/lib/krb5/asn.1/asn1buf.h | 147 ----------------
src/lib/krb5/asn.1/deps | 26 +--
7 files changed, 173 insertions(+), 585 deletions(-)
diff --git a/src/lib/krb5/asn.1/Makefile.in b/src/lib/krb5/asn.1/Makefile.in
index e2e6a35..fe29523 100644
--- a/src/lib/krb5/asn.1/Makefile.in
+++ b/src/lib/krb5/asn.1/Makefile.in
@@ -9,19 +9,16 @@ EHDRDIR=$(BUILDTOP)/include/krb5/asn.1
STLIBOBJS= \
asn1_encode.o\
- asn1buf.o\
asn1_k_encode.o\
ldap_key_seq.o
SRCS= \
$(srcdir)/asn1_encode.c\
- $(srcdir)/asn1buf.c\
$(srcdir)/asn1_k_encode.c\
$(srcdir)/ldap_key_seq.c
OBJS= \
$(OUTPRE)asn1_encode.$(OBJEXT)\
- $(OUTPRE)asn1buf.$(OBJEXT)\
$(OUTPRE)asn1_k_encode.$(OBJEXT)\
$(OUTPRE)ldap_key_seq.$(OBJEXT)
diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c
index a7a5a2f..a160cf4 100644
--- a/src/lib/krb5/asn.1/asn1_encode.c
+++ b/src/lib/krb5/asn.1/asn1_encode.c
@@ -26,97 +26,94 @@
#include "asn1_encode.h"
+struct asn1buf_st {
+ uint8_t *ptr; /* Position, moving backwards; may be NULL */
+ size_t count; /* Count of bytes written so far */
+};
+
/**** Functions for encoding primitive types ****/
-krb5_error_code
-k5_asn1_encode_bool(asn1buf *buf, intmax_t val, size_t *len_out)
+/* Insert one byte into buf going backwards. */
+static inline void
+insert_byte(asn1buf *buf, uint8_t o)
{
- uint8_t bval = val ? 0xFF : 0x00;
+ if (buf->ptr != NULL) {
+ buf->ptr--;
+ *buf->ptr = o;
+ }
+ buf->count++;
+}
- *len_out = 1;
- return asn1buf_insert_octet(buf, bval);
+/* Insert a block of bytes into buf going backwards (but without reversing
+ * bytes). */
+static inline void
+insert_bytes(asn1buf *buf, const void *bytes, size_t len)
+{
+ if (buf->ptr != NULL) {
+ memcpy(buf->ptr - len, bytes, len);
+ buf->ptr -= len;
+ }
+ buf->count += len;
}
-krb5_error_code
-k5_asn1_encode_int(asn1buf *buf, intmax_t val, size_t *len_out)
+void
+k5_asn1_encode_bool(asn1buf *buf, intmax_t val)
+{
+ insert_byte(buf, val ? 0xFF : 0x00);
+}
+
+void
+k5_asn1_encode_int(asn1buf *buf, intmax_t val)
{
- krb5_error_code ret;
- size_t len = 0;
long valcopy;
int digit;
valcopy = val;
do {
digit = valcopy & 0xFF;
- ret = asn1buf_insert_octet(buf, digit);
- if (ret)
- return ret;
- len++;
+ insert_byte(buf, digit);
valcopy = valcopy >> 8;
} while (valcopy != 0 && valcopy != ~0);
- if (val > 0 && (digit & 0x80) == 0x80) { /* make sure the high bit is */
- ret = asn1buf_insert_octet(buf, 0); /* of the proper signed-ness */
- if (ret)
- return ret;
- len++;
- } else if (val < 0 && (digit & 0x80) != 0x80) {
- ret = asn1buf_insert_octet(buf, 0xFF);
- if (ret)
- return ret;
- len++;
- }
-
-
- *len_out = len;
- return 0;
+ /* Make sure the high bit is of the proper signed-ness. */
+ if (val > 0 && (digit & 0x80) == 0x80)
+ insert_byte(buf, 0);
+ else if (val < 0 && (digit & 0x80) != 0x80)
+ insert_byte(buf, 0xFF);
}
-krb5_error_code
-k5_asn1_encode_uint(asn1buf *buf, uintmax_t val, size_t *len_out)
+void
+k5_asn1_encode_uint(asn1buf *buf, uintmax_t val)
{
- krb5_error_code ret;
- size_t len = 0;
uintmax_t valcopy;
int digit;
valcopy = val;
do {
digit = valcopy & 0xFF;
- ret = asn1buf_insert_octet(buf, digit);
- if (ret)
- return ret;
- len++;
+ insert_byte(buf, digit);
valcopy = valcopy >> 8;
} while (valcopy != 0);
- if (digit & 0x80) { /* make sure the high bit is */
- ret = asn1buf_insert_octet(buf, 0); /* of the proper signed-ness */
- if (ret)
- return ret;
- len++;
- }
-
- *len_out = len;
- return 0;
+ /* Make sure the high bit is of the proper signed-ness. */
+ if (digit & 0x80)
+ insert_byte(buf, 0);
}
krb5_error_code
-k5_asn1_encode_bytestring(asn1buf *buf, uint8_t *const *val, size_t len,
- size_t *len_out)
+k5_asn1_encode_bytestring(asn1buf *buf, uint8_t *const *val, size_t len)
{
if (len > 0 && val == NULL)
return ASN1_MISSING_FIELD;
- *len_out = len;
- return asn1buf_insert_octetstring(buf, len, *val);
+ insert_bytes(buf, *val, len);
+ return 0;
}
krb5_error_code
-k5_asn1_encode_generaltime(asn1buf *buf, time_t val, size_t *len_out)
+k5_asn1_encode_generaltime(asn1buf *buf, time_t val)
{
struct tm *gtime, gtimebuf;
- char s[16];
- uint8_t *sp;
+ char s[16], *sp;
time_t gmt_time = val;
int len;
@@ -124,7 +121,7 @@ k5_asn1_encode_generaltime(asn1buf *buf, time_t val, size_t *len_out)
* Time encoding: YYYYMMDDhhmmssZ
*/
if (gmt_time == 0) {
- sp = (uint8_t *)"19700101000000Z";
+ sp = "19700101000000Z";
} else {
/*
* Sanity check this just to be paranoid, as gmtime can return NULL,
@@ -157,23 +154,19 @@ k5_asn1_encode_generaltime(asn1buf *buf, time_t val, size_t *len_out)
if (SNPRINTF_OVERFLOW(len, sizeof(s)))
/* Shouldn't be possible given above tests. */
return ASN1_BAD_GMTIME;
- sp = (uint8_t *)s;
+ sp = s;
}
- return k5_asn1_encode_bytestring(buf, &sp, 15, len_out);
+ insert_bytes(buf, sp, 15);
+ return 0;
}
krb5_error_code
-k5_asn1_encode_bitstring(asn1buf *buf, uint8_t *const *val, size_t len,
- size_t *len_out)
+k5_asn1_encode_bitstring(asn1buf *buf, uint8_t *const *val, size_t len)
{
- krb5_error_code ret;
-
- ret = asn1buf_insert_octetstring(buf, len, *val);
- if (ret)
- return ret;
- *len_out = len + 1;
- return asn1buf_insert_octet(buf, '\0');
+ insert_bytes(buf, *val, len);
+ insert_byte(buf, 0);
+ return 0;
}
/**** Functions for decoding primitive types ****/
@@ -315,67 +308,38 @@ k5_asn1_decode_bitstring(const uint8_t *asn1, size_t len,
/* Encode a DER tag into buf with the tag parameters in t and the content
* length len. Place the length of the encoded tag in *retlen. */
static krb5_error_code
-make_tag(asn1buf *buf, const taginfo *t, size_t len, size_t *retlen)
+make_tag(asn1buf *buf, const taginfo *t, size_t len)
{
- krb5_error_code ret;
asn1_tagnum tag_copy;
- size_t sum = 0, length, len_copy;
+ size_t len_copy, oldcount;
if (t->tagnum > ASN1_TAGNUM_MAX)
return ASN1_OVERFLOW;
/* Encode the length of the content within the tag. */
if (len < 128) {
- ret = asn1buf_insert_octet(buf, len & 0x7F);
- if (ret)
- return ret;
- length = 1;
+ insert_byte(buf, len & 0x7F);
} else {
- length = 0;
- for (len_copy = len; len_copy != 0; len_copy >>= 8) {
- ret = asn1buf_insert_octet(buf, len_copy & 0xFF);
- if (ret)
- return ret;
- length++;
- }
- ret = asn1buf_insert_octet(buf, 0x80 | (length & 0x7F));
- if (ret)
- return ret;
- length++;
+ oldcount = buf->count;
+ for (len_copy = len; len_copy != 0; len_copy >>= 8)
+ insert_byte(buf, len_copy & 0xFF);
+ insert_byte(buf, 0x80 | ((buf->count - oldcount) & 0x7F));
}
- sum += length;
/* Encode the tag and construction bit. */
if (t->tagnum < 31) {
- ret = asn1buf_insert_octet(buf,
- t->asn1class | t->construction | t->tagnum);
- if (ret)
- return ret;
- length = 1;
+ insert_byte(buf, t->asn1class | t->construction | t->tagnum);
} else {
tag_copy = t->tagnum;
- length = 0;
- ret = asn1buf_insert_octet(buf, tag_copy & 0x7F);
- if (ret)
- return ret;
+ insert_byte(buf, tag_copy & 0x7F);
tag_copy >>= 7;
- length++;
- for (; tag_copy != 0; tag_copy >>= 7) {
- ret = asn1buf_insert_octet(buf, 0x80 | (tag_copy & 0x7F));
- if (ret)
- return ret;
- length++;
- }
+ for (; tag_copy != 0; tag_copy >>= 7)
+ insert_byte(buf, 0x80 | (tag_copy & 0x7F));
- ret = asn1buf_insert_octet(buf, t->asn1class | t->construction | 0x1F);
- if (ret)
- return ret;
- length++;
+ insert_byte(buf, t->asn1class | t->construction | 0x1F);
}
- sum += length;
- *retlen = sum;
return 0;
}
@@ -506,18 +470,17 @@ get_nullterm_sequence_len(const void *valp, const struct atype_info *seq)
}
static krb5_error_code
encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val,
- const struct atype_info *eltinfo, size_t *len_out);
+ const struct atype_info *eltinfo);
static krb5_error_code
encode_nullterm_sequence_of(asn1buf *buf, const void *val,
- const struct atype_info *type,
- int can_be_empty, size_t *len_out)
+ const struct atype_info *type, int can_be_empty)
{
size_t len = get_nullterm_sequence_len(val, type);
if (!can_be_empty && len == 0)
return ASN1_MISSING_FIELD;
- return encode_sequence_of(buf, len, val, type, len_out);
+ return encode_sequence_of(buf, len, val, type);
}
static intmax_t
@@ -644,8 +607,7 @@ store_count(size_t count, const struct counted_info *counted, void *val)
/* Split a DER encoding into tag and contents. Insert the contents into buf,
* then return the length of the contents and the tag. */
static krb5_error_code
-split_der(asn1buf *buf, uint8_t *const *der, size_t len,
- taginfo *tag_out, size_t *len_out)
+split_der(asn1buf *buf, uint8_t *const *der, size_t len, taginfo *tag_out)
{
krb5_error_code ret;
const uint8_t *contents, *remainder;
@@ -656,8 +618,8 @@ split_der(asn1buf *buf, uint8_t *const *der, size_t len,
return ret;
if (rlen != 0)
return ASN1_BAD_LENGTH;
- *len_out = clen;
- return asn1buf_insert_bytestring(buf, clen, contents);
+ insert_bytes(buf, contents, clen);
+ return 0;
}
/*
@@ -684,17 +646,16 @@ store_der(const taginfo *t, const uint8_t *asn1, size_t len, void *val,
}
static krb5_error_code
-encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq,
- size_t *len_out);
+encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq);
static krb5_error_code
encode_cntype(asn1buf *buf, const void *val, size_t len,
- const struct cntype_info *c, taginfo *tag_out, size_t *len_out);
+ const struct cntype_info *c, taginfo *tag_out);
/* Encode a value (contents only, no outer tag) according to a type, and return
* its encoded tag information. */
static krb5_error_code
encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
- taginfo *tag_out, size_t *len_out)
+ taginfo *tag_out)
{
krb5_error_code ret;
@@ -705,11 +666,11 @@ encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
case atype_fn: {
const struct fn_info *fn = a->tinfo;
assert(fn->enc != NULL);
- return fn->enc(buf, val, tag_out, len_out);
+ return fn->enc(buf, val, tag_out);
}
case atype_sequence:
assert(a->tinfo != NULL);
- ret = encode_sequence(buf, val, a->tinfo, len_out);
+ ret = encode_sequence(buf, val, a->tinfo);
if (ret)
return ret;
tag_out->asn1class = UNIVERSAL;
@@ -719,20 +680,19 @@ encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
case atype_ptr: {
const struct ptr_info *ptr = a->tinfo;
assert(ptr->basetype != NULL);
- return encode_atype(buf, LOADPTR(val, ptr), ptr->basetype, tag_out,
- len_out);
+ return encode_atype(buf, LOADPTR(val, ptr), ptr->basetype, tag_out);
}
case atype_offset: {
const struct offset_info *off = a->tinfo;
assert(off->basetype != NULL);
return encode_atype(buf, (const char *)val + off->dataoff,
- off->basetype, tag_out, len_out);
+ off->basetype, tag_out);
}
case atype_optional: {
const struct optional_info *opt = a->tinfo;
assert(opt->is_present != NULL);
if (opt->is_present(val))
- return encode_atype(buf, val, opt->basetype, tag_out, len_out);
+ return encode_atype(buf, val, opt->basetype, tag_out);
else
return ASN1_OMITTED;
}
@@ -744,16 +704,14 @@ encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
ret = load_count(val, counted, &count);
if (ret)
return ret;
- return encode_cntype(buf, dataptr, count, counted->basetype, tag_out,
- len_out);
+ return encode_cntype(buf, dataptr, count, counted->basetype, tag_out);
}
case atype_nullterm_sequence_of:
case atype_nonempty_nullterm_sequence_of:
assert(a->tinfo != NULL);
ret = encode_nullterm_sequence_of(buf, val, a->tinfo,
a->type ==
- atype_nullterm_sequence_of,
- len_out);
+ atype_nullterm_sequence_of);
if (ret)
return ret;
tag_out->asn1class = UNIVERSAL;
@@ -762,15 +720,14 @@ encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
break;
case atype_tagged_thing: {
const struct tagged_info *tag = a->tinfo;
- ret = encode_atype(buf, val, tag->basetype, tag_out, len_out);
+ size_t oldcount = buf->count;
+ ret = encode_atype(buf, val, tag->basetype, tag_out);
if (ret)
return ret;
if (!tag->implicit) {
- size_t tlen;
- ret = make_tag(buf, tag_out, *len_out, &tlen);
+ ret = make_tag(buf, tag_out, buf->count - oldcount);
if (ret)
return ret;
- *len_out += tlen;
tag_out->construction = tag->construction;
}
tag_out->asn1class = tag->tagtype;
@@ -778,34 +735,26 @@ encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
break;
}
case atype_bool:
- ret = k5_asn1_encode_bool(buf, load_int(val, a->size), len_out);
- if (ret)
- return ret;
+ k5_asn1_encode_bool(buf, load_int(val, a->size));
tag_out->asn1class = UNIVERSAL;
tag_out->construction = PRIMITIVE;
tag_out->tagnum = ASN1_BOOLEAN;
break;
case atype_int:
- ret = k5_asn1_encode_int(buf, load_int(val, a->size), len_out);
- if (ret)
- return ret;
+ k5_asn1_encode_int(buf, load_int(val, a->size));
tag_out->asn1class = UNIVERSAL;
tag_out->construction = PRIMITIVE;
tag_out->tagnum = ASN1_INTEGER;
break;
case atype_uint:
- ret = k5_asn1_encode_uint(buf, load_uint(val, a->size), len_out);
- if (ret)
- return ret;
+ k5_asn1_encode_uint(buf, load_uint(val, a->size));
tag_out->asn1class = UNIVERSAL;
tag_out->construction = PRIMITIVE;
tag_out->tagnum = ASN1_INTEGER;
break;
case atype_int_immediate: {
const struct immediate_info *imm = a->tinfo;
- ret = k5_asn1_encode_int(buf, imm->val, len_out);
- if (ret)
- return ret;
+ k5_asn1_encode_int(buf, imm->val);
tag_out->asn1class = UNIVERSAL;
tag_out->construction = PRIMITIVE;
tag_out->tagnum = ASN1_INTEGER;
@@ -821,20 +770,18 @@ encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
}
static krb5_error_code
-encode_atype_and_tag(asn1buf *buf, const void *val, const struct atype_info *a,
- size_t *len_out)
+encode_atype_and_tag(asn1buf *buf, const void *val, const struct atype_info *a)
{
taginfo t;
krb5_error_code ret;
- size_t clen, tlen;
+ size_t oldcount = buf->count;
- ret = encode_atype(buf, val, a, &t, &clen);
+ ret = encode_atype(buf, val, a, &t);
if (ret)
return ret;
- ret = make_tag(buf, &t, clen, &tlen);
+ ret = make_tag(buf, &t, buf->count - oldcount);
if (ret)
return ret;
- *len_out = clen + tlen;
return 0;
}
@@ -845,7 +792,7 @@ encode_atype_and_tag(asn1buf *buf, const void *val, const struct atype_info *a,
*/
static krb5_error_code
encode_cntype(asn1buf *buf, const void *val, size_t count,
- const struct cntype_info *c, taginfo *tag_out, size_t *len_out)
+ const struct cntype_info *c, taginfo *tag_out)
{
krb5_error_code ret;
@@ -853,7 +800,7 @@ encode_cntype(asn1buf *buf, const void *val, size_t count,
case cntype_string: {
const struct string_info *string = c->tinfo;
assert(string->enc != NULL);
- ret = string->enc(buf, val, count, len_out);
+ ret = string->enc(buf, val, count);
if (ret)
return ret;
tag_out->asn1class = UNIVERSAL;
@@ -862,13 +809,13 @@ encode_cntype(asn1buf *buf, const void *val, size_t count,
break;
}
case cntype_der:
- return split_der(buf, val, count, tag_out, len_out);
+ return split_der(buf, val, count, tag_out);
case cntype_seqof: {
const struct atype_info *a = c->tinfo;
const struct ptr_info *ptr = a->tinfo;
assert(a->type == atype_ptr);
val = LOADPTR(val, ptr);
- ret = encode_sequence_of(buf, count, val, ptr->basetype, len_out);
+ ret = encode_sequence_of(buf, count, val, ptr->basetype);
if (ret)
return ret;
tag_out->asn1class = UNIVERSAL;
@@ -880,8 +827,7 @@ encode_cntype(asn1buf *buf, const void *val, size_t count,
const struct choice_info *choice = c->tinfo;
if (count >= choice->n_options)
return ASN1_MISSING_FIELD;
- return encode_atype(buf, val, choice->options[count], tag_out,
- len_out);
+ return encode_atype(buf, val, choice->options[count], tag_out);
}
default:
@@ -894,41 +840,36 @@ encode_cntype(asn1buf *buf, const void *val, size_t count,
}
static krb5_error_code
-encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq,
- size_t *len_out)
+encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq)
{
krb5_error_code ret;
- size_t i, len, sum = 0;
+ size_t i;
for (i = seq->n_fields; i > 0; i--) {
- ret = encode_atype_and_tag(buf, val, seq->fields[i - 1], &len);
+ ret = encode_atype_and_tag(buf, val, seq->fields[i - 1]);
if (ret == ASN1_OMITTED)
continue;
else if (ret != 0)
return ret;
- sum += len;
}
- *len_out = sum;
return 0;
}
static krb5_error_code
encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val,
- const struct atype_info *eltinfo, size_t *len_out)
+ const struct atype_info *eltinfo)
{
krb5_error_code ret;
- size_t sum = 0, i, len;
+ size_t i;
const void *eltptr;
assert(eltinfo->size != 0);
for (i = seqlen; i > 0; i--) {
eltptr = (const char *)val + (i - 1) * eltinfo->size;
- ret = encode_atype_and_tag(buf, eltptr, eltinfo, &len);
+ ret = encode_atype_and_tag(buf, eltptr, eltinfo);
if (ret)
return ret;
- sum += len;
}
- *len_out = sum;
return 0;
}
@@ -1572,9 +1513,9 @@ error:
krb5_error_code
k5_asn1_encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
- taginfo *tag_out, size_t *len_out)
+ taginfo *tag_out)
{
- return encode_atype(buf, val, a, tag_out, len_out);
+ return encode_atype(buf, val, a, tag_out);
}
krb5_error_code
@@ -1588,28 +1529,48 @@ krb5_error_code
k5_asn1_full_encode(const void *rep, const struct atype_info *a,
krb5_data **code_out)
{
- size_t len;
krb5_error_code ret;
- asn1buf *buf = NULL;
+ asn1buf buf;
krb5_data *d;
+ uint8_t *bytes;
*code_out = NULL;
if (rep == NULL)
return ASN1_MISSING_FIELD;
- ret = asn1buf_create(&buf);
+
+ /* Make a first pass over rep to count the encoding size. */
+ buf.ptr = NULL;
+ buf.count = 0;
+ ret = encode_atype_and_tag(&buf, rep, a);
if (ret)
return ret;
- ret = encode_atype_and_tag(buf, rep, a, &len);
- if (ret)
- goto cleanup;
- ret = asn12krb5_buf(buf, &d);
- if (ret)
- goto cleanup;
- *code_out = d;
-cleanup:
- asn1buf_destroy(&buf);
- return ret;
+
+ /* Allocate space for the encoding. */
+ bytes = malloc(buf.count + 1);
+ if (bytes == NULL)
+ return ENOMEM;
+ bytes[buf.count] = 0;
+
+ /* Make a second pass over rep to encode it. buf.ptr moves backwards as we
+ * encode, and will always exactly return to the base. */
+ buf.ptr = bytes + buf.count;
+ buf.count = 0;
+ ret = encode_atype_and_tag(&buf, rep, a);
+ if (ret) {
+ free(bytes);
+ return ret;
+ }
+ assert(buf.ptr == bytes);
+
+ /* Create the output data object. */
+ *code_out = malloc(sizeof(*d));
+ if (*code_out == NULL) {
+ free(bytes);
+ return ENOMEM;
+ }
+ **code_out = make_data(bytes, buf.count);
+ return 0;
}
krb5_error_code
diff --git a/src/lib/krb5/asn.1/asn1_encode.h b/src/lib/krb5/asn.1/asn1_encode.h
index 1e17075..fde875b 100644
--- a/src/lib/krb5/asn.1/asn1_encode.h
+++ b/src/lib/krb5/asn.1/asn1_encode.h
@@ -29,9 +29,10 @@
#include "k5-int.h"
#include "krbasn1.h"
-#include "asn1buf.h"
#include <time.h>
+typedef struct asn1buf_st asn1buf;
+
typedef struct {
asn1_class asn1class;
asn1_construction construction;
@@ -45,18 +46,14 @@ typedef struct {
/* These functions are referenced by encoder structures. They handle the
* encoding of primitive ASN.1 types. */
-krb5_error_code k5_asn1_encode_bool(asn1buf *buf, intmax_t val,
- size_t *len_out);
-krb5_error_code k5_asn1_encode_int(asn1buf *buf, intmax_t val,
- size_t *len_out);
-krb5_error_code k5_asn1_encode_uint(asn1buf *buf, uintmax_t val,
- size_t *len_out);
+void k5_asn1_encode_bool(asn1buf *buf, intmax_t val);
+void k5_asn1_encode_int(asn1buf *buf, intmax_t val);
+void k5_asn1_encode_uint(asn1buf *buf, uintmax_t val);
krb5_error_code k5_asn1_encode_bytestring(asn1buf *buf, uint8_t *const *val,
- size_t len, size_t *len_out);
+ size_t len);
krb5_error_code k5_asn1_encode_bitstring(asn1buf *buf, uint8_t *const *val,
- size_t len, size_t *len_out);
-krb5_error_code k5_asn1_encode_generaltime(asn1buf *buf, time_t val,
- size_t *len_out);
+ size_t len);
+krb5_error_code k5_asn1_encode_generaltime(asn1buf *buf, time_t val);
/* These functions are referenced by encoder structures. They handle the
* decoding of primitive ASN.1 types. */
@@ -148,7 +145,7 @@ struct atype_info {
};
struct fn_info {
- krb5_error_code (*enc)(asn1buf *, const void *, taginfo *, size_t *);
+ krb5_error_code (*enc)(asn1buf *, const void *, taginfo *);
krb5_error_code (*dec)(const taginfo *, const uint8_t *, size_t, void *);
int (*check_tag)(const taginfo *);
void (*free_func)(void *);
@@ -226,7 +223,7 @@ struct cntype_info {
};
struct string_info {
- krb5_error_code (*enc)(asn1buf *, uint8_t *const *, size_t, size_t *);
+ krb5_error_code (*enc)(asn1buf *, uint8_t *const *, size_t);
krb5_error_code (*dec)(const uint8_t *, size_t, uint8_t **, size_t *);
unsigned int tagval : 5;
};
@@ -527,7 +524,7 @@ struct seq_info {
* Used only by kdc_req_body. */
krb5_error_code
k5_asn1_encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
- taginfo *tag_out, size_t *len_out);
+ taginfo *tag_out);
/* Decode the tag and contents of a type, storing the result in the
* caller-allocated C object val. Used only by kdc_req_body. */
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
index 0b6003b..65c84be 100644
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
@@ -121,13 +121,14 @@ DEFOPTIONALZEROTYPE(opt_principal, principal);
* with old implementations.
*/
static krb5_error_code
-encode_seqno(asn1buf *buf, const void *p, taginfo *rettag, size_t *len_out)
+encode_seqno(asn1buf *buf, const void *p, taginfo *rettag)
{
uint32_t val = *(uint32_t *)p;
rettag->asn1class = UNIVERSAL;
rettag->construction = PRIMITIVE;
rettag->tagnum = ASN1_INTEGER;
- return k5_asn1_encode_uint(buf, val, len_out);
+ k5_asn1_encode_uint(buf, val);
+ return 0;
}
static krb5_error_code
decode_seqno(const taginfo *t, const uint8_t *asn1, size_t len, void *p)
@@ -155,14 +156,13 @@ DEFOPTIONALZEROTYPE(opt_seqno, seqno);
/* Define the kerberos_time type, which is an ASN.1 generaltime represented in
* a krb5_timestamp. */
static krb5_error_code
-encode_kerberos_time(asn1buf *buf, const void *p, taginfo *rettag,
- size_t *len_out)
+encode_kerberos_time(asn1buf *buf, const void *p, taginfo *rettag)
{
time_t val = ts2tt(*(krb5_timestamp *)p);
rettag->asn1class = UNIVERSAL;
rettag->construction = PRIMITIVE;
rettag->tagnum = ASN1_GENERALTIME;
- return k5_asn1_encode_generaltime(buf, val, len_out);
+ return k5_asn1_encode_generaltime(buf, val);
}
static krb5_error_code
decode_kerberos_time(const taginfo *t, const uint8_t *asn1, size_t len,
@@ -229,15 +229,14 @@ DEFOPTIONALTYPE(opt_encrypted_data, nonempty_enc_data, NULL, encrypted_data);
/* Define the krb5_flags type, which is an ASN.1 bit string represented in a
* 32-bit integer. */
static krb5_error_code
-encode_krb5_flags(asn1buf *buf, const void *p, taginfo *rettag,
- size_t *len_out)
+encode_krb5_flags(asn1buf *buf, const void *p, taginfo *rettag)
{
uint8_t cbuf[4], *cptr = cbuf;
store_32_be((uint32_t)*(const krb5_flags *)p, cbuf);
rettag->asn1class = UNIVERSAL;
rettag->construction = PRIMITIVE;
rettag->tagnum = ASN1_BITSTRING;
- return k5_asn1_encode_bitstring(buf, &cptr, 4, len_out);
+ return k5_asn1_encode_bitstring(buf, &cptr, 4);
}
static krb5_error_code
decode_krb5_flags(const taginfo *t, const uint8_t *asn1, size_t len, void *val)
@@ -316,13 +315,14 @@ DEFOPTIONALZEROTYPE(opt_checksum_ptr, checksum_ptr);
/* Define the last_req_type type, which is an int32_t with some massaging on
* decode for backward compatibility. */
static krb5_error_code
-encode_lr_type(asn1buf *buf, const void *p, taginfo *rettag, size_t *len_out)
+encode_lr_type(asn1buf *buf, const void *p, taginfo *rettag)
{
int32_t val = *(int32_t *)p;
rettag->asn1class = UNIVERSAL;
rettag->construction = PRIMITIVE;
rettag->tagnum = ASN1_INTEGER;
- return k5_asn1_encode_int(buf, val, len_out);
+ k5_asn1_encode_int(buf, val);
+ return 0;
}
static krb5_error_code
decode_lr_type(const taginfo *t, const uint8_t *asn1, size_t len, void *p)
@@ -472,8 +472,7 @@ static const struct atype_info *kdc_req_hack_fields[] = {
};
DEFSEQTYPE(kdc_req_body_hack, kdc_req_hack, kdc_req_hack_fields);
static krb5_error_code
-encode_kdc_req_body(asn1buf *buf, const void *p, taginfo *tag_out,
- size_t *len_out)
+encode_kdc_req_body(asn1buf *buf, const void *p, taginfo *tag_out)
{
const krb5_kdc_req *val = p;
kdc_req_hack h;
@@ -487,8 +486,7 @@ encode_kdc_req_body(asn1buf *buf, const void *p, taginfo *tag_out,
h.server_realm = val->server->realm;
else
return ASN1_MISSING_FIELD;
- return k5_asn1_encode_atype(buf, &h, &k5_atype_kdc_req_body_hack, tag_out,
- len_out);
+ return k5_asn1_encode_atype(buf, &h, &k5_atype_kdc_req_body_hack, tag_out);
}
static void
free_kdc_req_body(void *val)
diff --git a/src/lib/krb5/asn.1/asn1buf.c b/src/lib/krb5/asn.1/asn1buf.c
deleted file mode 100644
index c27bfb9..0000000
--- a/src/lib/krb5/asn.1/asn1buf.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* Coding Buffer Implementation */
-
-/*
- * Implementation
- *
- * Encoding mode
- *
- * The encoding buffer is filled from bottom (lowest address) to top
- * (highest address). This makes it easier to expand the buffer,
- * since realloc preserves the existing portion of the buffer.
- *
- * Note: Since ASN.1 encoding must be done in reverse, this means
- * that you can't simply memcpy out the buffer data, since it will be
- * backwards. You need to reverse-iterate through it, instead.
- *
- * ***This decision may have been a mistake. In practice, the
- * implementation will probably be tuned such that reallocation is
- * rarely necessary. Also, the realloc probably has recopy the
- * buffer itself, so we don't really gain that much by avoiding an
- * explicit copy of the buffer. --Keep this in mind for future reference.
- *
- *
- * Decoding mode
- *
- * The decoding buffer is in normal order and is created by wrapping
- * an asn1buf around a krb5_data structure.
- */
-
-/*
- * Abstraction Function
- *
- * Programs should use just pointers to asn1buf's (e.g. asn1buf *mybuf).
- * These pointers must always point to a valid, allocated asn1buf
- * structure or be NULL.
- *
- * The contents of the asn1buf represent an octet string. This string
- * begins at base and continues to the octet immediately preceding next.
- * If next == base or mybuf == NULL, then the asn1buf represents an empty
- * octet string.
- */
-
-/*
- * Representation Invariant
- *
- * Pointers to asn1buf's must always point to a valid, allocated
- * asn1buf structure or be NULL.
- *
- * base points to a valid, allocated octet array or is NULL
- * bound, if non-NULL, points to the last valid octet
- * next >= base
- * next <= bound+2 (i.e. next should be able to step just past the bound,
- * but no further. (The bound should move out in response
- * to being crossed by next.))
- */
-
-#define ASN1BUF_OMIT_INLINE_FUNCS
-#include "asn1buf.h"
-#include <stdio.h>
-
-#ifdef USE_VALGRIND
-#include <valgrind/memcheck.h>
-#else
-#define VALGRIND_CHECK_READABLE(PTR,SIZE) ((void)0)
-#endif
-
-#if !defined(__GNUC__) || defined(CONFIG_SMALL)
-/*
- * Declare private procedures as static if they're not used for inline
- * expansion of other stuff elsewhere.
- */
-static unsigned int asn1buf_free(const asn1buf *);
-static krb5_error_code asn1buf_ensure_space(asn1buf *, unsigned int);
-static krb5_error_code asn1buf_expand(asn1buf *, unsigned int);
-#endif
-
-#define asn1_is_eoc(class, num, indef) \
- ((class) == UNIVERSAL && !(num) && !(indef))
-
-krb5_error_code
-asn1buf_create(asn1buf **buf)
-{
- *buf = (asn1buf*)malloc(sizeof(asn1buf));
- if (*buf == NULL) return ENOMEM;
- (*buf)->base = NULL;
- (*buf)->bound = NULL;
- (*buf)->next = NULL;
- return 0;
-}
-
-void
-asn1buf_destroy(asn1buf **buf)
-{
- if (*buf != NULL) {
- free((*buf)->base);
- free(*buf);
- *buf = NULL;
- }
-}
-
-#ifdef asn1buf_insert_octet
-#undef asn1buf_insert_octet
-#endif
-krb5_error_code
-asn1buf_insert_octet(asn1buf *buf, const int o)
-{
- krb5_error_code retval;
-
- retval = asn1buf_ensure_space(buf,1U);
- if (retval) return retval;
- *(buf->next) = (char)o;
- (buf->next)++;
- return 0;
-}
-
-krb5_error_code
-asn1buf_insert_bytestring(asn1buf *buf, const unsigned int len, const void *sv)
-{
- krb5_error_code retval;
- unsigned int length;
- const char *s = sv;
-
- retval = asn1buf_ensure_space(buf,len);
- if (retval) return retval;
- VALGRIND_CHECK_READABLE(sv, len);
- for (length=1; length<=len; length++,(buf->next)++)
- *(buf->next) = (s[len-length]);
- return 0;
-}
-
-krb5_error_code
-asn12krb5_buf(const asn1buf *buf, krb5_data **code)
-{
- unsigned int i;
- krb5_data *d;
-
- *code = NULL;
-
- d = calloc(1, sizeof(krb5_data));
- if (d == NULL)
- return ENOMEM;
- d->length = asn1buf_len(buf);
- d->data = malloc(d->length + 1);
- if (d->data == NULL) {
- free(d);
- return ENOMEM;
- }
- for (i=0; i < d->length; i++)
- d->data[i] = buf->base[d->length - i - 1];
- d->data[d->length] = '\0';
- d->magic = KV5M_DATA;
- *code = d;
- return 0;
-}
-
-/****************************************************************/
-/* Private Procedures */
-
-static int
-asn1buf_size(const asn1buf *buf)
-{
- if (buf == NULL || buf->base == NULL) return 0;
- return buf->bound - buf->base + 1;
-}
-
-#undef asn1buf_free
-unsigned int
-asn1buf_free(const asn1buf *buf)
-{
- if (buf == NULL || buf->base == NULL) return 0;
- else return buf->bound - buf->next + 1;
-}
-
-#undef asn1buf_ensure_space
-krb5_error_code
-asn1buf_ensure_space(asn1buf *buf, const unsigned int amount)
-{
- unsigned int avail = asn1buf_free(buf);
- if (avail >= amount)
- return 0;
- return asn1buf_expand(buf, amount-avail);
-}
-
-krb5_error_code
-asn1buf_expand(asn1buf *buf, unsigned int inc)
-{
-#define STANDARD_INCREMENT 200
- int next_offset = buf->next - buf->base;
- int bound_offset;
- if (buf->base == NULL) bound_offset = -1;
- else bound_offset = buf->bound - buf->base;
-
- if (inc < STANDARD_INCREMENT)
- inc = STANDARD_INCREMENT;
-
- buf->base = realloc(buf->base, asn1buf_size(buf) + inc);
- if (buf->base == NULL) return ENOMEM; /* XXX leak */
- buf->bound = (buf->base) + bound_offset + inc;
- buf->next = (buf->base) + next_offset;
- return 0;
-}
-
-#undef asn1buf_len
-int
-asn1buf_len(const asn1buf *buf)
-{
- return buf->next - buf->base;
-}
diff --git a/src/lib/krb5/asn.1/asn1buf.h b/src/lib/krb5/asn.1/asn1buf.h
deleted file mode 100644
index 494417f..0000000
--- a/src/lib/krb5/asn.1/asn1buf.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* Coding Buffer Specifications */
-#ifndef __ASN1BUF_H__
-#define __ASN1BUF_H__
-
-#include "k5-int.h"
-#include "krbasn1.h"
-
-typedef struct code_buffer_rep {
- char *base, *bound, *next;
-} asn1buf;
-
-
-/**************** Private Procedures ****************/
-
-#if (__GNUC__ >= 2) && !defined(CONFIG_SMALL)
-unsigned int asn1buf_free(const asn1buf *buf);
-/*
- * requires *buf is allocated
- * effects Returns the number of unused, allocated octets in *buf.
- */
-#define asn1buf_free(buf) \
- (((buf) == NULL || (buf)->base == NULL) \
- ? 0U \
- : (unsigned int)((buf)->bound - (buf)->next + 1))
-
-
-krb5_error_code asn1buf_ensure_space(asn1buf *buf, const unsigned int amount);
-/*
- * requires *buf is allocated
- * modifies *buf
- * effects If buf has less than amount octets of free space, then it is
- * expanded to have at least amount octets of free space.
- * Returns ENOMEM memory is exhausted.
- */
-#define asn1buf_ensure_space(buf,amount) \
- ((asn1buf_free(buf) < (amount)) \
- ? (asn1buf_expand((buf), (amount)-asn1buf_free(buf))) \
- : 0)
-
-krb5_error_code asn1buf_expand(asn1buf *buf, unsigned int inc);
-/*
- * requires *buf is allocated
- * modifies *buf
- * effects Expands *buf by allocating space for inc more octets.
- * Returns ENOMEM if memory is exhausted.
- */
-#endif
-
-int asn1buf_len(const asn1buf *buf);
-/*
- * requires *buf is allocated
- * effects Returns the length of the encoding in *buf.
- */
-#define asn1buf_len(buf) ((buf)->next - (buf)->base)
-
-/****** End of private procedures *****/
-
-/*
- * Overview
- *
- * The coding buffer is an array of char (to match a krb5_data structure)
- * with 3 reference pointers:
- * 1) base - The bottom of the octet array. Used for memory management
- * operations on the array (e.g. alloc, realloc, free).
- * 2) next - Points to the next available octet position in the array.
- * During encoding, this is the next free position, and it
- * advances as octets are added to the array.
- * During decoding, this is the next unread position, and it
- * advances as octets are read from the array.
- * 3) bound - Points to the top of the array. Used for bounds-checking.
- *
- * All pointers to encoding buffers should be initalized to NULL.
- *
- * Operations
- *
- * asn1buf_create
- * asn1buf_wrap_data
- * asn1buf_destroy
- * asn1buf_insert_octet
- * asn1buf_insert_charstring
- * asn1buf_remove_octet
- * asn1buf_remove_charstring
- * asn1buf_unparse
- * asn1buf_hex_unparse
- * asn12krb5_buf
- * asn1buf_remains
- *
- * (asn1buf_size)
- * (asn1buf_free)
- * (asn1buf_ensure_space)
- * (asn1buf_expand)
- * (asn1buf_len)
- */
-
-krb5_error_code asn1buf_create(asn1buf **buf);
-/*
- * effects Creates a new encoding buffer pointed to by *buf.
- * Returns ENOMEM if the buffer can't be created.
- */
-
-void asn1buf_destroy(asn1buf **buf);
-/* effects Deallocates **buf, sets *buf to NULL. */
-
-/*
- * requires *buf is allocated
- * effects Inserts o into the buffer *buf, expanding the buffer if
- * necessary. Returns ENOMEM memory is exhausted.
- */
-#if ((__GNUC__ >= 2) && !defined(ASN1BUF_OMIT_INLINE_FUNCS)) && !defined(CONFIG_SMALL)
-static inline krb5_error_code
-asn1buf_insert_octet(asn1buf *buf, const int o)
-{
- krb5_error_code retval;
-
- retval = asn1buf_ensure_space(buf,1U);
- if (retval) return retval;
- *(buf->next) = (char)o;
- (buf->next)++;
- return 0;
-}
-#else
-krb5_error_code asn1buf_insert_octet(asn1buf *buf, const int o);
-#endif
-
-krb5_error_code
-asn1buf_insert_bytestring(
- asn1buf *buf,
- const unsigned int len,
- const void *s);
-/*
- * requires *buf is allocated
- * modifies *buf
- * effects Inserts the contents of s (an array of length len)
- * into the buffer *buf, expanding the buffer if necessary.
- * Returns ENOMEM if memory is exhausted.
- */
-
-#define asn1buf_insert_octetstring asn1buf_insert_bytestring
-
-krb5_error_code asn12krb5_buf(const asn1buf *buf, krb5_data **code);
-/*
- * modifies *code
- * effects Instantiates **code with the krb5_data representation of **buf.
- */
-
-#endif
diff --git a/src/lib/krb5/asn.1/deps b/src/lib/krb5/asn.1/deps
index 47050d6..01d2d23 100644
--- a/src/lib/krb5/asn.1/deps
+++ b/src/lib/krb5/asn.1/deps
@@ -11,29 +11,19 @@ asn1_encode.so asn1_encode.po $(OUTPRE)asn1_encode.$(OBJEXT): \
$(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/port-sockets.h $(top_srcdir)/include/socket-utils.h \
- asn1_encode.c asn1_encode.h asn1buf.h krbasn1.h
-asn1buf.so asn1buf.po $(OUTPRE)asn1buf.$(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/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h asn1buf.c asn1buf.h \
- krbasn1.h
+ asn1_encode.c asn1_encode.h 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 \
$(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/port-sockets.h $(top_srcdir)/include/socket-utils.h \
- asn1_encode.h asn1_k_encode.c asn1buf.h krbasn1.h
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-spake.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/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h asn1_encode.h \
+ asn1_k_encode.c 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 \
@@ -45,4 +35,4 @@ ldap_key_seq.so ldap_key_seq.po $(OUTPRE)ldap_key_seq.$(OBJEXT): \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
$(top_srcdir)/include/socket-utils.h asn1_encode.h \
- asn1buf.h krbasn1.h ldap_key_seq.c
+ krbasn1.h ldap_key_seq.c
More information about the cvs-krb5
mailing list