The branch master has been updated via ca89174bc92c16f0a2a7eb86359b6c6fd1dd7a4d (commit) via c2278c8bc41b01df9fac5fc3d7134430a88dd0e5 (commit) from d74f23d2dbf2de0f374bff004c135242cfb65174 (commit)
- Log ----------------------------------------------------------------- commit ca89174bc92c16f0a2a7eb86359b6c6fd1dd7a4d Author: Richard Levitte <levi...@openssl.org> Date: Thu Sep 6 22:09:11 2018 +0200 ASN.1 DER: Make INT32 / INT64 types read badly encoded LONG zeroes The deprecated ASN.1 type LONG / ZLONG (incorrectly) produced zero length INTEGER encoding for zeroes. For the sake of backward compatibility, we allow those to be read without fault when using the replacement types INT32 / UINT32 / INT64 / UINT64. Fixes #7134 Reviewed-by: Tim Hudson <t...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/7144) commit c2278c8bc41b01df9fac5fc3d7134430a88dd0e5 Author: Richard Levitte <levi...@openssl.org> Date: Sat Sep 8 10:09:32 2018 +0200 TESTS: add test of decoding of invalid zero length ASN.1 INTEGER zero Confirms #7134 Reviewed-by: Tim Hudson <t...@openssl.org> Reviewed-by: Paul Dale <paul.d...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/7153) ----------------------------------------------------------------------- Summary of changes: crypto/asn1/x_int64.c | 24 +++ test/asn1_decode_test.c | 173 +++++++++++++++++++++ test/build.info | 6 +- .../{03-test_exdata.t => 04-test_asn1_decode.t} | 2 +- 4 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 test/asn1_decode_test.c copy test/recipes/{03-test_exdata.t => 04-test_asn1_decode.t} (87%) diff --git a/crypto/asn1/x_int64.c b/crypto/asn1/x_int64.c index f07ca3c..0ee552c 100644 --- a/crypto/asn1/x_int64.c +++ b/crypto/asn1/x_int64.c @@ -81,6 +81,16 @@ static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, return 0; cp = (char *)*pval; + + /* + * Strictly speaking, zero length is malformed. However, long_c2i + * (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course), + * so for the sake of backward compatibility, we still decode zero + * length INTEGERs as the number zero. + */ + if (len == 0) + goto long_compat; + if (!c2i_uint64_int(&utmp, &neg, &cont, len)) return 0; if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { @@ -95,6 +105,8 @@ static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, if (neg) /* c2i_uint64_int() returns positive values */ utmp = 0 - utmp; + + long_compat: memcpy(cp, &utmp, sizeof(utmp)); return 1; } @@ -172,6 +184,16 @@ static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, return 0; cp = (char *)*pval; + + /* + * Strictly speaking, zero length is malformed. However, long_c2i + * (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course), + * so for the sake of backward compatibility, we still decode zero + * length INTEGERs as the number zero. + */ + if (len == 0) + goto long_compat; + if (!c2i_uint64_int(&utmp, &neg, &cont, len)) return 0; if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { @@ -191,6 +213,8 @@ static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, return 0; } } + + long_compat: utmp2 = (uint32_t)utmp; memcpy(cp, &utmp2, sizeof(utmp2)); return 1; diff --git a/test/asn1_decode_test.c b/test/asn1_decode_test.c new file mode 100644 index 0000000..369023d --- /dev/null +++ b/test/asn1_decode_test.c @@ -0,0 +1,173 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <string.h> + +#include <openssl/rand.h> +#include <openssl/asn1t.h> +#include "internal/numbers.h" +#include "testutil.h" + +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wunused-function" +#endif +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wunused-function" +#endif + +/* Badly coded ASN.1 INTEGER zero wrapped in a sequence */ +static unsigned char t_invalid_zero[] = { + 0x30, 0x02, /* SEQUENCE tag + length */ + 0x02, 0x00 /* INTEGER tag + length */ +}; + +#if OPENSSL_API_COMPAT < 0x10200000L +/* LONG case ************************************************************* */ + +typedef struct { + long test_long; +} ASN1_LONG_DATA; + +ASN1_SEQUENCE(ASN1_LONG_DATA) = { + ASN1_EMBED(ASN1_LONG_DATA, test_long, LONG), +} static_ASN1_SEQUENCE_END(ASN1_LONG_DATA) + +IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_LONG_DATA) +IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_LONG_DATA) + +static int test_long(void) +{ + const unsigned char *p = t_invalid_zero; + ASN1_LONG_DATA *dectst = + d2i_ASN1_LONG_DATA(NULL, &p, sizeof(t_invalid_zero)); + + if (dectst == NULL) + return 0; /* Fail */ + + ASN1_LONG_DATA_free(dectst); + return 1; +} +#endif + +/* INT32 case ************************************************************* */ + +typedef struct { + int32_t test_int32; +} ASN1_INT32_DATA; + +ASN1_SEQUENCE(ASN1_INT32_DATA) = { + ASN1_EMBED(ASN1_INT32_DATA, test_int32, INT32), +} static_ASN1_SEQUENCE_END(ASN1_INT32_DATA) + +IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_INT32_DATA) +IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_INT32_DATA) + +static int test_int32(void) +{ + const unsigned char *p = t_invalid_zero; + ASN1_INT32_DATA *dectst = + d2i_ASN1_INT32_DATA(NULL, &p, sizeof(t_invalid_zero)); + + if (dectst == NULL) + return 0; /* Fail */ + + ASN1_INT32_DATA_free(dectst); + return 1; +} + +/* UINT32 case ************************************************************* */ + +typedef struct { + uint32_t test_uint32; +} ASN1_UINT32_DATA; + +ASN1_SEQUENCE(ASN1_UINT32_DATA) = { + ASN1_EMBED(ASN1_UINT32_DATA, test_uint32, UINT32), +} static_ASN1_SEQUENCE_END(ASN1_UINT32_DATA) + +IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_UINT32_DATA) +IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_UINT32_DATA) + +static int test_uint32(void) +{ + const unsigned char *p = t_invalid_zero; + ASN1_UINT32_DATA *dectst = + d2i_ASN1_UINT32_DATA(NULL, &p, sizeof(t_invalid_zero)); + + if (dectst == NULL) + return 0; /* Fail */ + + ASN1_UINT32_DATA_free(dectst); + return 1; +} + +/* INT64 case ************************************************************* */ + +typedef struct { + int64_t test_int64; +} ASN1_INT64_DATA; + +ASN1_SEQUENCE(ASN1_INT64_DATA) = { + ASN1_EMBED(ASN1_INT64_DATA, test_int64, INT64), +} static_ASN1_SEQUENCE_END(ASN1_INT64_DATA) + +IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_INT64_DATA) +IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_INT64_DATA) + +static int test_int64(void) +{ + const unsigned char *p = t_invalid_zero; + ASN1_INT64_DATA *dectst = + d2i_ASN1_INT64_DATA(NULL, &p, sizeof(t_invalid_zero)); + + if (dectst == NULL) + return 0; /* Fail */ + + ASN1_INT64_DATA_free(dectst); + return 1; +} + +/* UINT64 case ************************************************************* */ + +typedef struct { + uint64_t test_uint64; +} ASN1_UINT64_DATA; + +ASN1_SEQUENCE(ASN1_UINT64_DATA) = { + ASN1_EMBED(ASN1_UINT64_DATA, test_uint64, UINT64), +} static_ASN1_SEQUENCE_END(ASN1_UINT64_DATA) + +IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_UINT64_DATA) +IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_UINT64_DATA) + +static int test_uint64(void) +{ + const unsigned char *p = t_invalid_zero; + ASN1_UINT64_DATA *dectst = + d2i_ASN1_UINT64_DATA(NULL, &p, sizeof(t_invalid_zero)); + + if (dectst == NULL) + return 0; /* Fail */ + + ASN1_UINT64_DATA_free(dectst); + return 1; +} + +int setup_tests(void) +{ +#if OPENSSL_API_COMPAT < 0x10200000L + ADD_TEST(test_long); +#endif + ADD_TEST(test_int32); + ADD_TEST(test_uint32); + ADD_TEST(test_int64); + ADD_TEST(test_uint64); + return 1; +} diff --git a/test/build.info b/test/build.info index 2c02ecc..08657c8 100644 --- a/test/build.info +++ b/test/build.info @@ -44,7 +44,7 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN bio_callback_test \ bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \ pkey_meth_test pkey_meth_kdf_test uitest cipherbytes_test \ - asn1_encode_test asn1_string_table_test \ + asn1_encode_test asn1_decode_test asn1_string_table_test \ x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \ recordlentest drbgtest sslbuffertest \ recordlentest drbgtest drbg_cavs_test sslbuffertest \ @@ -410,6 +410,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN INCLUDE[asn1_encode_test]=../include DEPEND[asn1_encode_test]=../libcrypto libtestutil.a + SOURCE[asn1_decode_test]=asn1_decode_test.c + INCLUDE[asn1_decode_test]=../include + DEPEND[asn1_decode_test]=../libcrypto libtestutil.a + SOURCE[asn1_string_table_test]=asn1_string_table_test.c INCLUDE[asn1_string_table_test]=../include DEPEND[asn1_string_table_test]=../libcrypto libtestutil.a diff --git a/test/recipes/03-test_exdata.t b/test/recipes/04-test_asn1_decode.t similarity index 87% copy from test/recipes/03-test_exdata.t copy to test/recipes/04-test_asn1_decode.t index da66f95..d2c4563 100644 --- a/test/recipes/03-test_exdata.t +++ b/test/recipes/04-test_asn1_decode.t @@ -9,4 +9,4 @@ use OpenSSL::Test::Simple; -simple_test("test_exdata", "exdatatest"); +simple_test("test_asn1_decode", "asn1_decode_test"); _____ openssl-commits mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-commits