[gnome-keyring] egg-asn1x: More complete coverage for ASN.1 tests



commit 6f7ee2da70cf39b7e8ef2f2482a77b88fa60ed53
Author: Stef Walter <stefw gnome org>
Date:   Wed Nov 7 11:14:49 2012 +0100

    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.

 egg/egg-asn1x.c                                    |  139 +--
 egg/tests/Makefile.am                              |   18 +-
 ...nalname-1.der => test-personalname-invalid.der} |    0
 egg/tests/test-asn1.c                              | 1237 +++++++++++++++++++-
 egg/tests/test-asn1x.c                             |   58 +-
 egg/tests/test-symkey.c                            |    4 +-
 egg/tests/test.asn                                 |   34 +-
 pkcs11/gkm/gkm-data-der.c                          |    9 +-
 pkcs11/gkm/tests/test-data-der.c                   |    4 +-
 pkcs11/xdg-store/tests/dump-trust-file.c           |   11 +-
 pkcs11/xdg-store/tests/frob-trust-file.c           |    3 +-
 11 files changed, 1325 insertions(+), 192 deletions(-)
---
diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c
index c35cf1e..4205406 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 a6d51e1..669e896 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
similarity index 100%
rename from egg/tests/files/test-personalname-1.der
rename to egg/tests/files/test-personalname-invalid.der
diff --git a/egg/tests/test-asn1.c b/egg/tests/test-asn1.c
index 09645d6..3bd43a5 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;
@@ -373,113 +761,202 @@ test_universal_decode (void)
 	GNode *asn;
 	gchar *value;
 
