]> granicus.if.org Git - p11-kit/commitdiff
trust: Support a p11-kit specific serialization format
authorStef Walter <stefw@gnome.org>
Fri, 15 Mar 2013 10:50:24 +0000 (11:50 +0100)
committerStef Walter <stefw@gnome.org>
Fri, 15 Mar 2013 17:18:47 +0000 (18:18 +0100)
This is documented in doc/internals/ subdirectory
Add tests for the format as well.

https://bugs.freedesktop.org/show_bug.cgi?id=62156

16 files changed:
common/Makefile.am
common/basic.asn [new file with mode: 0644]
common/basic.asn.h [new file with mode: 0644]
doc/internal/persist-format.txt [new file with mode: 0644]
trust/Makefile.am
trust/parser.c
trust/persist.c [new file with mode: 0644]
trust/persist.h [new file with mode: 0644]
trust/tests/Makefile.am
trust/tests/input/verisign-v1.p11-kit [new file with mode: 0644]
trust/tests/test-builder.c
trust/tests/test-data.h
trust/tests/test-module.c
trust/tests/test-parser.c
trust/tests/test-persist.c [new file with mode: 0644]
trust/tests/test-token.c

index a132984f997eac315f4cb75e0141fa04f7cb45c9..3a54089e6d5ce38b61d7f81c28dd4ac612b18c32 100644 (file)
@@ -43,6 +43,7 @@ noinst_LTLIBRARIES += \
 
 libp11_data_la_SOURCES = \
        asn1.c asn1.h \
+       basic.asn basic.asn.h \
        base64.c base64.h \
        checksum.c checksum.h \
        oid.c oid.h \
@@ -59,5 +60,6 @@ libp11_data_la_CFLAGS = \
 asn:
        asn1Parser -o pkix.asn.h pkix.asn
        asn1Parser -o openssl.asn.h openssl.asn
+       asn1Parser -o basic.asn.h basic.asn
 
 endif # WITH_ASN1
diff --git a/common/basic.asn b/common/basic.asn
new file mode 100644 (file)
index 0000000..3c79a4b
--- /dev/null
@@ -0,0 +1,12 @@
+
+BASIC { }
+
+DEFINITIONS EXPLICIT TAGS ::=
+
+BEGIN
+
+Any ::= ANY
+
+ObjectIdentifier ::= OBJECT IDENTIFIER
+
+END
\ No newline at end of file
diff --git a/common/basic.asn.h b/common/basic.asn.h
new file mode 100644 (file)
index 0000000..b63447b
--- /dev/null
@@ -0,0 +1,13 @@
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <libtasn1.h>
+
+const ASN1_ARRAY_TYPE basic_asn1_tab[] = {
+  { "BASIC", 536872976, NULL },
+  { NULL, 1073741836, NULL },
+  { "Any", 1073741837, NULL },
+  { "ObjectIdentifier", 12, NULL },
+  { NULL, 0, NULL }
+};
diff --git a/doc/internal/persist-format.txt b/doc/internal/persist-format.txt
new file mode 100644 (file)
index 0000000..a0a3194
--- /dev/null
@@ -0,0 +1,54 @@
+These are some notes about the p11-kit persistence format
+
+The format is designed to be somewhat human readable and debuggable, and a bit
+transparent but it is also not encouraged to read/write this format from other
+applications or tools without first discussing this at the the mailing list:
+
+p11-glue@lists.freedesktop.org
+
+The format of the file reflects the PKCS#11 attributes exposed by p11-kit. The
+attributes have a one to one mapping with PKCS#11 attributes of similar names.
+No assumptions should be made that an attribute does what you think it does
+from the label.
+
+Each object in the file starts with the header '[p11-kit-object-v1]'. After that
+point there are names and valeus separated by colons. Whitespace surrounding
+the names and values is ignored.
+
+Boolean values are 'true' and 'false'. Unsigned long attributes are plain
+numbers. String/binary attributes are surrounded with quotes and percent
+encoded. Object id attributes are in their dotted form. Various PKCS#11
+constants are available.
+
+PEM blocks can be present within an object, and these contribute certain
+PKCS#11 attributes to the object. The attributes that come from PEM blocks
+never override those explicitly specified. A 'CERTIFICATE' type PEM block
+contributes the 'value', 'class', 'certificate-type', 'subject', 'issuer'
+'start-date', 'end-date', 'id', 'certificate-category', 'check-value',
+'serial-number' attributes with appropriate values.
+
+Comments starting with a '#' and blank lines are ignored.
+
+Only rudimentary checks are done to make sure that the resulting attributes
+make sense. This may change in the future, and invalid files will be
+unceremoniously rejected. So again use the mailing list if there's a need
+to be writing these files at this point:
+
+p11-glue@lists.freedesktop.org
+
+Example file:
+
+[p11-kit-object-v1]
+class = certificate
+modifiable = true
+java-midp-security-domain = 0
+label = "My special label"
+id = "%01%02%03go"
+
+-----BEGIN CERTIFICATE-----
+MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+................................................................
+B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy
+vUxFnmG6v4SBkgPR0ml8xQ==
+-----END CERTIFICATE-----
+x-distrusted = true
index 0f84205d45daa12a194ed1896d1d1628153e0ecd..aff512e5173d2875f84962943e9812bb7aa1d110 100644 (file)
@@ -14,6 +14,7 @@ MODULE_SRCS = \
        builder.c builder.h \
        index.c index.h \
        parser.c parser.h \
+       persist.c persist.h \
        module.c module.h \
        session.c session.h \
        token.c token.h \
index 0ab9468a41c4c8e454a43d095e898138e13be466..56d32268d72dc4fb8471fe65c746cc997ea20f38 100644 (file)
@@ -47,6 +47,7 @@
 #include "parser.h"
 #include "pem.h"
 #include "pkcs11x.h"
