summaryrefslogtreecommitdiff
path: root/egg
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2012-11-07 11:14:49 +0100
committerStef Walter <stefw@gnome.org>2012-11-09 12:15:39 +0100
commit6f7ee2da70cf39b7e8ef2f2482a77b88fa60ed53 (patch)
treecf330b564d798e0dce9c761207a22cd01c6ebd81 /egg
parent0023ffdf3fa02785ec1982b851a372f138297452 (diff)
downloadgnome-keyring-6f7ee2da70cf39b7e8ef2f2482a77b88fa60ed53.tar.gz
egg-asn1x: More complete coverage for ASN.1 tests
* Remove or change code that doesn't get executed in normal operation. * Fix a few bugs discovered during the testing.
Diffstat (limited to 'egg')
-rw-r--r--egg/egg-asn1x.c139
-rw-r--r--egg/tests/Makefile.am18
-rw-r--r--egg/tests/files/test-personalname-invalid.der (renamed from egg/tests/files/test-personalname-1.der)0
-rw-r--r--egg/tests/test-asn1.c1141
-rw-r--r--egg/tests/test-asn1x.c58
-rw-r--r--egg/tests/test-symkey.c4
-rw-r--r--egg/tests/test.asn34
7 files changed, 1263 insertions, 131 deletions
diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c
index c35cf1e1..42054066 100644
--- a/egg/egg-asn1x.c
+++ b/egg/egg-asn1x.c
@@ -217,8 +217,7 @@ bytes_new_with_allocator (EggAllocator allocator,
if (allocator) {
*data = (allocator) (NULL, length + 1);
- if (allocator == NULL)
- return NULL;
+ g_return_val_if_fail (*data != NULL, NULL);
closure = g_slice_new (AllocatorClosure);
closure->allocated = *data;
closure->allocator = allocator;
@@ -522,6 +521,7 @@ anode_failure (GNode *node, const gchar *failure)
g_free (an->failure);
an->failure = g_strdup_printf ("%s: %s", prefix, failure);
+ g_debug ("egg-asn1: %s", an->failure);
return FALSE; /* So this can be chained */
}
@@ -734,15 +734,12 @@ atlv_parse_length (const guchar *at,
g_assert (at != NULL);
g_assert (end != NULL);
- g_assert (end >= at);
+ g_assert (end > at);
g_assert (off != NULL);
*off = 0;
n_data = end - at;
- if (n_data == 0)
- return 0;
-
/* short form */
if (!(at[0] & 128)) {
*off = 1;
@@ -834,8 +831,7 @@ atlv_parse_der_tag (guchar cls,
end = bytes_get_end (data);
g_assert (*at <= end);
- if (*at + off + len > end)
- return "invalid length of tlv";
+ g_return_val_if_fail (*at + off + len <= end, "invalid length of tlv");
if (len < 0 && !(cls & ASN1_CLASS_STRUCTURED))
return "indefinite length on non-structured type";
@@ -992,10 +988,6 @@ anode_decode_sequence_or_set_of (GNode *node,
child = node->children;
g_return_val_if_fail (child, FALSE);
- /* Remove all the other children */
- while (child->next)
- anode_destroy (child->next);
-
for (ctlv = tlv->child, i = 0; ctlv != NULL; ctlv = ctlv->next, i++) {
/* Tag must have same tag as top */
@@ -1085,7 +1077,7 @@ anode_decode_primitive (GNode *node,
return anode_decode_choice (node, tlv);
default:
- return anode_failure (node, "primitive value of an unexpected type");
+ return anode_failure (node, "primitive value of an unexpected type"); /* UNREACHABLE: tag validation? */
}
}
@@ -1114,7 +1106,7 @@ anode_decode_structured (GNode *node,
return anode_decode_sequence_or_set_of (node, tlv);
default:
- return anode_failure (node, "structured value of an unexpected type");
+ return anode_failure (node, "structured value of an unexpected type"); /* UNREACHABLE: tag validation? */
}
}
@@ -1454,8 +1446,7 @@ atlv_unparse_to_bytes (Atlv *tlv,
g_return_val_if_fail (len != 0, NULL);
bytes = bytes_new_with_allocator (allocator, &data, len);
- if (data == NULL)
- return NULL;
+ g_return_val_if_fail (bytes != NULL, NULL);
at = data;
atlv_unparse_der (tlv, &at, data + len);
@@ -1498,8 +1489,7 @@ atlv_sort_perform (Atlv *tlv,
pairs = NULL;
for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next) {
bytes = atlv_unparse_to_bytes (ctlv, allocator);
- if (bytes == NULL)
- break;
+ g_return_if_fail (bytes != NULL);
pair = g_slice_new0 (SortPair);
pair->bytes = bytes;
@@ -1690,8 +1680,9 @@ anode_build_choice (GNode *node,
g_assert (anode_def_type (node) == EGG_ASN1X_CHOICE);
child = egg_asn1x_get_choice (node);
- if (!child)
- return FALSE;
+
+ /* Should have been checked by a previous validate */
+ g_return_val_if_fail (child != NULL, NULL);
return anode_build_anything (child, want);
}
@@ -1738,7 +1729,7 @@ anode_build_structured (GNode *node,
atlv_free (tlv);
return NULL;
}
- } else {
+ } else if (!want) {
atlv_free (tlv);
return NULL;
}
@@ -1846,10 +1837,9 @@ egg_asn1x_encode (GNode *asn,
return NULL;
tlv = anode_build_anything (asn, TRUE);
- if (tlv == NULL) {
- anode_failure (asn, "missing value(s)");
- return NULL;
- }
+
+ /* The above validate should cause build not to return NULL */
+ g_return_val_if_fail (tlv != NULL, NULL);
atlv_sort_perform (tlv, allocator);
@@ -2288,8 +2278,8 @@ anode_read_string_struct (GNode *node,
}
}
- if (value && remaining < 0)
- return FALSE;
+ if (value)
+ g_return_val_if_fail (remaining >= 0, FALSE);
return TRUE;
}
@@ -2308,10 +2298,7 @@ anode_read_string_simple (GNode *node,
buf = g_bytes_get_data (data, &len);
if (value) {
- if (*n_value < len) {
- *n_value = len;
- return FALSE;
- }
+ g_return_val_if_fail (*n_value >= len, FALSE);
memcpy (value, buf, len);
}
@@ -2332,14 +2319,13 @@ anode_read_boolean (GNode *node,
g_assert (value != NULL);
buf = g_bytes_get_data (data, &len);
- if (len != 1)
- return FALSE;
+ g_return_val_if_fail (len == 1, FALSE);
if (buf[0] == 0x00)
*value = FALSE;
else if (buf[0] == 0xFF)
*value = TRUE;
else
- return FALSE;
+ g_return_val_if_reached (FALSE);
return TRUE;
}
@@ -2436,7 +2422,7 @@ anode_read_object_id (GNode *node,
if (k < len) {
if (result)
- g_string_free (result, TRUE);
+ g_string_free (result, TRUE); /* UNREACHABLE: caught by validation */
return FALSE;
}
@@ -2719,10 +2705,8 @@ egg_asn1x_get_enumerated (GNode *node)
if (data == NULL)
return 0;
- /* TODO: Signed values */
-
if (!anode_read_integer_ulong (node, data, &val))
- return 0;
+ g_return_val_if_reached (0);
/* Format that as a string */
if (g_snprintf (buf, sizeof (buf), "%lu", val) < 0)
@@ -2835,9 +2819,10 @@ egg_asn1x_get_integer_as_raw (GNode *node)
an = node->data;
if (an->guarantee_unsigned) {
- g_warning ("cannot read integer set with egg_asn1x_set_integer_as_raw() "
- "via egg_asn1x_get_integer_as_raw()");
- return NULL;
+ g_warning ("cannot read integer set with " /* UNREACHABLE: */
+ "egg_asn1x_set_integer_as_raw() " /* UNREACHABLE: */
+ "via egg_asn1x_get_integer_as_raw()"); /* UNREACHABLE: */
+ return NULL; /* UNREACHABLE: unreachable by coverage testing */
}
raw = anode_get_value (node);
@@ -2866,8 +2851,8 @@ egg_asn1x_get_integer_as_usg (GNode *node)
if (!an->guarantee_unsigned) {
sign = !!(p[0] & 0x80);
if (sign) {
- g_warning ("invalid two's complement integer is negative, but expected unsigned");
- return NULL;
+ g_warning ("invalid two's complement integer"); /* UNREACHABLE: */
+ return NULL; /* UNREACHABLE: by coverage testing */
}
/* Strip off the extra zero byte that was preventing it from being negative */
@@ -2911,8 +2896,8 @@ egg_asn1x_take_integer_as_raw (GNode *node,
sign = !!(p[0] & 0x80);
if (sign) {
- g_warning ("integer in egg_asn1x_set_integer_as_raw is not two's complement");
- return;
+ g_warning ("integer is not two's complement"); /* UNREACHABLE: */
+ return; /* UNREACHABLE: unless warning */
}
anode_clr_value (node);
@@ -3009,8 +2994,7 @@ egg_asn1x_get_any_into_full (GNode *node,
/* If this node is explicit, then just get the contents */
if (anode_calc_explicit_for_flags (node, anode_def_flags (node), NULL)) {
tlv = tlv->child;
- if (tlv == NULL)
- return FALSE;
+ g_return_val_if_fail (tlv != NULL, FALSE);
}
if (!anode_decode_anything (into, tlv))
@@ -3153,16 +3137,14 @@ egg_asn1x_get_string_as_raw (GNode *node,
data = anode_get_value (node);
if (data != NULL) {
if (!anode_read_string_simple (node, data, NULL, &length))
- return NULL;
+ g_return_val_if_reached (NULL);
string = (allocator) (NULL, length + 1);
if (string == NULL)
- return NULL;
+ return NULL; /* UNREACHABLE: unless odd allocator */
- if (!anode_read_string_simple (node, data, string, &length)) {
- (allocator) (string, 0);
- return NULL;
- }
+ if (!anode_read_string_simple (node, data, string, &length))
+ g_return_val_if_reached (NULL);
/* Courtesy null termination, string must however be validated! */
string[length] = 0;
@@ -3177,12 +3159,10 @@ egg_asn1x_get_string_as_raw (GNode *node,
string = (allocator) (NULL, length + 1);
if (string == NULL)
- return NULL;
+ return NULL; /* UNREACHABLE: unless odd allocator */
- if (!anode_read_string_struct (node, tlv, string, &length)) {
- (allocator) (string, 0);
- return NULL;
- }
+ if (!anode_read_string_struct (node, tlv, string, &length))
+ g_return_val_if_reached (NULL); /* should have failed above */
/* Courtesy null termination, string must however be validated! */
string[length] = 0;
@@ -3468,7 +3448,7 @@ egg_asn1x_get_time_as_long (GNode *node)
return -1;
if (!anode_read_time (node, data, &when, &time))
- return -1;
+ g_return_val_if_reached (-1); /* already validated */
return time;
}
@@ -3500,7 +3480,7 @@ egg_asn1x_get_time_as_date (GNode *node,
return FALSE;
if (!anode_read_time (node, data, &when, &time))
- return FALSE;
+ g_return_val_if_reached (FALSE); /* already validated */
g_date_set_dmy (date, when.tm_mday, when.tm_mon + 1, when.tm_year + 1900);
return TRUE;
@@ -3520,7 +3500,7 @@ egg_asn1x_get_oid_as_string (GNode *node)
return NULL;
if (!anode_read_object_id (node, data, &oid))
- return NULL;
+ g_return_val_if_reached (NULL); /* should have been validated */
return oid;
}
@@ -3731,16 +3711,13 @@ anode_validate_enumerated (GNode *node,
g_assert (value != NULL);
- if (!anode_validate_integer (node, value))
- return FALSE;
-
buf = g_bytes_get_data (value, &length);
- g_assert (length > 0); /* Checked above */
/* Enumerated must be positive */
- if (buf[0] & 0x80)
+ if (length > 0 && (buf[0] & 0x80))
return anode_failure (node, "enumerated must be positive");
- return TRUE;
+
+ return anode_validate_integer (node, value);
}
static gboolean
@@ -3778,7 +3755,7 @@ anode_validate_string (GNode *node,
gsize length;
if (!anode_read_string_simple (node, value, NULL, &length))
- return anode_failure (node, "string content is invalid");
+ g_return_val_if_reached (FALSE);
return anode_validate_size (node, (gulong)length);
}
@@ -3839,12 +3816,16 @@ anode_validate_sequence_or_set (GNode *node,
{
GNode *child;
+ /* If this is optional, and has no values, then that's all good */
+ if (anode_def_flags (node) & FLAG_OPTION) {
+ if (!egg_asn1x_have (node))
+ return TRUE;
+ }
+
/* All of the children must validate properly */
for (child = node->children; child; child = child->next) {
- if (egg_asn1x_have (child)) {
- if (!anode_validate_anything (child, strict))
- return FALSE;
- }
+ if (!anode_validate_anything (child, strict))
+ return FALSE;
}
return TRUE;
@@ -3868,6 +3849,9 @@ anode_validate_sequence_or_set_of (GNode *node,
}
}
+ if (count == 0 && anode_def_flags (node) & FLAG_OPTION)
+ return TRUE;
+
return anode_validate_size (node, count);
}
@@ -3878,8 +3862,10 @@ anode_validate_anything (GNode *node,
GBytes *value;
Atlv *tlv;
gint type;
+ gint flags;
type = anode_def_type (node);
+ flags = anode_def_flags (node);
/* Handle these specially */
switch (type) {
@@ -3911,13 +3897,12 @@ anode_validate_anything (GNode *node,
case EGG_ASN1X_BIT_STRING:
return anode_validate_bit_string (node, value);
case EGG_ASN1X_OCTET_STRING:
+ case EGG_ASN1X_GENERALSTRING:
return anode_validate_string (node, value);
case EGG_ASN1X_OBJECT_ID:
return anode_validate_object_id (node, value);
case EGG_ASN1X_NULL:
return anode_validate_null (node, value);
- case EGG_ASN1X_GENERALSTRING:
- return anode_validate_string (node, value);
case EGG_ASN1X_TIME:
return anode_validate_time (node, value);
default:
@@ -3934,13 +3919,13 @@ anode_validate_anything (GNode *node,
case EGG_ASN1X_OCTET_STRING:
return TRUE;
default:
- break;
+ break; /* UNREACHABLE: fix compiler warning */
}
}
- if (anode_def_flags (node) & FLAG_OPTION)
+ if (flags & FLAG_OPTION)
return TRUE;
- if (anode_def_flags (node) & FLAG_DEFAULT)
+ if (flags & FLAG_DEFAULT)
return TRUE;
return anode_failure (node, "missing value");
}
diff --git a/egg/tests/Makefile.am b/egg/tests/Makefile.am
index a6d51e14..669e8964 100644
--- a/egg/tests/Makefile.am
+++ b/egg/tests/Makefile.am
@@ -22,6 +22,7 @@ LDADD = \
TEST_PROGS = \
test-asn1 \
+ test-asn1x \
test-dn \
test-cleanup \
test-hex \
@@ -38,6 +39,10 @@ test_asn1_SOURCES = \
test-asn1.c \
$(ASN_SRCS)
+test_asn1x_LDADD = \
+ $(top_builddir)/egg/libegg-asn1x.la \
+ $(LDADD)
+
check_PROGRAMS = $(TEST_PROGS)
test: $(TEST_PROGS)
@@ -53,16 +58,3 @@ EXTRA_DIST = \
DISTCLEANFILES = \
$(ASN_SRCS)
-
-# ------------------------------------------------------------------------------
-
-noinst_PROGRAMS = \
- test-asn1x
-
-test_asn1x_SOURCES = \
- test-asn1x.c
-
-test_asn1x_LDADD = \
- $(top_builddir)/egg/libegg-asn1x.la \
- $(LIBTASN1_LIBS) \
- $(LDADD)
diff --git a/egg/tests/files/test-personalname-1.der b/egg/tests/files/test-personalname-invalid.der
index 60d5d8c4..60d5d8c4 100644
--- a/egg/tests/files/test-personalname-1.der
+++ b/egg/tests/files/test-personalname-invalid.der
diff --git a/egg/tests/test-asn1.c b/egg/tests/test-asn1.c
index 09645d6d..3bd43a5d 100644
--- a/egg/tests/test-asn1.c
+++ b/egg/tests/test-asn1.c
@@ -104,6 +104,54 @@ test_boolean (void)
}
static void
+test_boolean_decode_bad (void)
+{
+ const gchar BOOLEAN_INVALID_LENGTH[] = "\x01\x02\x00\x00";
+ const gchar BOOLEAN_BAD_VALUE[] = "\x01\x01\x05";
+
+ GBytes *bytes;
+ GNode *asn;
+ gboolean ret;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBoolean");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (BOOLEAN_INVALID_LENGTH, XL (BOOLEAN_INVALID_LENGTH));
+ ret = egg_asn1x_decode (asn, bytes);
+ g_assert (ret == FALSE);
+ g_assert (strstr (egg_asn1x_message (asn), "invalid length boolean") != NULL);
+ g_bytes_unref (bytes);
+
+ bytes = g_bytes_new_static (BOOLEAN_BAD_VALUE, XL (BOOLEAN_BAD_VALUE));
+ ret = egg_asn1x_decode (asn, bytes);
+ g_assert (ret == FALSE);
+ g_assert (strstr (egg_asn1x_message (asn), "boolean must be true or false") != NULL);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_boolean_default (void)
+{
+ GNode *asn;
+ GBytes *bytes;
+
+ const gchar BOOLEAN[] = "\x30\x00";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBooleanDefault");
+ /* This is equal to the default value, and shouldn't be included */
+ egg_asn1x_set_boolean (egg_asn1x_node (asn, "boolean", NULL), TRUE);
+
+ bytes = egg_asn1x_encode (asn, NULL);
+ egg_asn1x_assert (bytes != NULL, asn);
+ egg_assert_cmpbytes (bytes, ==, BOOLEAN, XL (BOOLEAN));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_null (void)
{
GNode *asn;
@@ -161,6 +209,27 @@ test_integer (void)
}
static void
+test_integer_zero_length (void)
+{
+ const gchar INTEGER_EMPTY[] = "\x02\x00";
+
+ GBytes *bytes;
+ GNode *asn;
+ gboolean ret;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (INTEGER_EMPTY, XL (INTEGER_EMPTY));
+ ret = egg_asn1x_decode (asn, bytes);
+ g_assert (ret == FALSE);
+ g_assert (strstr (egg_asn1x_message (asn), "zero length integer") != NULL);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_unsigned (void)
{
GNode *asn;
@@ -216,6 +285,125 @@ test_unsigned (void)
}
static void
+test_unsigned_not_set (void)
+{
+ GNode *asn;
+ GBytes *bytes;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ g_assert (asn);
+
+ bytes = egg_asn1x_get_integer_as_usg (asn);
+ g_assert (bytes == NULL);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_unsigned_default (void)
+{
+ GNode *asn;
+ GBytes *bytes;
+
+ const gchar INTEGERS[] = "\x30\x06\x02\x01\x01\x02\x01\x02";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestIntegers");
+ egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "uint1", NULL), 1);
+ egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "uint2", NULL), 2);
+ /* This is equal to the default value, and shouldn't be included */
+ egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "uint3", NULL), 8888);
+
+ bytes = egg_asn1x_encode (asn, NULL);
+ egg_assert_cmpbytes (bytes, ==, INTEGERS, XL (INTEGERS));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_unsigned_constant (void)
+{
+ gulong value;
+ GNode *asn;
+
+ /* const gchar SEQ[] = "\x30\x00"; */
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestConstant");
+ if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &value))
+ g_assert_not_reached ();
+ g_assert_cmpint (value, ==, 3);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_unsigned_zero (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ const gchar DER[] = "\x02\x01\x00";
+
+ /* No bits set in 0 but should still be 1 byte */
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ egg_asn1x_set_integer_as_ulong (asn, 0);
+
+ bytes = egg_asn1x_encode (asn, NULL);
+ egg_asn1x_assert (bytes != NULL, asn);
+ egg_assert_cmpbytes (bytes, ==, DER, XL (DER));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_integer_raw (void)
+{
+ GNode *asn;
+ GBytes *bytes;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static ("\x01\x02\x03", 3);
+ egg_asn1x_set_integer_as_raw (asn, bytes);
+ g_bytes_unref (bytes);
+
+ bytes = egg_asn1x_encode (asn, NULL);
+ egg_assert_cmpbytes (bytes, ==, "\x02\x03\x01\x02\x03", 5);
+ g_bytes_unref (bytes);
+
+ bytes = egg_asn1x_get_integer_as_raw (asn);
+ egg_assert_cmpbytes (bytes, ==, "\x01\x02\x03", 3);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_integer_raw_not_twos_complement (void)
+{
+ GNode *asn;
+ GBytes *bytes;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static ("\x81\x02\x03", 3);
+
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) {
+ egg_asn1x_set_integer_as_raw (asn, bytes); /* UNREACHABLE: */
+ exit(0); /* UNREACHABLE: for code coverage */
+ }
+
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*not two's complement*");
+
+ g_bytes_unref (bytes);
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_octet_string (void)
{
GNode *asn;
@@ -251,6 +439,131 @@ test_octet_string (void)
}
static void
+test_octet_string_set_bad_utf8 (void)
+{
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestOctetString");
+ g_assert (asn);
+
+ if (egg_asn1x_set_string_as_utf8 (asn, "\xFF\xFA", NULL))
+ g_assert_not_reached ();
+
+ /* Shouldn't succeed */
+ if (egg_asn1x_get_string_as_utf8 (asn, NULL))
+ g_assert_not_reached ();
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_octet_string_bmp_as_utf8 (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+ gchar *data;
+
+ const gchar SFUER[] = "\x04\x06""\x00\x46\x00\xfc\x00\x72";
+
+ bytes = g_bytes_new_static (SFUER, XL (SFUER));
+ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestOctetString", bytes);
+ g_assert (asn != NULL);
+ g_bytes_unref (bytes);
+
+ data = egg_asn1x_get_bmpstring_as_utf8 (asn);
+ g_assert_cmpstr (data, ==, "F\303\274r");
+
+ g_free (data);
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_octet_string_get_as_bytes (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ bytes = g_bytes_new_static (SFARNSWORTH, XL (SFARNSWORTH));
+ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestOctetString", bytes);
+ g_assert (asn != NULL);
+ g_bytes_unref (bytes);
+
+ bytes = egg_asn1x_get_string_as_bytes (asn);
+ g_assert (bytes != NULL);
+ egg_assert_cmpbytes (bytes, ==, "farnsworth", 10);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_octet_string_set_as_bytes (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestOctetString");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static ("farnsworth", 10);
+ egg_asn1x_set_string_as_bytes (asn, bytes);
+ g_bytes_unref (bytes);
+
+ bytes = egg_asn1x_encode (asn, NULL);
+ g_assert (bytes != NULL);
+ egg_assert_cmpbytes (bytes, ==, SFARNSWORTH, XL (SFARNSWORTH));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_octet_string_structured (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+ guchar *string;
+ gsize n_string = 0;
+
+ const gchar STRUCTURED[] = "\x24\x0c"
+ "\x04\x04""blah"
+ "\x04\x04""blah";
+
+ bytes = g_bytes_new_static (STRUCTURED, XL (STRUCTURED));
+ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestOctetString", bytes);
+ g_bytes_unref (bytes);
+
+ string = egg_asn1x_get_string_as_raw (asn, NULL, &n_string);
+ g_assert_cmpstr ((gchar *)string, ==, "blahblah");
+ g_assert_cmpint (n_string, ==, 8);
+ g_free (string);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_octet_string_structured_bad (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+ guchar *string;
+ gsize n_string = 0;
+
+ const gchar STRUCTURED[] = "\x24\x0c"
+ "\x24\x04\x04\02""bl"
+ "\x04\x04""blah";
+
+ bytes = g_bytes_new_static (STRUCTURED, XL (STRUCTURED));
+ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestOctetString", bytes);
+ g_bytes_unref (bytes);
+
+ string = egg_asn1x_get_string_as_raw (asn, NULL, &n_string);
+ g_assert (string == NULL);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_generalized_time (void)
{
GBytes *bytes;
@@ -284,6 +597,19 @@ test_generalized_time (void)
}
static void
+test_time_get_missing (void)
+{
+ GDate date;
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestGeneralized");
+ if (egg_asn1x_get_time_as_date (asn, &date))
+ g_assert_not_reached ();
+ g_assert (egg_asn1x_get_time_as_long (asn) == -1);
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_implicit_encode (void)
{
GBytes *bytes;
@@ -348,6 +674,68 @@ test_explicit_decode (void)
}
static void
+test_explicit_no_context_specific (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ const gchar DER[] = "\x45\x0A\x04\x08""explicit";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestExplicit");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "missing context specific tag"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_explicit_no_context_child (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ const gchar DER[] = "\xA5\x00";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestExplicit");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "missing context specific child"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_explicit_extra_context_child (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ const gchar DER[] = "\xA5\x14"
+ "\x04\x08""explicit"
+ "\x04\x08""explicit";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestExplicit");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "multiple context specific children"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_explicit_encode (void)
{
GBytes *bytes;
@@ -485,12 +873,102 @@ test_bit_string_decode_ulong (void)
}
static void
+test_bit_string_ulong_too_long (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+ gulong bits;
+ guint n_bits;
+
+ const gchar BITS_TEST[] = "\x03\x20\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ /* Should work */
+
+ bytes = g_bytes_new_static (BITS_TEST, XL (BITS_TEST));
+ if (!egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_bytes_unref (bytes);
+
+ if (egg_asn1x_get_bits_as_ulong (asn, &bits, &n_bits))
+ g_assert_not_reached ();
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_bit_string_get_not_set (void)
+{
+ GNode *asn;
+ gulong bits;
+ guint n_bits;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+
+ if (egg_asn1x_get_bits_as_ulong (asn, &bits, &n_bits))
+ g_assert_not_reached ();
+ g_assert (egg_asn1x_get_bits_as_raw (asn, &n_bits) == NULL);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_bit_string_invalid_length (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ const gchar DER[] = "\x03\x00";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ /* Should work */
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "invalid length bit string"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_bit_string_invalid_empty (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ const gchar DER[] = "\x03\x01\x09";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+ g_assert (asn);
+
+ /* Should work */
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "invalid number of empty bits"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_bit_string_encode_decode (void)
{
GBytes *data;
GNode *asn;
guchar bits[] = { 0x5d, 0x6e, 0x83 };
GBytes *check;
+ GBytes *bytes;
const guchar *ch;
guint n_bits = 17;
guint n_check;
@@ -498,7 +976,9 @@ test_bit_string_encode_decode (void)
asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
g_assert (asn);
- egg_asn1x_take_bits_as_raw (asn, g_bytes_new (bits, 3), n_bits);
+ bytes = g_bytes_new (bits, 3);
+ egg_asn1x_set_bits_as_raw (asn, bytes, n_bits);
+ g_bytes_unref (bytes);
data = egg_asn1x_encode (asn, NULL);
g_assert (data);
@@ -603,7 +1083,7 @@ test_is_freed (gpointer unused)
}
static void
-test_any_set_raw (void)
+test_any_raw (void)
{
GBytes *bytes;
GNode *asn, *node;
@@ -632,18 +1112,22 @@ test_any_set_raw (void)
egg_assert_cmpbytes (data, ==, SEQ_ENCODING, XL (SEQ_ENCODING));
check = egg_asn1x_get_element_raw (node);
- g_assert (check);
+ g_assert (check != NULL);
+ egg_assert_cmpbytes (check, ==, SFARNSWORTH, XL (SFARNSWORTH));
+ g_bytes_unref (check);
+ check = egg_asn1x_get_any_raw (node, NULL);
+ g_assert (check != NULL);
egg_assert_cmpbytes (check, ==, SFARNSWORTH, XL (SFARNSWORTH));
+ g_bytes_unref (check);
g_bytes_unref (data);
- g_bytes_unref (check);
egg_asn1x_destroy (asn);
g_assert (is_freed);
}
static void
-test_any_set_raw_explicit (void)
+test_any_raw_explicit (void)
{
GBytes *bytes;
GNode *asn, *node;
@@ -675,6 +1159,161 @@ test_any_set_raw_explicit (void)
}
static void
+test_any_raw_invalid (void)
+{
+ GBytes *bytes;
+ GNode *asn, *node;
+
+ const gchar TRUNCATED[] = "\x04\x0A""farns";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestAnySeq");
+ g_assert (asn != NULL);
+
+ node = egg_asn1x_node (asn, "contents", NULL);
+ g_assert (node != NULL);
+
+ bytes = g_bytes_new_static (TRUNCATED, XL (TRUNCATED));
+ if (egg_asn1x_set_any_raw (node, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (node), "content is not encoded properly") != NULL);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_any_raw_not_set (void)
+{
+ GBytes *check;
+ GNode *asn, *node;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestAnySeq");
+ g_assert (asn != NULL);
+
+ node = egg_asn1x_node (asn, "contents", NULL);
+ g_assert (node != NULL);
+
+ check = egg_asn1x_get_any_raw (node, NULL);
+ g_assert (check == NULL);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_any_into (void)
+{
+ GBytes *bytes;
+ GNode *asn, *node;
+ GNode *part;
+ GBytes *data;
+ GBytes *check;
+
+ /* ENCODED SEQUENCE ANY with OCTET STRING */
+ const gchar SEQ_ENCODING[] = "\x30\x0C\x04\x0A""farnsworth";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestAnySeq");
+ g_assert (asn != NULL);
+
+ is_freed = FALSE;
+ node = egg_asn1x_node (asn, "contents", NULL);
+ g_assert (node);
+
+ bytes = g_bytes_new_with_free_func (SFARNSWORTH, XL (SFARNSWORTH),
+ test_is_freed, NULL);
+ part = egg_asn1x_create_and_decode (test_asn1_tab, "TestOctetString", bytes);
+ g_assert (part != NULL);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_set_any_from (node, part);
+ egg_asn1x_destroy (part);
+
+ data = egg_asn1x_encode (asn, NULL);
+ g_assert (data != NULL);
+ egg_assert_cmpbytes (data, ==, SEQ_ENCODING, XL (SEQ_ENCODING));
+
+ part = egg_asn1x_create (test_asn1_tab, "TestOctetString");
+ if (!egg_asn1x_get_any_into (node, part))
+ g_assert_not_reached ();
+
+ check = egg_asn1x_encode (part, NULL);
+ egg_asn1x_destroy (part);
+ g_assert (check != NULL);
+ egg_assert_cmpbytes (check, ==, SFARNSWORTH, XL (SFARNSWORTH));
+ g_bytes_unref (check);
+
+ g_bytes_unref (data);
+ egg_asn1x_destroy (asn);
+ g_assert (is_freed);
+}
+
+static void
+test_any_into_explicit (void)
+{
+ GBytes *bytes;
+ GNode *asn, *node;
+ GNode *part;
+ GBytes *data;
+ GBytes *check;
+
+ /* ENCODED SEQUENCE [89] ANY with OCTET STRING */
+ const gchar SEQ_ENCODING[] = "\x30\x0F\xBF\x59\x0C\x04\x0A""farnsworth";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestAnyExp");
+ g_assert (asn != NULL);
+
+ is_freed = FALSE;
+ node = egg_asn1x_node (asn, "contents", NULL);
+ g_assert (node);
+
+ bytes = g_bytes_new_with_free_func (SFARNSWORTH, XL (SFARNSWORTH),
+ test_is_freed, NULL);
+ part = egg_asn1x_create_and_decode (test_asn1_tab, "TestOctetString", bytes);
+ g_assert (part != NULL);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_set_any_from (node, part);
+ egg_asn1x_destroy (part);
+
+ data = egg_asn1x_encode (asn, NULL);
+ g_assert (data != NULL);
+ egg_assert_cmpbytes (data, ==, SEQ_ENCODING, XL (SEQ_ENCODING));
+
+ part = egg_asn1x_create (test_asn1_tab, "TestOctetString");
+ if (!egg_asn1x_get_any_into (node, part))
+ g_assert_not_reached ();
+
+ check = egg_asn1x_encode (part, NULL);
+ egg_asn1x_destroy (part);
+ g_assert (check != NULL);
+ egg_assert_cmpbytes (check, ==, SFARNSWORTH, XL (SFARNSWORTH));
+ g_bytes_unref (check);
+
+ g_bytes_unref (data);
+ egg_asn1x_destroy (asn);
+ g_assert (is_freed);
+}
+
+static void
+test_any_into_explicit_not_set (void)
+{
+ GNode *asn, *node;
+ GNode *part;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestAnyExp");
+ g_assert (asn != NULL);
+
+ node = egg_asn1x_node (asn, "contents", NULL);
+ g_assert (node);
+
+ part = egg_asn1x_create (test_asn1_tab, "TestOctetString");
+ if (egg_asn1x_get_any_into (node, part))
+ g_assert_not_reached ();
+
+ egg_asn1x_destroy (part);
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_choice_not_chosen (void)
{
GBytes *bytes;
@@ -763,6 +1402,114 @@ test_any_choice_set_raw_long_tag (void)
}
static void
+test_seq_of_any (void)
+{
+ GNode *asn;
+ GNode *integer;
+ GBytes *bytes;
+ gboolean ret;
+ gulong value;
+
+ const gchar DER[] = "\x30\x06"
+ "\x02\x01\x88"
+ "\x02\x01\x33";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestSeqOfAny");
+ g_assert (asn != NULL);
+
+ egg_asn1x_append (asn);
+ egg_asn1x_append (asn);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ ret = egg_asn1x_decode (asn, bytes);
+ egg_asn1x_assert (ret == TRUE, asn);
+ g_bytes_unref (bytes);
+
+ integer = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ g_assert (integer != NULL);
+
+ ret = egg_asn1x_get_any_into (egg_asn1x_node (asn, 1, NULL), integer);
+ egg_asn1x_assert (ret == TRUE, integer);
+ if (!egg_asn1x_get_integer_as_ulong (integer, &value))
+ g_assert_not_reached ();
+ g_assert_cmpint (value, ==, 0x88);
+
+ ret = egg_asn1x_get_any_into (egg_asn1x_node (asn, 2, NULL), integer);
+ egg_asn1x_assert (ret == TRUE, integer);
+ if (!egg_asn1x_get_integer_as_ulong (integer, &value))
+ g_assert_not_reached ();
+ g_assert_cmpint (value, ==, 0x33);
+
+ egg_asn1x_destroy (integer);
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_seq_of_invalid (void)
+{
+ GNode *asn;
+ GBytes *bytes;
+
+ const gchar DER[] = "\x30\x05"
+ "\x04\x00"
+ "\x02\x01\x88";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestSeqOf");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_seq_of_different (void)
+{
+ GNode *asn;
+ GBytes *bytes;
+
+ const gchar DER[] = "\x30\x05"
+ "\x02\x01\x88"
+ "\x04\x00";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestSeqOf");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_set_order (void)
+{
+ GNode *asn;
+ GBytes *bytes;
+
+ const gchar DER[] = "\x31\x0f"
+ "\xA2\x03\x02\x01\x99"
+ "\xA1\x03\x02\x01\x88"
+ "\xA3\x03\x02\x01\x88";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestSet");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "content must be in ascending order"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_append (void)
{
GBytes *bytes;
@@ -918,6 +1665,74 @@ test_enumerated (void)
egg_asn1x_destroy (asn);
}
+static void
+test_enumerated_decode_bad (void)
+{
+ const gchar ENUM_NEGATIVE[] = "\x0A\x01\x85";
+
+ GBytes *bytes;
+ GNode *asn;
+ gboolean ret;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestEnumerated");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (ENUM_NEGATIVE, XL (ENUM_NEGATIVE));
+ ret = egg_asn1x_decode (asn, bytes);
+ g_assert (ret == FALSE);
+ g_assert (strstr (egg_asn1x_message (asn), "enumerated must be positive") != NULL);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_enumerated_not_in_list (void)
+{
+ const gchar ENUM_OTHER[] = "\x0A\x01\x08";
+ const gchar ENUM_LARGE[] = "\x0A\x20\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
+
+ GBytes *bytes;
+ GNode *asn;
+ gboolean ret;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestEnumerated");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (ENUM_OTHER, XL (ENUM_OTHER));
+ ret = egg_asn1x_decode (asn, bytes);
+ g_assert (ret == FALSE);
+ g_assert (strstr (egg_asn1x_message (asn), "not part of list") != NULL);
+ g_bytes_unref (bytes);
+
+ bytes = g_bytes_new_static (ENUM_LARGE, XL (ENUM_LARGE));
+ ret = egg_asn1x_decode (asn, bytes);
+ g_assert (ret == FALSE);
+ g_assert (strstr (egg_asn1x_message (asn), "not part of list") != NULL);
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_enumerated_not_set (void)
+{
+ GNode *asn;
+ GQuark value;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestEnumerated");
+ g_assert (asn != NULL);
+
+ value = egg_asn1x_get_enumerated (asn);
+ g_assert (value == 0);
+
+ egg_asn1x_destroy (asn);
+}
+
+
typedef struct {
GNode *asn1;
guchar *data;
@@ -1148,7 +1963,7 @@ test_read_element (Test* test, gconstpointer unused)
}
static void
-test_oid (Test* test, gconstpointer unused)
+test_oid (void)
{
GBytes *buffer;
GNode *asn = NULL;
@@ -1190,6 +2005,57 @@ test_oid (Test* test, gconstpointer unused)
egg_asn1x_destroy (asn);
}
+static void
+test_oid_set_invalid (void)
+{
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestOid");
+ g_assert ("asn test structure is null" && asn != NULL);
+
+ if (egg_asn1x_set_oid_as_string (egg_asn1x_node (asn, "oid", NULL), "abcd"))
+ g_assert_not_reached ();
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_oid_decode_bad (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+ gboolean ret;
+
+ /* Has invalid leading integer in oid value */
+ const gchar INVALID_OID[] = "\x30\x07\x06\x05\x2b\x80\x83\x82\x1a";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestOid");
+ g_assert ("asn test structure is null" && asn != NULL);
+
+ bytes = g_bytes_new_static (INVALID_OID, XL (INVALID_OID));
+ ret = egg_asn1x_decode (asn, bytes);
+ g_assert (ret == FALSE);
+ g_assert (strstr (egg_asn1x_message (asn), "object id encoding is invalid") != NULL);
+
+ g_bytes_unref (bytes);
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_oid_get_no_value (void)
+{
+ GNode *asn;
+ gchar *oid;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestOid");
+ g_assert ("asn test structure is null" && asn != NULL);
+
+ oid = egg_asn1x_get_oid_as_string (egg_asn1x_node (asn, "oid", NULL));
+ g_assert (oid == NULL);
+
+ egg_asn1x_destroy (asn);
+}
+
typedef struct _TimeTestData {
gchar *value;
time_t ref;
@@ -1376,21 +2242,252 @@ test_nested_unexpected (void)
egg_asn1x_destroy (asn);
}
+static void
+test_create_and_decode_invalid (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ bytes = g_bytes_new_static ("", 0);
+ asn = egg_asn1x_create_and_decode (test_asn1_tab, "TestData", bytes);
+ g_assert (asn == NULL);
+ g_bytes_unref (bytes);
+}
+
+static void
+test_decode_extra (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestSeqOf");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static ("\x30\x00\x11", 3);
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "extra unexpected trailing data"));
+ g_bytes_unref (bytes);
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_decode_nested_short (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestSeqOfAny");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static ("\x30\x02\xA5\x08", 4);
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "content is not encoded properly"));
+ g_bytes_unref (bytes);
+
+ bytes = g_bytes_new_static ("\x30\x04\x30\x02\xA5\x08", 6);
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "content is not encoded properly"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_decode_indefinite_primitive (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static ("\x04\x80\x04\x01\x55\x00\x00", 7);
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "indefinite length on non-structured type"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_decode_invalid_long_length (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ const gchar DER[] = "\x04\xA0"
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01";
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "content is not encoded properly"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_decode_truncated_at_tag (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+
+ const gchar DER[] = "\x04";
+ asn = egg_asn1x_create (test_asn1_tab, "TestInteger");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ if (egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "content is not encoded properly"));
+ g_bytes_unref (bytes);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_decode_long_tag (void)
+{
+ GBytes *bytes;
+ GNode *asn;
+ gboolean ret;
+
+ const gchar DER[] = "\xbf\x89\x52\x03\x04\x01\x33";
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestTagLong");
+ g_assert (asn != NULL);
+
+ bytes = g_bytes_new_static (DER, XL (DER));
+ ret = egg_asn1x_decode (asn, bytes);
+ egg_asn1x_assert (ret == TRUE, asn);
+
+ g_bytes_unref (bytes);
+ egg_asn1x_destroy (asn);
+
+}
+
+static void
+test_create_quark (void)
+{
+ GNode *asn;
+
+ asn = egg_asn1x_create_quark (test_asn1_tab, g_quark_from_static_string ("1.5.13"));
+ g_assert (asn != NULL);
+ g_assert_cmpstr (egg_asn1x_name (asn), ==, "TestIntegers");
+}
+
+static void
+test_validate_default (void)
+{
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBooleanSeq");
+ /* We leave first boolean field empty */
+ egg_asn1x_set_boolean (egg_asn1x_node (asn, "boolean2", NULL), TRUE);
+ if (!egg_asn1x_validate (asn, TRUE))
+ g_assert_not_reached ();
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_validate_missing (void)
+{
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBooleanSeq");
+ /* No fields set */
+ if (egg_asn1x_validate (asn, TRUE))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "missing value") != NULL);
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_validate_seq_of_child_invalid (void)
+{
+ GNode *asn;
+ GNode *child;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestSeqOfSeq");
+ child = egg_asn1x_append (asn);
+ egg_asn1x_set_integer_as_ulong (egg_asn1x_node (child, "uint1", NULL), 5);
+ /* We didn't set uint2 or uint3 so the child is invalid */
+ if (egg_asn1x_validate (asn, TRUE))
+ g_assert_not_reached ();
+ g_assert (strstr (egg_asn1x_message (asn), "missing value") != NULL);
+ egg_asn1x_destroy (asn);
+
+}
+
+static void
+test_validate_optional_seq (void)
+{
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestSeqOptional");
+ if (!egg_asn1x_validate (asn, TRUE))
+ g_assert_not_reached ();
+ egg_asn1x_destroy (asn);
+}
+
+static void
+test_element_get_not_set (void)
+{
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestBooleanSeq");
+ g_assert (egg_asn1x_get_element_raw (asn) == NULL);
+ egg_asn1x_destroy (asn);
+}
+
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
+ g_test_add_func ("/asn1/decode/extra", test_decode_extra);
+ g_test_add_func ("/asn1/decode/nested-short", test_decode_nested_short);
+ g_test_add_func ("/asn1/decode/indefinite-primitive", test_decode_indefinite_primitive);
+ g_test_add_func ("/asn1/decode/invalid-long-length", test_decode_invalid_long_length);
+ g_test_add_func ("/asn1/decode/truncated-at-tag", test_decode_truncated_at_tag);
+ g_test_add_func ("/asn1/decode/decode-long-tag", test_decode_long_tag);
g_test_add_func ("/asn1/boolean", test_boolean);
+ g_test_add_func ("/asn1/boolean-bad", test_boolean_decode_bad);
+ g_test_add_func ("/asn1/boolean-default", test_boolean_default);
g_test_add_func ("/asn1/null", test_null);
g_test_add_func ("/asn1/integer", test_integer);
+ g_test_add_func ("/asn1/integer-zero-length", test_integer_zero_length);
+ g_test_add_func ("/asn1/integer/raw", test_integer_raw);
+ g_test_add_func ("/asn1/integer/raw-not-twos-complement", test_integer_raw_not_twos_complement);
g_test_add_func ("/asn1/unsigned", test_unsigned);
+ g_test_add_func ("/asn1/unsigned/not-set", test_unsigned_not_set);
+ g_test_add_func ("/asn1/unsigned/default", test_unsigned_default);
+ g_test_add_func ("/asn1/unsigned/constant", test_unsigned_constant);
+ g_test_add_func ("/asn1/unsigned/zero", test_unsigned_zero);
g_test_add_func ("/asn1/octet_string", test_octet_string);
+ g_test_add_func ("/asn1/octet-string/set-bad-utf8", test_octet_string_set_bad_utf8);
+ g_test_add_func ("/asn1/octet-string/bmp-as-utf8", test_octet_string_bmp_as_utf8);
+ g_test_add_func ("/asn1/octet-string/get-as-bytes", test_octet_string_get_as_bytes);
+ g_test_add_func ("/asn1/octet-string/set-as-bytes", test_octet_string_set_as_bytes);
+ g_test_add_func ("/asn1/octet-string/structured", test_octet_string_structured);
+ g_test_add_func ("/asn1/octet-string/structured-bad", test_octet_string_structured_bad);
g_test_add_func ("/asn1/generalized_time", test_generalized_time);
+ g_test_add_func ("/asn1/time-get-missing", test_time_get_missing);
g_test_add_func ("/asn1/implicit/decode", test_implicit_decode);
g_test_add_func ("/asn1/implicit/encode", test_implicit_encode);
g_test_add_func ("/asn1/explicit/decode", test_explicit_decode);
g_test_add_func ("/asn1/explicit/encode", test_explicit_encode);
+ g_test_add_func ("/asn1/explicit/no-context-specific", test_explicit_no_context_specific);
+ g_test_add_func ("/asn1/explicit/no-context-child", test_explicit_no_context_child);
+ g_test_add_func ("/asn1/explicit/extra-context-child", test_explicit_extra_context_child);
g_test_add_func ("/asn1/universal/decode", test_universal_decode);
g_test_add_func ("/asn1/universal/encode", test_universal_encode);
g_test_add_func ("/asn1/bit_string_decode", test_bit_string_decode);
@@ -1399,26 +2496,52 @@ main (int argc, char **argv)
g_test_add_func ("/asn1/bit_string_encode_decode", test_bit_string_encode_decode);
g_test_add_func ("/asn1/bit_string_encode_decode_ulong", test_bit_string_encode_decode_ulong);
g_test_add_func ("/asn1/bit_string_encode_decode_zero", test_bit_string_encode_decode_zero);
+ g_test_add_func ("/asn1/bit-string/ulong-too-long", test_bit_string_ulong_too_long);
+ g_test_add_func ("/asn1/bit-string/get-not-set", test_bit_string_get_not_set);
+ g_test_add_func ("/asn1/bit-string/invalid-length", test_bit_string_invalid_length);
+ g_test_add_func ("/asn1/bit-string/invalid-empty", test_bit_string_invalid_empty);
+ g_test_add_func ("/asn1/oid", test_oid);
+ g_test_add_func ("/asn1/oid/set-invalid", test_oid_set_invalid);
+ g_test_add_func ("/asn1/oid/get-no-value", test_oid_get_no_value);
+ g_test_add_func ("/asn1/oid/decode-bad", test_oid_decode_bad);
g_test_add_func ("/asn1/have", test_have);
- g_test_add_func ("/asn1/any_set_raw", test_any_set_raw);
- g_test_add_func ("/asn1/any_set_raw_explicit", test_any_set_raw_explicit);
+ g_test_add_func ("/asn1/any-raw", test_any_raw);
+ g_test_add_func ("/asn1/any-raw/explicit", test_any_raw_explicit);
+ g_test_add_func ("/asn1/any-raw/invalid", test_any_raw_invalid);
+ g_test_add_func ("/asn1/any-raw/not-set", test_any_raw_not_set);
+ g_test_add_func ("/asn1/any-into", test_any_into);
+ g_test_add_func ("/asn1/any-into/explicit", test_any_into_explicit);
+ g_test_add_func ("/asn1/any-into/explicit-not-set", test_any_into_explicit_not_set);
g_test_add_func ("/asn1/choice_not_chosen", test_choice_not_chosen);
g_test_add_func ("/asn1/any_choice_set_raw_short_tag", test_any_choice_set_raw_short_tag);
g_test_add_func ("/asn1/any_choice_set_raw_long_tag", test_any_choice_set_raw_long_tag);
+ g_test_add_func ("/asn1/seq-of-any", test_seq_of_any);\
+ g_test_add_func ("/asn1/seq-of-invalid", test_seq_of_invalid);
+ g_test_add_func ("/asn1/seq-of-different", test_seq_of_different);
+ g_test_add_func ("/asn1/set-order", test_set_order);
g_test_add_func ("/asn1/append", test_append);
g_test_add_func ("/asn1/append_and_clear", test_append_and_clear);
g_test_add_func ("/asn1/setof", test_setof);
g_test_add_func ("/asn1/setof_empty", test_setof_empty);
g_test_add_func ("/asn1/enumerated", test_enumerated);
+ g_test_add_func ("/asn1/enumerated-bad", test_enumerated_decode_bad);
+ g_test_add_func ("/asn1/enumerated-not-in-list", test_enumerated_not_in_list);
+ g_test_add_func ("/asn1/enumerated-not-set", test_enumerated_not_set);
g_test_add_func ("/asn1/nested-fails-with-extra", test_nested_fails_with_extra);
g_test_add_func ("/asn1/nested-unexpected", test_nested_unexpected);
+ g_test_add_func ("/asn1/create-and-decode-invalid", test_create_and_decode_invalid);
+ g_test_add_func ("/asn1/create-quark", test_create_quark);
+ g_test_add_func ("/asn1/validate-default", test_validate_default);
+ g_test_add_func ("/asn1/validate-missing", test_validate_missing);
+ g_test_add_func ("/asn1/validate-seq-of-child-invalid", test_validate_seq_of_child_invalid);
+ g_test_add_func ("/asn1/validate-optional-seq", test_validate_optional_seq);
+ g_test_add_func ("/asn1/get-element/not-set", test_element_get_not_set);
g_test_add ("/asn1/node_name", Test, NULL, setup, test_node_name, teardown);
g_test_add ("/asn1/asn1_integers", Test, NULL, setup, test_asn1_integers, teardown);
g_test_add ("/asn1/boolean_seq", Test, NULL, setup, test_boolean_seq, teardown);
g_test_add ("/asn1/write_value", Test, NULL, setup, test_write_value, teardown);
g_test_add ("/asn1/element_length_content", Test, NULL, setup, test_element_length_content, teardown);
g_test_add ("/asn1/read_element", Test, NULL, setup, test_read_element, teardown);
- g_test_add ("/asn1/oid", Test, NULL, setup, test_oid, teardown);
g_test_add ("/asn1/general_time", Test, NULL, setup, test_general_time, teardown);
g_test_add ("/asn1/utc_time", Test, NULL, setup, test_utc_time, teardown);
g_test_add ("/asn1/read_time", Test, NULL, setup, test_read_time, teardown);
diff --git a/egg/tests/test-asn1x.c b/egg/tests/test-asn1x.c
index ad75e625..78810de1 100644
--- a/egg/tests/test-asn1x.c
+++ b/egg/tests/test-asn1x.c
@@ -78,7 +78,6 @@ static const Fixture parse_test_fixtures[] = {
{ pkix_asn1_tab, SRCDIR "/files/test-certificate-1.der", "Certificate" },
{ pkix_asn1_tab, SRCDIR "/files/test-pkcs8-1.der", "pkcs-8-PrivateKeyInfo" },
{ pk_asn1_tab, SRCDIR "/files/test-rsakey-1.der", "RSAPrivateKey" },
- { pkix_asn1_tab, SRCDIR "/files/test-personalname-1.der", "PersonalName" },
{ pkix_asn1_tab, SRCDIR "/files/test-pkcs7-1.der", "pkcs-7-ContentInfo" },
{ pkix_asn1_tab, SRCDIR "/files/test-pkcs7-2.der", "pkcs-7-ContentInfo" },
};
@@ -120,31 +119,22 @@ test_decode_encode (Test *test,
const Fixture *fixture = data;
GNode *asn;
GBytes *encoded;
+ gboolean ret;
asn = egg_asn1x_create (fixture->defs, fixture->identifier);
if (g_test_verbose ())
egg_asn1x_dump (asn);
- if (!egg_asn1x_decode (asn, test->data)) {
- g_warning ("decode of %s failed: %s", fixture->identifier,
- egg_asn1x_message (asn));
- g_assert_not_reached ();
- }
+ ret = egg_asn1x_decode (asn, test->data);
+ egg_asn1x_assert (ret == TRUE, asn);
encoded = egg_asn1x_encode (asn, NULL);
- if (encoded == NULL) {
- g_warning ("encode of %s failed: %s", fixture->identifier,
- egg_asn1x_message (asn));
- g_assert_not_reached ();
- }
+ egg_asn1x_assert (encoded != NULL, asn);
/* Decode the encoding */
- if (!egg_asn1x_decode (asn, encoded)) {
- g_warning ("decode of encoded %s failed: %s", fixture->identifier,
- egg_asn1x_message (asn));
- g_assert_not_reached ();
- }
+ ret = egg_asn1x_decode (asn, encoded);
+ egg_asn1x_assert (ret == TRUE, asn);
egg_asn1x_clear (asn);
egg_asn1x_destroy (asn);
@@ -152,21 +142,38 @@ test_decode_encode (Test *test,
}
static void
+test_personal_name_invalid (Test *test,
+ gconstpointer unused)
+{
+ GNode *asn;
+ gboolean ret;
+
+ asn = egg_asn1x_create (pkix_asn1_tab, "PersonalName");
+
+ if (g_test_verbose ())
+ egg_asn1x_dump (asn);
+
+ ret = egg_asn1x_decode (asn, test->data);
+ g_assert (ret == FALSE);
+ g_assert (strstr (egg_asn1x_message (asn), "content size is out of bounds") != NULL);
+
+ egg_asn1x_destroy (asn);
+}
+
+static void
test_pkcs12_decode (Test *test,
gconstpointer unused)
{
GNode *asn;
+ gboolean ret;
asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PFX");
if (g_test_verbose ())
egg_asn1x_dump (asn);
- if (!egg_asn1x_decode (asn, test->data)) {
- g_warning ("decode of indefinite pkcs-12-PFX failed: %s",
- egg_asn1x_message (asn));
- g_assert_not_reached ();
- }
+ ret = egg_asn1x_decode (asn, test->data);
+ egg_asn1x_assert (ret == TRUE, asn);
egg_asn1x_destroy (asn);
}
@@ -179,11 +186,6 @@ main (int argc, char **argv)
g_test_init (&argc, &argv, NULL);
-#if 0
- /* Build up a personal name, which is a set */
- build_personal_name ();
-#endif
-
for (i = 0; i < G_N_ELEMENTS (parse_test_fixtures); i++) {
name = g_strdup_printf ("/asn1x/encode-decode-%s", parse_test_fixtures[i].identifier);
g_test_add (name, Test, &parse_test_fixtures[i], setup_parsing, test_decode_encode, teardown);
@@ -192,8 +194,8 @@ main (int argc, char **argv)
g_test_add ("/asn1x/pkcs12-decode/1", Test, SRCDIR "/files/test-pkcs12-1.der",
setup, test_pkcs12_decode, teardown);
- g_test_add ("/asn1x/pkcs12-decode/2", Test, SRCDIR "/files/test-pkcs12-2.der",
- setup, test_pkcs12_decode, teardown);
+ g_test_add ("/asn1x/pkcs5-personal-name/invalid", Test, SRCDIR "/files/test-personalname-invalid.der",
+ setup, test_personal_name_invalid, teardown);
return g_test_run ();
}
diff --git a/egg/tests/test-symkey.c b/egg/tests/test-symkey.c
index e83c3941..133cbf99 100644
--- a/egg/tests/test-symkey.c
+++ b/egg/tests/test-symkey.c
@@ -300,8 +300,6 @@ static const ReadCipher cipher_tests[] = {
"\x04\x08\x73\x61\x6c\x74\x73\x61\x6c\x74",
8, "plaintex", "\xB7\x7B\x54\xBF\x29\x4D\x31\x7D"
}
-
-
};
typedef struct {
@@ -636,7 +634,7 @@ main (int argc, char **argv)
egg_libgcrypt_initialize ();
/* Suppress these messages in tests */
- g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG,
+ g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO,
null_log_handler, NULL);
g_test_add_func ("/symkey/generate_key_simple", test_generate_key_simple);
diff --git a/egg/tests/test.asn b/egg/tests/test.asn
index 27dbf4aa..05676d70 100644
--- a/egg/tests/test.asn
+++ b/egg/tests/test.asn
@@ -24,12 +24,20 @@ TestUniversal ::= [UNIVERSAL 5] IMPLICIT OCTET STRING
TestBitString ::= BIT STRING
+test-integers-id OBJECT IDENTIFIER ::= {1 5 13}
+
TestIntegers ::= SEQUENCE {
uint1 INTEGER,
uint2 INTEGER,
- uint3 INTEGER
+ uint3 INTEGER DEFAULT 8888
+}
+
+TestConstant ::= SEQUENCE {
+ version TestVersion DEFAULT v3
}
+TestVersion ::= INTEGER { v1(1), v2(2), v3(3) }
+
TestData ::= SEQUENCE {
data OCTET STRING
}
@@ -39,10 +47,18 @@ TestBooleanSeq ::= SEQUENCE {
boolean2 BOOLEAN
}
+TestBooleanDefault ::= SEQUENCE {
+ boolean BOOLEAN DEFAULT TRUE
+}
+
TestOid ::= SEQUENCE {
oid OBJECT IDENTIFIER
}
+TestOidOptional ::= SEQUENCE {
+ oid OBJECT IDENTIFIER OPTIONAL
+}
+
TestAnySeq ::= SEQUENCE {
contents ANY
}
@@ -56,10 +72,26 @@ TestAnyChoice ::= CHOICE {
choiceLongTag [31] ANY
}
+TestSet ::= SET {
+ one [1] INTEGER,
+ two [2] INTEGER,
+ three [3] INTEGER
+}
+
+TestTagLong ::= [1234] EXPLICIT INTEGER
+
TestSeqOf ::= SEQUENCE OF INTEGER
TestSetOf ::= SET OF INTEGER
+TestSeqOfSeq ::= SEQUENCE OF TestIntegers
+
+TestSeqOfAny ::= SEQUENCE OF ANY
+
+TestSeqOptional ::= SEQUENCE {
+ integers TestIntegers OPTIONAL
+}
+
TestEnumerated ::= ENUMERATED {
valueZero (0),
valueOne (1),