-	asn = egg_asn1x_create (test_asn1_tab, "TestUniversal");
+	asn = egg_asn1x_create (test_asn1_tab, "TestUniversal");
+	g_assert (asn);
+
+	/* Should work */
+	bytes = g_bytes_new_static (SUNIVERSAL, XL (SUNIVERSAL));
+	if (!egg_asn1x_decode (asn, bytes))
+		g_assert_not_reached ();
+	g_bytes_unref (bytes);
+
+	value = egg_asn1x_get_string_as_utf8 (asn, NULL);
+	g_assert_cmpstr (value, ==, "universal");
+	g_free (value);
+
+	egg_asn1x_destroy (asn);
+}
+
+static void
+test_universal_encode (void)
+{
+	GBytes *bytes;
+	GNode *asn;
+
+	asn = egg_asn1x_create (test_asn1_tab, "TestUniversal");
+	g_assert (asn);
+
+	if (!egg_asn1x_set_string_as_utf8 (asn, g_strdup ("universal"), g_free))
+		g_assert_not_reached ();
+
+	bytes = egg_asn1x_encode (asn, NULL);
+	egg_assert_cmpbytes (bytes, ==, SUNIVERSAL, XL (SUNIVERSAL));
+
+	egg_asn1x_destroy (asn);
+	g_bytes_unref (bytes);
+}
+
+static void
+test_bit_string_decode (void)
+{
+	GBytes *bytes;
+	GNode *asn;
+	GBytes *bits;
+	guint n_bits;
+	const guchar *data;
+
+	asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+	g_assert (asn);
+
+	g_assert_cmpint (EGG_ASN1X_BIT_STRING, ==, egg_asn1x_type (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);
+
+	bits = egg_asn1x_get_bits_as_raw (asn, &n_bits);
+	g_assert (bits != NULL);
+	g_assert_cmpuint (n_bits, ==, 18);
+	data = g_bytes_get_data (bits, NULL);
+	g_assert_cmpint (data[0], ==, 0x6e);
+	g_assert_cmpint (data[1], ==, 0x5d);
+	g_assert_cmpint (data[2], ==, 0xc0);
+
+	g_bytes_unref (bits);
+	egg_asn1x_destroy (asn);
+}
+
+static void
+test_bit_string_decode_bad (void)
+{
+	GBytes *bytes;
+	GNode *asn;
+
+	asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
+	g_assert (asn);
+
+	/* Should not work */
+	bytes = g_bytes_new_static (BITS_BAD, XL (BITS_BAD));
+	if (egg_asn1x_decode (asn, bytes))
+		g_assert_not_reached ();
+	g_bytes_unref (bytes);
+
+	egg_asn1x_destroy (asn);
+}
+
+static void
+test_bit_string_decode_ulong (void)
+{
+	GBytes *bytes;
+	GNode *asn;
+	gulong bits;
+	guint n_bits;
+
+	asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
 	g_assert (asn);
 
 	/* Should work */
-	bytes = g_bytes_new_static (SUNIVERSAL, XL (SUNIVERSAL));
+	bytes = g_bytes_new_static (BITS_TEST, XL (BITS_TEST));
 	if (!egg_asn1x_decode (asn, bytes))
 		g_assert_not_reached ();
 	g_bytes_unref (bytes);
 
-	value = egg_asn1x_get_string_as_utf8 (asn, NULL);
-	g_assert_cmpstr (value, ==, "universal");
-	g_free (value);
+	if (!egg_asn1x_get_bits_as_ulong (asn, &bits, &n_bits))
+		g_assert_not_reached ();
+
+	g_assert_cmpuint (n_bits, ==, 18);
+	g_assert_cmphex (bits, ==, 0x1b977);
 
 	egg_asn1x_destroy (asn);
 }
 
 static void
-test_universal_encode (void)
+test_bit_string_ulong_too_long (void)
 {
 	GBytes *bytes;
 	GNode *asn;
+	gulong bits;
+	guint n_bits;
 
-	asn = egg_asn1x_create (test_asn1_tab, "TestUniversal");
+	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);
 
-	if (!egg_asn1x_set_string_as_utf8 (asn, g_strdup ("universal"), g_free))
+	/* 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);
 
-	bytes = egg_asn1x_encode (asn, NULL);
-	egg_assert_cmpbytes (bytes, ==, SUNIVERSAL, XL (SUNIVERSAL));
+	if (egg_asn1x_get_bits_as_ulong (asn, &bits, &n_bits))
+		g_assert_not_reached ();
 
 	egg_asn1x_destroy (asn);
-	g_bytes_unref (bytes);
 }
 
 static void
-test_bit_string_decode (void)
+test_bit_string_get_not_set (void)
 {
-	GBytes *bytes;
 	GNode *asn;
-	GBytes *bits;
+	gulong bits;
 	guint n_bits;
-	const guchar *data;
 
 	asn = egg_asn1x_create (test_asn1_tab, "TestBitString");
-	g_assert (asn);
 
-	g_assert_cmpint (EGG_ASN1X_BIT_STRING, ==, egg_asn1x_type (asn));
-
-	/* Should work */
-	bytes = g_bytes_new_static (BITS_TEST, XL (BITS_TEST));
-	if (!egg_asn1x_decode (asn, bytes))
+	if (egg_asn1x_get_bits_as_ulong (asn, &bits, &n_bits))
 		g_assert_not_reached ();
-	g_bytes_unref (bytes);
-
-	bits = egg_asn1x_get_bits_as_raw (asn, &n_bits);
-	g_assert (bits != NULL);
-	g_assert_cmpuint (n_bits, ==, 18);
-	data = g_bytes_get_data (bits, NULL);
-	g_assert_cmpint (data[0], ==, 0x6e);
-	g_assert_cmpint (data[1], ==, 0x5d);
-	g_assert_cmpint (data[2], ==, 0xc0);
+	g_assert (egg_asn1x_get_bits_as_raw (asn, &n_bits) == NULL);
 
-	g_bytes_unref (bits);
 	egg_asn1x_destroy (asn);
 }
 
 static void
