From 1d02266a174c939e9ca1460641c8eaa9dc2a7843 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Fri, 23 Nov 2012 21:00:50 +0100 Subject: [PATCH] simplified and renamed asn1_encode_string_der() and asn1_decode_string_der() --- NEWS | 2 +- lib/coding.c | 41 ++++++++++++++++++++++------------------- lib/decoding.c | 30 ++++++++++++++---------------- lib/int.h | 1 - lib/libtasn1.h | 12 +++++++----- lib/libtasn1.map | 4 ++-- tests/Test_strings.c | 21 +++++++++++---------- 7 files changed, 57 insertions(+), 54 deletions(-) diff --git a/NEWS b/NEWS index a8bd32a..a29e187 100644 --- a/NEWS +++ b/NEWS @@ -7,7 +7,7 @@ GNU Libtasn1 NEWS -*- outline -*- PrintableString, UniversalString, BMPString, UTF8String. When re-defined a warning is being print instead of failing. - Parser outputs more detailed syntax error message. -- Added asn1_decode_string_der() and asn1_encode_string_der(). +- Added asn1_decode_simple_der() and asn1_encode_simple_der(). * Noteworthy changes in release 3.0 (2012-10-28) [stable] - Added tool in tests/ to benchmark X.509 structure decoding. diff --git a/lib/coding.c b/lib/coding.c index 007703c..aa777f3 100644 --- a/lib/coding.c +++ b/lib/coding.c @@ -184,32 +184,38 @@ asn1_octet_der (const unsigned char *str, int str_len, /** - * asn1_encode_string_der: + * asn1_encode_simple_der: * @etype: The type of the string to be encoded (ASN1_ETYPE_) * @str: the string data. * @str_len: the string length - * @der: the encoded string - * @der_len: the bytes of the encoded string + * @tl: the encoded tag and length + * @tl_len: the bytes of the @tl field * - * Creates the DER encoding for the various ASN.1 STRING types. - * The DER encoding of the input data will be placed in the @der variable. + * Creates the DER encoding for various simple ASN.1 types like strings etc. + * It stores the tag and length in @tl, which should have space for at least + * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl. + * + * The complete DER encoding should consist of the value in @tl appended + * with the provided @str. * * Returns: %ASN1_SUCCESS if successful or an error value. **/ int -asn1_encode_string_der (unsigned int etype, const unsigned char *str, unsigned int str_len, - unsigned char **der, unsigned int *der_len) +asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned int str_len, + unsigned char *tl, unsigned int *tl_len) { - int tag_len, len_len, tlen; + int tag_len, len_len; + unsigned tlen; unsigned char der_tag[ASN1_MAX_TAG_SIZE]; unsigned char der_length[ASN1_MAX_LENGTH_SIZE]; unsigned char* p; - if (der == NULL) + if (str == NULL) return ASN1_VALUE_NOT_VALID; if (ETYPE_OK(etype) == 0) return ASN1_VALUE_NOT_VALID; + _asn1_tag_der (ETYPE_CLASS(etype), ETYPE_TAG(etype), der_tag, &tag_len); @@ -219,20 +225,17 @@ asn1_encode_string_der (unsigned int etype, const unsigned char *str, unsigned i if (tag_len <= 0 || len_len <= 0) return ASN1_VALUE_NOT_VALID; - tlen = tag_len + len_len + str_len; - - p = malloc(tlen); - if (p == NULL) - return ASN1_MEM_ALLOC_ERROR; - - *der = p; - *der_len = tag_len + len_len + str_len; + tlen = tag_len + len_len; + if (*tl_len < tlen) + return ASN1_MEM_ERROR; + + p = tl; memcpy(p, der_tag, tag_len); p+=tag_len; memcpy(p, der_length, len_len); - p+=len_len; - memcpy(p, str, str_len); + + *tl_len = tlen; return ASN1_SUCCESS; } diff --git a/lib/decoding.c b/lib/decoding.c index 82e5f4e..5df1f36 100644 --- a/lib/decoding.c +++ b/lib/decoding.c @@ -2868,23 +2868,23 @@ asn1_expand_octet_string (asn1_node definitions, asn1_node * element, } /** - * asn1_decode_string_der: + * asn1_decode_simple_der: * @etype: The type of the string to be encoded (ASN1_ETYPE_) * @der: the encoded string * @der_len: the bytes of the encoded string - * @str: the decoded string data. - * @str_len: the string length + * @str: a pointer to the data + * @str_len: the length of the data * - * Creates the DER encoding for the various ASN.1 STRING types. - * The DER encoding of the input data will be placed in the @der variable. + * Decodes a simple DER encoded type (e.g. a string, which is not constructed). + * The output is a pointer inside the @der. * * Returns: %ASN1_SUCCESS if successful or an error value. **/ int -asn1_decode_string_der (unsigned int etype, const unsigned char *der, unsigned int der_len, - unsigned char **str, unsigned int *str_len) +asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int der_len, + const unsigned char **str, unsigned int *str_len) { - int tag_len, len_len, tlen; + int tag_len, len_len; const unsigned char* p; unsigned char class; unsigned long tag; @@ -2900,6 +2900,9 @@ asn1_decode_string_der (unsigned int etype, const unsigned char *der, unsigned i ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); if (ret != ASN1_SUCCESS) return ret; + + if (class != ETYPE_CLASS(etype) || tag != ETYPE_TAG(etype)) + return ASN1_DER_ERROR; p += tag_len; der_len -= tag_len; @@ -2910,14 +2913,9 @@ asn1_decode_string_der (unsigned int etype, const unsigned char *der, unsigned i p += len_len; der_len -= len_len; - tlen = ret; - - *str = malloc(tlen); - if (*str == NULL) - return ASN1_MEM_ALLOC_ERROR; - - memcpy(*str, p, tlen); - *str_len = tlen; + + *str_len = ret; + *str = p; return ASN1_SUCCESS; } diff --git a/lib/int.h b/lib/int.h index daecada..9400cb8 100644 --- a/lib/int.h +++ b/lib/int.h @@ -39,7 +39,6 @@ #include #define ASN1_SMALL_VALUE_SIZE 16 -#define ASN1_MAX_TAG_SIZE 4 /* This structure is also in libtasn1.h, but then contains less fields. You cannot make any modifications to these first fields diff --git a/lib/libtasn1.h b/lib/libtasn1.h index 8c68205..6a164b0 100644 --- a/lib/libtasn1.h +++ b/lib/libtasn1.h @@ -272,7 +272,9 @@ extern "C" extern ASN1_API void asn1_perror (int error); +#define ASN1_MAX_TAG_SIZE 4 #define ASN1_MAX_LENGTH_SIZE 9 +#define ASN1_MAX_TL_SIZE (ASN1_MAX_TAG_SIZE+ASN1_MAX_LENGTH_SIZE) extern ASN1_API long asn1_get_length_der (const unsigned char *der, int der_len, int *len); @@ -285,12 +287,12 @@ extern "C" /* Other utility functions. */ extern ASN1_API - int asn1_decode_string_der (unsigned int etype, const unsigned char *der, unsigned int der_len, - unsigned char **str, unsigned int *str_len); + int asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int der_len, + const unsigned char **str, unsigned int *str_len); - extern ASN1_API - int asn1_encode_string_der (unsigned int etype, const unsigned char *str, unsigned int str_len, - unsigned char **der, unsigned int *der_len); + extern ASN1_API int + asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned int str_len, + unsigned char *tl, unsigned int *tl_len); extern ASN1_API asn1_node asn1_find_node (asn1_node pointer, const char *name); diff --git a/lib/libtasn1.map b/lib/libtasn1.map index 9ae741a..a2b9416 100644 --- a/lib/libtasn1.map +++ b/lib/libtasn1.map @@ -50,8 +50,8 @@ LIBTASN1_0_3 asn1_strerror; asn1_write_value; asn1_read_node_value; - asn1_encode_string_der; - asn1_decode_string_der; + asn1_encode_simple_der; + asn1_decode_simple_der; # Old symbols libtasn1_strerror; diff --git a/tests/Test_strings.c b/tests/Test_strings.c index c2b9da1..b43620f 100644 --- a/tests/Test_strings.c +++ b/tests/Test_strings.c @@ -37,7 +37,7 @@ struct tv static const struct tv tv[] = { {ASN1_ETYPE_IA5_STRING, 20, "\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72", - 22, "\x16\x14\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72"}, + 22, "\x16\x14\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72"}, {ASN1_ETYPE_PRINTABLE_STRING, 5, "\x4e\x69\x6b\x6f\x73", 7, "\x13\x05\x4e\x69\x6b\x6f\x73"}, {ASN1_ETYPE_UTF8_STRING, 12, "Αττική", @@ -52,8 +52,9 @@ int main (int argc, char *argv[]) { int ret; - unsigned char* der; - unsigned int der_len; + unsigned char tl[ASN1_MAX_TL_SIZE]; + unsigned int tl_len, der_len, str_len; + const unsigned char* str; unsigned int i; /* Dummy test */ @@ -61,35 +62,35 @@ main (int argc, char *argv[]) for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) { /* Encode */ - ret = asn1_encode_string_der(tv[i].etype, tv[i].str, tv[i].str_len, - &der, &der_len); + tl_len = sizeof(tl); + ret = asn1_encode_simple_der(tv[i].etype, tv[i].str, tv[i].str_len, + tl, &tl_len); if (ret != ASN1_SUCCESS) { fprintf(stderr, "Encoding error in %u: %s\n", i, asn1_strerror(ret)); return 1; } + der_len = tl_len+tv[i].str_len; - if (der_len != tv[i].der_len || memcmp(der, tv[i].der, der_len) != 0) + if (der_len != tv[i].der_len || memcmp(tl, tv[i].der, tl_len) != 0) { fprintf(stderr, "DER encoding differs in %u! (size: %u, expected: %u)\n", i, der_len, tv[i].der_len); return 1; } - free(der); /* decoding */ - ret = asn1_decode_string_der(tv[i].etype, tv[i].der, tv[i].der_len, &der, &der_len); + ret = asn1_decode_simple_der(tv[i].etype, tv[i].der, tv[i].der_len, &str, &str_len); if (ret != ASN1_SUCCESS) { fprintf(stderr, "Decoding error in %u: %s\n", i, asn1_strerror(ret)); return 1; } - if (der_len != tv[i].str_len || memcmp(der, tv[i].str, der_len) != 0) + if (str_len != tv[i].str_len || memcmp(str, tv[i].str, str_len) != 0) { fprintf(stderr, "DER decoded data differ in %u! (size: %u, expected: %u)\n", i, der_len, tv[i].str_len); return 1; } - free(der); } -- 2.7.4