diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/asn1.c | 110 | ||||
-rw-r--r-- | common/asn1.h | 21 | ||||
-rw-r--r-- | common/tests/test-asn1.c | 46 |
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); |