-test_bit_string_decode_bad (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 not work */
-	bytes = g_bytes_new_static (BITS_BAD, XL (BITS_BAD));
+	/* 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_decode_ulong (void)
+test_bit_string_invalid_empty (void)
 {
 	GBytes *bytes;
 	GNode *asn;
-	gulong bits;
-	guint n_bits;
+
+	const gchar DER[] =  "\x03\x01\x09";
 
 	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))
+	bytes = g_bytes_new_static (DER, XL (DER));
+	if (egg_asn1x_decode (asn, bytes))
 		g_assert_not_reached ();
-
-	g_assert_cmpuint (n_bits, ==, 18);
-	g_assert_cmphex (bits, ==, 0x1b977);
+	g_assert (strstr (egg_asn1x_message (asn), "invalid number of empty bits"));
+	g_bytes_unref (bytes);
 
 	egg_asn1x_destroy (asn);
 }
@@ -491,6 +968,7 @@ test_bit_string_encode_decode (void)
 	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;
@@ -756,10 +1395,118 @@ test_any_choice_set_raw_short_tag (void)
 }
 
 static void
-test_any_choice_set_raw_long_tag (void)
+test_any_choice_set_raw_long_tag (void)
+{
+	const gchar ENCODING[] = "\xBF\x1F\x0C\x04\x0A""farnsworth";
+	perform_asn1_any_choice_set_raw ("choiceLongTag", ENCODING, XL (ENCODING));
+}
+
+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)
 {
-	const gchar ENCODING[] = "\xBF\x1F\x0C\x04\x0A""farnsworth";
-	perform_asn1_any_choice_set_raw ("choiceLongTag", ENCODING, XL (ENCODING));
+	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
@@ -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 ad75e62..78810de 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 e83c394..133cbf9 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 27dbf4a..05676d7 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),
diff --git a/pkcs11/gkm/gkm-data-der.c b/pkcs11/gkm/gkm-data-der.c
index 6130d09..8df1b5d 100644
--- a/pkcs11/gkm/gkm-data-der.c
+++ b/pkcs11/gkm/gkm-data-der.c
@@ -967,7 +967,8 @@ prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password,
 {
 	GNode *asn1_params = NULL;
 	gcry_cipher_hd_t cih;
-	guchar salt[8];
+	guchar *salt;
+	gsize n_salt;
 	gcry_error_t gcry;
 	guchar *key, *iv;
 	gsize n_key;
@@ -986,7 +987,9 @@ prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password,
 
 	/* Randomize some input for the password based secret */
 	iterations = g_random_int_range (1000, 4096);
-	gcry_create_nonce (salt, sizeof (salt));
+	n_salt = 8;
+	salt = g_malloc (n_salt);
+	gcry_create_nonce (salt, n_salt);
 
 	/* Allocate space for the key and iv */
 	n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES);
@@ -1001,7 +1004,7 @@ prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password,
 	/* Now write out the parameters */
 	asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams");
 	g_return_val_if_fail (asn1_params, NULL);
-	egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, sizeof (salt), NULL);
+	egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, n_salt, g_free);
 	egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations);
 	egg_asn1x_set_any_from (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), asn1_params);
 
diff --git a/pkcs11/gkm/tests/test-data-der.c b/pkcs11/gkm/tests/test-data-der.c
index 0340739..61c55fc 100644
--- a/pkcs11/gkm/tests/test-data-der.c
+++ b/pkcs11/gkm/tests/test-data-der.c
@@ -373,7 +373,7 @@ find_extension (GNode *asn,
 		if (strcmp (exoid, oid) == 0) {
 			g_free (exoid);
 			node = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, "extnValue", NULL);
-			value = egg_asn1x_get_any_raw (node, NULL);
+			value = egg_asn1x_get_string_as_bytes (node);
 			g_assert (value);
 			return value;
 		}
@@ -392,7 +392,7 @@ test_read_basic_constraints (Test *test, gconstpointer unused)
 	gint path_len;
 	GkmDataResult res;
 
