Squashed 'lib/mbedtls/external/mbedtls/' content from commit 2ca6c285a0dd
git-subtree-dir: lib/mbedtls/external/mbedtls
git-subtree-split: 2ca6c285a0dd3f33982dd57299012dacab1ff206
diff --git a/tests/suites/test_suite_asn1parse.function b/tests/suites/test_suite_asn1parse.function
new file mode 100644
index 0000000..01a091b
--- /dev/null
+++ b/tests/suites/test_suite_asn1parse.function
@@ -0,0 +1,774 @@
+/* BEGIN_HEADER */
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "mbedtls/bignum.h"
+#include "mbedtls/asn1.h"
+#if defined(MBEDTLS_ASN1_WRITE_C)
+#include "mbedtls/asn1write.h"
+#endif
+
+/* Used internally to report an error that indicates a bug in a parsing function. */
+#define ERR_PARSE_INCONSISTENCY INT_MAX
+
+/* Use this magic value in some tests to indicate that the expected result
+ * should not be checked. */
+#define UNPREDICTABLE_RESULT 0x5552
+
+static int nested_parse(unsigned char **const p,
+ const unsigned char *const end)
+{
+ int ret;
+ size_t len = 0;
+ size_t len2 = 0;
+ unsigned char *const start = *p;
+ unsigned char *content_start;
+ unsigned char tag;
+
+ /* First get the length, skipping over the tag. */
+ content_start = start + 1;
+ ret = mbedtls_asn1_get_len(&content_start, end, &len);
+ TEST_ASSERT(content_start <= end);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Since we have a valid element start (tag and length), retrieve and
+ * check the tag. */
+ tag = start[0];
+ TEST_EQUAL(mbedtls_asn1_get_tag(p, end, &len2, tag ^ 1),
+ MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+ *p = start;
+ TEST_EQUAL(mbedtls_asn1_get_tag(p, end, &len2, tag), 0);
+ TEST_EQUAL(len, len2);
+ TEST_ASSERT(*p == content_start);
+ *p = content_start;
+
+ switch (tag & 0x1f) {
+ case MBEDTLS_ASN1_BOOLEAN:
+ {
+ int val = -257;
+ *p = start;
+ ret = mbedtls_asn1_get_bool(p, end, &val);
+ if (ret == 0) {
+ TEST_ASSERT(val == 0 || val == 1);
+ }
+ break;
+ }
+
+ case MBEDTLS_ASN1_INTEGER:
+ {
+#if defined(MBEDTLS_BIGNUM_C)
+ mbedtls_mpi mpi;
+ mbedtls_mpi_init(&mpi);
+ *p = start;
+ ret = mbedtls_asn1_get_mpi(p, end, &mpi);
+ mbedtls_mpi_free(&mpi);
+#else
+ *p = start + 1;
+ ret = mbedtls_asn1_get_len(p, end, &len);
+ *p += len;
+#endif
+ /* If we're sure that the number fits in an int, also
+ * call mbedtls_asn1_get_int(). */
+ if (ret == 0 && len < sizeof(int)) {
+ int val = -257;
+ unsigned char *q = start;
+ ret = mbedtls_asn1_get_int(&q, end, &val);
+ TEST_ASSERT(*p == q);
+ }
+ break;
+ }
+
+ case MBEDTLS_ASN1_BIT_STRING:
+ {
+ mbedtls_asn1_bitstring bs;
+ *p = start;
+ ret = mbedtls_asn1_get_bitstring(p, end, &bs);
+ break;
+ }
+
+ case MBEDTLS_ASN1_SEQUENCE:
+ {
+ while (*p <= end && *p < content_start + len && ret == 0) {
+ ret = nested_parse(p, content_start + len);
+ }
+ break;
+ }
+
+ case MBEDTLS_ASN1_OCTET_STRING:
+ case MBEDTLS_ASN1_NULL:
+ case MBEDTLS_ASN1_OID:
+ case MBEDTLS_ASN1_UTF8_STRING:
+ case MBEDTLS_ASN1_SET:
+ case MBEDTLS_ASN1_PRINTABLE_STRING:
+ case MBEDTLS_ASN1_T61_STRING:
+ case MBEDTLS_ASN1_IA5_STRING:
+ case MBEDTLS_ASN1_UTC_TIME:
+ case MBEDTLS_ASN1_GENERALIZED_TIME:
+ case MBEDTLS_ASN1_UNIVERSAL_STRING:
+ case MBEDTLS_ASN1_BMP_STRING:
+ default:
+ /* No further testing implemented for this tag. */
+ *p += len;
+ return 0;
+ }
+
+ TEST_ASSERT(*p <= end);
+ return ret;
+
+exit:
+ return ERR_PARSE_INCONSISTENCY;
+}
+
+int get_len_step(const data_t *input, size_t buffer_size,
+ size_t actual_length)
+{
+ unsigned char *buf = NULL;
+ unsigned char *p = NULL;
+ unsigned char *end;
+ size_t parsed_length;
+ int ret;
+
+ mbedtls_test_set_step(buffer_size);
+ /* Allocate a new buffer of exactly the length to parse each time.
+ * This gives memory sanitizers a chance to catch buffer overreads. */
+ if (buffer_size == 0) {
+ TEST_CALLOC(buf, 1);
+ end = buf + 1;
+ p = end;
+ } else {
+ TEST_CALLOC_OR_SKIP(buf, buffer_size);
+ if (buffer_size > input->len) {
+ memcpy(buf, input->x, input->len);
+ memset(buf + input->len, 'A', buffer_size - input->len);
+ } else {
+ memcpy(buf, input->x, buffer_size);
+ }
+ p = buf;
+ end = buf + buffer_size;
+ }
+
+ ret = mbedtls_asn1_get_len(&p, end, &parsed_length);
+
+ if (buffer_size >= input->len + actual_length) {
+ TEST_EQUAL(ret, 0);
+ TEST_ASSERT(p == buf + input->len);
+ TEST_EQUAL(parsed_length, actual_length);
+ } else {
+ TEST_EQUAL(ret, MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+ }
+ mbedtls_free(buf);
+ return 1;
+
+exit:
+ mbedtls_free(buf);
+ return 0;
+}
+
+typedef struct {
+ const unsigned char *input_start;
+ const char *description;
+} traverse_state_t;
+
+/* Value returned by traverse_callback if description runs out. */
+#define RET_TRAVERSE_STOP 1
+/* Value returned by traverse_callback if description has an invalid format
+ * (see traverse_sequence_of). */
+#define RET_TRAVERSE_ERROR 2
+
+
+static int traverse_callback(void *ctx, int tag,
+ unsigned char *content, size_t len)
+{
+ traverse_state_t *state = ctx;
+ size_t offset;
+ const char *rest = state->description;
+ unsigned long n;
+
+ TEST_ASSERT(content > state->input_start);
+ offset = content - state->input_start;
+ mbedtls_test_set_step(offset);
+
+ if (*rest == 0) {
+ return RET_TRAVERSE_STOP;
+ }
+ n = strtoul(rest, (char **) &rest, 0);
+ TEST_EQUAL(n, offset);
+ TEST_EQUAL(*rest, ',');
+ ++rest;
+ n = strtoul(rest, (char **) &rest, 0);
+ TEST_EQUAL(n, (unsigned) tag);
+ TEST_EQUAL(*rest, ',');
+ ++rest;
+ n = strtoul(rest, (char **) &rest, 0);
+ TEST_EQUAL(n, len);
+ if (*rest == ',') {
+ ++rest;
+ }
+
+ state->description = rest;
+ return 0;
+
+exit:
+ return RET_TRAVERSE_ERROR;
+}
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_ASN1_PARSE_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void parse_prefixes(const data_t *input,
+ int full_result,
+ int overfull_result)
+{
+ /* full_result: expected result from parsing the given string. */
+ /* overfull_result: expected_result from parsing the given string plus
+ * some trailing garbage. This may be UNPREDICTABLE_RESULT to accept
+ * any result: use this for invalid inputs that may or may not become
+ * valid depending on what the trailing garbage is. */
+
+ unsigned char *buf = NULL;
+ unsigned char *p = NULL;
+ size_t buffer_size;
+ int ret;
+
+ /* Test every prefix of the input, except the empty string.
+ * The first byte of the string is the tag. Without a tag byte,
+ * we wouldn't know what to parse the input as.
+ * Also test the input followed by an extra byte.
+ */
+ for (buffer_size = 1; buffer_size <= input->len + 1; buffer_size++) {
+ mbedtls_test_set_step(buffer_size);
+ /* Allocate a new buffer of exactly the length to parse each time.
+ * This gives memory sanitizers a chance to catch buffer overreads. */
+ TEST_CALLOC(buf, buffer_size);
+ memcpy(buf, input->x, buffer_size);
+ p = buf;
+ ret = nested_parse(&p, buf + buffer_size);
+
+ if (ret == ERR_PARSE_INCONSISTENCY) {
+ goto exit;
+ }
+ if (buffer_size < input->len) {
+ TEST_EQUAL(ret, MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+ } else if (buffer_size == input->len) {
+ TEST_EQUAL(ret, full_result);
+ } else { /* ( buffer_size > input->len ) */
+ if (overfull_result != UNPREDICTABLE_RESULT) {
+ TEST_EQUAL(ret, overfull_result);
+ }
+ }
+ if (ret == 0) {
+ TEST_ASSERT(p == buf + input->len);
+ }
+
+ mbedtls_free(buf);
+ buf = NULL;
+ }
+
+exit:
+ mbedtls_free(buf);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_len(const data_t *input, int actual_length_arg)
+{
+ size_t actual_length = actual_length_arg;
+ size_t buffer_size;
+
+ /* Test prefixes of a buffer containing the given length string
+ * followed by `actual_length` bytes of payload. To save a bit of
+ * time, we skip some "boring" prefixes: we don't test prefixes where
+ * the payload is truncated more than one byte away from either end,
+ * and we only test the empty string on a 1-byte input.
+ */
+ for (buffer_size = 1; buffer_size <= input->len + 1; buffer_size++) {
+ if (!get_len_step(input, buffer_size, actual_length)) {
+ goto exit;
+ }
+ }
+ if (!get_len_step(input, input->len + actual_length - 1, actual_length)) {
+ goto exit;
+ }
+ if (!get_len_step(input, input->len + actual_length, actual_length)) {
+ goto exit;
+ }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_boolean(const data_t *input,
+ int expected_value, int expected_result)
+{
+ unsigned char *p = input->x;
+ int val;
+ int ret;
+ ret = mbedtls_asn1_get_bool(&p, input->x + input->len, &val);
+ TEST_EQUAL(ret, expected_result);
+ if (expected_result == 0) {
+ TEST_EQUAL(val, expected_value);
+ TEST_ASSERT(p == input->x + input->len);
+ }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void empty_integer(const data_t *input)
+{
+ unsigned char *p;
+#if defined(MBEDTLS_BIGNUM_C)
+ mbedtls_mpi actual_mpi;
+#endif
+ int val;
+
+#if defined(MBEDTLS_BIGNUM_C)
+ mbedtls_mpi_init(&actual_mpi);
+#endif
+
+ /* An INTEGER with no content is not valid. */
+ p = input->x;
+ TEST_EQUAL(mbedtls_asn1_get_int(&p, input->x + input->len, &val),
+ MBEDTLS_ERR_ASN1_INVALID_LENGTH);
+
+#if defined(MBEDTLS_BIGNUM_C)
+ /* INTEGERs are sometimes abused as bitstrings, so the library accepts
+ * an INTEGER with empty content and gives it the value 0. */
+ p = input->x;
+ TEST_EQUAL(mbedtls_asn1_get_mpi(&p, input->x + input->len, &actual_mpi),
+ 0);
+ TEST_EQUAL(mbedtls_mpi_cmp_int(&actual_mpi, 0), 0);
+#endif
+
+exit:
+#if defined(MBEDTLS_BIGNUM_C)
+ mbedtls_mpi_free(&actual_mpi);
+#endif
+ /*empty cleanup in some configurations*/;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_integer(const data_t *input,
+ const char *expected_hex, int expected_result)
+{
+ unsigned char *p;
+#if defined(MBEDTLS_BIGNUM_C)
+ mbedtls_mpi expected_mpi;
+ mbedtls_mpi actual_mpi;
+ mbedtls_mpi complement;
+ int expected_result_for_mpi = expected_result;
+#endif
+ long expected_value;
+ int expected_result_for_int = expected_result;
+ int val;
+ int ret;
+
+#if defined(MBEDTLS_BIGNUM_C)
+ mbedtls_mpi_init(&expected_mpi);
+ mbedtls_mpi_init(&actual_mpi);
+ mbedtls_mpi_init(&complement);
+#endif
+
+ errno = 0;
+ expected_value = strtol(expected_hex, NULL, 16);
+ if (expected_result == 0 &&
+ (errno == ERANGE
+#if LONG_MAX > INT_MAX
+ || expected_value > INT_MAX || expected_value < INT_MIN
+#endif
+ )) {
+ /* The library returns the dubious error code INVALID_LENGTH
+ * for integers that are out of range. */
+ expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+ }
+ if (expected_result == 0 && expected_value < 0) {
+ /* The library does not support negative INTEGERs and
+ * returns the dubious error code INVALID_LENGTH.
+ * Test that we preserve the historical behavior. If we
+ * decide to change the behavior, we'll also change this test. */
+ expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+ }
+
+ p = input->x;
+ ret = mbedtls_asn1_get_int(&p, input->x + input->len, &val);
+ TEST_EQUAL(ret, expected_result_for_int);
+ if (ret == 0) {
+ TEST_EQUAL(val, expected_value);
+ TEST_ASSERT(p == input->x + input->len);
+ }
+
+#if defined(MBEDTLS_BIGNUM_C)
+ ret = mbedtls_test_read_mpi(&expected_mpi, expected_hex);
+ TEST_ASSERT(ret == 0 || ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
+ if (ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA) {
+ /* The data overflows the maximum MPI size. */
+ expected_result_for_mpi = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+ }
+ p = input->x;
+ ret = mbedtls_asn1_get_mpi(&p, input->x + input->len, &actual_mpi);
+ TEST_EQUAL(ret, expected_result_for_mpi);
+ if (ret == 0) {
+ if (expected_value >= 0) {
+ TEST_ASSERT(mbedtls_mpi_cmp_mpi(&actual_mpi,
+ &expected_mpi) == 0);
+ } else {
+ /* The library ignores the sign bit in ASN.1 INTEGERs
+ * (which makes sense insofar as INTEGERs are sometimes
+ * abused as bit strings), so the result of parsing them
+ * is a positive integer such that expected_mpi +
+ * actual_mpi = 2^n where n is the length of the content
+ * of the INTEGER. (Leading ff octets don't matter for the
+ * expected value, but they matter for the actual value.)
+ * Test that we don't change from this behavior. If we
+ * decide to fix the library to change the behavior on
+ * negative INTEGERs, we'll fix this test code. */
+ unsigned char *q = input->x + 1;
+ size_t len;
+ TEST_ASSERT(mbedtls_asn1_get_len(&q, input->x + input->len,
+ &len) == 0);
+ TEST_ASSERT(mbedtls_mpi_lset(&complement, 1) == 0);
+ TEST_ASSERT(mbedtls_mpi_shift_l(&complement, len * 8) == 0);
+ TEST_ASSERT(mbedtls_mpi_add_mpi(&complement, &complement,
+ &expected_mpi) == 0);
+ TEST_ASSERT(mbedtls_mpi_cmp_mpi(&complement,
+ &actual_mpi) == 0);
+ }
+ TEST_ASSERT(p == input->x + input->len);
+ }
+#endif
+
+exit:
+#if defined(MBEDTLS_BIGNUM_C)
+ mbedtls_mpi_free(&expected_mpi);
+ mbedtls_mpi_free(&actual_mpi);
+ mbedtls_mpi_free(&complement);
+#endif
+ /*empty cleanup in some configurations*/;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_enum(const data_t *input,
+ const char *expected_hex, int expected_result)
+{
+ unsigned char *p;
+ long expected_value;
+ int expected_result_for_enum = expected_result;
+ int val;
+ int ret;
+
+ errno = 0;
+ expected_value = strtol(expected_hex, NULL, 16);
+ if (expected_result == 0 &&
+ (errno == ERANGE
+#if LONG_MAX > INT_MAX
+ || expected_value > INT_MAX || expected_value < INT_MIN
+#endif
+ )) {
+ /* The library returns the dubious error code INVALID_LENGTH
+ * for integers that are out of range. */
+ expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+ }
+ if (expected_result == 0 && expected_value < 0) {
+ /* The library does not support negative INTEGERs and
+ * returns the dubious error code INVALID_LENGTH.
+ * Test that we preserve the historical behavior. If we
+ * decide to change the behavior, we'll also change this test. */
+ expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+ }
+
+ p = input->x;
+ ret = mbedtls_asn1_get_enum(&p, input->x + input->len, &val);
+ TEST_EQUAL(ret, expected_result_for_enum);
+ if (ret == 0) {
+ TEST_EQUAL(val, expected_value);
+ TEST_ASSERT(p == input->x + input->len);
+ }
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
+void get_mpi_too_large()
+{
+ unsigned char *buf = NULL;
+ unsigned char *p;
+ mbedtls_mpi actual_mpi;
+ size_t too_many_octets =
+ MBEDTLS_MPI_MAX_LIMBS * sizeof(mbedtls_mpi_uint) + 1;
+ size_t size = too_many_octets + 6;
+
+ mbedtls_mpi_init(&actual_mpi);
+
+ TEST_CALLOC(buf, size);
+ buf[0] = 0x02; /* tag: INTEGER */
+ buf[1] = 0x84; /* 4-octet length */
+ buf[2] = (too_many_octets >> 24) & 0xff;
+ buf[3] = (too_many_octets >> 16) & 0xff;
+ buf[4] = (too_many_octets >> 8) & 0xff;
+ buf[5] = too_many_octets & 0xff;
+ buf[6] = 0x01; /* most significant octet */
+
+ p = buf;
+ TEST_EQUAL(mbedtls_asn1_get_mpi(&p, buf + size, &actual_mpi),
+ MBEDTLS_ERR_MPI_ALLOC_FAILED);
+
+exit:
+ mbedtls_mpi_free(&actual_mpi);
+ mbedtls_free(buf);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_bitstring(const data_t *input,
+ int expected_length, int expected_unused_bits,
+ int expected_result, int expected_result_null)
+{
+ mbedtls_asn1_bitstring bs = { 0xdead, 0x21, NULL };
+ unsigned char *p = input->x;
+
+ TEST_EQUAL(mbedtls_asn1_get_bitstring(&p, input->x + input->len, &bs),
+ expected_result);
+ if (expected_result == 0) {
+ TEST_EQUAL(bs.len, (size_t) expected_length);
+ TEST_EQUAL(bs.unused_bits, expected_unused_bits);
+ TEST_ASSERT(bs.p != NULL);
+ TEST_EQUAL(bs.p - input->x + bs.len, input->len);
+ TEST_ASSERT(p == input->x + input->len);
+ }
+
+ p = input->x;
+ TEST_EQUAL(mbedtls_asn1_get_bitstring_null(&p, input->x + input->len,
+ &bs.len),
+ expected_result_null);
+ if (expected_result_null == 0) {
+ TEST_EQUAL(bs.len, (size_t) expected_length);
+ if (expected_result == 0) {
+ TEST_ASSERT(p == input->x + input->len - bs.len);
+ }
+ }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_sequence_of(const data_t *input, int tag,
+ const char *description,
+ int expected_result)
+{
+ /* The description string is a comma-separated list of integers.
+ * For each element in the SEQUENCE in input, description contains
+ * two integers: the offset of the element (offset from the start
+ * of input to the tag of the element) and the length of the
+ * element's contents.
+ * "offset1,length1,..." */
+
+ mbedtls_asn1_sequence head = { { 0, 0, NULL }, NULL };
+ mbedtls_asn1_sequence *cur;
+ unsigned char *p = input->x;
+ const char *rest = description;
+ unsigned long n;
+ unsigned int step = 0;
+
+ TEST_EQUAL(mbedtls_asn1_get_sequence_of(&p, input->x + input->len,
+ &head, tag),
+ expected_result);
+ if (expected_result == 0) {
+ TEST_ASSERT(p == input->x + input->len);
+
+ if (!*rest) {
+ TEST_EQUAL(head.buf.tag, 0);
+ TEST_ASSERT(head.buf.p == NULL);
+ TEST_EQUAL(head.buf.len, 0);
+ TEST_ASSERT(head.next == NULL);
+ } else {
+ cur = &head;
+ while (*rest) {
+ mbedtls_test_set_step(step);
+ TEST_ASSERT(cur != NULL);
+ TEST_EQUAL(cur->buf.tag, tag);
+ n = strtoul(rest, (char **) &rest, 0);
+ TEST_EQUAL(n, (size_t) (cur->buf.p - input->x));
+ ++rest;
+ n = strtoul(rest, (char **) &rest, 0);
+ TEST_EQUAL(n, cur->buf.len);
+ if (*rest) {
+ ++rest;
+ }
+ cur = cur->next;
+ ++step;
+ }
+ TEST_ASSERT(cur == NULL);
+ }
+ }
+
+exit:
+ mbedtls_asn1_sequence_free(head.next);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void traverse_sequence_of(const data_t *input,
+ int tag_must_mask, int tag_must_val,
+ int tag_may_mask, int tag_may_val,
+ const char *description,
+ int expected_result)
+{
+ /* The description string is a comma-separated list of integers.
+ * For each element in the SEQUENCE in input, description contains
+ * three integers: the offset of the element's content (offset from
+ * the start of input to the content of the element), the element's tag,
+ * and the length of the element's contents.
+ * "offset1,tag1,length1,..." */
+
+ unsigned char *p = input->x;
+ traverse_state_t traverse_state = { input->x, description };
+ int ret;
+
+ ret = mbedtls_asn1_traverse_sequence_of(&p, input->x + input->len,
+ (uint8_t) tag_must_mask, (uint8_t) tag_must_val,
+ (uint8_t) tag_may_mask, (uint8_t) tag_may_val,
+ traverse_callback, &traverse_state);
+ if (ret == RET_TRAVERSE_ERROR) {
+ goto exit;
+ }
+ TEST_EQUAL(ret, expected_result);
+ TEST_EQUAL(*traverse_state.description, 0);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_alg(const data_t *input,
+ int oid_offset, int oid_length,
+ int params_tag, int params_offset, int params_length,
+ int total_length,
+ int expected_result)
+{
+ mbedtls_asn1_buf oid = { -1, 0, NULL };
+ mbedtls_asn1_buf params = { -1, 0, NULL };
+ unsigned char *p = input->x;
+ int ret;
+
+ TEST_EQUAL(mbedtls_asn1_get_alg(&p, input->x + input->len,
+ &oid, ¶ms),
+ expected_result);
+ if (expected_result == 0) {
+ TEST_EQUAL(oid.tag, MBEDTLS_ASN1_OID);
+ TEST_EQUAL(oid.p - input->x, oid_offset);
+ TEST_EQUAL(oid.len, (size_t) oid_length);
+ TEST_EQUAL(params.tag, params_tag);
+ if (params_offset != 0) {
+ TEST_EQUAL(params.p - input->x, params_offset);
+ } else {
+ TEST_ASSERT(params.p == NULL);
+ }
+ TEST_EQUAL(params.len, (size_t) params_length);
+ TEST_EQUAL(p - input->x, total_length);
+ }
+
+ ret = mbedtls_asn1_get_alg_null(&p, input->x + input->len, &oid);
+ if (expected_result == 0 && params_offset == 0) {
+ TEST_EQUAL(oid.tag, MBEDTLS_ASN1_OID);
+ TEST_EQUAL(oid.p - input->x, oid_offset);
+ TEST_EQUAL(oid.len, (size_t) oid_length);
+ TEST_EQUAL(p - input->x, total_length);
+ } else {
+ TEST_ASSERT(ret != 0);
+ }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void find_named_data(data_t *oid0, data_t *oid1, data_t *oid2, data_t *oid3,
+ data_t *needle, int from, int position)
+{
+ mbedtls_asn1_named_data nd[] = {
+ { { 0x06, oid0->len, oid0->x }, { 0, 0, NULL }, NULL, 0 },
+ { { 0x06, oid1->len, oid1->x }, { 0, 0, NULL }, NULL, 0 },
+ { { 0x06, oid2->len, oid2->x }, { 0, 0, NULL }, NULL, 0 },
+ { { 0x06, oid3->len, oid3->x }, { 0, 0, NULL }, NULL, 0 },
+ };
+ mbedtls_asn1_named_data *pointers[ARRAY_LENGTH(nd) + 1];
+ size_t i;
+ const mbedtls_asn1_named_data *found;
+
+ for (i = 0; i < ARRAY_LENGTH(nd); i++) {
+ pointers[i] = &nd[i];
+ }
+ pointers[ARRAY_LENGTH(nd)] = NULL;
+ for (i = 0; i < ARRAY_LENGTH(nd); i++) {
+ nd[i].next = pointers[i+1];
+ }
+
+ found = mbedtls_asn1_find_named_data((const mbedtls_asn1_named_data *) pointers[from],
+ (const char *) needle->x,
+ needle->len);
+ TEST_ASSERT(found == pointers[position]);
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:!MBEDTLS_DEPRECATED_REMOVED:!MBEDTLS_DEPRECATED_WARNING */
+void free_named_data_null()
+{
+ mbedtls_asn1_free_named_data(NULL);
+ goto exit; /* Silence unused label warning */
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:!MBEDTLS_DEPRECATED_REMOVED:!MBEDTLS_DEPRECATED_WARNING */
+void free_named_data(int with_oid, int with_val, int with_next)
+{
+ mbedtls_asn1_named_data next =
+ { { 0x06, 0, NULL }, { 0, 0xcafe, NULL }, NULL, 0 };
+ mbedtls_asn1_named_data head =
+ { { 0x06, 0, NULL }, { 0, 0, NULL }, NULL, 0 };
+
+ if (with_oid) {
+ TEST_CALLOC(head.oid.p, 1);
+ }
+ if (with_val) {
+ TEST_CALLOC(head.val.p, 1);
+ }
+ if (with_next) {
+ head.next = &next;
+ }
+
+ mbedtls_asn1_free_named_data(&head);
+ TEST_ASSERT(head.oid.p == NULL);
+ TEST_ASSERT(head.val.p == NULL);
+ TEST_ASSERT(head.next == NULL);
+ TEST_ASSERT(next.val.len == 0xcafe);
+
+exit:
+ mbedtls_free(head.oid.p);
+ mbedtls_free(head.val.p);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void free_named_data_list(int length)
+{
+ mbedtls_asn1_named_data *head = NULL;
+ int i;
+
+ for (i = 0; i < length; i++) {
+ mbedtls_asn1_named_data *new = NULL;
+ TEST_CALLOC(new, 1);
+ new->next = head;
+ head = new;
+ }
+
+ mbedtls_asn1_free_named_data_list(&head);
+ TEST_ASSERT(head == NULL);
+ /* Most of the point of the test is that it doesn't leak memory.
+ * So this test is only really useful under a memory leak detection
+ * framework. */
+exit:
+ mbedtls_asn1_free_named_data_list(&head);
+}
+/* END_CASE */