fcd2d5a612
Previously, the API version limit was indicated with a numeric version number. This was "natural" in the pre-3.0.0 because the version was this simple number. With 3.0.0, the version is divided into three separate numbers, and it's only the major number that counts, but we still need to be able to support pre-3.0.0 version limits. Therefore, we allow OPENSSL_API_COMPAT to be defined with a pre-3.0.0 style numeric version number or with a simple major number, i.e. can be defined like this for any application: -D OPENSSL_API_COMPAT=0x10100000L -D OPENSSL_API_COMPAT=3 Since the pre-3.0.0 numerical version numbers are high, it's easy to distinguish between a simple major number and a pre-3.0.0 numerical version number and to thereby support both forms at the same time. Internally, we define the following macros depending on the value of OPENSSL_API_COMPAT: OPENSSL_API_0_9_8 OPENSSL_API_1_0_0 OPENSSL_API_1_1_0 OPENSSL_API_3 They indicate that functions marked for deprecation in the corresponding major release shall not be built if defined. Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/7724)
870 lines
29 KiB
C
870 lines
29 KiB
C
/*
|
|
* 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"
|
|
# pragma GCC diagnostic ignored "-Wformat"
|
|
#endif
|
|
#ifdef __clang__
|
|
# pragma clang diagnostic ignored "-Wunused-function"
|
|
# pragma clang diagnostic ignored "-Wformat"
|
|
#endif
|
|
|
|
/***** Custom test data ******************************************************/
|
|
|
|
/*
|
|
* We conduct tests with these arrays for every type we try out.
|
|
* You will find the expected results together with the test structures
|
|
* for each type, further down.
|
|
*/
|
|
|
|
static unsigned char t_zero[] = {
|
|
0x00
|
|
};
|
|
static unsigned char t_one[] = {
|
|
0x01
|
|
};
|
|
static unsigned char t_one_neg[] = {
|
|
0xff
|
|
};
|
|
static unsigned char t_minus_256[] = {
|
|
0xff, 0x00
|
|
};
|
|
static unsigned char t_longundef[] = {
|
|
0x7f, 0xff, 0xff, 0xff
|
|
};
|
|
static unsigned char t_9bytes_1[] = {
|
|
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
};
|
|
static unsigned char t_8bytes_1[] = {
|
|
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
static unsigned char t_8bytes_2[] = {
|
|
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
};
|
|
static unsigned char t_8bytes_3_pad[] = {
|
|
0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
};
|
|
static unsigned char t_8bytes_4_neg[] = {
|
|
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
static unsigned char t_8bytes_5_negpad[] = {
|
|
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
/* 32-bit long */
|
|
static unsigned char t_5bytes_1[] = {
|
|
0x01, 0xff, 0xff, 0xff, 0xff
|
|
};
|
|
static unsigned char t_4bytes_1[] = {
|
|
0x00, 0x80, 0x00, 0x00, 0x00
|
|
};
|
|
/* We make the last byte 0xfe to avoid a clash with ASN1_LONG_UNDEF */
|
|
static unsigned char t_4bytes_2[] = {
|
|
0x7f, 0xff, 0xff, 0xfe
|
|
};
|
|
static unsigned char t_4bytes_3_pad[] = {
|
|
0x00, 0x7f, 0xff, 0xff, 0xfe
|
|
};
|
|
static unsigned char t_4bytes_4_neg[] = {
|
|
0x80, 0x00, 0x00, 0x00
|
|
};
|
|
static unsigned char t_4bytes_5_negpad[] = {
|
|
0xff, 0x80, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
typedef struct {
|
|
unsigned char *bytes1;
|
|
size_t nbytes1;
|
|
unsigned char *bytes2;
|
|
size_t nbytes2;
|
|
} TEST_CUSTOM_DATA;
|
|
#define CUSTOM_DATA(v) \
|
|
{ v, sizeof(v), t_one, sizeof(t_one) }, \
|
|
{ t_one, sizeof(t_one), v, sizeof(v) }
|
|
|
|
static TEST_CUSTOM_DATA test_custom_data[] = {
|
|
CUSTOM_DATA(t_zero),
|
|
CUSTOM_DATA(t_longundef),
|
|
CUSTOM_DATA(t_one),
|
|
CUSTOM_DATA(t_one_neg),
|
|
CUSTOM_DATA(t_minus_256),
|
|
CUSTOM_DATA(t_9bytes_1),
|
|
CUSTOM_DATA(t_8bytes_1),
|
|
CUSTOM_DATA(t_8bytes_2),
|
|
CUSTOM_DATA(t_8bytes_3_pad),
|
|
CUSTOM_DATA(t_8bytes_4_neg),
|
|
CUSTOM_DATA(t_8bytes_5_negpad),
|
|
CUSTOM_DATA(t_5bytes_1),
|
|
CUSTOM_DATA(t_4bytes_1),
|
|
CUSTOM_DATA(t_4bytes_2),
|
|
CUSTOM_DATA(t_4bytes_3_pad),
|
|
CUSTOM_DATA(t_4bytes_4_neg),
|
|
CUSTOM_DATA(t_4bytes_5_negpad),
|
|
};
|
|
|
|
|
|
/***** Type specific test data ***********************************************/
|
|
|
|
/*
|
|
* First, a few utility things that all type specific data can use, or in some
|
|
* cases, MUST use.
|
|
*/
|
|
|
|
/*
|
|
* For easy creation of arrays of expected data. These macros correspond to
|
|
* the uses of CUSTOM_DATA above.
|
|
*/
|
|
#define CUSTOM_EXPECTED_SUCCESS(num, znum) \
|
|
{ 0xff, num, 1 }, \
|
|
{ 0xff, 1, znum }
|
|
#define CUSTOM_EXPECTED_FAILURE \
|
|
{ 0, 0, 0 }, \
|
|
{ 0, 0, 0 }
|
|
|
|
/*
|
|
* A structure to collect all test information in. There MUST be one instance
|
|
* of this for each test
|
|
*/
|
|
typedef int i2d_fn(void *a, unsigned char **pp);
|
|
typedef void *d2i_fn(void **a, unsigned char **pp, long length);
|
|
typedef void ifree_fn(void *a);
|
|
typedef struct {
|
|
ASN1_ITEM_EXP *asn1_type;
|
|
const char *name;
|
|
int skip; /* 1 if this package should be skipped */
|
|
|
|
/* An array of structures to compare decoded custom data with */
|
|
void *encode_expectations;
|
|
size_t encode_expectations_size;
|
|
size_t encode_expectations_elem_size;
|
|
|
|
/*
|
|
* An array of structures that are encoded into a DER blob, which is
|
|
* then decoded, and result gets compared with the original.
|
|
*/
|
|
void *encdec_data;
|
|
size_t encdec_data_size;
|
|
size_t encdec_data_elem_size;
|
|
|
|
/* The i2d function to use with this type */
|
|
i2d_fn *i2d;
|
|
/* The d2i function to use with this type */
|
|
d2i_fn *d2i;
|
|
/* Function to free a decoded structure */
|
|
ifree_fn *ifree;
|
|
} TEST_PACKAGE;
|
|
|
|
/* To facilitate the creation of an encdec_data array */
|
|
#define ENCDEC_DATA(num, znum) \
|
|
{ 0xff, num, 1 }, { 0xff, 1, znum }
|
|
#define ENCDEC_ARRAY(max, zmax, min, zmin) \
|
|
ENCDEC_DATA(max,zmax), \
|
|
ENCDEC_DATA(min,zmin), \
|
|
ENCDEC_DATA(1, 1), \
|
|
ENCDEC_DATA(-1, -1), \
|
|
ENCDEC_DATA(0, ASN1_LONG_UNDEF)
|
|
|
|
#if !OPENSSL_API_3
|
|
/***** LONG ******************************************************************/
|
|
|
|
typedef struct {
|
|
/* If decoding is expected to succeed, set this to 1, otherwise 0 */
|
|
ASN1_BOOLEAN success;
|
|
long test_long;
|
|
long test_zlong;
|
|
} ASN1_LONG_DATA;
|
|
|
|
ASN1_SEQUENCE(ASN1_LONG_DATA) = {
|
|
ASN1_SIMPLE(ASN1_LONG_DATA, success, ASN1_FBOOLEAN),
|
|
ASN1_SIMPLE(ASN1_LONG_DATA, test_long, LONG),
|
|
ASN1_EXP_OPT(ASN1_LONG_DATA, test_zlong, ZLONG, 0)
|
|
} static_ASN1_SEQUENCE_END(ASN1_LONG_DATA)
|
|
|
|
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_LONG_DATA)
|
|
IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_LONG_DATA)
|
|
|
|
static ASN1_LONG_DATA long_expected_32bit[] = {
|
|
/* The following should fail on the second because it's the default */
|
|
{ 0xff, 0, 1 }, { 0, 0, 0 }, /* t_zero */
|
|
{ 0, 0, 0 }, { 0xff, 1, 0x7fffffff }, /* t_longundef */
|
|
CUSTOM_EXPECTED_SUCCESS(1, 1), /* t_one */
|
|
CUSTOM_EXPECTED_SUCCESS(-1, -1), /* t_one_neg */
|
|
CUSTOM_EXPECTED_SUCCESS(-256, -256), /* t_minus_256 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_9bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_3_pad */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_5_negpad */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_5bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_1 (too large positive) */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MAX - 1, INT32_MAX -1), /* t_4bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_3_pad (illegal padding) */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MIN, INT32_MIN), /* t_4bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_5_negpad (illegal padding) */
|
|
};
|
|
static ASN1_LONG_DATA long_encdec_data_32bit[] = {
|
|
ENCDEC_ARRAY(LONG_MAX - 1, LONG_MAX, LONG_MIN, LONG_MIN),
|
|
/* Check that default numbers fail */
|
|
{ 0, ASN1_LONG_UNDEF, 1 }, { 0, 1, 0 }
|
|
};
|
|
|
|
static TEST_PACKAGE long_test_package_32bit = {
|
|
ASN1_ITEM_ref(ASN1_LONG_DATA), "LONG", sizeof(long) != 4,
|
|
long_expected_32bit,
|
|
sizeof(long_expected_32bit), sizeof(long_expected_32bit[0]),
|
|
long_encdec_data_32bit,
|
|
sizeof(long_encdec_data_32bit), sizeof(long_encdec_data_32bit[0]),
|
|
(i2d_fn *)i2d_ASN1_LONG_DATA, (d2i_fn *)d2i_ASN1_LONG_DATA,
|
|
(ifree_fn *)ASN1_LONG_DATA_free
|
|
};
|
|
|
|
static ASN1_LONG_DATA long_expected_64bit[] = {
|
|
/* The following should fail on the second because it's the default */
|
|
{ 0xff, 0, 1 }, { 0, 0, 0 }, /* t_zero */
|
|
{ 0, 0, 0 }, { 0xff, 1, 0x7fffffff }, /* t_longundef */
|
|
CUSTOM_EXPECTED_SUCCESS(1, 1), /* t_one */
|
|
CUSTOM_EXPECTED_SUCCESS(-1, -1), /* t_one_neg */
|
|
CUSTOM_EXPECTED_SUCCESS(-256, -256), /* t_minus_256 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_9bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(LONG_MAX, LONG_MAX), /* t_8bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_3_pad (illegal padding) */
|
|
CUSTOM_EXPECTED_SUCCESS(LONG_MIN, LONG_MIN), /* t_8bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_5_negpad (illegal padding) */
|
|
CUSTOM_EXPECTED_SUCCESS((long)0x1ffffffff, (long)0x1ffffffff), /* t_5bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS((long)0x80000000, (long)0x80000000), /* t_4bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MAX - 1, INT32_MAX -1), /* t_4bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_3_pad (illegal padding) */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MIN, INT32_MIN), /* t_4bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_5_negpad (illegal padding) */
|
|
};
|
|
static ASN1_LONG_DATA long_encdec_data_64bit[] = {
|
|
ENCDEC_ARRAY(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN),
|
|
/* Check that default numbers fail */
|
|
{ 0, ASN1_LONG_UNDEF, 1 }, { 0, 1, 0 }
|
|
};
|
|
|
|
static TEST_PACKAGE long_test_package_64bit = {
|
|
ASN1_ITEM_ref(ASN1_LONG_DATA), "LONG", sizeof(long) != 8,
|
|
long_expected_64bit,
|
|
sizeof(long_expected_64bit), sizeof(long_expected_64bit[0]),
|
|
long_encdec_data_64bit,
|
|
sizeof(long_encdec_data_64bit), sizeof(long_encdec_data_64bit[0]),
|
|
(i2d_fn *)i2d_ASN1_LONG_DATA, (d2i_fn *)d2i_ASN1_LONG_DATA,
|
|
(ifree_fn *)ASN1_LONG_DATA_free
|
|
};
|
|
#endif
|
|
|
|
/***** INT32 *****************************************************************/
|
|
|
|
typedef struct {
|
|
ASN1_BOOLEAN success;
|
|
int32_t test_int32;
|
|
int32_t test_zint32;
|
|
} ASN1_INT32_DATA;
|
|
|
|
ASN1_SEQUENCE(ASN1_INT32_DATA) = {
|
|
ASN1_SIMPLE(ASN1_INT32_DATA, success, ASN1_FBOOLEAN),
|
|
ASN1_EMBED(ASN1_INT32_DATA, test_int32, INT32),
|
|
ASN1_EXP_OPT_EMBED(ASN1_INT32_DATA, test_zint32, ZINT32, 0)
|
|
} static_ASN1_SEQUENCE_END(ASN1_INT32_DATA)
|
|
|
|
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_INT32_DATA)
|
|
IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_INT32_DATA)
|
|
|
|
static ASN1_INT32_DATA int32_expected[] = {
|
|
CUSTOM_EXPECTED_SUCCESS(0, 0), /* t_zero */
|
|
CUSTOM_EXPECTED_SUCCESS(ASN1_LONG_UNDEF, ASN1_LONG_UNDEF), /* t_zero */
|
|
CUSTOM_EXPECTED_SUCCESS(1, 1), /* t_one */
|
|
CUSTOM_EXPECTED_SUCCESS(-1, -1), /* t_one_neg */
|
|
CUSTOM_EXPECTED_SUCCESS(-256, -256), /* t_minus_256 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_9bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_3_pad */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_5_negpad */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_5bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_1 (too large positive) */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MAX - 1, INT32_MAX -1), /* t_4bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_3_pad (illegal padding) */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MIN, INT32_MIN), /* t_4bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_5_negpad (illegal padding) */
|
|
};
|
|
static ASN1_INT32_DATA int32_encdec_data[] = {
|
|
ENCDEC_ARRAY(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN),
|
|
};
|
|
|
|
static TEST_PACKAGE int32_test_package = {
|
|
ASN1_ITEM_ref(ASN1_INT32_DATA), "INT32", 0,
|
|
int32_expected, sizeof(int32_expected), sizeof(int32_expected[0]),
|
|
int32_encdec_data, sizeof(int32_encdec_data), sizeof(int32_encdec_data[0]),
|
|
(i2d_fn *)i2d_ASN1_INT32_DATA, (d2i_fn *)d2i_ASN1_INT32_DATA,
|
|
(ifree_fn *)ASN1_INT32_DATA_free
|
|
};
|
|
|
|
/***** UINT32 ****************************************************************/
|
|
|
|
typedef struct {
|
|
ASN1_BOOLEAN success;
|
|
uint32_t test_uint32;
|
|
uint32_t test_zuint32;
|
|
} ASN1_UINT32_DATA;
|
|
|
|
ASN1_SEQUENCE(ASN1_UINT32_DATA) = {
|
|
ASN1_SIMPLE(ASN1_UINT32_DATA, success, ASN1_FBOOLEAN),
|
|
ASN1_EMBED(ASN1_UINT32_DATA, test_uint32, UINT32),
|
|
ASN1_EXP_OPT_EMBED(ASN1_UINT32_DATA, test_zuint32, ZUINT32, 0)
|
|
} static_ASN1_SEQUENCE_END(ASN1_UINT32_DATA)
|
|
|
|
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_UINT32_DATA)
|
|
IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_UINT32_DATA)
|
|
|
|
static ASN1_UINT32_DATA uint32_expected[] = {
|
|
CUSTOM_EXPECTED_SUCCESS(0, 0), /* t_zero */
|
|
CUSTOM_EXPECTED_SUCCESS(ASN1_LONG_UNDEF, ASN1_LONG_UNDEF), /* t_zero */
|
|
CUSTOM_EXPECTED_SUCCESS(1, 1), /* t_one */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_one_neg (illegal negative value) */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_minus_256 (illegal negative value) */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_9bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_3_pad */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_5_negpad */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_5bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(0x80000000, 0x80000000), /* t_4bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MAX - 1, INT32_MAX -1), /* t_4bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_3_pad (illegal padding) */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_4_neg (illegal negative value) */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_5_negpad (illegal padding) */
|
|
};
|
|
static ASN1_UINT32_DATA uint32_encdec_data[] = {
|
|
ENCDEC_ARRAY(UINT32_MAX, UINT32_MAX, 0, 0),
|
|
};
|
|
|
|
static TEST_PACKAGE uint32_test_package = {
|
|
ASN1_ITEM_ref(ASN1_UINT32_DATA), "UINT32", 0,
|
|
uint32_expected, sizeof(uint32_expected), sizeof(uint32_expected[0]),
|
|
uint32_encdec_data, sizeof(uint32_encdec_data), sizeof(uint32_encdec_data[0]),
|
|
(i2d_fn *)i2d_ASN1_UINT32_DATA, (d2i_fn *)d2i_ASN1_UINT32_DATA,
|
|
(ifree_fn *)ASN1_UINT32_DATA_free
|
|
};
|
|
|
|
/***** INT64 *****************************************************************/
|
|
|
|
typedef struct {
|
|
ASN1_BOOLEAN success;
|
|
int64_t test_int64;
|
|
int64_t test_zint64;
|
|
} ASN1_INT64_DATA;
|
|
|
|
ASN1_SEQUENCE(ASN1_INT64_DATA) = {
|
|
ASN1_SIMPLE(ASN1_INT64_DATA, success, ASN1_FBOOLEAN),
|
|
ASN1_EMBED(ASN1_INT64_DATA, test_int64, INT64),
|
|
ASN1_EXP_OPT_EMBED(ASN1_INT64_DATA, test_zint64, ZINT64, 0)
|
|
} static_ASN1_SEQUENCE_END(ASN1_INT64_DATA)
|
|
|
|
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_INT64_DATA)
|
|
IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_INT64_DATA)
|
|
|
|
static ASN1_INT64_DATA int64_expected[] = {
|
|
CUSTOM_EXPECTED_SUCCESS(0, 0), /* t_zero */
|
|
CUSTOM_EXPECTED_SUCCESS(ASN1_LONG_UNDEF, ASN1_LONG_UNDEF), /* t_zero */
|
|
CUSTOM_EXPECTED_SUCCESS(1, 1), /* t_one */
|
|
CUSTOM_EXPECTED_SUCCESS(-1, -1), /* t_one_neg */
|
|
CUSTOM_EXPECTED_SUCCESS(-256, -256), /* t_minus_256 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_9bytes_1 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_1 (too large positive) */
|
|
CUSTOM_EXPECTED_SUCCESS(INT64_MAX, INT64_MAX), /* t_8bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_3_pad (illegal padding) */
|
|
CUSTOM_EXPECTED_SUCCESS(INT64_MIN, INT64_MIN), /* t_8bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_5_negpad (illegal padding) */
|
|
CUSTOM_EXPECTED_SUCCESS(0x1ffffffff, 0x1ffffffff), /* t_5bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(0x80000000, 0x80000000), /* t_4bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MAX - 1, INT32_MAX -1), /* t_4bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_3_pad (illegal padding) */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MIN, INT32_MIN), /* t_4bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_5_negpad (illegal padding) */
|
|
};
|
|
static ASN1_INT64_DATA int64_encdec_data[] = {
|
|
ENCDEC_ARRAY(INT64_MAX, INT64_MAX, INT64_MIN, INT64_MIN),
|
|
ENCDEC_ARRAY(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN),
|
|
};
|
|
|
|
static TEST_PACKAGE int64_test_package = {
|
|
ASN1_ITEM_ref(ASN1_INT64_DATA), "INT64", 0,
|
|
int64_expected, sizeof(int64_expected), sizeof(int64_expected[0]),
|
|
int64_encdec_data, sizeof(int64_encdec_data), sizeof(int64_encdec_data[0]),
|
|
(i2d_fn *)i2d_ASN1_INT64_DATA, (d2i_fn *)d2i_ASN1_INT64_DATA,
|
|
(ifree_fn *)ASN1_INT64_DATA_free
|
|
};
|
|
|
|
/***** UINT64 ****************************************************************/
|
|
|
|
typedef struct {
|
|
ASN1_BOOLEAN success;
|
|
uint64_t test_uint64;
|
|
uint64_t test_zuint64;
|
|
} ASN1_UINT64_DATA;
|
|
|
|
ASN1_SEQUENCE(ASN1_UINT64_DATA) = {
|
|
ASN1_SIMPLE(ASN1_UINT64_DATA, success, ASN1_FBOOLEAN),
|
|
ASN1_EMBED(ASN1_UINT64_DATA, test_uint64, UINT64),
|
|
ASN1_EXP_OPT_EMBED(ASN1_UINT64_DATA, test_zuint64, ZUINT64, 0)
|
|
} static_ASN1_SEQUENCE_END(ASN1_UINT64_DATA)
|
|
|
|
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_UINT64_DATA)
|
|
IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_UINT64_DATA)
|
|
|
|
static ASN1_UINT64_DATA uint64_expected[] = {
|
|
CUSTOM_EXPECTED_SUCCESS(0, 0), /* t_zero */
|
|
CUSTOM_EXPECTED_SUCCESS(ASN1_LONG_UNDEF, ASN1_LONG_UNDEF), /* t_zero */
|
|
CUSTOM_EXPECTED_SUCCESS(1, 1), /* t_one */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_one_neg (illegal negative value) */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_minus_256 (illegal negative value) */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_9bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS((uint64_t)INT64_MAX+1, (uint64_t)INT64_MAX+1),
|
|
/* t_8bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(INT64_MAX, INT64_MAX), /* t_8bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_3_pad */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_4_neg */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_8bytes_5_negpad */
|
|
CUSTOM_EXPECTED_SUCCESS(0x1ffffffff, 0x1ffffffff), /* t_5bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(0x80000000, 0x80000000), /* t_4bytes_1 */
|
|
CUSTOM_EXPECTED_SUCCESS(INT32_MAX - 1, INT32_MAX -1), /* t_4bytes_2 */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_3_pad (illegal padding) */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_4_neg (illegal negative value) */
|
|
CUSTOM_EXPECTED_FAILURE, /* t_4bytes_5_negpad (illegal padding) */
|
|
};
|
|
static ASN1_UINT64_DATA uint64_encdec_data[] = {
|
|
ENCDEC_ARRAY(UINT64_MAX, UINT64_MAX, 0, 0),
|
|
};
|
|
|
|
static TEST_PACKAGE uint64_test_package = {
|
|
ASN1_ITEM_ref(ASN1_UINT64_DATA), "UINT64", 0,
|
|
uint64_expected, sizeof(uint64_expected), sizeof(uint64_expected[0]),
|
|
uint64_encdec_data, sizeof(uint64_encdec_data), sizeof(uint64_encdec_data[0]),
|
|
(i2d_fn *)i2d_ASN1_UINT64_DATA, (d2i_fn *)d2i_ASN1_UINT64_DATA,
|
|
(ifree_fn *)ASN1_UINT64_DATA_free
|
|
};
|
|
|
|
/***** General testing functions *********************************************/
|
|
|
|
|
|
/* Template structure to map onto any test data structure */
|
|
typedef struct {
|
|
ASN1_BOOLEAN success;
|
|
unsigned char bytes[1]; /* In reality, there's more */
|
|
} EXPECTED;
|
|
|
|
/*
|
|
* do_decode returns a tristate:
|
|
*
|
|
* -1 Couldn't decode
|
|
* 0 decoded structure wasn't what was expected (failure)
|
|
* 1 decoded structure was what was expected (success)
|
|
*/
|
|
static int do_decode(unsigned char *bytes, long nbytes,
|
|
const EXPECTED *expected, size_t expected_size,
|
|
const TEST_PACKAGE *package)
|
|
{
|
|
EXPECTED *enctst = NULL;
|
|
const unsigned char *start;
|
|
int ret = 0;
|
|
|
|
start = bytes;
|
|
enctst = package->d2i(NULL, &bytes, nbytes);
|
|
if (enctst == NULL) {
|
|
if (expected->success == 0) {
|
|
ret = 1;
|
|
ERR_clear_error();
|
|
} else {
|
|
ret = -1;
|
|
}
|
|
} else {
|
|
if (start + nbytes == bytes
|
|
&& memcmp(enctst, expected, expected_size) == 0)
|
|
ret = 1;
|
|
else
|
|
ret = 0;
|
|
}
|
|
|
|
package->ifree(enctst);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* do_encode returns a tristate:
|
|
*
|
|
* -1 Couldn't encode
|
|
* 0 encoded DER wasn't what was expected (failure)
|
|
* 1 encoded DER was what was expected (success)
|
|
*/
|
|
static int do_encode(EXPECTED *input,
|
|
const unsigned char *expected, size_t expected_len,
|
|
const TEST_PACKAGE *package)
|
|
{
|
|
unsigned char *data = NULL;
|
|
int len;
|
|
int ret = 0;
|
|
|
|
len = package->i2d(input, &data);
|
|
if (len < 0)
|
|
return -1;
|
|
|
|
if ((size_t)len != expected_len
|
|
|| memcmp(data, expected, expected_len) != 0) {
|
|
if (input->success == 0) {
|
|
ret = 1;
|
|
ERR_clear_error();
|
|
} else {
|
|
ret = 0;
|
|
}
|
|
} else {
|
|
ret = 1;
|
|
}
|
|
|
|
OPENSSL_free(data);
|
|
return ret;
|
|
}
|
|
|
|
/* Do an encode/decode round trip */
|
|
static int do_enc_dec(EXPECTED *bytes, long nbytes,
|
|
const TEST_PACKAGE *package)
|
|
{
|
|
unsigned char *data = NULL;
|
|
int len;
|
|
int ret = 0;
|
|
void *p = bytes;
|
|
|
|
len = package->i2d(p, &data);
|
|
if (len < 0)
|
|
return -1;
|
|
|
|
ret = do_decode(data, len, bytes, nbytes, package);
|
|
OPENSSL_free(data);
|
|
return ret;
|
|
}
|
|
|
|
static size_t der_encode_length(size_t len, unsigned char **pp)
|
|
{
|
|
size_t lenbytes;
|
|
|
|
OPENSSL_assert(len < 0x8000);
|
|
if (len > 255)
|
|
lenbytes = 3;
|
|
else if (len > 127)
|
|
lenbytes = 2;
|
|
else
|
|
lenbytes = 1;
|
|
|
|
if (pp != NULL) {
|
|
if (lenbytes == 1) {
|
|
*(*pp)++ = (unsigned char)len;
|
|
} else {
|
|
*(*pp)++ = (unsigned char)(lenbytes - 1);
|
|
if (lenbytes == 2) {
|
|
*(*pp)++ = (unsigned char)(0x80 | len);
|
|
} else {
|
|
*(*pp)++ = (unsigned char)(0x80 | (len >> 8));
|
|
*(*pp)++ = (unsigned char)(len);
|
|
}
|
|
}
|
|
}
|
|
return lenbytes;
|
|
}
|
|
|
|
static size_t make_custom_der(const TEST_CUSTOM_DATA *custom_data,
|
|
unsigned char **encoding, int explicit_default)
|
|
{
|
|
size_t firstbytes, secondbytes = 0, secondbytesinner = 0, seqbytes;
|
|
const unsigned char t_true[] = { V_ASN1_BOOLEAN, 0x01, 0xff };
|
|
unsigned char *p = NULL;
|
|
size_t i;
|
|
|
|
/*
|
|
* The first item is just an INTEGER tag, INTEGER length and INTEGER content
|
|
*/
|
|
firstbytes =
|
|
1 + der_encode_length(custom_data->nbytes1, NULL)
|
|
+ custom_data->nbytes1;
|
|
|
|
for (i = custom_data->nbytes2; i > 0; i--) {
|
|
if (custom_data->bytes2[i - 1] != '\0')
|
|
break;
|
|
}
|
|
if (explicit_default || i > 0) {
|
|
/*
|
|
* The second item is an explicit tag, content length, INTEGER tag,
|
|
* INTEGER length, INTEGER bytes
|
|
*/
|
|
secondbytesinner =
|
|
1 + der_encode_length(custom_data->nbytes2, NULL)
|
|
+ custom_data->nbytes2;
|
|
secondbytes =
|
|
1 + der_encode_length(secondbytesinner, NULL) + secondbytesinner;
|
|
}
|
|
|
|
/*
|
|
* The whole sequence is the sequence tag, content length, BOOLEAN true
|
|
* (copied from t_true), the first (firstbytes) and second (secondbytes)
|
|
* items
|
|
*/
|
|
seqbytes =
|
|
1 + der_encode_length(sizeof(t_true) + firstbytes + secondbytes, NULL)
|
|
+ sizeof(t_true) + firstbytes + secondbytes;
|
|
|
|
*encoding = p = OPENSSL_malloc(seqbytes);
|
|
if (*encoding == NULL)
|
|
return 0;
|
|
|
|
/* Sequence tag */
|
|
*p++ = 0x30;
|
|
der_encode_length(sizeof(t_true) + firstbytes + secondbytes, &p);
|
|
|
|
/* ASN1_BOOLEAN TRUE */
|
|
memcpy(p, t_true, sizeof(t_true)); /* Marks decoding success */
|
|
p += sizeof(t_true);
|
|
|
|
/* First INTEGER item (non-optional) */
|
|
*p++ = V_ASN1_INTEGER;
|
|
der_encode_length(custom_data->nbytes1, &p);
|
|
memcpy(p, custom_data->bytes1, custom_data->nbytes1);
|
|
p += custom_data->nbytes1;
|
|
|
|
if (secondbytes > 0) {
|
|
/* Second INTEGER item (optional) */
|
|
/* Start with the explicit optional tag */
|
|
*p++ = 0xa0;
|
|
der_encode_length(secondbytesinner, &p);
|
|
*p++ = V_ASN1_INTEGER;
|
|
der_encode_length(custom_data->nbytes2, &p);
|
|
memcpy(p, custom_data->bytes2, custom_data->nbytes2);
|
|
p += custom_data->nbytes2;
|
|
}
|
|
|
|
OPENSSL_assert(seqbytes == (size_t)(p - *encoding));
|
|
|
|
return seqbytes;
|
|
}
|
|
|
|
/* Attempt to decode a custom encoding of the test structure */
|
|
static int do_decode_custom(const TEST_CUSTOM_DATA *custom_data,
|
|
const EXPECTED *expected, size_t expected_size,
|
|
const TEST_PACKAGE *package)
|
|
{
|
|
unsigned char *encoding = NULL;
|
|
/*
|
|
* We force the defaults to be explicitly encoded to make sure we test
|
|
* for defaults that shouldn't be present (i.e. we check for failure)
|
|
*/
|
|
size_t encoding_length = make_custom_der(custom_data, &encoding, 1);
|
|
int ret;
|
|
|
|
if (encoding_length == 0)
|
|
return -1;
|
|
|
|
ret = do_decode(encoding, encoding_length, expected, expected_size,
|
|
package);
|
|
OPENSSL_free(encoding);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Attempt to encode the test structure and compare it to custom DER */
|
|
static int do_encode_custom(EXPECTED *input,
|
|
const TEST_CUSTOM_DATA *custom_data,
|
|
const TEST_PACKAGE *package)
|
|
{
|
|
unsigned char *expected = NULL;
|
|
size_t expected_length = make_custom_der(custom_data, &expected, 0);
|
|
int ret;
|
|
|
|
if (expected_length == 0)
|
|
return -1;
|
|
|
|
ret = do_encode(input, expected, expected_length, package);
|
|
OPENSSL_free(expected);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int do_print_item(const TEST_PACKAGE *package)
|
|
{
|
|
#define DATA_BUF_SIZE 256
|
|
const ASN1_ITEM *i = ASN1_ITEM_ptr(package->asn1_type);
|
|
ASN1_VALUE *o;
|
|
int ret;
|
|
|
|
OPENSSL_assert(package->encode_expectations_elem_size <= DATA_BUF_SIZE);
|
|
if ((o = OPENSSL_malloc(DATA_BUF_SIZE)) == NULL)
|
|
return 0;
|
|
|
|
(void)RAND_bytes((unsigned char*)o,
|
|
(int)package->encode_expectations_elem_size);
|
|
ret = ASN1_item_print(bio_err, o, 0, i, NULL);
|
|
OPENSSL_free(o);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int test_intern(const TEST_PACKAGE *package)
|
|
{
|
|
unsigned int i;
|
|
size_t nelems;
|
|
int fail = 0;
|
|
|
|
if (package->skip)
|
|
return 1;
|
|
|
|
/* Do decode_custom checks */
|
|
nelems = package->encode_expectations_size
|
|
/ package->encode_expectations_elem_size;
|
|
OPENSSL_assert(nelems ==
|
|
sizeof(test_custom_data) / sizeof(test_custom_data[0]));
|
|
for (i = 0; i < nelems; i++) {
|
|
size_t pos = i * package->encode_expectations_elem_size;
|
|
switch (do_encode_custom((EXPECTED *)&((unsigned char *)package
|
|
->encode_expectations)[pos],
|
|
&test_custom_data[i], package)) {
|
|
case -1:
|
|
TEST_error("Failed custom encode round trip %u of %s",
|
|
i, package->name);
|
|
TEST_openssl_errors();
|
|
fail++;
|
|
break;
|
|
case 0:
|
|
TEST_error("Custom encode round trip %u of %s mismatch",
|
|
i, package->name);
|
|
TEST_openssl_errors();
|
|
fail++;
|
|
break;
|
|
case 1:
|
|
break;
|
|
default:
|
|
OPENSSL_die("do_encode_custom() return unknown value",
|
|
__FILE__, __LINE__);
|
|
}
|
|
switch (do_decode_custom(&test_custom_data[i],
|
|
(EXPECTED *)&((unsigned char *)package
|
|
->encode_expectations)[pos],
|
|
package->encode_expectations_elem_size,
|
|
package)) {
|
|
case -1:
|
|
TEST_error("Failed custom decode round trip %u of %s",
|
|
i, package->name);
|
|
TEST_openssl_errors();
|
|
fail++;
|
|
break;
|
|
case 0:
|
|
TEST_error("Custom decode round trip %u of %s mismatch",
|
|
i, package->name);
|
|
TEST_openssl_errors();
|
|
fail++;
|
|
break;
|
|
case 1:
|
|
break;
|
|
default:
|
|
OPENSSL_die("do_decode_custom() return unknown value",
|
|
__FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
/* Do enc_dec checks */
|
|
nelems = package->encdec_data_size / package->encdec_data_elem_size;
|
|
for (i = 0; i < nelems; i++) {
|
|
size_t pos = i * package->encdec_data_elem_size;
|
|
switch (do_enc_dec((EXPECTED *)&((unsigned char *)package
|
|
->encdec_data)[pos],
|
|
package->encdec_data_elem_size,
|
|
package)) {
|
|
case -1:
|
|
TEST_error("Failed encode/decode round trip %u of %s",
|
|
i, package->name);
|
|
TEST_openssl_errors();
|
|
fail++;
|
|
break;
|
|
case 0:
|
|
TEST_error("Encode/decode round trip %u of %s mismatch",
|
|
i, package->name);
|
|
fail++;
|
|
break;
|
|
case 1:
|
|
break;
|
|
default:
|
|
OPENSSL_die("do_enc_dec() return unknown value",
|
|
__FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
if (!do_print_item(package)) {
|
|
TEST_error("Printing of %s failed", package->name);
|
|
TEST_openssl_errors();
|
|
fail++;
|
|
}
|
|
|
|
return fail == 0;
|
|
}
|
|
|
|
#if !OPENSSL_API_3
|
|
static int test_long_32bit(void)
|
|
{
|
|
return test_intern(&long_test_package_32bit);
|
|
}
|
|
|
|
static int test_long_64bit(void)
|
|
{
|
|
return test_intern(&long_test_package_64bit);
|
|
}
|
|
#endif
|
|
|
|
static int test_int32(void)
|
|
{
|
|
return test_intern(&int32_test_package);
|
|
}
|
|
|
|
static int test_uint32(void)
|
|
{
|
|
return test_intern(&uint32_test_package);
|
|
}
|
|
|
|
static int test_int64(void)
|
|
{
|
|
return test_intern(&int64_test_package);
|
|
}
|
|
|
|
static int test_uint64(void)
|
|
{
|
|
return test_intern(&uint64_test_package);
|
|
}
|
|
|
|
int setup_tests(void)
|
|
{
|
|
#if !OPENSSL_API_3
|
|
ADD_TEST(test_long_32bit);
|
|
ADD_TEST(test_long_64bit);
|
|
#endif
|
|
ADD_TEST(test_int32);
|
|
ADD_TEST(test_uint32);
|
|
ADD_TEST(test_int64);
|
|
ADD_TEST(test_uint64);
|
|
return 1;
|
|
}
|