+#include "persist.h"
 #include "x509.h"
 
 #include <libtasn1.h>
@@ -65,6 +66,7 @@ struct _p11_parser {
        p11_index *index;
        p11_asn1_cache *asn1_cache;
        p11_dict *asn1_defs;
+       p11_persist *persist;
        char *basename;
        int flags;
 };
@@ -573,7 +575,38 @@ parse_pem_certificates (p11_parser *parser,
        return P11_PARSE_SUCCESS;
 }
 
+static int
+parse_p11_kit_persist (p11_parser *parser,
+                       const unsigned char *data,
+                       size_t length)
+{
+       p11_array *objects;
+       bool ret;
+       int i;
+
+       if (!p11_persist_magic (data, length))
+               return P11_PARSE_UNRECOGNIZED;
+
+       if (!parser->persist) {
+               parser->persist = p11_persist_new ();
+               return_val_if_fail (parser->persist != NULL, P11_PARSE_UNRECOGNIZED);
+       }
+
+       objects = p11_array_new (NULL);
+       return_val_if_fail (objects != NULL, P11_PARSE_FAILURE);
+
+       ret = p11_persist_read (parser->persist, parser->basename, data, length, objects);
+       if (ret) {
+               for (i = 0; i < objects->num; i++)
+                       sink_object (parser, objects->elem[i]);
+       }
+
+       p11_array_free (objects);
+       return ret ? P11_PARSE_SUCCESS : P11_PARSE_FAILURE;
+}
+
 static parser_func all_parsers[] = {
+       parse_p11_kit_persist,
        parse_pem_certificates,
        parse_der_x509_certificate,
        NULL,
@@ -598,6 +631,8 @@ p11_parser_new (p11_index *index,
 void
 p11_parser_free (p11_parser *parser)
 {
+       return_if_fail (parser != NULL);
+       p11_persist_free (parser->persist);
        free (parser);
 }
 
diff --git a/trust/persist.c b/trust/persist.c
new file mode 100644 (file)
index 0000000..69af697
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *     * Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the
+ *       following disclaimer.
+ *     * Redistributions in binary form must reproduce the
+ *       above copyright notice, this list of conditions and
+ *       the following disclaimer in the documentation and/or
+ *       other materials provided with the distribution.
+ *     * The names of contributors to this software may not be
+ *       used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+
+#include "asn1.h"
+#include "attrs.h"
+#include "constants.h"
+#include "debug.h"
+#include "lexer.h"
+#include "pem.h"
+#include "persist.h"
+#include "url.h"
+
+#include "basic.asn.h"
+
+#include <libtasn1.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#define PERSIST_HEADER "p11-kit-object-v1"
+
+struct _p11_persist {
+       p11_dict *constants;
+       node_asn *asn1_defs;
+
+       /* Used during parsing */
+       p11_lexer lexer;
+       CK_ATTRIBUTE *attrs;
+       bool result;
+       bool skip;
+};
+
+bool
+p11_persist_magic (const unsigned char *data,
+                   size_t length)
+{
+       return (strnstr ((char *)data, "[" PERSIST_HEADER "]", length) != NULL);
+}
+
+p11_persist *
+p11_persist_new (void)
+{
+       p11_persist *persist;
+
+       persist = calloc (1, sizeof (p11_persist));
+       return_val_if_fail (persist != NULL, NULL);
+
+       persist->constants = p11_constant_reverse (true);
+       return_val_if_fail (persist->constants != NULL, NULL);
+
+       return persist;
+}
+
+void
+p11_persist_free (p11_persist *persist)
+{
+       if (!persist)
+               return;
+       p11_dict_free (persist->constants);
+       asn1_delete_structure (&persist->asn1_defs);
+       free (persist);
+}
+
+struct constant {
+       CK_ULONG value;
+       const char *string;
+};
+
+static bool
+parse_string (p11_lexer *lexer,
+              CK_ATTRIBUTE *attr)
+{
+       const char *value;
+       const char *end;
+       size_t length;
+       unsigned char *data;
+
+       value = lexer->tok.field.value;
+       end = value + strlen (value);
+
+       /* Not a string/binary value */
+       if (value == end || value[0] != '\"' || *(end - 1) != '\"')
+               return false;
+
+       /* Note that we don't skip whitespace when decoding, as you might in other URLs */
+       data = p11_url_decode (value + 1, end - 1, "", &length);
+       if (data == NULL) {
+               p11_lexer_msg(lexer, "bad encoding of attribute value");
+               return false;
+       }
+
+       attr->pValue = data;
+       attr->ulValueLen = length;
+       return true;
+}
+
+static bool
+parse_bool (p11_lexer *lexer,
+            CK_ATTRIBUTE *attr)
+{
+       const char *value = lexer->tok.field.value;
+       CK_BBOOL boolean;
+
+       if (strcmp (value, "true") == 0) {
+               boolean = CK_TRUE;
+
+       } else if (strcmp (value, "false") == 0) {
+               boolean = CK_FALSE;
+
+       } else {
+               /* Not a valid boolean value */
+               return false;
+       }
+
+       attr->pValue = memdup (&boolean, sizeof (boolean));
+       return_val_if_fail (attr != NULL, FALSE);
+       attr->ulValueLen = sizeof (boolean);
+       return true;
+}
+
+static bool
+parse_ulong (p11_lexer *lexer,
+             CK_ATTRIBUTE *attr)
+{
+       unsigned long value;
+       char *end;
+
+       end = NULL;
+       value = strtoul (lexer->tok.field.value, &end, 10);
+
+       /* Not a valid number value */
+       if (!end || *end != '\0')
+               return false;
+
+       attr->pValue = memdup (&value, sizeof (CK_ULONG));
+       return_val_if_fail (attr->pValue != NULL, false);
+       attr->ulValueLen = sizeof (CK_ULONG);
+       return true;
+}
+
+static bool
+parse_constant (p11_persist *persist,
+                p11_lexer *lexer,
+                CK_ATTRIBUTE *attr)
+{
+       CK_ULONG value;
+
+       value = p11_constant_resolve (persist->constants, lexer->tok.field.value);
+
+       /* Not a valid constant */
+       if (value == CKA_INVALID)
+               return false;
+
+       attr->pValue = memdup (&value, sizeof (CK_ULONG));
+       return_val_if_fail (attr->pValue != NULL, false);
+       attr->ulValueLen = sizeof (CK_ULONG);
+       return true;
+}
+
+
+static bool
+parse_oid (p11_persist *persist,
+           p11_lexer *lexer,
+           CK_ATTRIBUTE *attr)
+{
+       char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, };
+       node_asn *asn;
+       size_t length;
+       char *value;
+       int ret;
+
+       value = lexer->tok.field.value;
+       length = strlen (value);
+
+       /* Not an OID value? */
+       if (length < 4 ||
+           strchr (value, '.') == NULL ||
+           strspn (value, "0123456790.") != length ||
+           strstr (value, "..") != NULL ||
+           value[0] == '.' || value[0] == '0' ||
+           value[length - 1] == '.' ||
+           strchr (value, '.') == strrchr (value, '.')) {
+               return false;
+       }
+
+       if (!persist->asn1_defs) {
+               ret = asn1_array2tree (basic_asn1_tab, &persist->asn1_defs, message);
+               if (ret != ASN1_SUCCESS) {
+                       p11_debug_precond ("failed to load BASIC definitions: %s: %s\n",
+                                          asn1_strerror (ret), message);
+                       return false;
+               }
+       }
+
+       ret = asn1_create_element (persist->asn1_defs, "BASIC.ObjectIdentifier", &asn);
+       if (ret != ASN1_SUCCESS) {
+               p11_debug_precond ("failed to create ObjectIdentifier element: %s\n",
+                                  asn1_strerror (ret));
+               return false;
+       }
+
+       ret = asn1_write_value (asn, "", value, 1);
+       if (ret == ASN1_VALUE_NOT_VALID) {
+               p11_lexer_msg (lexer, "invalid oid value");
+               asn1_delete_structure (&asn);
+               return false;
+       }
+       return_val_if_fail (ret == ASN1_SUCCESS, false);
+
+       attr->pValue = p11_asn1_encode (asn, &length);
+       return_val_if_fail (attr->pValue != NULL, false);
+       attr->ulValueLen = length;
+
+       asn1_delete_structure (&asn);
+       return true;
+}
+
+static bool
+parse_value (p11_persist *persist,
+             p11_lexer *lexer,
+             CK_ATTRIBUTE *attr)
+{
+       return parse_constant (persist, lexer, attr) ||
+              parse_string (lexer, attr) ||
+              parse_bool (lexer, attr) ||
+              parse_ulong (lexer, attr) ||
+              parse_oid (persist, lexer, attr);
+}
+
+static bool
+field_to_attribute (p11_persist *persist,
+                    p11_lexer *lexer)
+{
+       CK_ATTRIBUTE attr = { 0, };
+
+       attr.type = p11_constant_resolve (persist->constants, lexer->tok.field.name);
+       if (attr.type == CKA_INVALID || !p11_constant_name (p11_constant_types, attr.type)) {
+               p11_lexer_msg (lexer, "invalid or unsupported attribute");
+               return false;
+       }
+
+       if (!parse_value (persist, lexer, &attr)) {
+               p11_lexer_msg (lexer, "invalid value");
+               return false;
+       }
+
+       persist->attrs = p11_attrs_take (persist->attrs, attr.type,
+                                        attr.pValue, attr.ulValueLen);
+       return true;
+}
+
+static void
+on_pem_block (const char *type,
+              const unsigned char *contents,
+              size_t length,
+              void *user_data)
+{
+       CK_OBJECT_CLASS klassv = CKO_CERTIFICATE;
+       CK_CERTIFICATE_TYPE x509 = CKC_X_509;
+       CK_BBOOL modifiablev = CK_FALSE;
+
+       CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
+       CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
+       CK_ATTRIBUTE certificate_type = { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) };
+       CK_ATTRIBUTE value = { CKA_VALUE, };
+
+       p11_persist *store = user_data;
+       CK_ATTRIBUTE *attrs;
+
+       if (strcmp (type, "CERTIFICATE") == 0) {
+               value.pValue = (void *)contents;
+               value.ulValueLen = length;
+               attrs = p11_attrs_build (NULL, &klass, &modifiable, &certificate_type, &value, NULL);
+               store->attrs = p11_attrs_merge (store->attrs, attrs, false);
+               store->result = true;
+
+       } else {
+               p11_lexer_msg (&store->lexer, "unsupported pem block in store");
+               store->result = false;
+       }
+}
+
+static bool
+pem_to_attributes (p11_persist *store,
+                   p11_lexer *lexer)
+{
+       unsigned int count;
+
+       count = p11_pem_parse (lexer->tok.pem.begin,
+                              lexer->tok.pem.length,
+                              on_pem_block, store);
+
+       if (count == 0) {
+               p11_lexer_msg (lexer, "invalid pem block");
+               return false;
+       }
+
+       /* The lexer should have only matched one block */
+       return_val_if_fail (count == 1, false);
+       return store->result;
+}
+
+bool
+p11_persist_read (p11_persist *persist,
+                  const char *filename,
+                  const unsigned char *data,
+                  size_t length,
+                  p11_array *objects)
+{
+       bool failed = false;
+
+       return_val_if_fail (persist != NULL, false);
+       return_val_if_fail (objects != NULL, false);
+
+       persist->skip = false;
+       persist->result = false;
+       persist->attrs = NULL;
+
+       p11_lexer_init (&persist->lexer, filename, (const char *)data, length);
+       while (p11_lexer_next (&persist->lexer, &failed)) {
+               switch (persist->lexer.tok_type) {
+               case TOK_SECTION:
+                       if (persist->attrs && !p11_array_push (objects, persist->attrs))
+                               return_val_if_reached (false);
+                       persist->attrs = NULL;
+                       if (strcmp (persist->lexer.tok.section.name, PERSIST_HEADER) != 0) {
+                               p11_lexer_msg (&persist->lexer, "unrecognized or invalid section header");
+                               persist->skip = true;
+                       } else {
+                               persist->attrs = p11_attrs_build (NULL, NULL);
+                               return_val_if_fail (persist->attrs != NULL, false);
+                               persist->skip = false;
+                       }
+                       failed = false;
+                       break;
+               case TOK_FIELD:
+                       if (persist->skip) {
+                               failed = false;
+                       } else if (!persist->attrs) {
+                               p11_lexer_msg (&persist->lexer, "attribute before p11-kit section header");
+                               failed = true;
+                       } else {
+                               failed = !field_to_attribute (persist, &persist->lexer);
+                       }
+                       break;
+               case TOK_PEM:
+                       if (persist->skip) {
+                               failed = false;
+                       } else if (!persist->attrs) {
+                               p11_lexer_msg (&persist->lexer, "pem block before p11-kit section header");
+                               failed = true;
+                       } else {
+                               failed = !pem_to_attributes (persist, &persist->lexer);
+                       }
+                       break;
+               }
+
+               if (failed)
+                       break;
+       }
+
+       if (persist->attrs && !p11_array_push (objects, persist->attrs))
+               return_val_if_reached (false);
+       persist->attrs = NULL;
+
+       p11_lexer_done (&persist->lexer);
+       return !failed;
+}
diff --git a/trust/persist.h b/trust/persist.h
new file mode 100644 (file)
index 0000000..04762f4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *     * Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the
+ *       following disclaimer.
+ *     * Redistributions in binary form must reproduce the
+ *       above copyright notice, this list of conditions and
+ *       the following disclaimer in the documentation and/or
+ *       other materials provided with the distribution.
+ *     * The names of contributors to this software may not be
+ *       used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#ifndef P11_PERSIST_H_
+#define P11_PERSIST_H_
+
+#include "array.h"
+#include "compat.h"
+#include "dict.h"
+
+#include <sys/types.h>
+
+typedef struct _p11_persist p11_persist;
+
+p11_persist *    p11_persist_new    (void);
+
+bool             p11_persist_magic  (const unsigned char *data,
+                                     size_t length);
+
+bool             p11_persist_read   (p11_persist *persist,
+                                     const char *filename,
+                                     const unsigned char *data,
+                                     size_t length,
+                                     p11_array *objects);
+
+void             p11_persist_free   (p11_persist *persist);
+
+#endif /* P11_PERSIST_H_ */
index a675a56650088d5c7c19c56d3f6ed87805b754c5..fa7012090e0f06b9e66b99cd530a2f994061dc7b 100644 (file)
@@ -26,6 +26,7 @@ LDADD = \
        $(NULL)
 
 CHECK_PROGS = \