-	extension = egg_asn1x_get_any_raw (egg_asn1x_node (test->certificate, "tbsCertificate", "extensions", 1, "extnValue", NULL), NULL);
+	extension = egg_asn1x_get_string_as_bytes (egg_asn1x_node (test->certificate, "tbsCertificate", "extensions", 1, "extnValue", NULL));
 	g_assert (extension != NULL);
 
 	res = gkm_data_der_read_basic_constraints (extension, &is_ca, &path_len);
diff --git a/pkcs11/xdg-store/tests/dump-trust-file.c b/pkcs11/xdg-store/tests/dump-trust-file.c
index 32eb4db..2d3a4d9 100644
--- a/pkcs11/xdg-store/tests/dump-trust-file.c
+++ b/pkcs11/xdg-store/tests/dump-trust-file.c
@@ -61,10 +61,10 @@ dump_certificate_reference (GNode *asn)
 		barf_and_die ("couldn't parse certificate", egg_asn1x_message (name));
 	g_bytes_unref (element);
 
-	issuer = egg_dn_read (name);
+	issuer = egg_dn_read (egg_asn1x_node (name, "rdnSequence", NULL));
 	g_return_if_fail (issuer);
 
-	data = egg_asn1x_get_integer_as_raw (egg_asn1x_node (asn, "serial", NULL));
+	data = egg_asn1x_get_integer_as_raw (egg_asn1x_node (asn, "serialNumber", NULL));
 	g_return_if_fail (data != NULL);
 	serial = egg_hex_encode (g_bytes_get_data (data, NULL), g_bytes_get_size (data));
 
@@ -96,13 +96,13 @@ dump_certificate_complete (GNode *asn)
 		barf_and_die ("couldn't parse certificate", egg_asn1x_message (cert));
 	g_bytes_unref (element);
 
-	issuer = egg_dn_read (egg_asn1x_node (asn, "issuer", NULL));
+	issuer = egg_dn_read (egg_asn1x_node (cert, "tbsCertificate", "issuer", "rdnSequence", NULL));
 	g_return_if_fail (issuer);
 
-	subject = egg_dn_read (egg_asn1x_node (asn, "subject", NULL));
+	subject = egg_dn_read (egg_asn1x_node (cert, "tbsCertificate", "subject", "rdnSequence", NULL));
 	g_return_if_fail (subject);
 
-	data = egg_asn1x_get_integer_as_raw (egg_asn1x_node (asn, "serial", NULL));
+	data = egg_asn1x_get_integer_as_raw (egg_asn1x_node (cert, "tbsCertificate", "serialNumber", NULL));
 	g_return_if_fail (data != NULL);
 	serial = egg_hex_encode (g_bytes_get_data (data, NULL), g_bytes_get_size (data));
 	g_bytes_unref (data);
@@ -193,7 +193,6 @@ main(int argc, char* argv[])
 	}
 
 	egg_asn1x_destroy (asn);
-	g_free (contents);
 
 	return 0;
 }
diff --git a/pkcs11/xdg-store/tests/frob-trust-file.c b/pkcs11/xdg-store/tests/frob-trust-file.c
index 79232c6..a16b731 100644
--- a/pkcs11/xdg-store/tests/frob-trust-file.c
+++ b/pkcs11/xdg-store/tests/frob-trust-file.c
@@ -186,14 +186,13 @@ add_trust_purpose_to_file (const gchar *filename, const gchar *purpose)
 	if (result == NULL)
 		barf_and_die ("couldn't encode trust file", egg_asn1x_message (asn));
 
-	g_free (data);
 	egg_asn1x_destroy (asn);
 
 	if (!g_file_set_contents (filename, g_bytes_get_data (result, NULL),
 	                          g_bytes_get_size (result), &err))
 		barf_and_die ("couldn't write trust file", egg_error_message (err));
 
-	g_free (result);
+	g_bytes_unref (result);
 }
 
 /* --------------------------------------------------------------------------------



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]