From 372881f5efa8b16c889bcb10547f35e9e2bd59f8 Mon Sep 17 00:00:00 2001 From: Johan Danielsson Date: Tue, 1 Jul 1997 23:52:30 +0000 Subject: [PATCH] Now all decode_* and encode_* functions now take a final size_t* argument, that they return the size in. Return values are zero for success, and anything else (such as some ASN1_* constant) for error. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1951 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/asn1/Makefile.am | 3 + lib/asn1/asn1_locl.h | 6 +- lib/asn1/der.h | 64 ++++--- lib/asn1/der_get.c | 393 ++++++++++++++++++++++-------------------- lib/asn1/der_length.c | 2 +- lib/asn1/der_put.c | 375 +++++++++++++++++++++------------------- lib/asn1/gen.c | 8 +- lib/asn1/gen.h | 6 - lib/asn1/gen_decode.c | 175 ++++++++++++++----- lib/asn1/gen_encode.c | 39 +++-- lib/asn1/gen_maybe.c | 23 +-- lib/asn1/libasn1.h | 2 + lib/asn1/parse.y | 3 +- lib/asn1/symbol.h | 2 +- 14 files changed, 624 insertions(+), 477 deletions(-) diff --git a/lib/asn1/Makefile.am b/lib/asn1/Makefile.am index 5ea0853b4..336bd75c1 100644 --- a/lib/asn1/Makefile.am +++ b/lib/asn1/Makefile.am @@ -2,6 +2,9 @@ AUTOMAKE_OPTIONS = no-dependencies foreign +WFLAGS=-Wall -Wno-unused -Wconversion -Wmissing-prototypes -Wredundant-decls +CFLAGS=$(WFLAGS) @CFLAGS@ + lib_LIBRARIES = libasn1.a SUFFIXES = .x diff --git a/lib/asn1/asn1_locl.h b/lib/asn1/asn1_locl.h index e91fa0514..791c02209 100644 --- a/lib/asn1/asn1_locl.h +++ b/lib/asn1/asn1_locl.h @@ -18,8 +18,11 @@ #include "symbol.h" +void generate_type (Symbol *); +void generate_constant (Symbol *); void generate_type_encode (Symbol *s); void generate_type_decode (Symbol *s); +void generate_seq_type_decode (Symbol *s); void generate_type_free (Symbol *s); void generate_type_length (Symbol *s); void generate_type_copy (Symbol *s); @@ -27,11 +30,8 @@ void generate_type_maybe (Symbol *s); void init_generate (char *filename); void close_generate(void); -void initsym(void); int yyparse(void); -int fix_dce(int, int*); - extern FILE *headerfile, *codefile, *logfile; #endif /* __ASN1_LOCL_H__ */ diff --git a/lib/asn1/der.h b/lib/asn1/der.h index dfa534d41..cee5c0619 100644 --- a/lib/asn1/der.h +++ b/lib/asn1/der.h @@ -30,42 +30,49 @@ time_t timegm (struct tm *); void time2generalizedtime (time_t t, octet_string *s); -int der_get_int (unsigned char *p, int len, unsigned *ret); -int der_get_length (unsigned char *p, int len, int *ret); -int der_get_general_string (unsigned char *p, int len, general_string *str); -int der_get_octet_string (unsigned char *p, int len, octet_string *data); -int der_get_tag (unsigned char *p, int len, - Der_class *class, Der_type *type, int *tag); -int der_match_tag (unsigned char *p, int len, - Der_class class, Der_type type, int tag); -int der_match_tag_and_length (unsigned char *p, int len, +int der_get_int (unsigned char *p, size_t len, unsigned *ret, size_t *size); +int der_get_length (unsigned char *p, size_t len, size_t *val, size_t *size); +int der_get_general_string (unsigned char *p, size_t len, + general_string *str, size_t *size); +int der_get_octet_string (unsigned char *p, size_t len, + octet_string *data, size_t *size); +int der_get_tag (unsigned char *p, size_t len, + Der_class *class, Der_type *type, + int *tag, size_t *size); + +int der_match_tag (unsigned char *p, size_t len, + Der_class class, Der_type type, + int tag, size_t *size); +int der_match_tag_and_length (unsigned char *p, size_t len, Der_class class, Der_type type, int tag, - int *length_ret); -int decode_integer (unsigned char *p, int len, unsigned *num); -int decode_general_string (unsigned char *p, int len, general_string *str); -int decode_octet_string (unsigned char *p, int len, octet_string *k); -int decode_generalized_time (unsigned char *p, int len, time_t *t); + size_t *length_ret, size_t *size); + +int decode_integer (unsigned char*, size_t, unsigned*, size_t*); +int decode_general_string (unsigned char*, size_t, general_string*, size_t*); +int decode_octet_string (unsigned char*, size_t, octet_string*, size_t*); +int decode_generalized_time (unsigned char*, size_t, time_t*, size_t*); -int der_put_int (unsigned char *p, int len, unsigned val); -int der_put_length (unsigned char *p, int len, int val); -int der_put_general_string (unsigned char *p, int len, general_string *str); -int der_put_octet_string (unsigned char *p, int len, octet_string *data); -int der_put_tag (unsigned char *p, int len, Der_class class, Der_type type, - int tag); -int der_put_length_and_tag (unsigned char *p, int len, int len_val, - Der_class class, Der_type type, int tag); -int encode_integer (unsigned char *p, int len, unsigned *data); -int encode_general_string (unsigned char *p, int len, general_string *data); -int encode_octet_string (unsigned char *p, int len, octet_string *k); -int encode_generalized_time (unsigned char *p, int len, time_t *t); +int der_put_int (unsigned char *p, size_t len, unsigned val, size_t*); +int der_put_length (unsigned char *p, size_t len, unsigned val, size_t*); +int der_put_general_string (unsigned char *p, size_t len, general_string *str, size_t*); +int der_put_octet_string (unsigned char *p, size_t len, octet_string *data, size_t*); +int der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, + int tag, size_t*); +int der_put_length_and_tag (unsigned char*, size_t, size_t, + Der_class, Der_type, int, size_t*); + +int encode_integer (unsigned char *p, size_t len, unsigned *data, size_t*); +int encode_general_string (unsigned char *p, size_t len, general_string *data, size_t*); +int encode_octet_string (unsigned char *p, size_t len, octet_string *k, size_t*); +int encode_generalized_time (unsigned char *p, size_t len, time_t *t, size_t*); void free_integer (unsigned *num); void free_general_string (general_string *str); void free_octet_string (octet_string *k); void free_generalized_time (time_t *t); -size_t length_len (int len); +size_t length_len (size_t len); size_t length_integer (unsigned *data); size_t length_general_string (general_string *data); size_t length_octet_string (octet_string *k); @@ -74,6 +81,7 @@ size_t length_generalized_time (time_t *t); void copy_general_string (const general_string *from, general_string *to); void copy_octet_string (const octet_string *from, octet_string *to); -int fix_dce(int reallen, int *len); +int fix_dce(size_t reallen, size_t *len); #endif /* __DER_H__ */ + diff --git a/lib/asn1/der_get.c b/lib/asn1/der_get.c index 3da2fc2ea..353134d21 100644 --- a/lib/asn1/der_get.c +++ b/lib/asn1/der_get.c @@ -9,252 +9,273 @@ RCSID("$Id$"); * indicating how many actually got read, or <0 in case of errors. */ -int -der_get_int (unsigned char *p, int len, unsigned *ret) -{ - int val = 0; - int oldlen = len; +/* + * All decoding functions take a pointer `p' to first position in + * which to read, from the left, `len' which means the maximum number + * of characters we are able to read and return the status as an int + */ - while (len--) - val = val * 256 + *p++; - *ret = val; - return oldlen; -} int -der_get_length (unsigned char *p, int len, int *ret) +der_get_int (unsigned char *p, size_t len, unsigned *ret, size_t *size) { - int val; + unsigned val = 0; + size_t oldlen = len; - if (--len < 0) - return -1; - val = *p++; - if (val < 128) { + while (len--) + val = val * 256 + *p++; *ret = val; - return 1; - } else { - int l; - unsigned tmp; - - val &= 0x7F; - if (len < val) - return -1; - l = der_get_int (p, val, &tmp); - *ret = tmp; - if (l < 0) - return l; - else - return l+1; - } + *size = oldlen; + return 0; } int -der_get_general_string (unsigned char *p, int len, general_string *str) +der_get_length (unsigned char *p, size_t len, size_t *val, size_t *size) { - int l, slen; - char *s; + size_t v; - l = der_get_length (p, len, &slen); - if (l < 0) - return l; - p += l; - len -= l; - if (len < slen) - return -1; - s = malloc (slen + 1); - if (s == NULL) - return -1; - memcpy (s, p, slen); - s[slen] = '\0'; - *str = s; - return slen + l; + if (--len < 0) + return ASN1_OVERRUN; + v = *p++; + if (v < 128) { + *val = v; + *size = 1; + } else { + int e; + size_t l; + unsigned tmp; + + v &= 0x7F; + if (len < v) + return ASN1_OVERRUN; + e = der_get_int (p, v, &tmp, &l); + if(e) return e; + *val = tmp; + *size = l + 1; + } + return 0; } int -der_get_octet_string (unsigned char *p, int len, octet_string *data) +der_get_general_string (unsigned char *p, size_t len, + general_string *str, size_t *size) { - int l, slen; + size_t l, slen; + char *s; + int e; - l = der_get_length (p, len, &slen); - if (l < 0) - return l; - p += l; - len -= l; - if (len < slen) - return -1; - data->length = slen; - data->data = malloc(slen); - if (data->data == NULL && data->length != 0) - return -1; - memcpy (data->data, p, slen); - return slen + l; + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + if (len < slen) + return ASN1_OVERRUN; + s = malloc (slen + 1); + if (s == NULL) + return ENOMEM; + memcpy (s, p, slen); + s[slen] = '\0'; + *str = s; + *size = slen + l; + return 0; } int -der_get_tag (unsigned char *p, int len, Der_class *class, Der_type *type, - int *tag) +der_get_octet_string (unsigned char *p, size_t len, + octet_string *data, size_t *size) { - if (len < 1) - return -1; - *class = ((*p) >> 6) & 0x03; - *type = ((*p) >> 5) & 0x01; - *tag = (*p) & 0x1F; - return 1; + size_t l, slen; + int e; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + if (len < slen) + ASN1_OVERRUN; + data->length = slen; + data->data = malloc(slen); + if (data->data == NULL && data->length != 0) + return ENOMEM; + memcpy (data->data, p, slen); + *size = slen + l; + return 0; } int -der_match_tag (unsigned char *p, int len, Der_class class, Der_type type, - int tag) +der_get_tag (unsigned char *p, size_t len, Der_class *class, Der_type *type, + int *tag, size_t *size) { - int l; - Der_class thisclass; - Der_type thistype; - int thistag; - - l = der_get_tag (p, len, &thisclass, &thistype, &thistag); - if (l < 0) - return l; - if (class == thisclass && type == thistype && tag == thistag) - return l; - else - return -1; + if (len < 1) + return ASN1_OVERRUN; + *class = ((*p) >> 6) & 0x03; + *type = ((*p) >> 5) & 0x01; + *tag = (*p) & 0x1F; + *size = 1; + return 0; } int -der_match_tag_and_length (unsigned char *p, int len, +der_match_tag (unsigned char *p, size_t len, Der_class class, Der_type type, + int tag, size_t *size) +{ + size_t l; + Der_class thisclass; + Der_type thistype; + int thistag; + int e; + + e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l); + if (e) return e; + if (class != thisclass || type != thistype) + return ASN1_BAD_ID; + if(tag > thistag) + return ASN1_MISPLACED_FIELD; + if(tag < thistag) + return ASN1_MISSING_FIELD; + *size = l; + return 0; +} + +int +der_match_tag_and_length (unsigned char *p, size_t len, Der_class class, Der_type type, int tag, - int *length_ret) + size_t *length_ret, size_t *size) { - int ret = 0; - int l; + size_t l, ret = 0; + int e; - l = der_match_tag (p, len, class, type, tag); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - l = der_get_length (p, len, length_ret); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - return ret; + e = der_match_tag (p, len, class, type, tag, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, length_ret, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + *size = ret; + return 0; } int -decode_integer (unsigned char *p, int len, unsigned *num) +decode_integer (unsigned char *p, size_t len, unsigned *num, size_t *size) { - int ret = 0; - int l, reallen; + size_t ret = 0; + size_t l, reallen; + int e; - l = der_match_tag (p, len, UNIV, PRIM, UT_Integer); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - l = der_get_length (p, len, &reallen); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - l = der_get_int (p, reallen, num); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - return ret; + e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, &reallen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_int (p, reallen, num, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + *size = ret; + return 0; } int -decode_general_string (unsigned char *p, int len, general_string *str) +decode_general_string (unsigned char *p, size_t len, + general_string *str, size_t *size) { - int ret = 0; - int l; + size_t ret = 0; + size_t l; + int e; - l = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - l = der_get_general_string (p, len, str); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - return ret; + e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_general_string (p, len, str, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + *size = ret; + return 0; } int -decode_octet_string (unsigned char *p, int len, octet_string *k) +decode_octet_string (unsigned char *p, size_t len, + octet_string *k, size_t *size) { - int ret = 0; - int l; + size_t ret = 0; + size_t l; + int e; - l = der_match_tag (p, len, UNIV, PRIM, UT_OctetString); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - l = der_get_octet_string (p, len, k); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - return ret; + e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_octet_string (p, len, k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + *size = ret; + return 0; } static void generalizedtime2time (char *s, time_t *t) { - struct tm tm; + struct tm tm; - sscanf (s, "%04d%02d%02d%02d%02d%02dZ", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, - &tm.tm_min, &tm.tm_sec); - tm.tm_year -= 1900; - tm.tm_mon -= 1; - *t = timegm (&tm); + sscanf (s, "%04d%02d%02d%02d%02d%02dZ", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, + &tm.tm_min, &tm.tm_sec); + tm.tm_year -= 1900; + tm.tm_mon -= 1; + *t = timegm (&tm); } int -decode_generalized_time (unsigned char *p, int len, time_t *t) +decode_generalized_time (unsigned char *p, size_t len, time_t *t, size_t *size) { - octet_string k; - char times[32]; /* XXX */ - int ret = 0; - int l; + octet_string k; + char *times; + size_t ret = 0; + size_t l; + int e; - l = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - l = der_get_octet_string (p, len, &k); - if (l < 0) - return l; - p += l; - len -= l; - ret += l; - strncpy(times, (char*)k.data, k.length); - times[k.length] = 0; - generalizedtime2time (times, t); - free (k.data); - return ret; + e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_octet_string (p, len, &k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + times = realloc(k.data, k.length + 1); + if (times == NULL){ + free(k.data); + return ENOMEM; + } + times[k.length] = 0; + generalizedtime2time (times, t); + free (times); + *size = ret; + return 0; } int -fix_dce(int reallen, int *len) +fix_dce(size_t reallen, size_t *len) { if(reallen == 0) return 1; diff --git a/lib/asn1/der_length.c b/lib/asn1/der_length.c index e55a77135..141b75024 100644 --- a/lib/asn1/der_length.c +++ b/lib/asn1/der_length.c @@ -15,7 +15,7 @@ length_int (unsigned val) } size_t -length_len (int len) +length_len (size_t len) { if (len < 128) return 1; diff --git a/lib/asn1/der_put.c b/lib/asn1/der_put.c index d4103fb9e..8268ab87e 100644 --- a/lib/asn1/der_put.c +++ b/lib/asn1/der_put.c @@ -12,183 +12,204 @@ RCSID("$Id$"); */ int -der_put_int (unsigned char *p, int len, unsigned val) +der_put_int (unsigned char *p, size_t len, unsigned val, size_t *size) { - unsigned char *base = p; + unsigned char *base = p; - if (val) { - while (len > 0 && val) { - *p-- = val % 256; - val /= 256; - --len; - } - if (val) - return -1; - else - return base - p; - } else if (len < 1) - return -1; - else { - *p = 0; - return 1; - } -} - -int -der_put_length (unsigned char *p, int len, int val) -{ - if (val < 128) { - if (len < 1) - return -1; + if (val) { + while (len > 0 && val) { + *p-- = val % 256; + val /= 256; + --len; + } + if (val) + return ASN1_OVERFLOW; + else + return base - p; + } else if (len < 1) + return ASN1_OVERFLOW; else { - *p = val; - return 1; + *p = 0; + *size = 1; + return 0; } - } else { - int l; +} - l = der_put_int (p, len - 1,val); - if (l < 0) - return l; +int +der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) +{ + if (val < 128) { + if (len < 1) + return ASN1_OVERFLOW; + else { + *p = val; + *size = 1; + return 0; + } + } else { + size_t l; + int e; + + e = der_put_int (p, len - 1, val, &l); + if (e) + return e; + p -= l; + *p = 0x80 | l; + *size = l + 1; + return 0; + } +} + +int +der_put_general_string (unsigned char *p, size_t len, + general_string *str, size_t *size) +{ + size_t slen = strlen(*str); + size_t l; + int e; + + if (len < slen) + return ASN1_OVERFLOW; + p -= slen; + len -= slen; + memcpy (p+1, *str, slen); + e = der_put_length (p, len, slen, &l); + if(e) + return e; + *size = slen + l; + return 0; +} + +int +der_put_octet_string (unsigned char *p, size_t len, + octet_string *data, size_t *size) +{ + size_t l; + int e; + + if (len < data->length) + return ASN1_OVERFLOW; + p -= data->length; + len -= data->length; + memcpy (p+1, data->data, data->length); + e = der_put_length (p, len, data->length, &l); + if(e) + return e; + *size = l + data->length; + return 0; +} + +int +der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, + int tag, size_t *size) +{ + if (len < 1) + return ASN1_OVERFLOW; + *p = (class << 6) | (type << 5) | tag; /* XXX */ + *size = 1; + return 0; +} + +int +der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, + Der_class class, Der_type type, int tag, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_length (p, len, len_val, &l); + if(e) + return e; p -= l; - *p = 0x80 | l; - return l + 1; - } + len -= l; + ret += l; + e = der_put_tag (p, len, class, type, tag, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; } int -der_put_general_string (unsigned char *p, int len, general_string *str) +encode_integer (unsigned char *p, size_t len, unsigned *data, size_t *size) { - int slen = strlen(*str); - int l; - - if (len < slen) - return -1; - p -= slen; - len -= slen; - memcpy (p+1, *str, slen); - l = der_put_length (p, len, slen); - if(l < 0) - return l; - return slen + l; + unsigned num = *data; + size_t ret = 0; + size_t l; + int e; + + e = der_put_int (p, len, num, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length (p, len, l, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_tag (p, len, UNIV, PRIM, UT_Integer, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; } int -der_put_octet_string (unsigned char *p, int len, octet_string *data) +encode_general_string (unsigned char *p, size_t len, + general_string *data, size_t *size) { - int l; + size_t ret = 0; + size_t l; + int e; - if (len < data->length) - return -1; - p -= data->length; - len -= data->length; - memcpy (p+1, data->data, data->length); - l = der_put_length (p, len, data->length); - if (l < 0) - return l; - return l + data->length; + e = der_put_general_string (p, len, data, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_tag (p, len, UNIV, PRIM, UT_GeneralString, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; } int -der_put_tag (unsigned char *p, int len, Der_class class, Der_type type, - int tag) +encode_octet_string (unsigned char *p, size_t len, + octet_string *k, size_t *size) { - if (len < 1) - return -1; - *p = (class << 6) | (type << 5) | tag; /* XXX */ - return 1; -} + size_t ret = 0; + size_t l; + int e; -int -der_put_length_and_tag (unsigned char *p, int len, int len_val, - Der_class class, Der_type type, int tag) -{ - int ret = 0; - int l; - - l = der_put_length (p, len, len_val); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - l = der_put_tag (p, len, class, type, tag); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - return ret; -} - -int -encode_integer (unsigned char *p, int len, unsigned *data) -{ - unsigned num = *data; - int ret = 0; - int l; - - l = der_put_int (p, len, num); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - l = der_put_length (p, len, l); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - l = der_put_tag (p, len, UNIV, PRIM, UT_Integer); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - return ret; -} - -int -encode_general_string (unsigned char *p, int len, general_string *data) -{ - int ret = 0; - int l; - - l = der_put_general_string (p, len, data); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - l = der_put_tag (p, len, UNIV, PRIM, UT_GeneralString); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - return ret; -} - -int -encode_octet_string (unsigned char *p, int len, octet_string *k) -{ - int ret = 0; - int l; - - l = der_put_octet_string (p, len, k); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - l = der_put_tag (p, len, UNIV, PRIM, UT_OctetString); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - return ret; + e = der_put_octet_string (p, len, k, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_tag (p, len, UNIV, PRIM, UT_OctetString, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; } void @@ -205,25 +226,27 @@ time2generalizedtime (time_t t, octet_string *s) } int -encode_generalized_time (unsigned char *p, int len, time_t *t) +encode_generalized_time (unsigned char *p, size_t len, time_t *t, size_t *size) { - octet_string k; - int l; - int ret = 0; + size_t ret = 0; + size_t l; + octet_string k; + int e; - time2generalizedtime (*t, &k); - l = der_put_octet_string (p, len, &k); - free (k.data); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - l = der_put_tag (p, len, UNIV, PRIM, UT_GeneralizedTime); - if (l < 0) - return l; - p -= l; - len -= l; - ret += l; - return ret; + time2generalizedtime (*t, &k); + e = der_put_octet_string (p, len, &k, &l); + free (k.data); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; } diff --git a/lib/asn1/gen.c b/lib/asn1/gen.c index 52becd7a8..4e245f0d2 100644 --- a/lib/asn1/gen.c +++ b/lib/asn1/gen.c @@ -276,12 +276,16 @@ generate_type (Symbol *s) fprintf (codefile, "/* Generated from %s */\n" "/* Do not edit */\n\n" + "#include \"libasn1.h\"\n\n" +#if 0 "#include \n" "#include \n" "#include \n" "#include <" STEM ".h>\n\n" - "#include \n", - orig_filename); + "#include \n" + "#include \n" +#endif + ,orig_filename); generate_type_header (s); generate_type_encode (s); generate_type_decode (s); diff --git a/lib/asn1/gen.h b/lib/asn1/gen.h index 4d838b55a..2928be848 100644 --- a/lib/asn1/gen.h +++ b/lib/asn1/gen.h @@ -3,9 +3,3 @@ #include #include "symbol.h" -void init_generate (char *); -void close_generate (); -void generate_constant (Symbol *); -void generate_type (Symbol *); - -extern FILE *headerfile, *codefile; diff --git a/lib/asn1/gen_decode.c b/lib/asn1/gen_decode.c index 3a27e629e..471aee10d 100644 --- a/lib/asn1/gen_decode.c +++ b/lib/asn1/gen_decode.c @@ -6,7 +6,7 @@ static void decode_primitive (char *typename, char *name) { fprintf (codefile, - "l = decode_%s(p, len, %s);\n" + "e = decode_%s(p, len, %s, &l);\n" "FORW;\n", typename, name); @@ -21,7 +21,7 @@ decode_type (char *name, Type *t) decode_type (name, t->symbol->type); #endif fprintf (codefile, - "l = decode_%s(p, len, %s);\n" + "e = decode_%s(p, len, %s, &l);\n" "FORW;\n", t->symbol->gen_name, name); break; @@ -37,11 +37,11 @@ decode_type (char *name, Type *t) int pos; fprintf (codefile, - "l = der_match_tag_and_length (p, len, UNIV, PRIM, UT_BitString," - "&reallen);\n" + "e = der_match_tag_and_length (p, len, UNIV, PRIM, UT_BitString," + "&reallen, &l);\n" "FORW;\n" "if(len < reallen)\n" - "return -1;\n" + "return ASN1_OVERRUN;\n" "p++;\n" "len--;\n" "reallen--;\n" @@ -71,35 +71,67 @@ decode_type (char *name, Type *t) break; fprintf (codefile, - "l = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence," - "&reallen);\n" + "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence," + "&reallen, &l);\n" "FORW;\n" "{\n" "int dce_fix;\n" "if((dce_fix = fix_dce(reallen, &len)) < 0)\n" - "return -1;\n"); + "return ASN1_BAD_FORMAT;\n"); for (m = t->members; m && tag != m->val; m = m->next) { char *s = malloc(2 + strlen(name) + 1 + strlen(m->gen_name) + 3); sprintf (s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); + if (0 && m->type->type == TType){ + if(m->optional) + fprintf (codefile, + "%s = malloc(sizeof(*%s));\n", s, s); + fprintf (codefile, + "e = decode_seq_%s(p, len, %d, %d, %s, &l);\n", + m->type->symbol->gen_name, + m->val, + m->optional, + s); + if(m->optional) + fprintf (codefile, + "if (e == ASN1_MISSING_FIELD) {\n" + "free(%s);\n" + "%s = NULL;\n" + "e = l = 0;\n" + "}\n", + s, s); + + fprintf (codefile, "FORW;\n"); + + }else{ fprintf (codefile, "{\n" - "int newlen, oldlen;\n\n" - "l = der_match_tag (p, len, CONTEXT, CONS, %d);\n", + "size_t newlen, oldlen;\n\n" + "e = der_match_tag (p, len, CONTEXT, CONS, %d, &l);\n", m->val); fprintf (codefile, - "if(l >= 0) {\n" + "if (e)\n"); + if(m->optional) + /* XXX should look at e */ + fprintf (codefile, + "%s = NULL;\n", s); + else + fprintf (codefile, + "return e;\n"); + fprintf (codefile, + "else {\n"); + fprintf (codefile, "p += l;\n" "len -= l;\n" "ret += l;\n" - "l = der_get_length (p, len, &newlen);\n" + "e = der_get_length (p, len, &newlen, &l);\n" "FORW;\n" "{\n" "int dce_fix;\n" "oldlen = len;\n" "if((dce_fix = fix_dce(newlen, &len)) < 0)" - "return -1;\n"); + "return ASN1_BAD_FORMAT;\n"); if (m->optional) fprintf (codefile, "%s = malloc(sizeof(*%s));\n", @@ -107,30 +139,23 @@ decode_type (char *name, Type *t) decode_type (s, m->type); fprintf (codefile, "if(dce_fix){\n" - "l = der_match_tag_and_length (p, len, 0, 0, 0, &reallen);\n" + "e = der_match_tag_and_length (p, len, 0, 0, 0, " + "&reallen, &l);\n" "FORW;\n" "}else \n" "len = oldlen - newlen;\n" "}\n" - "}\n" - "else {\n"); - if(m->optional) - fprintf (codefile, - "%s = NULL;\n" - "}\n", s); - else - fprintf (codefile, - "return l;\n" - "}\n"); + "}\n"); fprintf (codefile, "}\n"); + } if (tag == -1) tag = m->val; free (s); } fprintf(codefile, "if(dce_fix){\n" - "l = der_match_tag_and_length (p, len, 0, 0, 0, &reallen);\n" + "e = der_match_tag_and_length (p, len, 0, 0, 0, &reallen, &l);\n" "FORW;\n" "}\n" "}\n"); @@ -141,11 +166,11 @@ decode_type (char *name, Type *t) char *n = malloc(2*strlen(name) + 20); fprintf (codefile, - "l = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence," - "&reallen);\n" + "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence," + "&reallen, &l);\n" "FORW;\n" "if(len < reallen)\n" - "return -1;\n" + "return ASN1_OVERRUN;\n" "len = reallen;\n"); fprintf (codefile, @@ -170,17 +195,18 @@ decode_type (char *name, Type *t) break; case TApplication: fprintf (codefile, - "l = der_match_tag_and_length (p, len, APPL, CONS, %d, &reallen);\n" + "e = der_match_tag_and_length (p, len, APPL, CONS, %d, " + "&reallen, &l);\n" "FORW;\n" "{\n" "int dce_fix;\n" "if((dce_fix = fix_dce(reallen, &len)) < 0)\n" - "return -1;\n", + "return ASN1_BAD_FORMAT;\n", t->application); decode_type (name, t->subtype); fprintf(codefile, "if(dce_fix){\n" - "l = der_match_tag_and_length (p, len, 0, 0, 0, &reallen);\n" + "e = der_match_tag_and_length (p, len, 0, 0, 0, &reallen, &l);\n" "FORW;\n" "}\n" "}\n"); @@ -195,34 +221,33 @@ void generate_type_decode (Symbol *s) { fprintf (headerfile, - "int decode_%s(unsigned char *, int, %s *);\n", + "int decode_%s(unsigned char *, size_t, %s *, size_t *);\n", s->gen_name, s->gen_name); fprintf (codefile, "#define FORW " - "if(l < 0)" - "return l;" - "p += l;" - "len -= l;" + "if(e) return e; " + "p += l; " + "len -= l; " "ret += l\n\n"); fprintf (codefile, "int\n" - "decode_%s(unsigned char *p, int len, %s *data)\n" + "decode_%s(unsigned char *p, size_t len, %s *data, size_t *size)\n" "{\n", s->gen_name, s->gen_name); switch (s->type->type) { case TInteger: - fprintf (codefile, "return decode_integer (p, len, data);\n"); + fprintf (codefile, "return decode_integer (p, len, data, size);\n"); break; case TOctetString: - fprintf (codefile, "return decode_octet_string (p, len, data);\n"); + fprintf (codefile, "return decode_octet_string (p, len, data, size);\n"); break; case TGeneralizedTime: - fprintf (codefile, "return decode_generalized_time (p, len, data);\n"); + fprintf (codefile, "return decode_generalized_time (p, len, data, size);\n"); break; case TGeneralString: - fprintf (codefile, "return decode_general_string (p, len, data);\n"); + fprintf (codefile, "return decode_general_string (p, len, data, size);\n"); break; case TBitString: case TSequence: @@ -230,11 +255,14 @@ generate_type_decode (Symbol *s) case TApplication: case TType: fprintf (codefile, - "int ret = 0, reallen;\n" - "int l, i;\n\n"); + "size_t ret = 0, reallen;\n" + "size_t l;\n" + "int e, i;\n\n"); decode_type ("data", s->type); - fprintf (codefile, "return ret;\n"); + fprintf (codefile, + "*size = ret;\n" + "return 0;\n"); break; default: abort (); @@ -242,6 +270,65 @@ generate_type_decode (Symbol *s) fprintf (codefile, "}\n\n"); } +void +generate_seq_type_decode (Symbol *s) +{ + fprintf (headerfile, + "int decode_seq_%s(unsigned char *, size_t, int, int, " + "%s *, size_t *);\n", + s->gen_name, s->gen_name); + + fprintf (codefile, "int\n" + "decode_seq_%s(unsigned char *p, size_t len, int tag, " + "int optional, %s *data, size_t *size)\n" + "{\n", + s->gen_name, s->gen_name); + + fprintf (codefile, + "size_t newlen, oldlen;\n" + "size_t l, ret = 0;\n" + "int e;\n" + "int dce_fix;\n"); + + fprintf (codefile, + "e = der_match_tag(p, len, CONTEXT, CONS, tag, &l);\n" + "if (e)\n" + "return e;\n"); + fprintf (codefile, + "p += l;\n" + "len -= l;\n" + "ret += l;\n" + "e = der_get_length(p, len, &newlen, &l);\n" + "if (e)\n" + "return e;\n" + "p += l;\n" + "len -= l;\n" + "ret += l;\n" + "oldlen = len;\n" + "if ((dce_fix = fix_dce(newlen, &len)) < 0)\n" + "return ASN1_BAD_FORMAT;\n" + "e = decode_%s(p, len, data, &l);\n" + "if (e)\n" + "return e;\n" + "p += l;\n" + "len -= l;\n" + "ret += l;\n" + "if (dce_fix) {\n" + "size_t reallen;\n\n" + "e = der_match_tag_and_length(p, len, 0, 0, 0, &reallen, &l);\n" + "if (e)\n" + "return e;\n" + "ret += l;\n" + "}\n", + s->gen_name); + fprintf (codefile, + "*size = ret;\n" + "return 0;\n"); + + fprintf (codefile, "}\n\n"); +} + + #if 0 static void generate_type_decode (Symbol *s) diff --git a/lib/asn1/gen_encode.c b/lib/asn1/gen_encode.c index fe52233cf..14fb19677 100644 --- a/lib/asn1/gen_encode.c +++ b/lib/asn1/gen_encode.c @@ -6,7 +6,7 @@ static void encode_primitive (char *typename, char *name) { fprintf (codefile, - "l = encode_%s(p, len, %s);\n" + "e = encode_%s(p, len, %s, &l);\n" "BACK;\n", typename, name); @@ -21,7 +21,7 @@ encode_type (char *name, Type *t) encode_type (name, t->symbol->type); #endif fprintf (codefile, - "l = encode_%s(p, len, %s);\n" + "e = encode_%s(p, len, %s, &l);\n" "BACK;\n", t->symbol->gen_name, name); break; @@ -77,8 +77,8 @@ encode_type (char *name, Type *t) "len -= 2;\n" "ret += 2;\n" "}\n\n" - "l = der_put_length_and_tag (p, len, ret, UNIV, PRIM," - "UT_BitString);\n" + "e = der_put_length_and_tag (p, len, ret, UNIV, PRIM," + "UT_BitString, &l);\n" "BACK;\n", rest); break; @@ -105,7 +105,8 @@ encode_type (char *name, Type *t) #endif encode_type (s, m->type); fprintf (codefile, - "l = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, %d);\n" + "e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, " + "%d, &l);\n" "BACK;\n", m->val); #if 1 @@ -118,7 +119,7 @@ encode_type (char *name, Type *t) free (s); } fprintf (codefile, - "l = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence);\n" + "e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l);\n" "BACK;\n"); break; } @@ -141,7 +142,7 @@ encode_type (char *name, Type *t) "ret += oldret;\n" #endif "}\n" - "l = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence);\n" + "e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l);\n" "BACK;\n"); free (n); break; @@ -155,7 +156,7 @@ encode_type (char *name, Type *t) case TApplication: encode_type (name, t->subtype); fprintf (codefile, - "l = der_put_length_and_tag (p, len, ret, APPL, CONS, %d);\n" + "e = der_put_length_and_tag (p, len, ret, APPL, CONS, %d, &l);\n" "BACK;\n", t->application); break; @@ -168,29 +169,29 @@ void generate_type_encode (Symbol *s) { fprintf (headerfile, - "int encode_%s(unsigned char *, int, %s *);\n", + "int encode_%s(unsigned char *, size_t, %s *, size_t *);\n", s->gen_name, s->gen_name); - fprintf (codefile, "#define BACK if (l < 0) return l; p -= l; len -= l; ret += l\n\n"); + fprintf (codefile, "#define BACK if (e) return e; p -= l; len -= l; ret += l\n\n"); fprintf (codefile, "int\n" - "encode_%s(unsigned char *p, int len, %s *data)\n" + "encode_%s(unsigned char *p, size_t len, %s *data, size_t *size)\n" "{\n", s->gen_name, s->gen_name); switch (s->type->type) { case TInteger: - fprintf (codefile, "return encode_integer (p, len, data);\n"); + fprintf (codefile, "return encode_integer (p, len, data, size);\n"); break; case TOctetString: - fprintf (codefile, "return encode_octet_string (p, len, data);\n"); + fprintf (codefile, "return encode_octet_string (p, len, data, size);\n"); break; case TGeneralizedTime: - fprintf (codefile, "return encode_generalized_time (p, len, data);\n"); + fprintf (codefile, "return encode_generalized_time (p, len, data, size);\n"); break; case TGeneralString: - fprintf (codefile, "return encode_general_string (p, len, data);\n"); + fprintf (codefile, "return encode_general_string (p, len, data, size);\n"); break; case TBitString: case TSequence: @@ -198,11 +199,13 @@ generate_type_encode (Symbol *s) case TApplication: case TType: fprintf (codefile, - "int ret = 0;\n" - "int l, i;\n\n"); + "size_t ret = 0;\n" + "size_t l;\n" + "int i, e;\n\n"); encode_type ("data", s->type); - fprintf (codefile, "return ret;\n"); + fprintf (codefile, "*size = ret;\n" + "return 0;\n"); break; default: abort (); diff --git a/lib/asn1/gen_maybe.c b/lib/asn1/gen_maybe.c index 46e4e4a63..adba64789 100644 --- a/lib/asn1/gen_maybe.c +++ b/lib/asn1/gen_maybe.c @@ -6,47 +6,48 @@ void generate_type_maybe (Symbol *s) { fprintf (headerfile, - "int maybe_%s(unsigned char *, int);\n", + "int maybe_%s(unsigned char *, size_t);\n", s->gen_name); fprintf (codefile, "int\n" - "maybe_%s(unsigned char *p, int len)\n" - "{\n ", + "maybe_%s(unsigned char *p, size_t len)\n" + "{\n " + "size_t size;\n ", s->gen_name); switch (s->type->type) { case TInteger: fprintf (codefile, "return der_match_tag (p, len, UNIV, " - "PRIM, UT_Integer) >= 0;\n"); + "PRIM, UT_Integer, &size) == 0;\n"); break; case TOctetString: fprintf (codefile, "return der_match_tag (p, len, UNIV, " - "PRIM, UT_OctetString) >= 0;\n"); + "PRIM, UT_OctetString, &size) == 0;\n"); break; case TGeneralizedTime: fprintf (codefile, "return der_match_tag (p, len, UNIV, " - "PRIM, UT_GeneralizedTime) >= 0;\n"); + "PRIM, UT_GeneralizedTime, &size) == 0;\n"); break; case TGeneralString: fprintf (codefile, "return der_match_tag (p, len, UNIV, " - "PRIM, UT_GeneralString) >= 0;\n"); + "PRIM, UT_GeneralString, &size) == 0;\n"); break; case TBitString: fprintf (codefile, "return der_match_tag (p, len, UNIV, " - "PRIM, UT_BitString) >= 0;\n"); + "PRIM, UT_BitString, &size) == 0;\n"); break; case TSequence: case TSequenceOf: fprintf (codefile, "return der_match_tag (p, len, UNIV, " - "CONS, UT_Sequence) >= 0;\n"); + "CONS, UT_Sequence, &size) == 0;\n"); break; case TApplication: fprintf (codefile, "return der_match_tag (p, len, APPL, " - "CONS, %d) >= 0;\n", s->type->application); + "CONS, %d, &size) == 0;\n", s->type->application); break; case TType: - fprintf (codefile, "return maybe_%s(p, len) >= 0;\n", + fprintf (codefile, "return maybe_%s(p, len) == 0;\n", s->type->symbol->gen_name); break; default: diff --git a/lib/asn1/libasn1.h b/lib/asn1/libasn1.h index f8f0cfd41..0af65bbd0 100644 --- a/lib/asn1/libasn1.h +++ b/lib/asn1/libasn1.h @@ -6,5 +6,7 @@ #include "asn1_locl.h" #include "asn1.h" #include "der.h" +#include "asn1_err.h" +#include #endif /* __LIBASN1_H__ */ diff --git a/lib/asn1/parse.y b/lib/asn1/parse.y index e1f404bd9..19cb3cd94 100644 --- a/lib/asn1/parse.y +++ b/lib/asn1/parse.y @@ -9,10 +9,11 @@ #include #include "symbol.h" #include "lex.h" -#include "gen.h" +#include "asn1_locl.h" static Type *new_type (Typetype t); void yyerror (char *); +int yylex(); #ifndef HAVE_STRDUP char *strdup(char *); diff --git a/lib/asn1/symbol.h b/lib/asn1/symbol.h index 00d1785f1..5e3b3b796 100644 --- a/lib/asn1/symbol.h +++ b/lib/asn1/symbol.h @@ -43,7 +43,7 @@ struct symbol { typedef struct symbol Symbol; -void initsym (); +void initsym (void); Symbol *addsym (char *); void output_name (char *); #endif