+       test-persist \
        test-parser \
        test-index \
        test-builder \
diff --git a/trust/tests/input/verisign-v1.p11-kit b/trust/tests/input/verisign-v1.p11-kit
new file mode 100644 (file)
index 0000000..eaa080d
--- /dev/null
@@ -0,0 +1,17 @@
+[p11-kit-object-v1]
+trusted: true
+
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f
+zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi
+TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G
+CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW
+NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV
+Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb
+-----END CERTIFICATE-----
index f8797067242760685da0e0cd32e500351bc08e52..3d3d067ebe1dab74da1e744f68c1ffc603c5519e 100644 (file)
@@ -341,45 +341,6 @@ test_build_certificate_non_ca (CuTest *cu)
        teardown (cu);
 }
 
-static const unsigned char verisign_v1_ca[] = {
-       0x30, 0x82, 0x02, 0x3c, 0x30, 0x82, 0x01, 0xa5, 0x02, 0x10, 0x3f, 0x69, 0x1e, 0x81, 0x9c, 0xf0,
-       0x9a, 0x4a, 0xf3, 0x73, 0xff, 0xb9, 0x48, 0xa2, 0xe4, 0xdd, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
-       0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06,
-       0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
-       0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63,
-       0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73,
-       0x73, 0x20, 0x31, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61,
-       0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-       0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x36,
-       0x30, 0x31, 0x32, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30,
-       0x38, 0x30, 0x32, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09,
-       0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
-       0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e,
-       0x63, 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61,
-       0x73, 0x73, 0x20, 0x31, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d,
-       0x61, 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
-       0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x81, 0x9f, 0x30, 0x0d,
-       0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
-       0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xe5, 0x19, 0xbf, 0x6d, 0xa3, 0x56, 0x61, 0x2d,
-       0x99, 0x48, 0x71, 0xf6, 0x67, 0xde, 0xb9, 0x8d, 0xeb, 0xb7, 0x9e, 0x86, 0x80, 0x0a, 0x91, 0x0e,
-       0xfa, 0x38, 0x25, 0xaf, 0x46, 0x88, 0x82, 0xe5, 0x73, 0xa8, 0xa0, 0x9b, 0x24, 0x5d, 0x0d, 0x1f,
-       0xcc, 0x65, 0x6e, 0x0c, 0xb0, 0xd0, 0x56, 0x84, 0x18, 0x87, 0x9a, 0x06, 0x9b, 0x10, 0xa1, 0x73,
-       0xdf, 0xb4, 0x58, 0x39, 0x6b, 0x6e, 0xc1, 0xf6, 0x15, 0xd5, 0xa8, 0xa8, 0x3f, 0xaa, 0x12, 0x06,
-       0x8d, 0x31, 0xac, 0x7f, 0xb0, 0x34, 0xd7, 0x8f, 0x34, 0x67, 0x88, 0x09, 0xcd, 0x14, 0x11, 0xe2,
-       0x4e, 0x45, 0x56, 0x69, 0x1f, 0x78, 0x02, 0x80, 0xda, 0xdc, 0x47, 0x91, 0x29, 0xbb, 0x36, 0xc9,
-       0x63, 0x5c, 0xc5, 0xe0, 0xd7, 0x2d, 0x87, 0x7b, 0xa1, 0xb7, 0x32, 0xb0, 0x7b, 0x30, 0xba, 0x2a,
-       0x2f, 0x31, 0xaa, 0xee, 0xa3, 0x67, 0xda, 0xdb, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06,
-       0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
-       0x58, 0x15, 0x29, 0x39, 0x3c, 0x77, 0xa3, 0xda, 0x5c, 0x25, 0x03, 0x7c, 0x60, 0xfa, 0xee, 0x09,
-       0x99, 0x3c, 0x27, 0x10, 0x70, 0xc8, 0x0c, 0x09, 0xe6, 0xb3, 0x87, 0xcf, 0x0a, 0xe2, 0x18, 0x96,
-       0x35, 0x62, 0xcc, 0xbf, 0x9b, 0x27, 0x79, 0x89, 0x5f, 0xc9, 0xc4, 0x09, 0xf4, 0xce, 0xb5, 0x1d,
-       0xdf, 0x2a, 0xbd, 0xe5, 0xdb, 0x86, 0x9c, 0x68, 0x25, 0xe5, 0x30, 0x7c, 0xb6, 0x89, 0x15, 0xfe,
-       0x67, 0xd1, 0xad, 0xe1, 0x50, 0xac, 0x3c, 0x7c, 0x62, 0x4b, 0x8f, 0xba, 0x84, 0xd7, 0x12, 0x15,
-       0x1b, 0x1f, 0xca, 0x5d, 0x0f, 0xc1, 0x52, 0x94, 0x2a, 0x11, 0x99, 0xda, 0x7b, 0xcf, 0x0c, 0x36,
-       0x13, 0xd5, 0x35, 0xdc, 0x10, 0x19, 0x59, 0xea, 0x94, 0xc1, 0x00, 0xbf, 0x75, 0x8f, 0xd9, 0xfa,
-       0xfd, 0x76, 0x04, 0xdb, 0x62, 0xbb, 0x90, 0x6a, 0x03, 0xd9, 0x46, 0x35, 0xd9, 0xf8, 0x7c, 0x5b,
-};
-
 static void
 test_build_certificate_v1_ca (CuTest *cu)
 {
index b07830d1553ba520ba5599be07e9de41dc0d8c44..9daff87d1d7c3404287ab3a614469928f5d30e9c 100644 (file)
@@ -230,4 +230,43 @@ static const char test_cacert3_ca_serial[] = {
        0x02, 0x03, 0x0a, 0x41, 0x8a,
 };
 
+static const unsigned char verisign_v1_ca[] = {
+       0x30, 0x82, 0x02, 0x3c, 0x30, 0x82, 0x01, 0xa5, 0x02, 0x10, 0x3f, 0x69, 0x1e, 0x81, 0x9c, 0xf0,
+       0x9a, 0x4a, 0xf3, 0x73, 0xff, 0xb9, 0x48, 0xa2, 0xe4, 0xdd, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+       0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06,
+       0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+       0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63,
+       0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73,
+       0x73, 0x20, 0x31, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61,
+       0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+       0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x36,
+       0x30, 0x31, 0x32, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30,
+       0x38, 0x30, 0x32, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09,
+       0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+       0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e,
+       0x63, 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61,
+       0x73, 0x73, 0x20, 0x31, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d,
+       0x61, 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+       0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+       0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+       0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xe5, 0x19, 0xbf, 0x6d, 0xa3, 0x56, 0x61, 0x2d,
+       0x99, 0x48, 0x71, 0xf6, 0x67, 0xde, 0xb9, 0x8d, 0xeb, 0xb7, 0x9e, 0x86, 0x80, 0x0a, 0x91, 0x0e,
+       0xfa, 0x38, 0x25, 0xaf, 0x46, 0x88, 0x82, 0xe5, 0x73, 0xa8, 0xa0, 0x9b, 0x24, 0x5d, 0x0d, 0x1f,
+       0xcc, 0x65, 0x6e, 0x0c, 0xb0, 0xd0, 0x56, 0x84, 0x18, 0x87, 0x9a, 0x06, 0x9b, 0x10, 0xa1, 0x73,
+       0xdf, 0xb4, 0x58, 0x39, 0x6b, 0x6e, 0xc1, 0xf6, 0x15, 0xd5, 0xa8, 0xa8, 0x3f, 0xaa, 0x12, 0x06,
+       0x8d, 0x31, 0xac, 0x7f, 0xb0, 0x34, 0xd7, 0x8f, 0x34, 0x67, 0x88, 0x09, 0xcd, 0x14, 0x11, 0xe2,
+       0x4e, 0x45, 0x56, 0x69, 0x1f, 0x78, 0x02, 0x80, 0xda, 0xdc, 0x47, 0x91, 0x29, 0xbb, 0x36, 0xc9,
+       0x63, 0x5c, 0xc5, 0xe0, 0xd7, 0x2d, 0x87, 0x7b, 0xa1, 0xb7, 0x32, 0xb0, 0x7b, 0x30, 0xba, 0x2a,
+       0x2f, 0x31, 0xaa, 0xee, 0xa3, 0x67, 0xda, 0xdb, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06,
+       0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+       0x58, 0x15, 0x29, 0x39, 0x3c, 0x77, 0xa3, 0xda, 0x5c, 0x25, 0x03, 0x7c, 0x60, 0xfa, 0xee, 0x09,
+       0x99, 0x3c, 0x27, 0x10, 0x70, 0xc8, 0x0c, 0x09, 0xe6, 0xb3, 0x87, 0xcf, 0x0a, 0xe2, 0x18, 0x96,
+       0x35, 0x62, 0xcc, 0xbf, 0x9b, 0x27, 0x79, 0x89, 0x5f, 0xc9, 0xc4, 0x09, 0xf4, 0xce, 0xb5, 0x1d,
+       0xdf, 0x2a, 0xbd, 0xe5, 0xdb, 0x86, 0x9c, 0x68, 0x25, 0xe5, 0x30, 0x7c, 0xb6, 0x89, 0x15, 0xfe,
+       0x67, 0xd1, 0xad, 0xe1, 0x50, 0xac, 0x3c, 0x7c, 0x62, 0x4b, 0x8f, 0xba, 0x84, 0xd7, 0x12, 0x15,
+       0x1b, 0x1f, 0xca, 0x5d, 0x0f, 0xc1, 0x52, 0x94, 0x2a, 0x11, 0x99, 0xda, 0x7b, 0xcf, 0x0c, 0x36,
+       0x13, 0xd5, 0x35, 0xdc, 0x10, 0x19, 0x59, 0xea, 0x94, 0xc1, 0x00, 0xbf, 0x75, 0x8f, 0xd9, 0xfa,
+       0xfd, 0x76, 0x04, 0xdb, 0x62, 0xbb, 0x90, 0x6a, 0x03, 0xd9, 0x46, 0x35, 0xd9, 0xf8, 0x7c, 0x5b,
+};
+
 #endif /* TEST_DATA_H_ */
index 772dc8a809ba03145ee0100cbfb53e91098b5cb3..52eafe0e533cc1aea02480fae8e2cfaa52b1320f 100644 (file)
@@ -513,7 +513,7 @@ test_find_certificates (CuTest *cu)
        setup (cu);
 
        count = find_objects (cu, match, sessions, objects, 16);
-       CuAssertIntEquals (cu, 7, count);
+       CuAssertIntEquals (cu, 8, count);
 
        for (i = 0; i < count; i++)
                check_certificate (cu, sessions[i], objects[i]);
index a63d7a51dcc243fb3fdd98e486f2630b6a503db8..69049f7f8abcd286d8e12fdbe04efa055feaf307 100644 (file)
@@ -155,6 +155,37 @@ test_parse_pem_certificate (CuTest *cu)
        teardown (cu);
 }
 
