summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/asn1.c110
-rw-r--r--common/asn1.h21
-rw-r--r--common/tests/test-asn1.c46
3 files changed, 177 insertions, 0 deletions
diff --git a/common/asn1.c b/common/asn1.c
index 4f650ee..44f96eb 100644
--- a/common/asn1.c
+++ b/common/asn1.c
@@ -546,3 +546,113 @@ p11_asn1_tlv_length (const unsigned char *data,
return -1;
}
+
+typedef struct {
+ node_asn *node;
+ char *struct_name;
+ size_t length;
+} asn1_item;
+
+static void
+free_asn1_item (void *data)
+{
+ asn1_item *item = data;
+ free (item->struct_name);
+ asn1_delete_structure (&item->node);
+ free (item);
+}
+
+struct _p11_asn1_cache {
+ p11_dict *defs;
+ p11_dict *items;
+};
+
+p11_asn1_cache *
+p11_asn1_cache_new (void)
+{
+ p11_asn1_cache *cache;
+
+ cache = calloc (1, sizeof (p11_asn1_cache));
+ return_val_if_fail (cache != NULL, NULL);
+
+ cache->defs = p11_asn1_defs_load ();
+ return_val_if_fail (cache->defs != NULL, NULL);
+
+ cache->items = p11_dict_new (p11_dict_direct_hash, p11_dict_direct_equal,
+ NULL, free_asn1_item);
+ return_val_if_fail (cache->items != NULL, NULL);
+
+ return cache;
+}
+
+node_asn *
+p11_asn1_cache_get (p11_asn1_cache *cache,
+ const char *struct_name,
+ const unsigned char *der,
+ size_t der_len)
+{
+ asn1_item *item;
+
+ return_val_if_fail (cache != NULL, NULL);
+ return_val_if_fail (struct_name != NULL, NULL);
+ return_val_if_fail (der != NULL, NULL);
+
+ item = p11_dict_get (cache->items, der);
+ if (item != NULL) {
+ return_val_if_fail (item->length == der_len, NULL);
+ return_val_if_fail (strcmp (item->struct_name, struct_name) == 0, NULL);
+ return item->node;
+ }
+
+ return NULL;
+}
+
+void
+p11_asn1_cache_take (p11_asn1_cache *cache,
+ node_asn *node,
+ const char *struct_name,
+ const unsigned char *der,
+ size_t der_len)
+{
+ asn1_item *item;
+
+ return_if_fail (cache != NULL);
+ return_if_fail (struct_name != NULL);
+ return_if_fail (der != NULL);
+ return_if_fail (der_len != 0);
+
+ item = calloc (1, sizeof (asn1_item));
+ return_if_fail (item != NULL);
+
+ item->length = der_len;
+ item->node = node;
+ item->struct_name = strdup (struct_name);
+ return_if_fail (item->struct_name != NULL);
+
+ if (!p11_dict_set (cache->items, (void *)der, item))
+ return_if_reached ();
+}
+
+void
+p11_asn1_cache_flush (p11_asn1_cache *cache)
+{
+ return_if_fail (cache != NULL);
+ p11_dict_clear (cache->items);
+}
+
+p11_dict *
+p11_asn1_cache_defs (p11_asn1_cache *cache)
+{
+ return_val_if_fail (cache != NULL, NULL);
+ return cache->defs;
+}
+
+void
+p11_asn1_cache_free (p11_asn1_cache *cache)
+{
+ if (!cache)
+ return;
+ p11_dict_free (cache->items);
+ p11_dict_free (cache->defs);
+ free (cache);
+}
diff --git a/common/asn1.h b/common/asn1.h
index 76a84ed..c79e8f6 100644
--- a/common/asn1.h
+++ b/common/asn1.h
@@ -39,6 +39,8 @@
#ifndef P11_ASN1_H_
#define P11_ASN1_H_
+typedef struct _p11_asn1_cache p11_asn1_cache;
+
p11_dict * p11_asn1_defs_load (void);
node_asn * p11_asn1_decode (p11_dict *asn1_defs,
@@ -62,4 +64,23 @@ time_t p11_asn1_parse_general (const char *time_str,
ssize_t p11_asn1_tlv_length (const unsigned char *data,
size_t length);
+p11_asn1_cache * p11_asn1_cache_new (void);
+
+p11_dict * p11_asn1_cache_defs (p11_asn1_cache *cache);
+
+node_asn * p11_asn1_cache_get (p11_asn1_cache *cache,
+ const char *struct_name,
+ const unsigned char *der,
+ size_t der_len);
+
+void p11_asn1_cache_take (p11_asn1_cache *cache,
+ node_asn *node,
+ const char *struct_name,
+ const unsigned char *der,
+ size_t der_len);
+
+void p11_asn1_cache_flush (p11_asn1_cache *cache);
+
+void p11_asn1_cache_free (p11_asn1_cache *cache);
+
#endif /* P11_ASN1_H_ */
diff --git a/common/tests/test-asn1.c b/common/tests/test-asn1.c
index 0034623..0335fa6 100644
--- a/common/tests/test-asn1.c
+++ b/common/tests/test-asn1.c
@@ -89,6 +89,51 @@ test_tlv_length (CuTest *cu)
teardown (cu);
}
+static const unsigned char test_eku_server_and_client[] = {
+ 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x03, 0x02,
+};
+
+static void
+test_asn1_cache (CuTest *cu)
+{
+ p11_asn1_cache *cache;
+ p11_dict *defs;
+ node_asn *asn;
+ node_asn *check;
+
+ cache = p11_asn1_cache_new ();
+ CuAssertPtrNotNull (cu, cache);
+
+ defs = p11_asn1_cache_defs (cache);
+ CuAssertPtrNotNull (cu, defs);
+
+ asn = p11_asn1_decode (defs, "PKIX1.ExtKeyUsageSyntax",
+ test_eku_server_and_client,
+ sizeof (test_eku_server_and_client), NULL);
+ CuAssertPtrNotNull (cu, defs);
+
+ /* Place the parsed data in the cache */
+ p11_asn1_cache_take (cache, asn, "PKIX1.ExtKeyUsageSyntax",
+ test_eku_server_and_client,
+ sizeof (test_eku_server_and_client));
+
+ /* Get it back out */
+ check = p11_asn1_cache_get (cache, "PKIX1.ExtKeyUsageSyntax",
+ test_eku_server_and_client,
+ sizeof (test_eku_server_and_client));
+ CuAssertPtrEquals (cu, asn, check);
+
+ /* Flush should remove it */
+ p11_asn1_cache_flush (cache);
+ check = p11_asn1_cache_get (cache, "PKIX1.ExtKeyUsageSyntax",
+ test_eku_server_and_client,
+ sizeof (test_eku_server_and_client));
+ CuAssertPtrEquals (cu, NULL, check);
+
+ p11_asn1_cache_free (cache);
+}
+
int
main (void)
{
@@ -100,6 +145,7 @@ main (void)
p11_debug_init ();
SUITE_ADD_TEST (suite, test_tlv_length);
+ SUITE_ADD_TEST (suite, test_asn1_cache);
CuSuiteRun (suite);
CuSuiteSummary (suite, output);