[gcr] egg: Encode DER tag classes correctly
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcr] egg: Encode DER tag classes correctly
- Date: Thu, 24 Nov 2011 06:58:12 +0000 (UTC)
commit 77bbfca91cba5e9428c0c716a1a5cd82ae40717b
Author: Stef Walter <stefw collabora co uk>
Date: Thu Nov 17 10:31:37 2011 +0100
egg: Encode DER tag classes correctly
* Encode DER tag classes correctly for universal, application
and private classes
egg/egg-asn1x.c | 38 ++++++++++++++------
egg/tests/test-asn1.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++---
egg/tests/test.asn | 2 +
3 files changed, 119 insertions(+), 16 deletions(-)
---
diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c
index 8638c37..5a7db21 100644
--- a/egg/egg-asn1x.c
+++ b/egg/egg-asn1x.c
@@ -601,22 +601,35 @@ anode_calc_tag (GNode *node)
}
static gboolean
-anode_calc_explicit_for_flags (GNode *node, gint flags)
+anode_calc_explicit_for_flags (GNode *node,
+ gint flags,
+ guchar *cls_type)
{
const EggAsn1xDef *opt;
if ((flags & FLAG_TAG) != FLAG_TAG)
return FALSE;
opt = anode_opt_lookup (node, EGG_ASN1X_TAG, NULL);
g_return_val_if_fail (opt, FALSE);
+ if (cls_type) {
+ if (opt->type & FLAG_UNIVERSAL)
+ *cls_type = ASN1_CLASS_UNIVERSAL;
+ else if (opt->type & FLAG_APPLICATION)
+ *cls_type = ASN1_CLASS_APPLICATION;
+ else if (opt->type & FLAG_PRIVATE)
+ *cls_type = ASN1_CLASS_PRIVATE;
+ else
+ *cls_type = ASN1_CLASS_CONTEXT_SPECIFIC;
+ }
if ((opt->type & FLAG_IMPLICIT) == FLAG_IMPLICIT)
return FALSE;
return TRUE;
}
static gboolean
-anode_calc_explicit (GNode *node)
+anode_calc_explicit (GNode *node,
+ guchar *cls_type)
{
- return anode_calc_explicit_for_flags (node, anode_def_flags (node));
+ return anode_calc_explicit_for_flags (node, anode_def_flags (node), cls_type);
}
/* -------------------------------------------------------------------------
@@ -1057,7 +1070,7 @@ anode_decode_structured (GNode *node,
end = tlv->end;
/* An explicit, wrapped tag */
- if (anode_calc_explicit_for_flags (node, flags)) {
+ if (anode_calc_explicit_for_flags (node, flags, NULL)) {
if ((tlv->cls & ASN1_CLASS_CONTEXT_SPECIFIC) == 0)
return anode_failure (node, "missing context specific tag");
if (!anode_decode_tlv_for_contents (tlv, TRUE, &ctlv))
@@ -1314,6 +1327,7 @@ anode_encode_tlv_and_enc (GNode *node,
GDestroyNotify destroy)
{
gboolean explicit = FALSE;
+ guchar cls_type;
gulong tag;
gint flags;
Atlv tlv;
@@ -1358,11 +1372,11 @@ anode_encode_tlv_and_enc (GNode *node,
/* Build up the class */
flags = anode_def_flags (node);
if (flags & FLAG_TAG) {
- explicit = anode_calc_explicit_for_flags (node, flags);
+ explicit = anode_calc_explicit_for_flags (node, flags, &cls_type);
if (explicit)
flags &= ~FLAG_TAG;
else
- tlv.cls |= ASN1_CLASS_CONTEXT_SPECIFIC;
+ tlv.cls |= cls_type;
}
/* And now the tag */
@@ -1393,6 +1407,7 @@ anode_encode_build (GNode *node,
guchar *data,
gsize n_data)
{
+ guchar cls_type;
gint type;
guchar cls;
gulong tag;
@@ -1415,10 +1430,10 @@ anode_encode_build (GNode *node,
}
/* Encode any explicit tag */
- if (anode_calc_explicit (node)) {
+ if (anode_calc_explicit (node, &cls_type)) {
tag = anode_calc_tag (node);
g_return_val_if_fail (tag != G_MAXULONG, FALSE);
- cls = (ASN1_CLASS_STRUCTURED | ASN1_CLASS_CONTEXT_SPECIFIC);
+ cls = (ASN1_CLASS_STRUCTURED | cls_type);
g_assert (tlv->oft > 0 && tlv->oft < tlv->off);
off = anode_encode_cls_tag_len (data, n_data, cls, tag, (tlv->off - tlv->oft) + tlv->len);
g_assert (off == tlv->oft);
@@ -2895,7 +2910,7 @@ egg_asn1x_get_element_raw (GNode *node)
if (backing == NULL)
return NULL;
- if (anode_calc_explicit (node)) {
+ if (anode_calc_explicit (node, NULL)) {
len = (tlv->len + tlv->off) - tlv->oft;
p = tlv->buf + tlv->oft;
} else {
@@ -2914,6 +2929,7 @@ egg_asn1x_set_element_raw (GNode *node,
Atlv dtlv, *tlv;
gint oft, flags;
const guchar *data;
+ guchar cls_type;
EggBytes *sub;
gsize size;
@@ -2952,8 +2968,8 @@ egg_asn1x_set_element_raw (GNode *node,
tlv->buf = tlv->end = NULL;
/* Explicit tagging: leave space for the outer tag */
- if (anode_calc_explicit (node)) {
- oft = anode_encode_cls_tag_len (NULL, 0, (ASN1_CLASS_STRUCTURED | ASN1_CLASS_CONTEXT_SPECIFIC),
+ if (anode_calc_explicit (node, &cls_type)) {
+ oft = anode_encode_cls_tag_len (NULL, 0, (ASN1_CLASS_STRUCTURED | cls_type),
anode_calc_tag (node), size);
tlv->off += oft;
diff --git a/egg/tests/test-asn1.c b/egg/tests/test-asn1.c
index caf01af..7844c92 100644
--- a/egg/tests/test-asn1.c
+++ b/egg/tests/test-asn1.c
@@ -42,7 +42,8 @@ const gchar BFALSE[] = "\x01\x01\x00";
const gchar BTRUE[] = "\x01\x01\xFF";
const gchar SFARNSWORTH[] = "\x04\x0A""farnsworth";
const gchar SIMPLICIT[] = "\x85\x08""implicit";
-const gchar SEXPLICIT[] = "\xE5\x0A\x04\x08""explicit";
+const gchar SEXPLICIT[] = "\xA5\x0A\x04\x08""explicit";
+const gchar SUNIVERSAL[] = "\x05\x09""universal";
const gchar TGENERALIZED[] = "\x18\x0F""20070725130528Z";
const gchar BITS_TEST[] = "\x03\x04\x06\x6e\x5d\xc0";
const gchar BITS_BAD[] = "\x03\x04\x06\x6e\x5d\xc1";
@@ -285,7 +286,7 @@ test_generalized_time (void)
}
static void
-test_implicit (void)
+test_implicit_encode (void)
{
EggBytes *bytes;
GNode *asn;
@@ -307,7 +308,26 @@ test_implicit (void)
}
static void
-test_explicit (void)
+test_implicit_decode (void)
+{
+ EggBytes *bytes;
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestImplicit");
+ g_assert (asn);
+
+ if (!egg_asn1x_set_string_as_utf8 (asn, g_strdup ("implicit"), g_free))
+ g_assert_not_reached ();
+
+ bytes = egg_asn1x_encode (asn, NULL);
+ egg_assert_cmpbytes (bytes, ==, SIMPLICIT, XL (SIMPLICIT));
+
+ egg_asn1x_destroy (asn);
+ egg_bytes_unref (bytes);
+}
+
+static void
+test_explicit_decode (void)
{
EggBytes *bytes;
GNode *asn;
@@ -330,6 +350,67 @@ test_explicit (void)
}
static void
+test_explicit_encode (void)
+{
+ EggBytes *bytes;
+ GNode *asn;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestExplicit");
+ g_assert (asn);
+
+ if (!egg_asn1x_set_string_as_utf8 (asn, g_strdup ("explicit"), g_free))
+ g_assert_not_reached ();
+
+ bytes = egg_asn1x_encode (asn, NULL);
+ egg_assert_cmpbytes (bytes, ==, SEXPLICIT, XL (SEXPLICIT));
+
+ egg_asn1x_destroy (asn);
+ egg_bytes_unref (bytes);
+}
+
+static void
+test_universal_decode (void)
+{
+ EggBytes *bytes;
+ GNode *asn;
+ gchar *value;
+
+ asn = egg_asn1x_create (test_asn1_tab, "TestUniversal");
+ g_assert (asn);
+
+ /* Should work */
+ bytes = egg_bytes_new_static (SUNIVERSAL, XL (SUNIVERSAL));
+ if (!egg_asn1x_decode (asn, bytes))
+ g_assert_not_reached ();
+ egg_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)
+{
+ EggBytes *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);
+ egg_bytes_unref (bytes);
+}
+
+static void
test_bit_string_decode (void)
{
EggBytes *bytes;
@@ -1278,8 +1359,12 @@ main (int argc, char **argv)
g_test_add_func ("/asn1/unsigned", test_unsigned);
g_test_add_func ("/asn1/octet_string", test_octet_string);
g_test_add_func ("/asn1/generalized_time", test_generalized_time);
- g_test_add_func ("/asn1/implicit", test_implicit);
- g_test_add_func ("/asn1/explicit", test_explicit);
+ 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/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);
g_test_add_func ("/asn1/bit_string_decode_bad", test_bit_string_decode_bad);
g_test_add_func ("/asn1/bit_string_decode_ulong", test_bit_string_decode_ulong);
diff --git a/egg/tests/test.asn b/egg/tests/test.asn
index 28cb176..5412a63 100644
--- a/egg/tests/test.asn
+++ b/egg/tests/test.asn
@@ -18,6 +18,8 @@ TestImplicit ::= [5] IMPLICIT OCTET STRING
TestExplicit ::= [5] EXPLICIT OCTET STRING
+TestUniversal ::= [UNIVERSAL 5] IMPLICIT OCTET STRING
+
TestBitString ::= BIT STRING
TestIntegers ::= SEQUENCE {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]