+static void
+test_parse_p11_kit_persist (CuTest *cu)
+{
+       CK_ATTRIBUTE *cert;
+       int ret;
+
+       CK_ATTRIBUTE expected[] = {
+               { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+               { CKA_CLASS, &certificate, sizeof (certificate) },
+               { CKA_VALUE, (void *)verisign_v1_ca, sizeof (verisign_v1_ca) },
+               { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+               { CKA_TRUSTED, &truev, sizeof (truev) },
+               { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
+               { CKA_INVALID },
+       };
+
+       setup (cu);
+
+       ret = p11_parse_file (test.parser, SRCDIR "/input/verisign-v1.p11-kit",
+                             P11_PARSE_FLAG_NONE);
+       CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
+
+       /* Should have gotten certificate  */
+       CuAssertIntEquals (cu, 1, p11_index_size (test.index));
+
+       cert = parsed_attrs (certificate_match);
+       test_check_attrs (cu, expected, cert);
+
+       teardown (cu);
+}
+
 static void
 test_parse_openssl_trusted (CuTest *cu)
 {
@@ -420,6 +451,7 @@ main (void)
 
        SUITE_ADD_TEST (suite, test_parse_der_certificate);
        SUITE_ADD_TEST (suite, test_parse_pem_certificate);
+       SUITE_ADD_TEST (suite, test_parse_p11_kit_persist);
        SUITE_ADD_TEST (suite, test_parse_openssl_trusted);
        SUITE_ADD_TEST (suite, test_parse_openssl_distrusted);
        SUITE_ADD_TEST (suite, test_parse_anchor);
diff --git a/trust/tests/test-persist.c b/trust/tests/test-persist.c
new file mode 100644 (file)
index 0000000..d3bd117
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2013 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *     * Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the
+ *       following disclaimer.
+ *     * Redistributions in binary form must reproduce the
+ *       above copyright notice, this list of conditions and
+ *       the following disclaimer in the documentation and/or
+ *       other materials provided with the distribution.
+ *     * The names of contributors to this software may not be
+ *       used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "array.h"
+#include "attrs.h"
+#include "compat.h"
+#include "debug.h"
+#include "library.h"
+#include "persist.h"
+#include "pkcs11.h"
+#include "pkcs11x.h"
+
+#include "test-data.h"
+
+static void
+test_magic (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "value: \"blah\"\n"
+                           "application: \"test-persist\"\n";
+
+       const char *other = "            "
+                       "\n\n[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "value: \"blah\"\n"
+                           "application: \"test-persist\"\n";
+
+       CuAssertTrue (tc, p11_persist_magic ((unsigned char *)input, strlen (input)));
+       CuAssertTrue (tc, !p11_persist_magic ((unsigned char *)input, 5));
+       CuAssertTrue (tc, p11_persist_magic ((unsigned char *)other, strlen (other)));
+       CuAssertTrue (tc, !p11_persist_magic ((unsigned char *)"blah", 4));
+}
+
+static p11_array *
+args_to_array (void *arg,
+               ...) GNUC_NULL_TERMINATED;
+
+static p11_array *
+args_to_array (void *arg,
+               ...)
+{
+       p11_array *array = p11_array_new (NULL);
+
+       va_list (va);
+       va_start (va, arg);
+
+       while (arg != NULL) {
+               p11_array_push (array, arg);
+               arg = va_arg (va, void *);
+       }
+
+       va_end (va);
+
+       return array;
+}
+
+static void
+check_read_msg (CuTest *tc,
+                const char *file,
+                int line,
+                const char *input,
+                p11_array *expected)
+{
+       p11_array *objects;
+       p11_persist *persist;
+       int i;
+
+       persist = p11_persist_new ();
+       objects = p11_array_new (p11_attrs_free);
+
+       if (p11_persist_read (persist, "test", (const unsigned char *)input, strlen (input), objects)) {
+               CuAssert_Line (tc, file, line, "decoding should have failed", expected != NULL);
+               for (i = 0; i < expected->num; i++) {
+                       CuAssert_Line (tc, file, line, "too few objects read", i < objects->num);
+                       test_check_attrs_msg (tc, file, line, expected->elem[i], objects->elem[i]);
+               }
+               CuAssert_Line (tc, file, line, "too many objects read", i == objects->num);
+       } else {
+               CuAssert_Line (tc, file, line, "decoding failed", expected == NULL);
+       }
+
+       p11_array_free (objects);
+       p11_persist_free (persist);
+       p11_array_free (expected);
+}
+
+#define check_read_success(tc, input, objs) \
+       check_read_msg (tc, __FILE__, __LINE__, input, args_to_array objs)
+
+#define check_read_failure(tc, input) \
+       check_read_msg (tc, __FILE__, __LINE__, input, NULL)
+
+static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
+static CK_CERTIFICATE_TYPE x509 = CKC_X_509;
+static CK_OBJECT_CLASS nss_trust = CKO_NSS_TRUST;
+static CK_OBJECT_CLASS data = CKO_DATA;
+static CK_BBOOL truev = CK_TRUE;
+static CK_BBOOL falsev = CK_FALSE;
+
+static void
+test_simple (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "value: \"blah\"\n"
+                           "application: \"test-persist\"\n";
+
+       CK_ATTRIBUTE expected[] = {
+               { CKA_CLASS, &data, sizeof (data) },
+               { CKA_VALUE, "blah", 4 },
+               { CKA_APPLICATION, "test-persist", 12 },
+               { CKA_INVALID },
+       };
+
+       check_read_success (tc, input, (expected, NULL));
+}
+
+static void
+test_number (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "value: 29202390239\n"
+                           "application: \"test-persist\"\n";
+
+       CK_ULONG value = 29202390239;
+
+       CK_ATTRIBUTE expected[] = {
+               { CKA_CLASS, &data, sizeof (data) },
+               { CKA_VALUE, &value, sizeof (value) },
+               { CKA_APPLICATION, "test-persist", 12 },
+               { CKA_INVALID },
+       };
+
+       check_read_success (tc, input, (expected, NULL));
+}
+
+static void
+test_bool (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "private: true\n"
+                           "modifiable: false\n"
+                           "application: \"test-persist\"\n";
+
+       CK_ATTRIBUTE expected[] = {
+               { CKA_CLASS, &data, sizeof (data) },
+               { CKA_PRIVATE, &truev, sizeof (truev) },
+               { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+               { CKA_APPLICATION, "test-persist", 12 },
+               { CKA_INVALID },
+       };
+
+       check_read_success (tc, input, (expected, NULL));
+}
+
+static void
+test_oid (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "object-id: 1.2.3.4";
+
+       CK_ATTRIBUTE expected[] = {
+               { CKA_CLASS, &data, sizeof (data) },
+               { CKA_OBJECT_ID, "\x06\x03*\x03\x04", 5 },
+               { CKA_INVALID },
+       };
+
+       check_read_success (tc, input, (expected, NULL));
+}
+
+static void
+test_constant (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "trust-server-auth: nss-trust-unknown";
+
+       CK_TRUST trust = CKT_NSS_TRUST_UNKNOWN;
+
+       CK_ATTRIBUTE expected[] = {
+               { CKA_CLASS, &data, sizeof (data) },
+               { CKA_TRUST_SERVER_AUTH, &trust, sizeof (trust) },
+               { CKA_INVALID },
+       };
+
+       check_read_success (tc, input, (expected, NULL));
+}
+
+static void
+test_multiple (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "object-id: 1.2.3.4\n"
+                           "[p11-kit-object-v1]\n"
+                           "class: nss-trust\n"
+                           "trust-server-auth: nss-trust-unknown";
+
+       CK_TRUST trust = CKT_NSS_TRUST_UNKNOWN;
+
+       CK_ATTRIBUTE expected1[] = {
+               { CKA_CLASS, &data, sizeof (data) },
+               { CKA_OBJECT_ID, "\x06\x03*\x03\x04", 5 },
+               { CKA_INVALID },
+       };
+
+       CK_ATTRIBUTE expected2[] = {
+               { CKA_CLASS, &nss_trust, sizeof (nss_trust) },
+               { CKA_TRUST_SERVER_AUTH, &trust, sizeof (trust) },
+               { CKA_INVALID },
+       };
+
+       check_read_success (tc, input, (expected1, expected2, NULL));
+}
+
+static void
+test_pem_block (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: certificate\n"
+                           "id: \"292c92\"\n"
+           "-----BEGIN CERTIFICATE-----\n"
+           "MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG\n"
+           "A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz\n"
+           "cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2\n"
+           "MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV\n"
+           "BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt\n"
+           "YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN\n"
+           "ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f\n"
+           "zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi\n"
+           "TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G\n"
+           "CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW\n"
+           "NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV\n"
+           "Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb\n"
+           "-----END CERTIFICATE-----\n"
+                           "\n"
+                           "trusted: true";
+
+       CK_ATTRIBUTE expected[] = {
+               { CKA_CLASS, &certificate, sizeof (certificate) },
+               { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+               { CKA_TRUSTED, &truev, sizeof (truev) },
+               { CKA_VALUE, &verisign_v1_ca, sizeof (verisign_v1_ca) },
+               { CKA_INVALID },
+       };
+
+       check_read_success (tc, input, (expected, NULL));
+}
+
+static void
+test_pem_invalid (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: certificate\n"
+           "-----BEGIN CERT-----\n"
+           "MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG\n"
+           "A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz\n"
+           "cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2\n"
+           "MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV\n"
+           "BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt\n"
+           "YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN\n"
+           "ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f\n"
+           "zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi\n"
+           "TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G\n"
+           "CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW\n"
+           "NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV\n"
+           "Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb\n"
+           "-----END CERTIFICATEXXX-----\n";
+
+       p11_message_quiet ();
+
+       check_read_failure (tc, input);
+
+       p11_message_loud ();
+}
+
+static void
+test_pem_unsupported (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: certificate\n"
+                           "-----BEGIN BLOCK1-----\n"
+                           "aYNNXqshlVxCdo8QfKeXh3GUzd/yn4LYIVgQrx4a\n"
+                           "-----END BLOCK1-----\n";
+
+       p11_message_quiet ();
+
+       check_read_failure (tc, input);
+
+       p11_message_loud ();
+}
+
+static void
+test_pem_first (CuTest *tc)
+{
+       const char *input = "-----BEGIN BLOCK1-----\n"
+                           "aYNNXqshlVxCdo8QfKeXh3GUzd/yn4LYIVgQrx4a\n"
+                           "-----END BLOCK1-----\n"
+                           "[p11-kit-object-v1]\n"
+                           "class: certificate\n";
+
+       p11_message_quiet ();
+
+       check_read_failure (tc, input);
+
+       p11_message_loud ();
+}
+
+static void
+test_skip_unknown (CuTest *tc)
+{
+       const char *input = "[version-2]\n"
+                           "class: data\n"
+                           "object-id: 1.2.3.4\n"
+                           "-----BEGIN BLOCK1-----\n"
+                           "aYNNXqshlVxCdo8QfKeXh3GUzd/yn4LYIVgQrx4a\n"
+                           "-----END BLOCK1-----\n"
+                           "[p11-kit-object-v1]\n"
+                           "class: nss-trust\n"
+                           "trust-server-auth: nss-trust-unknown";
+
+       CK_TRUST trust = CKT_NSS_TRUST_UNKNOWN;
+
+       CK_ATTRIBUTE expected2[] = {
+               { CKA_CLASS, &nss_trust, sizeof (nss_trust) },
+               { CKA_TRUST_SERVER_AUTH, &trust, sizeof (trust) },
+               { CKA_INVALID },
+       };
+
+       p11_message_quiet ();
+
+       check_read_success (tc, input, (expected2, NULL));
+
+       p11_message_loud ();
+}
+
+static void
+test_bad_value (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "value: \"%38%\"\n";
+
+       p11_message_quiet ();
+
+       check_read_failure (tc, input);
+
+       p11_message_loud ();
+}
+
+static void
+test_bad_oid (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "object-id: 1.2";
+
+       p11_message_quiet ();
+
+       check_read_failure (tc, input);
+
+       p11_message_loud ();
+}
+
+static void
+test_bad_field (CuTest *tc)
+{
+       const char *input = "[p11-kit-object-v1]\n"
+                           "class: data\n"
+                           "invalid-field: true";
+
+       p11_message_quiet ();
+
+       check_read_failure (tc, input);
+
+       p11_message_loud ();
+}
+
+static void
+test_attribute_first (CuTest *tc)
+{
+       const char *input = "class: data\n"
+                           "[p11-kit-object-v1]\n"
+                           "invalid-field: true";
+
+       p11_message_quiet ();
+
+       check_read_failure (tc, input);
+
+       p11_message_loud ();
+}
+
+int
+main (void)
+{
+       CuString *output = CuStringNew ();
+       CuSuite* suite = CuSuiteNew ();
+       int ret;
+
+       putenv ("P11_KIT_STRICT=1");
+       p11_debug_init ();
+       p11_library_init ();
+
+       SUITE_ADD_TEST (suite, test_magic);
+       SUITE_ADD_TEST (suite, test_simple);
+       SUITE_ADD_TEST (suite, test_number);
+       SUITE_ADD_TEST (suite, test_bool);
+       SUITE_ADD_TEST (suite, test_oid);
+       SUITE_ADD_TEST (suite, test_constant);
+       SUITE_ADD_TEST (suite, test_multiple);
+       SUITE_ADD_TEST (suite, test_pem_block);
+       SUITE_ADD_TEST (suite, test_pem_invalid);
+       SUITE_ADD_TEST (suite, test_pem_unsupported);
+       SUITE_ADD_TEST (suite, test_pem_first);
+       SUITE_ADD_TEST (suite, test_bad_value);
+       SUITE_ADD_TEST (suite, test_bad_oid);
+       SUITE_ADD_TEST (suite, test_bad_field);
+       SUITE_ADD_TEST (suite, test_skip_unknown);
+       SUITE_ADD_TEST (suite, test_attribute_first);
+
+       CuSuiteRun (suite);
+       CuSuiteSummary (suite, output);
+       CuSuiteDetails (suite, output);
+       printf ("%s\n", output->buffer);
+       ret = suite->failCount;
+       CuSuiteDelete (suite);
+       CuStringDelete (output);
+
+       return ret;
+}
index 5cca23355508f82c72eae73173483520f7de7f5c..c62fae2a8d78e40d5e081fa1d74b28324ce4a324 100644 (file)
@@ -74,7 +74,7 @@ test_token_load (CuTest *cu)
        setup (cu, SRCDIR "/input");
 
        count = p11_token_load (test.token);
-       CuAssertIntEquals (cu, 6, count);
+       CuAssertIntEquals (cu, 7, count);
 
        /* A certificate and trust object for each parsed object + builtin */
        index = p11_token_index (test.token);