summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2013-01-24 11:34:47 +0100
committerStef Walter <stefw@gnome.org>2013-02-05 14:54:46 +0100
commit5147d71466455b3d087b3f3a7472a35e8216c55a (patch)
tree4b81eee35b7d0ec877a34c4fde06478d700a3960
parent603c7d4eb996f51178ccc9d235597497bbb2c7a4 (diff)
Add basic trust module
This is based off the roots-store from gnome-keyring and loads certificates from a root directory and exposes them as PKCS#11 objects.
-rw-r--r--Makefile.am7
-rw-r--r--build/Makefile.am2
-rw-r--r--build/certs/Makefile.am27
-rw-r--r--build/certs/cacert-ca.derbin0 -> 1857 bytes
-rw-r--r--build/certs/cacert3.derbin0 -> 1885 bytes
-rw-r--r--build/certs/self-server.derbin0 -> 396 bytes
-rw-r--r--build/certs/self-signed-with-eku.derbin0 -> 480 bytes
-rw-r--r--build/certs/self-signed-with-ku.derbin0 -> 501 bytes
-rw-r--r--build/certs/testing-ca.derbin0 -> 970 bytes
-rw-r--r--build/certs/testing-server.derbin0 -> 554 bytes
-rw-r--r--build/certs/with-eku.conf19
-rw-r--r--build/certs/with-ku.conf19
-rw-r--r--common/Makefile.am15
-rw-r--r--common/compat.c107
-rw-r--r--common/compat.h17
-rw-r--r--common/debug.c1
-rw-r--r--common/debug.h11
-rw-r--r--common/pkix.asn566
-rw-r--r--common/pkix.asn.h408
-rw-r--r--common/tests/Makefile.am20
-rw-r--r--common/tests/frob-cert.c147
-rw-r--r--common/tests/frob-eku.c101
-rw-r--r--common/tests/frob-ku.c134
-rw-r--r--configure.ac128
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/p11-kit-config.xml10
-rw-r--r--doc/p11-kit-devel.xml24
-rw-r--r--doc/p11-kit-docs.sgml1
-rw-r--r--doc/p11-kit-trust.xml90
-rw-r--r--doc/style.css6
-rw-r--r--p11-kit/Makefile.am1
-rw-r--r--p11-kit/conf.c37
-rw-r--r--p11-kit/p11-kit-1.pc.in3
-rw-r--r--trust/Makefile.am52
-rw-r--r--trust/module.c1517
-rw-r--r--trust/module.h42
-rw-r--r--trust/p11-kit-trust.module6
-rw-r--r--trust/parser.c1103
-rw-r--r--trust/parser.h108
-rw-r--r--trust/session.c206
-rw-r--r--trust/session.h78
-rw-r--r--trust/tests/Makefile.am44
-rw-r--r--trust/tests/anchors/cacert3.derbin0 -> 1885 bytes
-rw-r--r--trust/tests/anchors/testing-ca.derbin0 -> 970 bytes
-rw-r--r--trust/tests/certificates/cacert-ca.derbin0 -> 1857 bytes
-rw-r--r--trust/tests/certificates/self-signed-with-eku.derbin0 -> 480 bytes
-rw-r--r--trust/tests/certificates/self-signed-with-ku.derbin0 -> 501 bytes
-rw-r--r--trust/tests/files/cacert-ca.derbin0 -> 1857 bytes
-rw-r--r--trust/tests/files/cacert3.derbin0 -> 1885 bytes
-rw-r--r--trust/tests/files/self-server.derbin0 -> 396 bytes
-rw-r--r--trust/tests/files/testing-server.derbin0 -> 554 bytes
-rw-r--r--trust/tests/files/unrecognized-file.txt1
-rw-r--r--trust/tests/test-data.c128
-rw-r--r--trust/tests/test-data.h220
-rw-r--r--trust/tests/test-module.c331
-rw-r--r--trust/tests/test-parser.c315
-rw-r--r--trust/tests/test-session.c160
-rw-r--r--trust/tests/test-token.c106
-rw-r--r--trust/token.c256
-rw-r--r--trust/token.h51
60 files changed, 6580 insertions, 47 deletions
diff --git a/Makefile.am b/Makefile.am
index 7ab4468..44608c9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,8 +1,15 @@
+if WITH_TRUST_MODULE
+TRUST_DIR = trust
+else
+TRUST_DIR =
+endif
+
SUBDIRS = \
build \
common \
p11-kit \
+ $(TRUST_DIR) \
tools \
doc \
po
diff --git a/build/Makefile.am b/build/Makefile.am
index f8841ec..de76c58 100644
--- a/build/Makefile.am
+++ b/build/Makefile.am
@@ -1,4 +1,6 @@
+SUBDIRS = certs
+
EXTRA_DIST = \
cutest \
Makefile.tests
diff --git a/build/certs/Makefile.am b/build/certs/Makefile.am
new file mode 100644
index 0000000..03dca0d
--- /dev/null
+++ b/build/certs/Makefile.am
@@ -0,0 +1,27 @@
+
+# Note that nothing here is distributed. It just lives in the git repository
+# We copy everything into its final location, and those test files are
+# distributed in the tarballs
+
+TRUST = $(top_srcdir)/trust/tests
+
+prepare-certs:
+ cp -v cacert3.der $(TRUST)/anchors
+ cp -v cacert3.der $(TRUST)/files
+ cp -v cacert-ca.der $(TRUST)/certificates
+ cp -v cacert-ca.der $(TRUST)/files
+ cp -v self-server.der $(TRUST)/files
+ cp -v self-signed-with-eku.der $(TRUST)/certificates
+ cp -v self-signed-with-ku.der $(TRUST)/certificates
+ cp -v testing-ca.der $(TRUST)/anchors
+ cp -v testing-server.der $(TRUST)/files
+
+# Rebuild the self-signed certificates. This is almost never necessary and
+# will require other changes in the code, mostly here as documentation
+build-self-signed:
+ openssl req -new -x509 -outform DER -out self-signed-with-eku.der \
+ -newkey rsa -keyout /dev/null -nodes -subj /CN=self-signed-with-eku.example.com \
+ -config with-eku.conf -set_serial 888 -extensions v3_ca
+ openssl req -new -x509 -outform DER -out self-signed-with-ku.der \
+ -newkey rsa -keyout /dev/null -nodes -subj /CN=self-signed-with-ku.example.com \
+ -config with-ku.conf -set_serial 888 -extensions v3_ca
diff --git a/build/certs/cacert-ca.der b/build/certs/cacert-ca.der
new file mode 100644
index 0000000..719b0ff
--- /dev/null
+++ b/build/certs/cacert-ca.der
Binary files differ
diff --git a/build/certs/cacert3.der b/build/certs/cacert3.der
new file mode 100644
index 0000000..56f8c88
--- /dev/null
+++ b/build/certs/cacert3.der
Binary files differ
diff --git a/build/certs/self-server.der b/build/certs/self-server.der
new file mode 100644
index 0000000..68fe9af
--- /dev/null
+++ b/build/certs/self-server.der
Binary files differ
diff --git a/build/certs/self-signed-with-eku.der b/build/certs/self-signed-with-eku.der
new file mode 100644
index 0000000..33e0760
--- /dev/null
+++ b/build/certs/self-signed-with-eku.der
Binary files differ
diff --git a/build/certs/self-signed-with-ku.der b/build/certs/self-signed-with-ku.der
new file mode 100644
index 0000000..e6f36e3
--- /dev/null
+++ b/build/certs/self-signed-with-ku.der
Binary files differ
diff --git a/build/certs/testing-ca.der b/build/certs/testing-ca.der
new file mode 100644
index 0000000..d3f70ea
--- /dev/null
+++ b/build/certs/testing-ca.der
Binary files differ
diff --git a/build/certs/testing-server.der b/build/certs/testing-server.der
new file mode 100644
index 0000000..cf2de65
--- /dev/null
+++ b/build/certs/testing-server.der
Binary files differ
diff --git a/build/certs/with-eku.conf b/build/certs/with-eku.conf
new file mode 100644
index 0000000..8eab21d
--- /dev/null
+++ b/build/certs/with-eku.conf
@@ -0,0 +1,19 @@
+#
+# Use with the following command
+# $ openssl req -new -x509 -outform DER -out self-signed-with-ku.pem \
+# -newkey rsa -keyout self-signed-with-ku.key -nodes \
+# -config with-ku.conf -set_serial 888 -extensions v3_ca
+#
+
+[ req ]
+default_bits = 1024
+distinguished_name = req_distinguished_name
+x509_extensions = v3_ca
+dirstring_type = nobmp
+
+[ req_distinguished_name ]
+commonName = Common Name
+commonName_max = 64
+
+[ v3_ca ]
+keyUsage=keyCertSign,digitalSignature \ No newline at end of file
diff --git a/build/certs/with-ku.conf b/build/certs/with-ku.conf
new file mode 100644
index 0000000..aa0acc1
--- /dev/null
+++ b/build/certs/with-ku.conf
@@ -0,0 +1,19 @@
+#
+# Use with the following command
+# $ openssl req -new -x509 -outform DER -out self-signed-with-eku.pem \
+# -newkey rsa -keyout self-signed-with-eku.key -nodes \
+# -config with-eku.conf -set_serial 888 -extensions v3_ca
+#
+
+[ req ]
+default_bits = 1024
+distinguished_name = req_distinguished_name
+x509_extensions = v3_ca
+dirstring_type = nobmp
+
+[ req_distinguished_name ]
+commonName = Common Name
+commonName_max = 64
+
+[ v3_ca ]
+extendedKeyUsage=clientAuth,emailProtection,1.2.3.4 \ No newline at end of file
diff --git a/common/Makefile.am b/common/Makefile.am
index aae9b35..5f2852e 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -26,17 +26,24 @@ libp11_library_la_SOURCES = \
dict.c dict.h \
library.c library.h \
pkcs11.h pkcs11x.h \
- pkix.asn pkix.asn.h \
$(NULL)
+libp11_mock_la_SOURCES = \
+ mock.c mock.h \
+ $(NULL)
+
+if WITH_ASN1
+
noinst_LTLIBRARIES += \
libp11-data.la \
$(NULL)
libp11_data_la_SOURCES = \
checksum.c checksum.h \
+ pkix.asn pkix.asn.h \
$(NULL)
-libp11_mock_la_SOURCES = \
- mock.c mock.h \
- $(NULL)
+asn:
+ asn1Parser -o pkix.asn.h pkix.asn
+
+endif # WITH_ASN1
diff --git a/common/compat.c b/common/compat.c
index a22071a..74fb130 100644
--- a/common/compat.c
+++ b/common/compat.c
@@ -37,6 +37,7 @@
#include "compat.h"
#include <assert.h>
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -185,6 +186,72 @@ p11_thread_join (p11_thread_t thread)
#endif /* OS_WIN32 */
+#ifndef HAVE_STRNSTR
+
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+#include <string.h>
+
+/*
+ * Find the first occurrence of find in s, where the search is limited to the
+ * first slen characters of s.
+ */
+char *
+strnstr (const char *s,
+ const char *find,
+ size_t slen)
+{
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != '\0') {
+ len = strlen (find);
+ do {
+ do {
+ if (slen-- < 1 || (sc = *s++) == '\0')
+ return (NULL);
+ } while (sc != c);
+ if (len > slen)
+ return (NULL);
+ } while (strncmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+
+#endif /* HAVE_STRNSTR */
+
#ifndef HAVE_MEMDUP
void *
@@ -204,3 +271,43 @@ memdup (void *data,
}
#endif /* HAVE_MEMDUP */
+
+#ifndef HAVE_STRCONCAT
+
+#include <stdarg.h>
+
+char *
+strconcat (const char *first,
+ ...)
+{
+ size_t length = 0;
+ const char *arg;
+ char *result, *at;
+ va_list va;
+
+ va_start (va, first);
+
+ for (arg = first; arg; arg = va_arg (va, const char*))
+ length += strlen (arg);
+
+ va_end (va);
+
+ at = result = malloc (length + 1);
+ if (result == NULL)
+ return NULL;
+
+ va_start (va, first);
+
+ for (arg = first; arg; arg = va_arg (va, const char*)) {
+ length = strlen (arg);
+ memcpy (at, arg, length);
+ at += length;
+ }
+
+ va_end (va);
+
+ *at = 0;
+ return result;
+}
+
+#endif /* HAVE_STRCONCAT */
diff --git a/common/compat.h b/common/compat.h
index 6305768..68786a7 100644
--- a/common/compat.h
+++ b/common/compat.h
@@ -39,8 +39,6 @@
#include <sys/types.h>
-typedef enum { false, true } bool;
-
#if !defined(__cplusplus) && (__GNUC__ > 2)
#define GNUC_PRINTF(x, y) __attribute__((__format__(__printf__, x, y)))
#else
@@ -175,6 +173,14 @@ typedef void * dl_module_t;
#include <errno.h>
#endif /* HAVE_ERRNO_H */
+#ifndef HAVE_STRNSTR
+
+char * strnstr (const char *s,
+ const char *find,
+ size_t slen);
+
+#endif /* HAVE_STRNSTR */
+
#ifndef HAVE_MEMDUP
void * memdup (void *data,
@@ -188,4 +194,11 @@ void * memdup (void *data,
typedef enum { false, true } bool;
#endif
+#ifndef HAVE_STRCONCAT
+
+char * strconcat (const char *first,
+ ...) GNUC_NULL_TERMINATED;
+
+#endif /* HAVE_STRCONCAT */
+
#endif /* __COMPAT_H__ */
diff --git a/common/debug.c b/common/debug.c
index 2728bf6..1ef51d3 100644
--- a/common/debug.c
+++ b/common/debug.c
@@ -55,6 +55,7 @@ static struct DebugKey debug_keys[] = {
{ "conf", P11_DEBUG_CONF },
{ "uri", P11_DEBUG_URI },
{ "proxy", P11_DEBUG_PROXY },
+ { "trust", P11_DEBUG_TRUST },
{ 0, }
};
diff --git a/common/debug.h b/common/debug.h
index 2374b6f..ff2af0f 100644
--- a/common/debug.h
+++ b/common/debug.h
@@ -43,6 +43,7 @@ enum {
P11_DEBUG_CONF = 1 << 2,
P11_DEBUG_URI = 1 << 3,
P11_DEBUG_PROXY = 1 << 4,
+ P11_DEBUG_TRUST = 1 << 5,
};
extern int p11_debug_current_flags;
@@ -83,6 +84,16 @@ void p11_debug_precond (const char *format,
return v; \
} while (false)
+#define warn_if_reached(v) \
+ do { \
+ p11_debug_precond ("p11-kit: shouldn't be reached at %s\n", __func__); \
+ } while (false)
+
+#define warn_if_fail(x) \
+ do { if (!(x)) { \
+ p11_debug_precond ("p11-kit: '%s' not true at %s\n", #x, __func__); \
+ } } while (false)
+
#endif /* DEBUG_H */
/* -----------------------------------------------------------------------------
diff --git a/common/pkix.asn b/common/pkix.asn
new file mode 100644
index 0000000..38bb028
--- /dev/null
+++ b/common/pkix.asn
@@ -0,0 +1,566 @@
+
+PKIX1 { }
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+-- This contains both PKIX1Implicit88 and RFC2630 ASN.1 modules.
+
+id-pkix OBJECT IDENTIFIER ::=
+ { iso(1) identified-organization(3) dod(6) internet(1)
+ security(5) mechanisms(5) pkix(7) }
+
+-- ISO arc for standard certificate and CRL extensions
+
+-- authority key identifier OID and syntax
+
+AuthorityKeyIdentifier ::= SEQUENCE {
+ keyIdentifier [0] KeyIdentifier OPTIONAL,
+ authorityCertIssuer [1] GeneralNames OPTIONAL,
+ authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ -- authorityCertIssuer and authorityCertSerialNumber shall both
+ -- be present or both be absgent
+
+KeyIdentifier ::= OCTET STRING
+
+-- subject key identifier OID and syntax
+
+SubjectKeyIdentifier ::= KeyIdentifier
+
+-- key usage extension OID and syntax
+
+KeyUsage ::= BIT STRING
+
+-- Directory string type --
+
+DirectoryString ::= CHOICE {
+ teletexString TeletexString (SIZE (1..MAX)),
+ printableString PrintableString (SIZE (1..MAX)),
+ universalString UniversalString (SIZE (1..MAX)),
+ utf8String UTF8String (SIZE (1..MAX)),
+ bmpString BMPString (SIZE(1..MAX)),
+ -- IA5String is added here to handle old UID encoded as ia5String --
+ -- See tests/userid/ for more information. It shouldn't be here, --
+ -- so if it causes problems, considering dropping it. --
+ ia5String IA5String (SIZE(1..MAX)) }
+
+SubjectAltName ::= GeneralNames
+
+GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+
+GeneralName ::= CHOICE {
+ otherName [0] AnotherName,
+ rfc822Name [1] IA5String,
+ dNSName [2] IA5String,
+ x400Address [3] ANY,
+-- Changed to work with the libtasn1 parser.
+ directoryName [4] EXPLICIT RDNSequence, --Name,
+ ediPartyName [5] ANY, --EDIPartyName replaced by ANY to save memory
+ uniformResourceIdentifier [6] IA5String,
+ iPAddress [7] OCTET STRING,
+ registeredID [8] OBJECT IDENTIFIER }
+
+-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as
+-- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax
+
+AnotherName ::= SEQUENCE {
+ type-id OBJECT IDENTIFIER,
+ value [0] EXPLICIT ANY DEFINED BY type-id }
+
+-- issuer alternative name extension OID and syntax
+
+IssuerAltName ::= GeneralNames
+
+-- basic constraints extension OID and syntax
+
+BasicConstraints ::= SEQUENCE {
+ cA BOOLEAN DEFAULT FALSE,
+ pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+
+-- CRL distribution points extension OID and syntax
+
+CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+
+DistributionPoint ::= SEQUENCE {
+ distributionPoint [0] EXPLICIT DistributionPointName OPTIONAL,
+ reasons [1] ReasonFlags OPTIONAL,
+ cRLIssuer [2] GeneralNames OPTIONAL
+}
+
+DistributionPointName ::= CHOICE {
+ fullName [0] GeneralNames,
+ nameRelativeToCRLIssuer [1] RelativeDistinguishedName
+}
+
+ReasonFlags ::= BIT STRING
+
+-- extended key usage extension OID and syntax
+
+ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+
+KeyPurposeId ::= OBJECT IDENTIFIER
+
+-- CRL number extension OID and syntax
+
+CRLNumber ::= INTEGER (0..MAX)
+
+-- certificate issuer CRL entry extension OID and syntax
+
+CertificateIssuer ::= GeneralNames
+
+-- --------------------------------------
+-- EXPLICIT
+-- --------------------------------------
+
+-- UNIVERSAL Types defined in '93 and '98 ASN.1
+-- but required by this specification
+
+NumericString ::= [UNIVERSAL 18] IMPLICIT OCTET STRING
+
+IA5String ::= [UNIVERSAL 22] IMPLICIT OCTET STRING
+
+TeletexString ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
+
+PrintableString ::= [UNIVERSAL 19] IMPLICIT OCTET STRING
+
+UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING
+ -- UniversalString is defined in ASN.1:1993
+
+BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING
+ -- BMPString is the subtype of UniversalString and models
+ -- the Basic Multilingual Plane of ISO/IEC/ITU 10646-1
+
+UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING
+ -- The content of this type conforms to RFC 2279.
+
+
+-- attribute data types --
+
+Attribute ::= SEQUENCE {
+ type AttributeType,
+ values SET OF AttributeValue
+ -- at least one value is required --
+}
+
+AttributeType ::= OBJECT IDENTIFIER
+
+AttributeValue ::= ANY DEFINED BY type
+
+AttributeTypeAndValue ::= SEQUENCE {
+ type AttributeType,
+ value AttributeValue }
+
+-- suggested naming attributes: Definition of the following
+-- information object set may be augmented to meet local
+-- requirements. Note that deleting members of the set may
+-- prevent interoperability with conforming implementations.
+-- presented in pairs: the AttributeType followed by the
+-- type definition for the corresponding AttributeValue
+
+-- Arc for standard naming attributes
+id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4}
+
+-- Attributes of type NameDirectoryString
+
+-- gnutls: Note that the Object ID (id-at*) is being set just before the
+-- actual definition. This is done in order for asn1_find_structure_from_oid
+-- to work (locate structure from OID).
+-- Maybe this is inefficient and memory consuming. Should we replace with
+-- a table that maps OIDs to structures?
+
+PostalAddress ::= SEQUENCE OF DirectoryString
+
+ -- Legacy attributes
+
+emailAddress AttributeType ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 1 }
+
+Pkcs9email ::= IA5String (SIZE (1..ub-emailaddress-length))
+
+-- naming data types --
+
+Name ::= CHOICE { -- only one possibility for now --
+ rdnSequence RDNSequence }
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+DistinguishedName ::= RDNSequence
+
+RelativeDistinguishedName ::=
+ SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+
+
+
+-- --------------------------------------------------------
+-- certificate and CRL specific structures begin here
+-- --------------------------------------------------------
+
+Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING }
+
+TBSCertificate ::= SEQUENCE {
+ version [0] EXPLICIT Version DEFAULT v1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier,
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ -- If present, version shall be v2 or v3
+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ -- If present, version shall be v2 or v3
+ extensions [3] EXPLICIT Extensions OPTIONAL
+ -- If present, version shall be v3 --
+}
+
+Version ::= INTEGER { v1(0), v2(1), v3(2) }
+
+CertificateSerialNumber ::= INTEGER
+
+Validity ::= SEQUENCE {
+ notBefore Time,
+ notAfter Time }
+
+Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime }
+
+UniqueIdentifier ::= BIT STRING
+
+SubjectPublicKeyInfo ::= SEQUENCE {
+ algorithm AlgorithmIdentifier,
+ subjectPublicKey BIT STRING }
+
+Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+
+Extension ::= SEQUENCE {
+ extnID OBJECT IDENTIFIER,
+ critical BOOLEAN DEFAULT FALSE,
+ extnValue OCTET STRING }
+
+
+-- ------------------------------------------
+-- CRL structures
+-- ------------------------------------------
+
+CertificateList ::= SEQUENCE {
+ tbsCertList TBSCertList,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING }
+
+TBSCertList ::= SEQUENCE {
+ version Version OPTIONAL,
+ -- if present, shall be v2
+ signature AlgorithmIdentifier,
+ issuer Name,
+ thisUpdate Time,
+ nextUpdate Time OPTIONAL,
+ revokedCertificates SEQUENCE OF SEQUENCE {
+ userCertificate CertificateSerialNumber,
+ revocationDate Time,
+ crlEntryExtensions Extensions OPTIONAL
+ -- if present, shall be v2
+ } OPTIONAL,
+ crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ -- if present, shall be v2 --
+}
+
+-- Version, Time, CertificateSerialNumber, and Extensions were
+-- defined earlier for use in the certificate structure
+
+AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters ANY DEFINED BY algorithm OPTIONAL }
+ -- contains a value of the type
+ -- registered for use with the
+ -- algorithm object identifier value
+
+-- Algorithm OIDs and parameter structures
+
+Dss-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+}
+
+DomainParameters ::= SEQUENCE {
+ p INTEGER, -- odd prime, p=jq +1
+ g INTEGER, -- generator, g
+ q INTEGER, -- factor of p-1
+ j INTEGER OPTIONAL, -- subgroup factor, j>= 2
+ validationParms ValidationParms OPTIONAL }
+
+ValidationParms ::= SEQUENCE {
+ seed BIT STRING,
+ pgenCounter INTEGER }
+
+Dss-Parms ::= SEQUENCE {
+ p INTEGER,
+ q INTEGER,
+ g INTEGER }
+
+-- x400 address syntax starts here
+-- OR Names
+
+CountryName ::= [APPLICATION 1] CHOICE {
+ x121-dcc-code NumericString
+ (SIZE (ub-country-name-numeric-length)),
+ iso-3166-alpha2-code PrintableString
+ (SIZE (ub-country-name-alpha-length)) }
+
+OrganizationName ::= PrintableString
+ (SIZE (1..ub-organization-name-length))
+-- see also teletex-organization-name
+
+NumericUserIdentifier ::= NumericString
+ (SIZE (1..ub-numeric-user-id-length))
+
+-- see also teletex-personal-name
+
+OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
+ OF OrganizationalUnitName
+-- see also teletex-organizational-unit-names
+
+OrganizationalUnitName ::= PrintableString (SIZE
+ (1..ub-organizational-unit-name-length))
+
+-- Extension types and attribute values
+--
+
+CommonName ::= PrintableString
+
+-- END of PKIX1Implicit88
+
+
+-- BEGIN of RFC2630
+
+-- Cryptographic Message Syntax
+
+pkcs-7-ContentInfo ::= SEQUENCE {
+ contentType pkcs-7-ContentType,
+ content [0] EXPLICIT ANY DEFINED BY contentType }
+
+pkcs-7-DigestInfo ::= SEQUENCE {
+ digestAlgorithm pkcs-7-DigestAlgorithmIdentifier,
+ digest pkcs-7-Digest
+}
+
+pkcs-7-Digest ::= OCTET STRING
+
+pkcs-7-ContentType ::= OBJECT IDENTIFIER
+
+pkcs-7-SignedData ::= SEQUENCE {
+ version pkcs-7-CMSVersion,
+ digestAlgorithms pkcs-7-DigestAlgorithmIdentifiers,
+ encapContentInfo pkcs-7-EncapsulatedContentInfo,
+ certificates [0] IMPLICIT pkcs-7-CertificateSet OPTIONAL,
+ crls [1] IMPLICIT pkcs-7-CertificateRevocationLists OPTIONAL,
+ signerInfos pkcs-7-SignerInfos
+}
+
+pkcs-7-CMSVersion ::= INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) }
+
+pkcs-7-DigestAlgorithmIdentifiers ::= SET OF pkcs-7-DigestAlgorithmIdentifier
+
+pkcs-7-DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+
+pkcs-7-EncapsulatedContentInfo ::= SEQUENCE {
+ eContentType pkcs-7-ContentType,
+ eContent [0] EXPLICIT OCTET STRING OPTIONAL }
+
+-- We don't use CertificateList here since we only want
+-- to read the raw data.
+pkcs-7-CertificateRevocationLists ::= SET OF ANY
+
+pkcs-7-CertificateChoices ::= CHOICE {
+-- Although the paper uses Certificate type, we
+-- don't use it since, we don't need to parse it.
+-- We only need to read and store it.
+ certificate ANY
+}
+
+pkcs-7-CertificateSet ::= SET OF pkcs-7-CertificateChoices
+
+pkcs-7-SignerInfos ::= SET OF ANY -- this is not correct but we don't use it
+ -- anyway
+
+
+-- BEGIN of RFC2986
+
+-- Certificate requests
+pkcs-10-CertificationRequestInfo ::= SEQUENCE {
+ version INTEGER { v1(0) },
+ subject Name,
+ subjectPKInfo SubjectPublicKeyInfo,
+ attributes [0] Attributes
+}
+
+Attributes ::= SET OF Attribute
+
+pkcs-10-CertificationRequest ::= SEQUENCE {
+ certificationRequestInfo pkcs-10-CertificationRequestInfo,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING
+}
+
+-- stuff from PKCS#9
+
+pkcs-9-at-challengePassword OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 7}
+
+pkcs-9-challengePassword ::= CHOICE {
+ printableString PrintableString,
+ utf8String UTF8String }
+
+pkcs-9-localKeyId ::= OCTET STRING
+
+-- PKCS #8 stuff
+
+-- Private-key information syntax
+
+pkcs-8-PrivateKeyInfo ::= SEQUENCE {
+ version pkcs-8-Version,
+ privateKeyAlgorithm AlgorithmIdentifier,
+ privateKey pkcs-8-PrivateKey,
+ attributes [0] Attributes OPTIONAL }
+
+pkcs-8-Version ::= INTEGER {v1(0)}
+
+pkcs-8-PrivateKey ::= OCTET STRING
+
+pkcs-8-Attributes ::= SET OF Attribute
+
+-- Encrypted private-key information syntax
+
+pkcs-8-EncryptedPrivateKeyInfo ::= SEQUENCE {
+ encryptionAlgorithm AlgorithmIdentifier,
+ encryptedData pkcs-8-EncryptedData
+}
+
+pkcs-8-EncryptedData ::= OCTET STRING
+
+-- PKCS #5 stuff
+
+pkcs-5-des-EDE3-CBC-params ::= OCTET STRING (SIZE(8))
+pkcs-5-aes128-CBC-params ::= OCTET STRING (SIZE(16))
+pkcs-5-aes192-CBC-params ::= OCTET STRING (SIZE(16))
+pkcs-5-aes256-CBC-params ::= OCTET STRING (SIZE(16))
+
+pkcs-5-PBES2-params ::= SEQUENCE {
+ keyDerivationFunc AlgorithmIdentifier,
+ encryptionScheme AlgorithmIdentifier }
+
+-- PBKDF2
+
+-- pkcs-5-algid-hmacWithSHA1 AlgorithmIdentifier ::=
+-- {algorithm pkcs-5-id-hmacWithSHA1, parameters NULL : NULL}
+
+pkcs-5-PBKDF2-params ::= SEQUENCE {
+ salt CHOICE {
+ specified OCTET STRING,
+ otherSource AlgorithmIdentifier
+ },
+ iterationCount INTEGER (1..MAX),
+ keyLength INTEGER (1..MAX) OPTIONAL,
+ prf AlgorithmIdentifier OPTIONAL -- DEFAULT pkcs-5-id-hmacWithSHA1
+}
+
+-- PKCS #12 stuff
+
+pkcs-12-PFX ::= SEQUENCE {
+ version INTEGER {v3(3)},
+ authSafe pkcs-7-ContentInfo,
+ macData pkcs-12-MacData OPTIONAL
+}
+
+pkcs-12-PbeParams ::= SEQUENCE {
+ salt OCTET STRING,
+ iterations INTEGER
+}
+
+pkcs-12-MacData ::= SEQUENCE {
+ mac pkcs-7-DigestInfo,
+ macSalt OCTET STRING,
+ iterations INTEGER DEFAULT 1
+-- Note: The default is for historical reasons and its use is
+-- deprecated. A higher value, like 1024 is recommended.
+}
+
+pkcs-12-AuthenticatedSafe ::= SEQUENCE OF pkcs-7-ContentInfo
+ -- Data if unencrypted
+ -- EncryptedData if password-encrypted
+ -- EnvelopedData if public key-encrypted
+
+pkcs-12-SafeContents ::= SEQUENCE OF pkcs-12-SafeBag
+
+pkcs-12-SafeBag ::= SEQUENCE {
+ bagId OBJECT IDENTIFIER,
+ bagValue [0] EXPLICIT ANY DEFINED BY badId,
+ bagAttributes SET OF pkcs-12-PKCS12Attribute OPTIONAL
+}
+
+-- Bag types
+
+pkcs-12-KeyBag ::= pkcs-8-PrivateKeyInfo
+
+-- Shrouded KeyBag
+
+pkcs-12-PKCS8ShroudedKeyBag ::= pkcs-8-EncryptedPrivateKeyInfo
+
+-- CertBag
+
+pkcs-12-CertBag ::= SEQUENCE {
+ certId OBJECT IDENTIFIER,
+ certValue [0] EXPLICIT ANY DEFINED BY certId
+}
+
+-- x509Certificate BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {pkcs-9-certTypes 1}}
+-- DER-encoded X.509 certificate stored in OCTET STRING
+
+pkcs-12-CRLBag ::= SEQUENCE {
+ crlId OBJECT IDENTIFIER,
+ crlValue [0] EXPLICIT ANY DEFINED BY crlId
+}
+
+pkcs-12-SecretBag ::= SEQUENCE {
+ secretTypeId OBJECT IDENTIFIER,
+ secretValue [0] EXPLICIT ANY DEFINED BY secretTypeId
+}
+
+-- x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {pkcs-9-crlTypes 1}}
+-- DER-encoded X.509 CRL stored in OCTET STRING
+
+pkcs-12-PKCS12Attribute ::= Attribute
+
+-- PKCS #7 stuff (needed in PKCS 12)
+
+pkcs-7-Data ::= OCTET STRING
+
+pkcs-7-EncryptedData ::= SEQUENCE {
+ version pkcs-7-CMSVersion,
+ encryptedContentInfo pkcs-7-EncryptedContentInfo,
+ unprotectedAttrs [1] IMPLICIT pkcs-7-UnprotectedAttributes OPTIONAL }
+
+pkcs-7-EncryptedContentInfo ::= SEQUENCE {
+ contentType pkcs-7-ContentType,
+ contentEncryptionAlgorithm pkcs-7-ContentEncryptionAlgorithmIdentifier,
+ encryptedContent [0] IMPLICIT pkcs-7-EncryptedContent OPTIONAL }
+
+pkcs-7-ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+
+pkcs-7-EncryptedContent ::= OCTET STRING
+
+pkcs-7-UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute
+
+-- rfc3820
+
+ProxyCertInfo ::= SEQUENCE {
+ pCPathLenConstraint INTEGER (0..MAX) OPTIONAL,
+ proxyPolicy ProxyPolicy }
+
+ProxyPolicy ::= SEQUENCE {
+ policyLanguage OBJECT IDENTIFIER,
+ policy OCTET STRING OPTIONAL }
+
+END
diff --git a/common/pkix.asn.h b/common/pkix.asn.h
new file mode 100644
index 0000000..d5d5cc4
--- /dev/null
+++ b/common/pkix.asn.h
@@ -0,0 +1,408 @@
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <libtasn1.h>
+
+const ASN1_ARRAY_TYPE pkix_asn1_tab[] = {
+ { "PKIX1", 536875024, NULL },
+ { NULL, 1073741836, NULL },
+ { "id-pkix", 1879048204, NULL },
+ { "iso", 1073741825, "1"},
+ { "identified-organization", 1073741825, "3"},
+ { "dod", 1073741825, "6"},
+ { "internet", 1073741825, "1"},
+ { "security", 1073741825, "5"},
+ { "mechanisms", 1073741825, "5"},
+ { "pkix", 1, "7"},
+ { "AuthorityKeyIdentifier", 1610612741, NULL },
+ { "keyIdentifier", 1610637314, "KeyIdentifier"},
+ { NULL, 4104, "0"},
+ { "authorityCertIssuer", 1610637314, "GeneralNames"},
+ { NULL, 4104, "1"},
+ { "authorityCertSerialNumber", 536895490, "CertificateSerialNumber"},
+ { NULL, 4104, "2"},
+ { "KeyIdentifier", 1073741831, NULL },
+ { "SubjectKeyIdentifier", 1073741826, "KeyIdentifier"},
+ { "KeyUsage", 1073741830, NULL },
+ { "DirectoryString", 1610612754, NULL },
+ { "teletexString", 1612709890, "TeletexString"},
+ { "MAX", 524298, "1"},
+ { "printableString", 1612709890, "PrintableString"},
+ { "MAX", 524298, "1"},
+ { "universalString", 1612709890, "UniversalString"},
+ { "MAX", 524298, "1"},
+ { "utf8String", 1612709890, "UTF8String"},
+ { "MAX", 524298, "1"},
+ { "bmpString", 1612709890, "BMPString"},
+ { "MAX", 524298, "1"},
+ { "ia5String", 538968066, "IA5String"},
+ { "MAX", 524298, "1"},
+ { "SubjectAltName", 1073741826, "GeneralNames"},
+ { "GeneralNames", 1612709899, NULL },
+ { "MAX", 1074266122, "1"},
+ { NULL, 2, "GeneralName"},
+ { "GeneralName", 1610612754, NULL },
+ { "otherName", 1610620930, "AnotherName"},
+ { NULL, 4104, "0"},
+ { "rfc822Name", 1610620930, "IA5String"},
+ { NULL, 4104, "1"},
+ { "dNSName", 1610620930, "IA5String"},
+ { NULL, 4104, "2"},
+ { "x400Address", 1610620941, NULL },
+ { NULL, 4104, "3"},
+ { "directoryName", 1610620930, "RDNSequence"},
+ { NULL, 2056, "4"},
+ { "ediPartyName", 1610620941, NULL },
+ { NULL, 4104, "5"},
+ { "uniformResourceIdentifier", 1610620930, "IA5String"},
+ { NULL, 4104, "6"},
+ { "iPAddress", 1610620935, NULL },
+ { NULL, 4104, "7"},
+ { "registeredID", 536879116, NULL },
+ { NULL, 4104, "8"},
+ { "AnotherName", 1610612741, NULL },
+ { "type-id", 1073741836, NULL },
+ { "value", 541073421, NULL },
+ { NULL, 1073743880, "0"},
+ { "type-id", 1, NULL },
+ { "IssuerAltName", 1073741826, "GeneralNames"},
+ { "BasicConstraints", 1610612741, NULL },
+ { "cA", 1610645508, NULL },
+ { NULL, 131081, NULL },
+ { "pathLenConstraint", 537411587, NULL },
+ { "0", 10, "MAX"},
+ { "CRLDistributionPoints", 1612709899, NULL },
+ { "MAX", 1074266122, "1"},
+ { NULL, 2, "DistributionPoint"},
+ { "DistributionPoint", 1610612741, NULL },
+ { "distributionPoint", 1610637314, "DistributionPointName"},
+ { NULL, 2056, "0"},
+ { "reasons", 1610637314, "ReasonFlags"},
+ { NULL, 4104, "1"},
+ { "cRLIssuer", 536895490, "GeneralNames"},
+ { NULL, 4104, "2"},
+ { "DistributionPointName", 1610612754, NULL },
+ { "fullName", 1610620930, "GeneralNames"},
+ { NULL, 4104, "0"},
+ { "nameRelativeToCRLIssuer", 536879106, "RelativeDistinguishedName"},
+ { NULL, 4104, "1"},
+ { "ReasonFlags", 1073741830, NULL },
+ { "ExtKeyUsageSyntax", 1612709899, NULL },
+ { "MAX", 1074266122, "1"},
+ { NULL, 2, "KeyPurposeId"},
+ { "KeyPurposeId", 1073741836, NULL },
+ { "CRLNumber", 1611137027, NULL },
+ { "0", 10, "MAX"},
+ { "CertificateIssuer", 1073741826, "GeneralNames"},
+ { "NumericString", 1610620935, NULL },
+ { NULL, 4360, "18"},
+ { "IA5String", 1610620935, NULL },
+ { NULL, 4360, "22"},
+ { "TeletexString", 1610620935, NULL },
+ { NULL, 4360, "20"},
+ { "PrintableString", 1610620935, NULL },
+ { NULL, 4360, "19"},
+ { "UniversalString", 1610620935, NULL },
+ { NULL, 4360, "28"},
+ { "BMPString", 1610620935, NULL },
+ { NULL, 4360, "30"},
+ { "UTF8String", 1610620935, NULL },
+ { NULL, 4360, "12"},
+ { "Attribute", 1610612741, NULL },
+ { "type", 1073741826, "AttributeType"},
+ { "values", 536870927, NULL },
+ { NULL, 2, "AttributeValue"},
+ { "AttributeType", 1073741836, NULL },
+ { "AttributeValue", 1614807053, NULL },
+ { "type", 1, NULL },
+ { "AttributeTypeAndValue", 1610612741, NULL },
+ { "type", 1073741826, "AttributeType"},
+ { "value", 2, "AttributeValue"},
+ { "id-at", 1879048204, NULL },
+ { "joint-iso-ccitt", 1073741825, "2"},
+ { "ds", 1073741825, "5"},
+ { NULL, 1, "4"},
+ { "PostalAddress", 1610612747, NULL },
+ { NULL, 2, "DirectoryString"},
+ { "emailAddress", 1880096780, "AttributeType"},
+ { "iso", 1073741825, "1"},
+ { "member-body", 1073741825, "2"},
+ { "us", 1073741825, "840"},
+ { "rsadsi", 1073741825, "113549"},
+ { "pkcs", 1073741825, "1"},
+ { NULL, 1073741825, "9"},
+ { NULL, 1, "1"},
+ { "Pkcs9email", 1612709890, "IA5String"},
+ { "ub-emailaddress-length", 524298, "1"},
+ { "Name", 1610612754, NULL },
+ { "rdnSequence", 2, "RDNSequence"},
+ { "RDNSequence", 1610612747, NULL },
+ { NULL, 2, "RelativeDistinguishedName"},
+ { "DistinguishedName", 1073741826, "RDNSequence"},
+ { "RelativeDistinguishedName", 1612709903, NULL },
+ { "MAX", 1074266122, "1"},
+ { NULL, 2, "AttributeTypeAndValue"},
+ { "Certificate", 1610612741, NULL },
+ { "tbsCertificate", 1073741826, "TBSCertificate"},
+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ { "signature", 6, NULL },
+ { "TBSCertificate", 1610612741, NULL },
+ { "version", 1610653698, "Version"},
+ { NULL, 1073741833, "v1"},
+ { NULL, 2056, "0"},
+ { "serialNumber", 1073741826, "CertificateSerialNumber"},
+ { "signature", 1073741826, "AlgorithmIdentifier"},
+ { "issuer", 1073741826, "Name"},
+ { "validity", 1073741826, "Validity"},
+ { "subject", 1073741826, "Name"},
+ { "subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"},
+ { "issuerUniqueID", 1610637314, "UniqueIdentifier"},
+ { NULL, 4104, "1"},
+ { "subjectUniqueID", 1610637314, "UniqueIdentifier"},
+ { NULL, 4104, "2"},
+ { "extensions", 536895490, "Extensions"},
+ { NULL, 2056, "3"},
+ { "Version", 1610874883, NULL },
+ { "v1", 1073741825, "0"},
+ { "v2", 1073741825, "1"},
+ { "v3", 1, "2"},
+ { "CertificateSerialNumber", 1073741827, NULL },
+ { "Validity", 1610612741, NULL },
+ { "notBefore", 1073741826, "Time"},
+ { "notAfter", 2, "Time"},
+ { "Time", 1610612754, NULL },
+ { "utcTime", 1090519057, NULL },
+ { "generalTime", 8388625, NULL },
+ { "UniqueIdentifier", 1073741830, NULL },
+ { "SubjectPublicKeyInfo", 1610612741, NULL },
+ { "algorithm", 1073741826, "AlgorithmIdentifier"},
+ { "subjectPublicKey", 6, NULL },
+ { "Extensions", 1612709899, NULL },
+ { "MAX", 1074266122, "1"},
+ { NULL, 2, "Extension"},
+ { "Extension", 1610612741, NULL },
+ { "extnID", 1073741836, NULL },
+ { "critical", 1610645508, NULL },
+ { NULL, 131081, NULL },
+ { "extnValue", 7, NULL },
+ { "CertificateList", 1610612741, NULL },
+ { "tbsCertList", 1073741826, "TBSCertList"},
+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ { "signature", 6, NULL },
+ { "TBSCertList", 1610612741, NULL },
+ { "version", 1073758210, "Version"},
+ { "signature", 1073741826, "AlgorithmIdentifier"},
+ { "issuer", 1073741826, "Name"},
+ { "thisUpdate", 1073741826, "Time"},
+ { "nextUpdate", 1073758210, "Time"},
+ { "revokedCertificates", 1610629131, NULL },
+ { NULL, 536870917, NULL },
+ { "userCertificate", 1073741826, "CertificateSerialNumber"},
+ { "revocationDate", 1073741826, "Time"},
+ { "crlEntryExtensions", 16386, "Extensions"},
+ { "crlExtensions", 536895490, "Extensions"},
+ { NULL, 2056, "0"},
+ { "AlgorithmIdentifier", 1610612741, NULL },
+ { "algorithm", 1073741836, NULL },
+ { "parameters", 541081613, NULL },
+ { "algorithm", 1, NULL },
+ { "Dss-Sig-Value", 1610612741, NULL },
+ { "r", 1073741827, NULL },
+ { "s", 3, NULL },
+ { "DomainParameters", 1610612741, NULL },
+ { "p", 1073741827, NULL },
+ { "g", 1073741827, NULL },
+ { "q", 1073741827, NULL },
+ { "j", 1073758211, NULL },
+ { "validationParms", 16386, "ValidationParms"},
+ { "ValidationParms", 1610612741, NULL },
+ { "seed", 1073741830, NULL },
+ { "pgenCounter", 3, NULL },
+ { "Dss-Parms", 1610612741, NULL },
+ { "p", 1073741827, NULL },
+ { "q", 1073741827, NULL },
+ { "g", 3, NULL },
+ { "CountryName", 1610620946, NULL },
+ { NULL, 1073746952, "1"},
+ { "x121-dcc-code", 1612709890, "NumericString"},
+ { NULL, 1048586, "ub-country-name-numeric-length"},
+ { "iso-3166-alpha2-code", 538968066, "PrintableString"},
+ { NULL, 1048586, "ub-country-name-alpha-length"},
+ { "OrganizationName", 1612709890, "PrintableString"},
+ { "ub-organization-name-length", 524298, "1"},
+ { "NumericUserIdentifier", 1612709890, "NumericString"},
+ { "ub-numeric-user-id-length", 524298, "1"},
+ { "OrganizationalUnitNames", 1612709899, NULL },
+ { "ub-organizational-units", 1074266122, "1"},
+ { NULL, 2, "OrganizationalUnitName"},
+ { "OrganizationalUnitName", 1612709890, "PrintableString"},
+ { "ub-organizational-unit-name-length", 524298, "1"},
+ { "CommonName", 1073741826, "PrintableString"},
+ { "pkcs-7-ContentInfo", 1610612741, NULL },
+ { "contentType", 1073741826, "pkcs-7-ContentType"},
+ { "content", 541073421, NULL },
+ { NULL, 1073743880, "0"},
+ { "contentType", 1, NULL },
+ { "pkcs-7-DigestInfo", 1610612741, NULL },
+ { "digestAlgorithm", 1073741826, "pkcs-7-DigestAlgorithmIdentifier"},
+ { "digest", 2, "pkcs-7-Digest"},
+ { "pkcs-7-Digest", 1073741831, NULL },
+ { "pkcs-7-ContentType", 1073741836, NULL },
+ { "pkcs-7-SignedData", 1610612741, NULL },
+ { "version", 1073741826, "pkcs-7-CMSVersion"},
+ { "digestAlgorithms", 1073741826, "pkcs-7-DigestAlgorithmIdentifiers"},
+ { "encapContentInfo", 1073741826, "pkcs-7-EncapsulatedContentInfo"},
+ { "certificates", 1610637314, "pkcs-7-CertificateSet"},
+ { NULL, 4104, "0"},
+ { "crls", 1610637314, "pkcs-7-CertificateRevocationLists"},
+ { NULL, 4104, "1"},
+ { "signerInfos", 2, "pkcs-7-SignerInfos"},
+ { "pkcs-7-CMSVersion", 1610874883, NULL },
+ { "v0", 1073741825, "0"},
+ { "v1", 1073741825, "1"},
+ { "v2", 1073741825, "2"},
+ { "v3", 1073741825, "3"},
+ { "v4", 1, "4"},
+ { "pkcs-7-DigestAlgorithmIdentifiers", 1610612751, NULL },
+ { NULL, 2, "pkcs-7-DigestAlgorithmIdentifier"},
+ { "pkcs-7-DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
+ { "pkcs-7-EncapsulatedContentInfo", 1610612741, NULL },
+ { "eContentType", 1073741826, "pkcs-7-ContentType"},
+ { "eContent", 536895495, NULL },
+ { NULL, 2056, "0"},
+ { "pkcs-7-CertificateRevocationLists", 1610612751, NULL },
+ { NULL, 13, NULL },
+ { "pkcs-7-CertificateChoices", 1610612754, NULL },
+ { "certificate", 13, NULL },
+ { "pkcs-7-CertificateSet", 1610612751, NULL },
+ { NULL, 2, "pkcs-7-CertificateChoices"},
+ { "pkcs-7-SignerInfos", 1610612751, NULL },
+ { NULL, 13, NULL },
+ { "pkcs-10-CertificationRequestInfo", 1610612741, NULL },
+ { "version", 1610874883, NULL },
+ { "v1", 1, "0"},
+ { "subject", 1073741826, "Name"},
+ { "subjectPKInfo", 1073741826, "SubjectPublicKeyInfo"},
+ { "attributes", 536879106, "Attributes"},
+ { NULL, 4104, "0"},
+ { "Attributes", 1610612751, NULL },
+ { NULL, 2, "Attribute"},
+ { "pkcs-10-CertificationRequest", 1610612741, NULL },
+ { "certificationRequestInfo", 1073741826, "pkcs-10-CertificationRequestInfo"},
+ { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ { "signature", 6, NULL },
+ { "pkcs-9-at-challengePassword", 1879048204, NULL },
+ { "iso", 1073741825, "1"},
+ { "member-body", 1073741825, "2"},
+ { "us", 1073741825, "840"},
+ { "rsadsi", 1073741825, "113549"},
+ { "pkcs", 1073741825, "1"},
+ { NULL, 1073741825, "9"},
+ { NULL, 1, "7"},
+ { "pkcs-9-challengePassword", 1610612754, NULL },
+ { "printableString", 1073741826, "PrintableString"},
+ { "utf8String", 2, "UTF8String"},
+ { "pkcs-9-localKeyId", 1073741831, NULL },
+ { "pkcs-8-PrivateKeyInfo", 1610612741, NULL },
+ { "version", 1073741826, "pkcs-8-Version"},
+ { "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ { "privateKey", 1073741826, "pkcs-8-PrivateKey"},
+ { "attributes", 536895490, "Attributes"},
+ { NULL, 4104, "0"},
+ { "pkcs-8-Version", 1610874883, NULL },
+ { "v1", 1, "0"},
+ { "pkcs-8-PrivateKey", 1073741831, NULL },
+ { "pkcs-8-Attributes", 1610612751, NULL },
+ { NULL, 2, "Attribute"},
+ { "pkcs-8-EncryptedPrivateKeyInfo", 1610612741, NULL },
+ { "encryptionAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ { "encryptedData", 2, "pkcs-8-EncryptedData"},
+ { "pkcs-8-EncryptedData", 1073741831, NULL },
+ { "pkcs-5-des-EDE3-CBC-params", 1612709895, NULL },
+ { NULL, 1048586, "8"},
+ { "pkcs-5-aes128-CBC-params", 1612709895, NULL },
+ { NULL, 1048586, "16"},
+ { "pkcs-5-aes192-CBC-params", 1612709895, NULL },
+ { NULL, 1048586, "16"},
+ { "pkcs-5-aes256-CBC-params", 1612709895, NULL },
+ { NULL, 1048586, "16"},
+ { "pkcs-5-PBES2-params", 1610612741, NULL },
+ { "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"},
+ { "encryptionScheme", 2, "AlgorithmIdentifier"},
+ { "pkcs-5-PBKDF2-params", 1610612741, NULL },
+ { "salt", 1610612754, NULL },
+ { "specified", 1073741831, NULL },
+ { "otherSource", 2, "AlgorithmIdentifier"},
+ { "iterationCount", 1611137027, NULL },
+ { "1", 10, "MAX"},
+ { "keyLength", 1611153411, NULL },
+ { "1", 10, "MAX"},
+ { "prf", 16386, "AlgorithmIdentifier"},
+ { "pkcs-12-PFX", 1610612741, NULL },
+ { "version", 1610874883, NULL },
+ { "v3", 1, "3"},
+ { "authSafe", 1073741826, "pkcs-7-ContentInfo"},
+ { "macData", 16386, "pkcs-12-MacData"},
+ { "pkcs-12-PbeParams", 1610612741, NULL },
+ { "salt", 1073741831, NULL },
+ { "iterations", 3, NULL },
+ { "pkcs-12-MacData", 1610612741, NULL },
+ { "mac", 1073741826, "pkcs-7-DigestInfo"},
+ { "macSalt", 1073741831, NULL },
+ { "iterations", 536903683, NULL },
+ { NULL, 9, "1"},
+ { "pkcs-12-AuthenticatedSafe", 1610612747, NULL },
+ { NULL, 2, "pkcs-7-ContentInfo"},
+ { "pkcs-12-SafeContents", 1610612747, NULL },
+ { NULL, 2, "pkcs-12-SafeBag"},
+ { "pkcs-12-SafeBag", 1610612741, NULL },
+ { "bagId", 1073741836, NULL },
+ { "bagValue", 1614815245, NULL },
+ { NULL, 1073743880, "0"},
+ { "badId", 1, NULL },
+ { "bagAttributes", 536887311, NULL },
+ { NULL, 2, "pkcs-12-PKCS12Attribute"},
+ { "pkcs-12-KeyBag", 1073741826, "pkcs-8-PrivateKeyInfo"},
+ { "pkcs-12-PKCS8ShroudedKeyBag", 1073741826, "pkcs-8-EncryptedPrivateKeyInfo"},
+ { "pkcs-12-CertBag", 1610612741, NULL },
+ { "certId", 1073741836, NULL },
+ { "certValue", 541073421, NULL },
+ { NULL, 1073743880, "0"},
+ { "certId", 1, NULL },
+ { "pkcs-12-CRLBag", 1610612741, NULL },
+ { "crlId", 1073741836, NULL },
+ { "crlValue", 541073421, NULL },
+ { NULL, 1073743880, "0"},
+ { "crlId", 1, NULL },
+ { "pkcs-12-SecretBag", 1610612741, NULL },
+ { "secretTypeId", 1073741836, NULL },
+ { "secretValue", 541073421, NULL },
+ { NULL, 1073743880, "0"},
+ { "secretTypeId", 1, NULL },
+ { "pkcs-12-PKCS12Attribute", 1073741826, "Attribute"},
+ { "pkcs-7-Data", 1073741831, NULL },
+ { "pkcs-7-EncryptedData", 1610612741, NULL },
+ { "version", 1073741826, "pkcs-7-CMSVersion"},
+ { "encryptedContentInfo", 1073741826, "pkcs-7-EncryptedContentInfo"},
+ { "unprotectedAttrs", 536895490, "pkcs-7-UnprotectedAttributes"},
+ { NULL, 4104, "1"},
+ { "pkcs-7-EncryptedContentInfo", 1610612741, NULL },
+ { "contentType", 1073741826, "pkcs-7-ContentType"},
+ { "contentEncryptionAlgorithm", 1073741826, "pkcs-7-ContentEncryptionAlgorithmIdentifier"},
+ { "encryptedContent", 536895490, "pkcs-7-EncryptedContent"},
+ { NULL, 4104, "0"},
+ { "pkcs-7-ContentEncryptionAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
+ { "pkcs-7-EncryptedContent", 1073741831, NULL },
+ { "pkcs-7-UnprotectedAttributes", 1612709903, NULL },
+ { "MAX", 1074266122, "1"},
+ { NULL, 2, "Attribute"},
+ { "ProxyCertInfo", 1610612741, NULL },
+ { "pCPathLenConstraint", 1611153411, NULL },
+ { "0", 10, "MAX"},
+ { "proxyPolicy", 2, "ProxyPolicy"},
+ { "ProxyPolicy", 536870917, NULL },
+ { "policyLanguage", 1073741836, NULL },
+ { "policy", 16391, NULL },
+ { NULL, 0, NULL }
+};
diff --git a/common/tests/Makefile.am b/common/tests/Makefile.am
index e3f2063..be92e8d 100644
--- a/common/tests/Makefile.am
+++ b/common/tests/Makefile.am
@@ -14,12 +14,10 @@ INCLUDES = \
LDADD = \
$(top_builddir)/common/libp11-library.la \
$(top_builddir)/common/libp11-compat.la \
- $(top_builddir)/common/libp11-data.la \
$(CUTEST_LIBS) \
$(NULL)
CHECK_PROGS = \
- test-checksum \
test-dict \
test-array \
test-attrs \
@@ -30,3 +28,21 @@ noinst_PROGRAMS = \
$(CHECK_PROGS)
TESTS = $(CHECK_PROGS:=$(EXEEXT))
+
+if WITH_ASN1
+
+LDADD += \
+ $(top_builddir)/common/libp11-data.la \
+ $(LIBTASN1_LIBS)
+ $(NULL)
+
+CHECK_PROGS += \
+ test-checksum
+
+noinst_PROGRAMS += \
+ frob-ku \
+ frob-eku \
+ frob-cert \
+ $(NULL)
+
+endif # WITH_ASN1
diff --git a/common/tests/frob-cert.c b/common/tests/frob-cert.c
new file mode 100644
index 0000000..f8ad392
--- /dev/null
+++ b/common/tests/frob-cert.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include "config.h"
+#include "compat.h"
+
+#include <libtasn1.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pkix.asn.h"
+
+#define err_if_fail(ret, msg) \
+ do { if ((ret) != ASN1_SUCCESS) { \
+ fprintf (stderr, "%s: %s\n", msg, asn1_strerror (ret)); \
+ exit (1); \
+ } } while (0)
+
+static ssize_t
+tlv_length (const unsigned char *data,
+ size_t length)
+{
+ unsigned char cls;
+ int counter = 0;
+ int cb, len;
+ unsigned long tag;
+
+ if (asn1_get_tag_der (data, length, &cls, &cb, &tag) == ASN1_SUCCESS) {
+ counter += cb;
+ len = asn1_get_length_der (data + cb, length - cb, &cb);
+ counter += cb;
+ if (len >= 0) {
+ len += counter;
+ if (length >= len)
+ return len;
+ }
+ }
+
+ return -1;
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, };
+ node_asn *definitions = NULL;
+ node_asn *cert = NULL;
+ unsigned char *data;
+ struct stat sb;
+ int start, end;
+ ssize_t len;
+ int ret;
+ int fd;
+
+ if (argc != 4) {
+ fprintf (stderr, "usage: frob-cert struct field filename\n");
+ return 2;
+ }
+
+ ret = asn1_array2tree (pkix_asn1_tab, &definitions, message);
+ if (ret != ASN1_SUCCESS) {
+ fprintf (stderr, "definitions: %s\n", message);
+ return 1;
+ }
+
+ ret = asn1_create_element (definitions, argv[1], &cert);
+ err_if_fail (ret, "Certificate");
+
+ fd = open (argv[3], O_RDONLY);
+ if (fd == -1) {
+ fprintf (stderr, "couldn't open file: %s\n", argv[3]);
+ return 1;
+ }
+
+ if (fstat (fd, &sb) < 0) {
+ fprintf (stderr, "couldn't stat file: %s\n", argv[3]);
+ return 1;
+ }
+
+ data = mmap (NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == NULL) {
+ fprintf (stderr, "couldn't map file: %s\n", argv[3]);
+ return 1;
+ }
+
+ ret = asn1_der_decoding (&cert, data, sb.st_size, message);
+ err_if_fail (ret, message);
+
+ ret = asn1_der_decoding_startEnd (cert, data, sb.st_size, argv[2], &start, &end);
+ err_if_fail (ret, "asn1_der_decoding_startEnd");
+
+ len = tlv_length (data + start, sb.st_size - start);
+ assert (len >= 0);
+
+ fprintf (stderr, "%lu %d %d %ld\n", sb.st_size, start, end, len);
+ fwrite (data + start, 1, len, stdout);
+ fflush (stdout);
+
+ munmap (data, sb.st_size);
+ close (fd);
+
+ asn1_delete_structure (&cert);
+ asn1_delete_structure (&definitions);
+
+ return 0;
+}
diff --git a/common/tests/frob-eku.c b/common/tests/frob-eku.c
new file mode 100644
index 0000000..42bf50b
--- /dev/null
+++ b/common/tests/frob-eku.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include "config.h"
+#include "compat.h"
+
+#include <libtasn1.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pkix.asn.h"
+
+#define err_if_fail(ret, msg) \
+ do { if ((ret) != ASN1_SUCCESS) { \
+ fprintf (stderr, "%s: %s\n", msg, asn1_strerror (ret)); \
+ exit (1); \
+ } } while (0)
+
+int
+main (int argc,
+ char *argv[])
+{
+ char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, };
+ node_asn *definitions = NULL;
+ node_asn *ekus = NULL;
+ char *buf;
+ int len;
+ int ret;
+ int i;
+
+ ret = asn1_array2tree (pkix_asn1_tab, &definitions, message);
+ if (ret != ASN1_SUCCESS) {
+ fprintf (stderr, "definitions: %s\n", message);
+ return 1;
+ }
+
+ ret = asn1_create_element (definitions, "PKIX1.ExtKeyUsageSyntax", &ekus);
+ err_if_fail (ret, "ExtKeyUsageSyntax");
+
+ for (i = 1; i < argc; i++) {
+ ret = asn1_write_value (ekus, "", "NEW", 1);
+ err_if_fail (ret, "NEW");
+
+ ret = asn1_write_value (ekus, "?LAST", argv[i], strlen (argv[i]));
+ err_if_fail (ret, "asn1_write_value");
+ }
+
+ len = 0;
+ ret = asn1_der_coding (ekus, "", NULL, &len, message);
+ assert (ret == ASN1_MEM_ERROR);
+
+ buf = malloc (len);
+ assert (buf != NULL);
+ ret = asn1_der_coding (ekus, "", buf, &len, message);
+ if (ret != ASN1_SUCCESS) {
+ fprintf (stderr, "asn1_der_coding: %s\n", message);
+ return 1;
+ }
+
+ fwrite (buf, 1, len, stdout);
+ fflush (stdout);
+
+ asn1_delete_structure (&ekus);
+ asn1_delete_structure (&definitions);
+
+ return 0;
+}
diff --git a/common/tests/frob-ku.c b/common/tests/frob-ku.c
new file mode 100644
index 0000000..c0abd88
--- /dev/null
+++ b/common/tests/frob-ku.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include "config.h"
+#include "compat.h"
+
+#include <libtasn1.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pkix.asn.h"
+
+#define err_if_fail(ret, msg) \
+ do { if ((ret) != ASN1_SUCCESS) { \
+ fprintf (stderr, "%s: %s\n", msg, asn1_strerror (ret)); \
+ exit (1); \
+ } } while (0)
+
+enum {
+ KU_DIGITAL_SIGNATURE = 128,
+ KU_NON_REPUDIATION = 64,
+ KU_KEY_ENCIPHERMENT = 32,
+ KU_DATA_ENCIPHERMENT = 16,
+ KU_KEY_AGREEMENT = 8,
+ KU_KEY_CERT_SIGN = 4,
+ KU_CRL_SIGN = 2,
+ KU_ENCIPHER_ONLY = 1,
+ KU_DECIPHER_ONLY = 32768,
+};
+
+int
+main (int argc,
+ char *argv[])
+{
+ char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, };
+ node_asn *definitions = NULL;
+ node_asn *ku = NULL;
+ unsigned int usage = 0;
+ char bits[2];
+ char *buf;
+ int len;
+ int ret;
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp (argv[i], "digital-signature") == 0)
+ usage |= KU_DIGITAL_SIGNATURE;
+ else if (strcmp (argv[i], "non-repudiation") == 0)
+ usage |= KU_NON_REPUDIATION;
+ else if (strcmp (argv[i], "key-encipherment") == 0)
+ usage |= KU_KEY_ENCIPHERMENT;
+ else if (strcmp (argv[i], "data-encipherment") == 0)
+ usage |= KU_DATA_ENCIPHERMENT;
+ else if (strcmp (argv[i], "key-agreement") == 0)
+ usage |= KU_KEY_AGREEMENT;
+ else if (strcmp (argv[i], "key-cert-sign") == 0)
+ usage |= KU_KEY_CERT_SIGN;
+ else if (strcmp (argv[i], "crl-sign") == 0)
+ usage |= KU_CRL_SIGN;
+ else {
+ fprintf (stderr, "unsupported or unknown key usage: %s\n", argv[i]);
+ return 2;
+ }
+ }
+
+ ret = asn1_array2tree (pkix_asn1_tab, &definitions, message);
+ if (ret != ASN1_SUCCESS) {
+ fprintf (stderr, "definitions: %s\n", message);
+ return 1;
+ }
+
+ ret = asn1_create_element (definitions, "PKIX1.KeyUsage", &ku);
+ err_if_fail (ret, "KeyUsage");
+
+ bits[0] = usage & 0xff;
+ bits[1] = (usage >> 8) & 0xff;
+
+ ret = asn1_write_value (ku, "", bits, 9);
+ err_if_fail (ret, "asn1_write_value");
+
+ len = 0;
+ ret = asn1_der_coding (ku, "", NULL, &len, message);
+ assert (ret == ASN1_MEM_ERROR);
+
+ buf = malloc (len);
+ assert (buf != NULL);
+ ret = asn1_der_coding (ku, "", buf, &len, message);
+ if (ret != ASN1_SUCCESS) {
+ fprintf (stderr, "asn1_der_coding: %s\n", message);
+ return 1;
+ }
+
+ fwrite (buf, 1, len, stdout);
+ fflush (stdout);
+
+ asn1_delete_structure (&ku);
+ asn1_delete_structure (&definitions);
+
+ return 0;
+}
diff --git a/configure.ac b/configure.ac
index 426be4f..63235fd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -57,6 +57,9 @@ esac
AC_MSG_RESULT([$os_win32])
AM_CONDITIONAL(OS_WIN32, test "$os_win32" = "yes")
+AC_C_BIGENDIAN
+AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+
# ------------------------------------------------------------------------------
# Checks for libraries and headers
@@ -68,8 +71,8 @@ if test "$os_unix" = "yes"; then
AC_SEARCH_LIBS([nanosleep], [rt], [],
[AC_MSG_ERROR([could not find nanosleep])])
AC_CHECK_MEMBERS([struct dirent.d_type],,,[#include <dirent.h>])
- AC_CHECK_HEADERS([err.h errno.h stdbool.h])
AC_CHECK_FUNCS([getprogname getexecname memdup])
+ AC_CHECK_FUNCS([getprogname getexecname strnstr memdup])
# Check if these are declared and/or available to link against
AC_CHECK_DECLS([program_invocation_short_name])
@@ -120,6 +123,114 @@ AC_SUBST(p11_user_config_modules)
AC_SUBST(p11_module_path)
# --------------------------------------------------------------------
+# libtasn1 support
+
+AC_ARG_WITH([libtasn1],
+ AS_HELP_STRING([--without-libtasn1],
+ [Disable dependency on libtasn1])
+)
+
+if test "$with_libtasn1" != "no"; then
+ PKG_CHECK_MODULES(LIBTASN1, libtasn1)
+ AC_SUBST(LIBTASN1_CFLAGS)
+ AC_SUBST(LIBTASN1_LIBS)
+ with_libtasn1="yes"
+fi
+
+AM_CONDITIONAL(WITH_ASN1, test "$with_libtasn1" = "yes")
+
+# --------------------------------------------------------------------
+# Trust Module
+
+AC_ARG_ENABLE([trust-module],
+ AS_HELP_STRING([--disable-trust-module],
+ [Disable building the trust module])
+)
+
+AC_MSG_CHECKING([if trust module is enabled])
+
+if test "$enable_trust_module" != "no"; then
+ if test "$with_libtasn1" != "yes"; then
+ AC_MSG_ERROR([need --with-libtasn1 in order to use the trust module.])
+ fi
+ enable_trust_module="yes"
+fi
+
+AC_MSG_RESULT([$enable_trust_module])
+AM_CONDITIONAL(WITH_TRUST_MODULE, test "$enable_trust_module" = "yes")
+
+AC_ARG_WITH([system-anchors],
+ AS_HELP_STRING([--with-system-anchors=@<:@path@:>@]:
+ [files or directories containing system CA anchors])
+)
+
+AC_MSG_CHECKING([location of system CA anchors])
+
+if test "$enable_trust_module" != "yes"; then
+ if test "$with_system_anchors" != ""; then
+ AC_MSG_ERROR([need --enable-trust-module in order to use system anchors.])
+ fi
+ with_system_anchors="no"
+fi
+
+# This option was disabled, no anchors
+if test "$with_system_anchors" = "no"; then
+ with_system_anchors=""
+ AC_MSG_RESULT([disabled])
+
+# Option was not set, try to detect
+elif test "$with_system_anchors" = ""; then
+ for f in /etc/pki/tls/certs/ca-bundle.crt \
+ /etc/ssl/certs/ca-certificates.crt \
+ /etc/ssl/ca-bundle.pem \
+ /etc/ssl/ca-bundle.crt; do
+ if test -f "$f"; then
+ with_system_anchors="$f"
+ break
+ fi
+ done
+
+ if test "$with_system_anchors" = ""; then
+ AC_MSG_ERROR([could not find. Use --with-system-anchors=path to set, or --without-system-anchors to disable])
+ fi
+
+ AC_MSG_RESULT($with_system_anchors)
+else
+ AC_MSG_RESULT($with_system_anchors)
+fi
+
+AC_DEFINE_UNQUOTED(SYSTEM_ANCHORS, ["$with_system_anchors"], [The system anchor paths])
+AC_SUBST(with_system_anchors)
+
+AC_ARG_WITH([system-certificates],
+ AS_HELP_STRING([--with-system-certificates=@<:@path@:>@]:
+ [files or directories containing additional system certificates])
+)
+
+AC_MSG_CHECKING([location of additional system certificates])
+
+if test "$enable_trust_module" != "yes"; then
+ if test "$with_system_certificates" != ""; then
+ AC_MSG_ERROR([need --enable-trust-module in order to use additional system certificates.])
+ fi
+ with_system_certificates=""
+fi
+
+# This option was disabled, no additional certificates
+if test "$with_system_certificates" = "no"; then
+ with_system_certificates=""
+fi
+
+if test "$with_system_certificates" = ""; then
+ AC_MSG_RESULT([disabled])
+else
+ AC_MSG_RESULT($with_system_certificates)
+fi
+
+AC_DEFINE_UNQUOTED(SYSTEM_CERTIFICATES, ["$with_system_certificates"], [Additional system certificate paths])
+AC_SUBST(with_system_certificates)
+
+# --------------------------------------------------------------------
# GTK Doc
dnl check for tools
@@ -287,12 +398,19 @@ AC_SUBST(GENHTML)
P11KIT_LT_RELEASE=$P11KIT_CURRENT:$P11KIT_REVISION:$P11KIT_AGE
AC_SUBST(P11KIT_LT_RELEASE)
+echo $PACKAGE_VERSION | tr '.' ' ' | while read major minor unused; do
+ AC_DEFINE_UNQUOTED(PACKAGE_MAJOR, $major, [Major version of package])
+ AC_DEFINE_UNQUOTED(PACKAGE_MINOR, $minor, [Minor version of package])
+ break
+done
+
eval SHLEXT=$shrext_cmds
AC_DEFINE_UNQUOTED(SHLEXT, ["$SHLEXT"], [File extension for shared libraries])
AC_SUBST(SHLEXT)
AC_CONFIG_FILES([Makefile
build/Makefile
+ build/certs/Makefile
common/Makefile
common/tests/Makefile
doc/Makefile
@@ -303,6 +421,8 @@ AC_CONFIG_FILES([Makefile
p11-kit/p11-kit-1.pc
p11-kit/pkcs11.conf.example
tools/Makefile
+ trust/Makefile
+ trust/tests/Makefile
])
AC_OUTPUT
@@ -318,4 +438,10 @@ AC_MSG_NOTICE([build options:
User global config: $p11_user_config_file
User module config directory: $p11_user_config_modules
Load relative module paths from: $p11_module_path
+
+ With libtasn1 dependency: $with_libtasn1
+
+ Build trust module: $enable_trust_module
+ System certificate anchor paths: $with_system_anchors
+ Other system certificate paths: $with_system_certificates
])
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 1846993..3154215 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -52,6 +52,7 @@ IGNORE_HFILES= \
dict.h \
mock-module.h \
pkcs11.h \
+ pkcs11x.h \
private.h \
util.h \
array.h \
@@ -66,6 +67,7 @@ HTML_IMAGES=
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files=p11-kit-config.xml p11-kit-sharing.xml \
p11-kit-devel.xml \
+ p11-kit-trust.xml \
p11-kit.xml \
$(NULL)
diff --git a/doc/p11-kit-config.xml b/doc/p11-kit-config.xml
index d35b112..da413e0 100644
--- a/doc/p11-kit-config.xml
+++ b/doc/p11-kit-config.xml
@@ -167,6 +167,16 @@ critical: yes
not present, then any process will load the module.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>trust-policy</term>
+ <listitem>
+ <para>If this setting is present then this module is used to load
+ trust policy information such as certificate anchors and black lists.
+ The value should be an integer. Modules with a lower number are loaded
+ first. Trust policy information in modules loaded later overrides
+ those loaded first.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
<para>Do not specify both <literal>enable-in</literal> and <literal>disable-in</literal>
diff --git a/doc/p11-kit-devel.xml b/doc/p11-kit-devel.xml
index f2a1f58..f3acde1 100644
--- a/doc/p11-kit-devel.xml
+++ b/doc/p11-kit-devel.xml
@@ -131,6 +131,8 @@ $ make install
<listitem><para><command>xsltproc</command> is required to build the command
manual pages. Use <literal>--enable-doc</literal> to control this
dependency.</para></listitem>
+ <listitem><para><command>libtasn1</command> is required to build the trust
+ module and code that interacts with certificates.</para></listitem>
</itemizedlist>
</section>
@@ -143,6 +145,10 @@ $ make install
<variablelist>
<varlistentry>
+ <term><option>--disable-trust-module</option></term>
+ <listitem><para>Disables building of the trust policy module.</para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>--disable-debug</option>, <option>--enable-debug</option></term>
<listitem><para>By default p11-kit is built with debug symbols assertions and
and precondition checks. Enabling the debug option configures even more
@@ -164,11 +170,29 @@ $ make install
compiler warnings become errors.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>--with-libtasn1</option>, <option>--without-libtasn1</option></term>
+ <listitem><para>Build with a dependency on the libtasn1 library. This dependency
+ allows the trust policy module to be built as well as other code that interacts with
+ certificates.</para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>--with-module-path</option></term>
<listitem><para>Specify the path to look for PKCS#11 modules which were
listed in a module config file with a relative path.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>--with-system-anchors</option></term>
+ <listitem><para>Specify the files or directories to look for system
+ certificate anchors. Multiple files and/or directories are specified with
+ a <literal>:</literal> in between them.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--with-system-certificates</option></term>
+ <listitem><para>Specify the files or directories to look for other
+ non-anchor system certificates. Multiple files and/or directories are
+ specified with a <literal>:</literal> in between them.</para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>--with-system-config</option></term>
<listitem><para>Specify the path to look for p11-kit config files. This
usually defaults to something like <literal>/etc/pkcs11</literal></para></listitem>
diff --git a/doc/p11-kit-docs.sgml b/doc/p11-kit-docs.sgml
index 2d3760a..5627f6f 100644
--- a/doc/p11-kit-docs.sgml
+++ b/doc/p11-kit-docs.sgml
@@ -13,6 +13,7 @@
<xi:include href="p11-kit-config.xml"/>
<xi:include href="p11-kit-sharing.xml"/>
+ <xi:include href="p11-kit-trust.xml"/>
<chapter xml:id="tools">
<title>Command Line Tools</title>
diff --git a/doc/p11-kit-trust.xml b/doc/p11-kit-trust.xml
new file mode 100644
index 0000000..7496f7b
--- /dev/null
+++ b/doc/p11-kit-trust.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+]>
+<chapter xml:id="trust">
+<title>Trust Policy Module</title>
+
+ <para>The trust module provides system certificate anchors, blacklists
+ and other trust policy to crypto libraries applications. This
+ information is exposed as PKCS#11 objects.</para>
+
+<section id="trust-files">
+ <title>Files loaded by the Module</title>
+
+ <para>The trust module loads certificates and trust policy information
+ from preconfigured directories and allows them to be looked up via
+ PKCS#11. The directories can be determined with using the following
+ commands:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>System Anchors: certificates in these locations
+ are automatically treated as certificate authority anchors
+ unless they contain information that prevents that. To check
+ which locations are being used, run the following command:</para>
+<programlisting>
+$ pkg-config --variable p11_system_anchors p11-kit-1
+/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/anchors
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>System Certificates: certificates in these locations
+ are not treated as anchors, but simply made available through
+ the module. To find out which directory is used, run the
+ following command:</para>
+<programlisting>
+$ pkg-config --variable p11_system_certificates p11-kit-1
+/etc/pki/tls/other-certs
+</programlisting>
+ </listitem>
+ </itemizedlist>
+
+ <para>Files in the following formats are supported for loading by the
+ trust policy module:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>X.509 certificates</term>
+ <listitem><para>X.509 certificates in raw DER format.</para></listitem>
+ </varlistentry>
+ </variablelist>
+</section>
+
+<section id="trust-nss">
+ <title>Using the Trust Policy Module with NSS</title>
+
+ <para>The trust policy module is a drop in replacement for the
+ <literal>libnssckbi.so</literal> module and thus works out of
+ the box with NSS. The module may be used to replace the
+ <literal>libnssckbi.so</literal> file via an distribution
+ specific alternatives mechanism or otherwise.</para>
+
+ <para>Alternatively NSS applications like Firefox or Thunderbird
+ may be configured to use the trust policy module by adding
+ the <literal>p11-kit-trust.so</literal> PKCS#11 module via their
+ GUI or command line configuration.</para>
+</section>
+
+<section id="trust-disable">
+ <title>Disabling the Trust Policy Module</title>
+
+ <para>This module is installed and enabled by default. It may
+ be disabled in the following ways:</para>
+
+ <itemizedlist>
+ <listitem><para>Use the <option>--disable-trust-module</option>
+ during the <link linkend="devel-building-configure">p11-kit
+ build</link>.</para></listitem>
+ <listitem><para>Disable loading trust policy information
+ from this module by adding a file to <literal>/etc/pkcs11/modules</literal>
+ called <literal>p11-kit-trust.module</literal> containing a
+ <literal>trust-policy:</literal> line.</para></listitem>
+ <listitem><para>Disable this module completely by
+ adding a file to <literal>/etc/pkcs11/modules</literal>
+ called <literal>p11-kit-trust.module</literal> containing a
+ <literal>enable-in:</literal> line.</para></listitem>
+ </itemizedlist>
+
+</section>
+
+</chapter>
diff --git a/doc/style.css b/doc/style.css
index e70190a..b4b8d47 100644
--- a/doc/style.css
+++ b/doc/style.css
@@ -99,10 +99,14 @@ DIV.toc DL {
margin-bottom: 0;
}
-DIV.toc > DL > DT {
+DIV.book > DIV.toc > DL > DT {
margin-top: 1em;
}
DIV.toc DT {
margin-bottom: 0.3em;
}
+
+TABLE.variablelist SPAN.term {
+ padding-right: 1em;
+}
diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am
index fd0b90a..650fe44 100644
--- a/p11-kit/Makefile.am
+++ b/p11-kit/Makefile.am
@@ -24,6 +24,7 @@ MODULE_SRCS = \
modules.c \
pkcs11.h \
pin.c \
+ pkcs11.h \
proxy.c \
private.h \
messages.c \
diff --git a/p11-kit/conf.c b/p11-kit/conf.c
index 68b6343..0f98636 100644
--- a/p11-kit/conf.c
+++ b/p11-kit/conf.c
@@ -111,43 +111,6 @@ strequal (const char *one, const char *two)
return strcmp (one, two) == 0;
}
-static char *
-strconcat (const char *first,
- ...) GNUC_NULL_TERMINATED;
-
-static char *
-strconcat (const char *first,
- ...)
-{
- size_t length = 0;
- const char *arg;
- char *result, *at;
- va_list va;
-
- va_start (va, first);
-
- for (arg = first; arg; arg = va_arg (va, const char*))
- length += strlen (arg);
-
- va_end (va);
-
- at = result = malloc (length + 1);
- return_val_if_fail (result != NULL, NULL);
-
- va_start (va, first);
-
- for (arg = first; arg; arg = va_arg (va, const char*)) {
- length = strlen (arg);
- memcpy (at, arg, length);
- at += length;
- }
-
- va_end (va);
-
- *at = 0;
- return result;
-}
-
/* -----------------------------------------------------------------------------
* CONFIG PARSER
*/
diff --git a/p11-kit/p11-kit-1.pc.in b/p11-kit/p11-kit-1.pc.in
index d0d378d..441904d 100644
--- a/p11-kit/p11-kit-1.pc.in
+++ b/p11-kit/p11-kit-1.pc.in
@@ -10,6 +10,9 @@ p11_module_configs=@p11_package_config_modules@
p11_module_path=@p11_module_path@
proxy_module=@libdir@/p11-kit-proxy.so
+p11_system_anchors=@with_system_anchors@
+p11_system_certificates=@with_system_certificates@
+
# This is for compatibility. Other packages were using this to determine
# the directory they should install their module configs to, so override
# this and redirect them to the new location
diff --git a/trust/Makefile.am b/trust/Makefile.am
new file mode 100644
index 0000000..413bb51
--- /dev/null
+++ b/trust/Makefile.am
@@ -0,0 +1,52 @@
+NULL =
+
+SUBDIRS = . tests
+
+COMMON = $(top_srcdir)/common
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/common \
+ $(NULL)
+
+MODULE_SRCS = \
+ parser.c parser.h \
+ module.c module.h \
+ session.c session.h \
+ token.c token.h \
+ $(NULL)
+
+configdir = $(p11_package_config_modules)
+config_DATA = p11-kit-trust.module
+
+moduledir = $(p11_module_path)
+module_LTLIBRARIES = \
+ p11-kit-trust.la
+
+p11_kit_trust_la_CFLAGS = \
+ $(LIBTASN1_CFLAGS)
+
+p11_kit_trust_la_LIBADD = \
+ $(top_builddir)/common/libp11-data.la \
+ $(top_builddir)/common/libp11-library.la \
+ $(top_builddir)/common/libp11-compat.la \
+ $(LIBTASN1_LIBS)
+
+p11_kit_trust_la_LDFLAGS = \
+ -no-undefined -module -avoid-version \
+ -version-info $(P11KIT_LT_RELEASE) \
+ -export-symbols-regex 'C_GetFunctionList' \
+ $(NULL)
+
+p11_kit_trust_la_SOURCES = $(MODULE_SRCS)
+
+noinst_LTLIBRARIES = \
+ libtrust-testable.la
+
+libtrust_testable_la_LDFLAGS = \
+ -no-undefined
+
+libtrust_testable_la_SOURCES = $(MODULE_SRCS)
+
+EXTRA_DIST = \
+ p11-kit-trust.module
diff --git a/trust/module.c b/trust/module.c
new file mode 100644
index 0000000..ab28095
--- /dev/null
+++ b/trust/module.c
@@ -0,0 +1,1517 @@
+/*
+ * Copyright (C) 2012 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 "attrs.h"
+#define P11_DEBUG_FLAG P11_DEBUG_TRUST
+#include "debug.h"
+#include "dict.h"
+#include "library.h"
+#include "module.h"
+#include "pkcs11.h"
+#include "session.h"
+#include "token.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MANUFACTURER_ID "PKCS#11 Kit "
+#define LIBRARY_DESCRIPTION "PKCS#11 Kit Trust Module "
+#define SLOT_DESCRIPTION "System Certificates, Trust Anchors, and Black Lists "
+#define TOKEN_LABEL "System Trust Anchors and Policy "
+#define TOKEN_MODEL "PKCS#11 Kit "
+#define TOKEN_SERIAL_NUMBER "1 "
+
+/* Arbitrary non-zero and non-one choice */
+#define SYSTEM_SLOT_ID 18UL
+
+static struct _Shared {
+ p11_dict *sessions;
+ p11_token *token;
+ char *anchor_paths;
+ char *certificate_paths;
+} gl = { NULL, NULL };
+
+/* Used during FindObjects */
+typedef struct _FindObjects {
+ CK_ATTRIBUTE *match;
+ CK_OBJECT_HANDLE *snapshot;
+ CK_ULONG iterator;
+} FindObjects;
+
+static CK_FUNCTION_LIST sys_function_list;
+
+static void
+find_objects_free (void *data)
+{
+ FindObjects *find = data;
+ p11_attrs_free (find->match);
+ free (find->snapshot);
+ free (find);
+}
+
+static CK_RV
+lookup_session (CK_SESSION_HANDLE handle,
+ p11_session **session)
+{
+ p11_session *sess;
+
+ if (!gl.sessions)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ sess = p11_dict_get (gl.sessions, &handle);
+ if (!sess)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (sess && session)
+ *session = sess;
+ return CKR_OK;
+}
+
+static void
+parse_argument (char *arg)
+{
+ char *value;
+
+ value = arg + strcspn (arg, ":=");
+ if (!*value)
+ value = NULL;
+ else
+ *(value++) = 0;
+
+ if (strcmp (arg, "anchors") == 0) {
+ free (gl.anchor_paths);
+ gl.anchor_paths = value ? strdup (value) : NULL;
+
+ } else if (strcmp (arg, "certificates") == 0) {
+ free (gl.certificate_paths);
+ gl.certificate_paths = value ? strdup (value) : NULL;
+
+ } else {
+ p11_message ("unrecognized module argument: %s", arg);
+ }
+}
+
+static void
+parse_arguments (const char *string)
+{
+ char quote = '\0';
+ char *src, *dup, *at, *arg;
+
+ if (!string)
+ return;
+
+ src = dup = strdup (string);
+ if (!dup) {
+ p11_message ("couldn't allocate memory for argument string");
+ return;
+ }
+
+ arg = at = src;
+ for (src = dup; *src; src++) {
+
+ /* Matching quote */
+ if (quote == *src) {
+ quote = '\0';
+
+ /* Inside of quotes */
+ } else if (quote != '\0') {
+ if (*src == '\\') {
+ *at++ = *src++;
+ if (!*src) {
+ p11_message ("couldn't parse argument string: %s", string);
+ goto done;
+ }
+ if (*src != quote)
+ *at++ = '\\';
+ }
+ *at++ = *src;
+
+ /* Space, not inside of quotes */
+ } else if (isspace(*src)) {
+ *at = 0;
+ parse_argument (arg);
+ arg = at;
+
+ /* Other character outside of quotes */
+ } else {
+ switch (*src) {
+ case '\'':
+ case '"':
+ quote = *src;
+ break;
+ case '\\':
+ *at++ = *src++;
+ if (!*src) {
+ p11_message ("couldn't parse argument string: %s", string);
+ goto done;
+ }
+ /* fall through */
+ default:
+ *at++ = *src;
+ break;
+ }
+ }
+ }
+
+
+ if (at != arg) {
+ *at = 0;
+ parse_argument (arg);
+ }
+
+done:
+ free (dup);
+}
+
+static CK_RV
+sys_C_Finalize (CK_VOID_PTR reserved)
+{
+ CK_RV rv = CKR_OK;
+
+ p11_debug ("in");
+
+ /* WARNING: This function must be reentrant */
+
+ if (reserved) {
+ rv = CKR_ARGUMENTS_BAD;
+
+ } else {
+ p11_lock ();
+
+ if (!gl.sessions) {
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ } else {
+ free (gl.certificate_paths);
+ free (gl.anchor_paths);
+ gl.certificate_paths = gl.anchor_paths = NULL;
+
+ p11_dict_free (gl.sessions);
+ gl.sessions = NULL;
+
+ p11_token_free (gl.token);
+ gl.token = NULL;
+
+ rv = CKR_OK;
+ }
+
+ p11_unlock ();
+ }
+
+ p11_debug ("out: 0x%lx", rv);
+ return rv;
+}
+
+static CK_RV
+sys_C_Initialize (CK_VOID_PTR init_args)
+{
+ CK_C_INITIALIZE_ARGS *args = NULL;
+ int supplied_ok;
+ CK_RV rv;
+
+ p11_library_init_once ();
+
+ /* WARNING: This function must be reentrant */
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = CKR_OK;
+
+ /* pReserved must be NULL */
+ args = init_args;
+
+ /* ALL supplied function pointers need to have the value either NULL or non-NULL. */
+ supplied_ok = (args->CreateMutex == NULL && args->DestroyMutex == NULL &&
+ args->LockMutex == NULL && args->UnlockMutex == NULL) ||
+ (args->CreateMutex != NULL && args->DestroyMutex != NULL &&
+ args->LockMutex != NULL && args->UnlockMutex != NULL);
+ if (!supplied_ok) {
+ p11_message ("invalid set of mutex calls supplied");
+ rv = CKR_ARGUMENTS_BAD;
+ }
+
+ /*
+ * When the CKF_OS_LOCKING_OK flag isn't set return an error.
+ * We must be able to use our pthread functionality.
+ */
+ if (!(args->flags & CKF_OS_LOCKING_OK)) {
+ p11_message ("can't do without os locking");
+ rv = CKR_CANT_LOCK;
+ }
+
+ /*
+ * We support setting the socket path and other arguments from from the
+ * pReserved pointer, similar to how NSS PKCS#11 components are initialized.
+ */
+ if (rv == CKR_OK) {
+ if (args->pReserved)
+ parse_arguments ((const char*)args->pReserved);
+
+ gl.sessions = p11_dict_new (p11_dict_ulongptr_hash,
+ p11_dict_ulongptr_equal,
+ NULL, p11_session_free);
+
+ gl.token = p11_token_new (gl.anchor_paths ? gl.anchor_paths : SYSTEM_ANCHORS,
+ gl.certificate_paths ? gl.certificate_paths : SYSTEM_CERTIFICATES);
+
+ if (gl.sessions == NULL || gl.token == NULL) {
+ warn_if_reached ();
+ rv = CKR_GENERAL_ERROR;
+ }
+ }
+
+ p11_unlock ();
+
+ if (rv != CKR_OK)
+ sys_C_Finalize (NULL);
+
+ p11_debug ("out: 0x%lx", rv);
+ return rv;
+}
+
+static CK_RV
+sys_C_GetInfo (CK_INFO_PTR info)
+{
+ CK_RV rv = CKR_OK;
+
+ p11_library_init_once ();
+
+ p11_debug ("in");
+
+ return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_lock ();
+
+ if (!gl.sessions)
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ p11_unlock ();
+
+ if (rv == CKR_OK) {
+ memset (info, 0, sizeof (*info));
+ info->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
+ info->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
+ info->libraryVersion.major = PACKAGE_MAJOR;
+ info->libraryVersion.minor = PACKAGE_MINOR;
+ info->flags = 0;
+ strncpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
+ strncpy ((char*)info->libraryDescription, LIBRARY_DESCRIPTION, 32);
+ }
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+ /* Can be called before C_Initialize */
+ return_val_if_fail (list != NULL, CKR_ARGUMENTS_BAD);
+
+ *list = &sys_function_list;
+ return CKR_OK;
+}
+
+static CK_RV
+sys_C_GetSlotList (CK_BBOOL token_present,
+ CK_SLOT_ID_PTR slot_list,
+ CK_ULONG_PTR count)
+{
+ CK_RV rv = CKR_OK;
+
+ return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ if (!gl.sessions)
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ p11_unlock ();
+
+ if (rv != CKR_OK) {
+ /* already failed */
+
+ } else if (!slot_list) {
+ *count = 1;
+ rv = CKR_OK;
+
+ } else if (*count < 1) {
+ *count = 1;
+ rv = CKR_BUFFER_TOO_SMALL;
+
+ } else {
+ slot_list[0] = SYSTEM_SLOT_ID;
+ *count = 1;
+ rv = CKR_OK;
+ }
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_GetSlotInfo (CK_SLOT_ID id,
+ CK_SLOT_INFO_PTR info)
+{
+ CK_RV rv = CKR_OK;
+
+ return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+ return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ if (!gl.sessions)
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ p11_unlock ();
+
+ if (rv == CKR_OK) {
+ memset (info, 0, sizeof (*info));
+ info->firmwareVersion.major = 0;
+ info->firmwareVersion.minor = 0;
+ info->hardwareVersion.major = 0;
+ info->hardwareVersion.minor = 0;
+ info->flags = CKF_TOKEN_PRESENT;
+ strncpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
+ strncpy ((char*)info->slotDescription, SLOT_DESCRIPTION, 64);
+ }
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_GetTokenInfo (CK_SLOT_ID id,
+ CK_TOKEN_INFO_PTR info)
+{
+ CK_RV rv = CKR_OK;
+
+ return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+ return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ if (!gl.sessions)
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ p11_unlock ();
+
+ if (rv == CKR_OK) {
+ memset (info, 0, sizeof (*info));
+ info->firmwareVersion.major = 0;
+ info->firmwareVersion.minor = 0;
+ info->hardwareVersion.major = 0;
+ info->hardwareVersion.minor = 0;
+ info->flags = CKF_TOKEN_INITIALIZED | CKF_WRITE_PROTECTED;
+ strncpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
+ strncpy ((char*)info->label, TOKEN_LABEL, 32);
+ strncpy ((char*)info->model, TOKEN_MODEL, 16);
+ strncpy ((char*)info->serialNumber, TOKEN_SERIAL_NUMBER, 16);
+ info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
+ info->ulMaxRwSessionCount = 0;
+ info->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
+ info->ulMaxPinLen = 0;
+ info->ulMinPinLen = 0;
+ info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ }
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_GetMechanismList (CK_SLOT_ID id,
+ CK_MECHANISM_TYPE_PTR mechanism_list,
+ CK_ULONG_PTR count)
+{
+ CK_RV rv = CKR_OK;
+
+ return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ *count = 0;
+
+ p11_debug ("out: 0x%lx", rv);
+ return rv;
+}
+
+static CK_RV
+sys_C_GetMechanismInfo (CK_SLOT_ID id,
+ CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR info)
+{
+ return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+ return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_InitToken (CK_SLOT_ID id,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len,
+ CK_UTF8CHAR_PTR label)
+{
+ return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+ return_val_if_reached (CKR_TOKEN_WRITE_PROTECTED);
+}
+
+static CK_RV
+sys_C_WaitForSlotEvent (CK_FLAGS flags,
+ CK_SLOT_ID_PTR slot,
+ CK_VOID_PTR reserved)
+{
+ p11_debug ("not supported");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+sys_C_OpenSession (CK_SLOT_ID id,
+ CK_FLAGS flags,
+ CK_VOID_PTR user_data,
+ CK_NOTIFY callback,
+ CK_SESSION_HANDLE_PTR handle)
+{
+ p11_session *session;
+ CK_RV rv = CKR_OK;
+
+ return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+ return_val_if_fail (handle != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ if (!gl.sessions) {
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ } else if (!(flags & CKF_SERIAL_SESSION)) {
+ rv = CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+
+ } else if (flags & CKF_RW_SESSION) {
+ rv = CKR_TOKEN_WRITE_PROTECTED;
+
+ } else {
+ session = p11_session_new (gl.token);
+ if (p11_dict_set (gl.sessions, &session->handle, session)) {
+ rv = CKR_OK;
+ *handle = session->handle;
+ p11_debug ("session: %lu", *handle);
+ } else {
+ warn_if_reached ();
+ rv = CKR_GENERAL_ERROR;
+ }
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_CloseSession (CK_SESSION_HANDLE handle)
+{
+ CK_RV rv = CKR_OK;
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ if (!gl.sessions) {
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ } else if (p11_dict_remove (gl.sessions, &handle)) {
+ rv = CKR_OK;
+
+ } else {
+ rv = CKR_SESSION_HANDLE_INVALID;
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_CloseAllSessions (CK_SLOT_ID id)
+{
+ CK_RV rv = CKR_OK;
+
+ return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ if (!gl.sessions) {
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ } else {
+ p11_dict_clear (gl.sessions);
+ rv = CKR_OK;
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_GetFunctionStatus (CK_SESSION_HANDLE handle)
+{
+ return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+}
+
+static CK_RV
+sys_C_CancelFunction (CK_SESSION_HANDLE handle)
+{
+ return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+}
+
+static CK_RV
+sys_C_GetSessionInfo (CK_SESSION_HANDLE handle,
+ CK_SESSION_INFO_PTR info)
+{
+ CK_RV rv;
+
+ return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, NULL);
+
+ p11_unlock ();
+
+ if (rv == CKR_OK) {
+ info->flags = CKF_SERIAL_SESSION;
+ info->slotID = SYSTEM_SLOT_ID;
+ info->state = CKS_RO_PUBLIC_SESSION;
+ info->ulDeviceError = 0;
+ }
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_InitPIN (CK_SESSION_HANDLE handle,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len)
+{
+ return_val_if_reached (CKR_TOKEN_WRITE_PROTECTED);
+}
+
+static CK_RV
+sys_C_SetPIN (CK_SESSION_HANDLE handle,
+ CK_UTF8CHAR_PTR old_pin,
+ CK_ULONG old_pin_len,
+ CK_UTF8CHAR_PTR new_pin,
+ CK_ULONG new_pin_len)
+{
+ return_val_if_reached (CKR_TOKEN_WRITE_PROTECTED);
+}
+
+static CK_RV
+sys_C_GetOperationState (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR operation_state,
+ CK_ULONG_PTR operation_state_len)
+{
+ p11_debug ("not supported");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+sys_C_SetOperationState (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR operation_state,
+ CK_ULONG operation_state_len,
+ CK_OBJECT_HANDLE encryption_key,
+ CK_OBJECT_HANDLE authentication_key)
+{
+ p11_debug ("not supported");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+sys_C_Login (CK_SESSION_HANDLE handle,
+ CK_USER_TYPE user_type,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len)
+{
+ return_val_if_reached (CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+sys_C_Logout (CK_SESSION_HANDLE handle)
+{
+ return_val_if_reached (CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+sys_C_CreateObject (CK_SESSION_HANDLE handle,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_object)
+{
+ CK_ATTRIBUTE *attrs;
+ p11_session *session;
+ CK_BBOOL token;
+ CK_RV rv;
+
+ return_val_if_fail (new_object != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, &session);
+ if (rv == CKR_OK) {
+ if (p11_attrs_findn_bool (template, count, CKA_TOKEN, &token) && token)
+ rv = CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ if (rv == CKR_OK) {
+ attrs = p11_attrs_buildn (NULL, template, count);
+ rv = p11_session_add_object (session, attrs, new_object);
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_CopyObject (CK_SESSION_HANDLE handle,
+ CK_OBJECT_HANDLE object,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_object)
+{
+ CK_BBOOL vfalse = CK_FALSE;
+ CK_ATTRIBUTE token = { CKA_TOKEN, &vfalse, sizeof (vfalse) };
+ p11_session *session;
+ CK_ATTRIBUTE *original;
+ CK_ATTRIBUTE *attrs;
+ CK_BBOOL val;
+ CK_RV rv;
+
+ return_val_if_fail (new_object != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, &session);
+ if (rv == CKR_OK) {
+ original = p11_session_get_object (session, object, NULL);
+ if (original == NULL)
+ rv = CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ if (rv == CKR_OK) {
+ if (p11_attrs_findn_bool (template, count, CKA_TOKEN, &val) && val)
+ rv = CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ if (rv == CKR_OK) {
+ attrs = p11_attrs_dup (original);
+ attrs = p11_attrs_buildn (attrs, template, count);
+ attrs = p11_attrs_build (attrs, &token, NULL);
+ rv = p11_session_add_object (session, attrs, new_object);
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_DestroyObject (CK_SESSION_HANDLE handle,
+ CK_OBJECT_HANDLE object)
+{
+ p11_session *session;
+ CK_RV rv;
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, &session);
+ if (rv == CKR_OK)
+ rv = p11_session_del_object (session, object);
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_GetObjectSize (CK_SESSION_HANDLE handle,
+ CK_OBJECT_HANDLE object,
+ CK_ULONG_PTR size)
+{
+ p11_session *session;
+ CK_RV rv;
+
+ return_val_if_fail (size != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, &session);
+ if (rv == CKR_OK) {
+ if (p11_session_get_object (session, object, NULL)) {
+ *size = CK_UNAVAILABLE_INFORMATION;
+ rv = CKR_OK;
+ } else {
+ rv = CKR_OBJECT_HANDLE_INVALID;
+ }
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_GetAttributeValue (CK_SESSION_HANDLE handle,
+ CK_OBJECT_HANDLE object,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG count)
+{
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *result;
+ CK_ATTRIBUTE *attr;
+ p11_session *session;
+ CK_ULONG i;
+ CK_RV rv;
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, &session);
+ if (rv == CKR_OK) {
+ attrs = p11_session_get_object (session, object, NULL);
+ if (attrs == NULL)
+ rv = CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ if (rv == CKR_OK) {
+ for (i = 0; i < count; i++) {
+ result = template + i;
+ attr = p11_attrs_find (attrs, result->type);
+ if (!attr) {
+ result->ulValueLen = (CK_ULONG)-1;
+ rv = CKR_ATTRIBUTE_TYPE_INVALID;
+ continue;
+ }
+
+ if (!result->pValue) {
+ result->ulValueLen = attr->ulValueLen;
+ continue;
+ }
+
+ if (result->ulValueLen >= attr->ulValueLen) {
+ memcpy (result->pValue, attr->pValue, attr->ulValueLen);
+ result->ulValueLen = attr->ulValueLen;
+ continue;
+ }
+
+ result->ulValueLen = (CK_ULONG)-1;
+ rv = CKR_BUFFER_TOO_SMALL;
+ }
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_SetAttributeValue (CK_SESSION_HANDLE handle,
+ CK_OBJECT_HANDLE object,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG count)
+{
+ p11_session *session;
+ CK_RV rv;
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, &session);
+ if (rv == CKR_OK)
+ rv = p11_session_set_object (session, object, template, count);
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_FindObjectsInit (CK_SESSION_HANDLE handle,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG count)
+{
+ CK_OBJECT_HANDLE *handle_ptr;
+ CK_BBOOL want_token_objects;
+ CK_BBOOL want_session_objects;
+ CK_BBOOL token;
+ p11_dict *objects;
+ FindObjects *find;
+ p11_session *session;
+ p11_dictiter iter;
+ CK_ULONG i;
+ CK_RV rv;
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ /* Are we searching for token objects? */
+ if (p11_attrs_findn_bool (template, count, CKA_TOKEN, &token)) {
+ want_token_objects = token;
+ want_session_objects = !token;
+ } else {
+ want_token_objects = CK_TRUE;
+ want_session_objects = CK_TRUE;
+ }
+
+ rv = lookup_session (handle, &session);
+
+ /* Refresh from disk if this session hasn't yet */
+ if (rv == CKR_OK && want_token_objects && !session->loaded) {
+ session->loaded = CK_TRUE;
+ p11_token_load (gl.token);
+ }
+
+ if (rv == CKR_OK) {
+ objects = p11_token_objects (gl.token);
+
+ find = calloc (1, sizeof (FindObjects));
+ warn_if_fail (find != NULL);
+
+ /* Make a copy of what we're matching */
+ if (find) {
+ find->match = p11_attrs_buildn (NULL, template, count);
+ warn_if_fail (find->match != NULL);
+
+ /* Build a session snapshot of all objects */
+ find->iterator = 0;
+ count = p11_dict_size (objects) + p11_dict_size (session->objects) + 1;
+ find->snapshot = calloc (count, sizeof (CK_OBJECT_HANDLE));
+ warn_if_fail (find->snapshot != NULL);
+ }
+
+ if (find && find->snapshot) {
+ i = 0;
+
+ if (want_token_objects) {
+ p11_dict_iterate (objects, &iter);
+ for ( ; p11_dict_next (&iter, (void *)&handle_ptr, NULL); i++) {
+ assert (i < count);
+ find->snapshot[i] = *handle_ptr;
+ }
+ }
+
+ if (want_session_objects) {
+ p11_dict_iterate (session->objects, &iter);
+ for ( ; p11_dict_next (&iter, (void *)&handle_ptr, NULL); i++) {
+ assert (i < count);
+ find->snapshot[i] = *handle_ptr;
+ }
+ }
+
+ assert (i < count);
+ assert (find->snapshot[i] == 0UL);
+ }
+
+ if (!find || !find->snapshot || !find->match)
+ rv = CKR_HOST_MEMORY;
+ else
+ p11_session_set_operation (session, find_objects_free, find);
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_FindObjects (CK_SESSION_HANDLE handle,
+ CK_OBJECT_HANDLE_PTR objects,
+ CK_ULONG max_count,
+ CK_ULONG_PTR count)
+{
+ CK_OBJECT_HANDLE object;
+ CK_ATTRIBUTE *attrs;
+ FindObjects *find = NULL;
+ p11_session *session;
+ CK_ULONG matched;
+ CK_RV rv;
+
+ return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, &session);
+ if (rv == CKR_OK) {
+ if (session->cleanup != find_objects_free)
+ rv = CKR_OPERATION_NOT_INITIALIZED;
+ find = session->operation;
+ }
+
+ if (rv == CKR_OK) {
+ matched = 0;
+ while (matched < max_count) {
+ object = find->snapshot[find->iterator];
+ if (!object)
+ break;
+
+ find->iterator++;
+
+ attrs = p11_session_get_object (session, object, NULL);
+ if (attrs == NULL)
+ continue;
+
+ if (p11_attrs_match (attrs, find->match)) {
+ objects[matched] = object;
+ matched++;
+ }
+ }
+
+ *count = matched;
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_FindObjectsFinal (CK_SESSION_HANDLE handle)
+{
+ p11_session *session;
+ CK_RV rv;
+
+ p11_debug ("in");
+
+ p11_lock ();
+
+ rv = lookup_session (handle, &session);
+ if (rv == CKR_OK) {
+ if (session->cleanup != find_objects_free)
+ rv = CKR_OPERATION_NOT_INITIALIZED;
+ else
+ p11_session_set_operation (session, NULL, NULL);
+ }
+
+ p11_unlock ();
+
+ p11_debug ("out: 0x%lx", rv);
+
+ return rv;
+}
+
+static CK_RV
+sys_C_EncryptInit (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_Encrypt (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR data,
+ CK_ULONG data_len,
+ CK_BYTE_PTR encrypted_data,
+ CK_ULONG_PTR encrypted_data_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_EncryptUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR part,
+ CK_ULONG part_len,
+ CK_BYTE_PTR encrypted_part,
+ CK_ULONG_PTR encrypted_part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_EncryptFinal (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR last_part,
+ CK_ULONG_PTR last_part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DecryptInit (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_Decrypt (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR enc_data,
+ CK_ULONG enc_data_len,
+ CK_BYTE_PTR data,
+ CK_ULONG_PTR data_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DecryptUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR enc_part,
+ CK_ULONG enc_part_len,
+ CK_BYTE_PTR part,
+ CK_ULONG_PTR part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DecryptFinal (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR last_part,
+ CK_ULONG_PTR last_part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DigestInit (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_Digest (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR data,
+ CK_ULONG data_len,
+ CK_BYTE_PTR digest,
+ CK_ULONG_PTR digest_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DigestUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR part,
+ CK_ULONG part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DigestKey (CK_SESSION_HANDLE handle,
+ CK_OBJECT_HANDLE key)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DigestFinal (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR digest,
+ CK_ULONG_PTR digest_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_SignInit (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_Sign (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR data,
+ CK_ULONG data_len,
+ CK_BYTE_PTR signature,
+ CK_ULONG_PTR signature_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_SignUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR part,
+ CK_ULONG part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_SignFinal (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR signature,
+ CK_ULONG_PTR signature_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_SignRecoverInit (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_SignRecover (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR data,
+ CK_ULONG data_len,
+ CK_BYTE_PTR signature,
+ CK_ULONG_PTR signature_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_VerifyInit (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_Verify (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR data,
+ CK_ULONG data_len,
+ CK_BYTE_PTR signature,
+ CK_ULONG signature_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_VerifyUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR part,
+ CK_ULONG part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_VerifyFinal (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR signature,
+ CK_ULONG signature_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_VerifyRecoverInit (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_VerifyRecover (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR signature,
+ CK_ULONG signature_len,
+ CK_BYTE_PTR data,
+ CK_ULONG_PTR data_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DigestEncryptUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR part,
+ CK_ULONG part_len,
+ CK_BYTE_PTR enc_part,
+ CK_ULONG_PTR enc_part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DecryptDigestUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR enc_part,
+ CK_ULONG enc_part_len,
+ CK_BYTE_PTR part,
+ CK_ULONG_PTR part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_SignEncryptUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR part,
+ CK_ULONG part_len,
+ CK_BYTE_PTR enc_part,
+ CK_ULONG_PTR enc_part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_DecryptVerifyUpdate (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR enc_part,
+ CK_ULONG enc_part_len,
+ CK_BYTE_PTR part,
+ CK_ULONG_PTR part_len)
+{
+ return_val_if_reached (CKR_OPERATION_NOT_INITIALIZED);
+}
+
+static CK_RV
+sys_C_GenerateKey (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_GenerateKeyPair (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_template,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_template,
+ CK_ULONG priv_count,
+ CK_OBJECT_HANDLE_PTR pub_key,
+ CK_OBJECT_HANDLE_PTR priv_key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_WrapKey (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE wrapping_key,
+ CK_OBJECT_HANDLE key,
+ CK_BYTE_PTR wrapped_key,
+ CK_ULONG_PTR wrapped_key_len)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_UnwrapKey (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE unwrapping_key,
+ CK_BYTE_PTR wrapped_key,
+ CK_ULONG wrapped_key_len,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_DeriveKey (CK_SESSION_HANDLE handle,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE base_key,
+ CK_ATTRIBUTE_PTR template,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR key)
+{
+ return_val_if_reached (CKR_MECHANISM_INVALID);
+}
+
+static CK_RV
+sys_C_SeedRandom (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR seed,
+ CK_ULONG seed_len)
+{
+ return_val_if_reached (CKR_RANDOM_NO_RNG);
+}
+
+static CK_RV
+sys_C_GenerateRandom (CK_SESSION_HANDLE handle,
+ CK_BYTE_PTR random_data,
+ CK_ULONG random_len)
+{
+ return_val_if_reached (CKR_RANDOM_NO_RNG);
+}
+
+/* --------------------------------------------------------------------
+ * MODULE ENTRY POINT
+ */
+
+static CK_FUNCTION_LIST sys_function_list = {
+ { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, /* version */
+ sys_C_Initialize,
+ sys_C_Finalize,
+ sys_C_GetInfo,
+ sys_C_GetFunctionList,
+ sys_C_GetSlotList,
+ sys_C_GetSlotInfo,
+ sys_C_GetTokenInfo,
+ sys_C_GetMechanismList,
+ sys_C_GetMechanismInfo,
+ sys_C_InitToken,
+ sys_C_InitPIN,
+ sys_C_SetPIN,
+ sys_C_OpenSession,
+ sys_C_CloseSession,
+ sys_C_CloseAllSessions,
+ sys_C_GetSessionInfo,
+ sys_C_GetOperationState,
+ sys_C_SetOperationState,
+ sys_C_Login,
+ sys_C_Logout,
+ sys_C_CreateObject,
+ sys_C_CopyObject,
+ sys_C_DestroyObject,
+ sys_C_GetObjectSize,
+ sys_C_GetAttributeValue,
+ sys_C_SetAttributeValue,
+ sys_C_FindObjectsInit,
+ sys_C_FindObjects,
+ sys_C_FindObjectsFinal,
+ sys_C_EncryptInit,
+ sys_C_Encrypt,
+ sys_C_EncryptUpdate,
+ sys_C_EncryptFinal,
+ sys_C_DecryptInit,
+ sys_C_Decrypt,
+ sys_C_DecryptUpdate,
+ sys_C_DecryptFinal,
+ sys_C_DigestInit,
+ sys_C_Digest,
+ sys_C_DigestUpdate,
+ sys_C_DigestKey,
+ sys_C_DigestFinal,
+ sys_C_SignInit,
+ sys_C_Sign,
+ sys_C_SignUpdate,
+ sys_C_SignFinal,
+ sys_C_SignRecoverInit,
+ sys_C_SignRecover,
+ sys_C_VerifyInit,
+ sys_C_Verify,
+ sys_C_VerifyUpdate,
+ sys_C_VerifyFinal,
+ sys_C_VerifyRecoverInit,
+ sys_C_VerifyRecover,
+ sys_C_DigestEncryptUpdate,
+ sys_C_DecryptDigestUpdate,
+ sys_C_SignEncryptUpdate,
+ sys_C_DecryptVerifyUpdate,
+ sys_C_GenerateKey,
+ sys_C_GenerateKeyPair,
+ sys_C_WrapKey,
+ sys_C_UnwrapKey,
+ sys_C_DeriveKey,
+ sys_C_SeedRandom,
+ sys_C_GenerateRandom,
+ sys_C_GetFunctionStatus,
+ sys_C_CancelFunction,
+ sys_C_WaitForSlotEvent
+};
+
+#ifdef OS_WIN32
+__declspec(dllexport)
+#endif
+
+CK_RV
+C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+ return sys_C_GetFunctionList (list);
+}
+
+CK_ULONG
+p11_module_next_id (void)
+{
+ static CK_ULONG unique = 0x10;
+ return (unique)++;
+}
diff --git a/trust/module.h b/trust/module.h
new file mode 100644
index 0000000..13b928a
--- /dev/null
+++ b/trust/module.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 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 "pkcs11.h"
+
+#ifndef P11_MODULE_H_
+#define P11_MODULE_H_
+
+CK_ULONG p11_module_next_id (void);
+
+#endif /* P11_MODULE_H_ */
diff --git a/trust/p11-kit-trust.module b/trust/p11-kit-trust.module
new file mode 100644
index 0000000..ad0f254
--- /dev/null
+++ b/trust/p11-kit-trust.module
@@ -0,0 +1,6 @@
+
+# This is a module config for the 'included' p11-kit trust module
+module: p11-kit-trust.so
+
+# The order in which this is loaded in the trust policy
+trust-policy: 1
diff --git a/trust/parser.c b/trust/parser.c
new file mode 100644
index 0000000..ef72474
--- /dev/null
+++ b/trust/parser.c
@@ -0,0 +1,1103 @@
+/*
+ * Copyright (C) 2012 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 "attrs.h"
+#include "checksum.h"
+#define P11_DEBUG_FLAG P11_DEBUG_TRUST
+#include "debug.h"
+#include "dict.h"
+#include "library.h"
+#include "module.h"
+#include "parser.h"
+#include "pkcs11x.h"
+
+#include <libtasn1.h>
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pkix.asn.h"
+
+struct _p11_parser {
+ node_asn *pkix_definitions;
+ p11_parser_sink sink;
+ void *sink_data;
+ const char *probable_label;
+ int flags;
+};
+
+typedef int (* parser_func) (p11_parser *parser,
+ const unsigned char *data,
+ size_t length);
+
+static node_asn *
+decode_asn1 (p11_parser *parser,
+ const char *struct_name,
+ const unsigned char *data,
+ size_t length,
+ char *message)
+{
+ char msg[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+ node_asn *definitions;
+ node_asn *el = NULL;
+ int ret;
+
+ if (message == NULL)
+ message = msg;
+
+ if (strncmp (struct_name, "PKIX1.", 6) == 0) {
+ definitions = parser->pkix_definitions;
+
+ } else {
+ p11_debug_precond ("unknown prefix for element: %s", struct_name);
+ return NULL;
+ }
+
+ ret = asn1_create_element (definitions, struct_name, &el);
+ if (ret != ASN1_SUCCESS) {
+ p11_debug_precond ("failed to create element %s at %s: %d",
+ struct_name, __func__, ret);
+ return NULL;
+ }
+
+ return_val_if_fail (ret == ASN1_SUCCESS, NULL);
+
+ /* asn1_der_decoding destroys the element if fails */
+ ret = asn1_der_decoding (&el, data, length, message);
+
+ if (ret != ASN1_SUCCESS) {
+ p11_debug ("couldn't parse %s: %s: %s",
+ struct_name, asn1_strerror (ret), message);
+ return NULL;
+ }
+
+ return el;
+}
+
+static void
+sink_object (p11_parser *parser,
+ CK_ATTRIBUTE *attrs)
+{
+ if (parser->sink)
+ (parser->sink) (attrs, parser->sink_data);
+ else
+ p11_attrs_free (attrs);
+}
+
+#define ID_LENGTH P11_CHECKSUM_SHA1_LENGTH
+
+static void
+id_generate (p11_parser *parser,
+ CK_BYTE *vid)
+{
+ CK_ULONG val = p11_module_next_id ();
+ p11_checksum_sha1 (vid, &val, sizeof (val), NULL);
+}
+
+static CK_ATTRIBUTE *
+build_object (p11_parser *parser,
+ CK_ATTRIBUTE *attrs,
+ CK_OBJECT_CLASS vclass,
+ CK_BYTE *vid,
+ const char *explicit_label)
+{
+ CK_BBOOL vtrue = CK_TRUE;
+ CK_BBOOL vfalse = CK_FALSE;
+ const char *vlabel;
+
+ CK_ATTRIBUTE klass = { CKA_CLASS, &vclass, sizeof (vclass) };
+ CK_ATTRIBUTE token = { CKA_TOKEN, &vtrue, sizeof (vtrue) };
+ CK_ATTRIBUTE private = { CKA_PRIVATE, &vfalse, sizeof (vfalse) };
+ CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &vfalse, sizeof (vfalse) };
+ CK_ATTRIBUTE id = { CKA_ID, vid, ID_LENGTH };
+ CK_ATTRIBUTE label = { CKA_LABEL, };
+
+ vlabel = explicit_label ? (char *)explicit_label : parser->probable_label;
+ if (vlabel) {
+ label.pValue = (void *)vlabel;
+ label.ulValueLen = strlen (vlabel);
+ } else {
+ label.type = CKA_INVALID;
+ }
+
+ if (!vid)
+ id.type = CKA_INVALID;
+
+ return p11_attrs_build (attrs, &klass, &token, &private, &modifiable,
+ &id, &label, NULL);
+}
+
+static void
+calc_check_value (const unsigned char *data,
+ size_t length,
+ CK_BYTE *check_value)
+{
+ unsigned char checksum[P11_CHECKSUM_SHA1_LENGTH];
+ p11_checksum_sha1 (checksum, data, length, NULL);
+ memcpy (check_value, checksum, 3);
+}
+
+static int
+atoin (const char *p,
+ int digits)
+{
+ int ret = 0, base = 1;
+ while(--digits >= 0) {
+ if (p[digits] < '0' || p[digits] > '9')
+ return -1;
+ ret += (p[digits] - '0') * base;
+ base *= 10;
+ }
+ return ret;
+}
+
+static int
+two_to_four_digit_year (int year)
+{
+ time_t now;
+ struct tm tm;
+ int century, current;
+
+ return_val_if_fail (year >= 0 && year <= 99, -1);
+
+ /* Get the current year */
+ now = time (NULL);
+ return_val_if_fail (now >= 0, -1);
+ if (!gmtime_r (&now, &tm))
+ return_val_if_reached (-1);
+
+ current = (tm.tm_year % 100);
+ century = (tm.tm_year + 1900) - current;
+
+ /*
+ * Check if it's within 40 years before the
+ * current date.
+ */
+ if (current < 40) {
+ if (year < current)
+ return century + year;
+ if (year > 100 - (40 - current))
+ return (century - 100) + year;
+ } else {
+ if (year < current && year > (current - 40))
+ return century + year;
+ }
+
+ /*
+ * If it's after then adjust for overflows to
+ * the next century.
+ */
+ if (year < current)
+ return century + 100 + year;
+ else
+ return century + year;
+}
+
+static bool
+parse_utc_time (const char *time,
+ size_t n_time,
+ struct tm *when,
+ int *offset)
+{
+ const char *p, *e;
+ int year;
+
+ assert (when != NULL);
+ assert (time != NULL);
+ assert (offset != NULL);
+
+ /* YYMMDDhhmmss.ffff Z | +0000 */
+ if (n_time < 6 || n_time >= 28)
+ return false;
+
+ /* Reset everything to default legal values */
+ memset (when, 0, sizeof (*when));
+ *offset = 0;
+ when->tm_mday = 1;
+
+ /* Select the digits part of it */
+ p = time;
+ for (e = p; *e >= '0' && *e <= '9'; ++e);
+
+ if (p + 2 <= e) {
+ year = atoin (p, 2);
+ p += 2;
+
+ /*
+ * 40 years in the past is our century. 60 years
+ * in the future is the next century.
+ */
+ when->tm_year = two_to_four_digit_year (year) - 1900;
+ }
+ if (p + 2 <= e) {
+ when->tm_mon = atoin (p, 2) - 1;
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when->tm_mday = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when->tm_hour = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when->tm_min = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when->tm_sec = atoin (p, 2);
+ p += 2;
+ }
+
+ if (when->tm_year < 0 || when->tm_year > 9999 ||
+ when->tm_mon < 0 || when->tm_mon > 11 ||
+ when->tm_mday < 1 || when->tm_mday > 31 ||
+ when->tm_hour < 0 || when->tm_hour > 23 ||
+ when->tm_min < 0 || when->tm_min > 59 ||
+ when->tm_sec < 0 || when->tm_sec > 59)
+ return false;
+
+ /* Make sure all that got parsed */
+ if (p != e)
+ return false;
+
+ /* Now the remaining optional stuff */
+ e = time + n_time;
+
+ /* See if there's a fraction, and discard it if so */
+ if (p < e && *p == '.' && p + 5 <= e)
+ p += 5;
+
+ /* See if it's UTC */
+ if (p < e && *p == 'Z') {
+ p += 1;
+
+ /* See if it has a timezone */
+ } else if ((*p == '-' || *p == '+') && p + 3 <= e) {
+ int off, neg;
+
+ neg = *p == '-';
+ ++p;
+
+ off = atoin (p, 2) * 3600;
+ if (off < 0 || off > 86400)
+ return false;
+ p += 2;
+
+ if (p + 2 <= e) {
+ off += atoin (p, 2) * 60;
+ p += 2;
+ }
+
+ /* Use TZ offset */
+ if (neg)
+ *offset = 0 - off;
+ else
+ *offset = off;
+ }
+
+ /* Make sure everything got parsed */
+ if (p != e)
+ return false;
+
+ return true;
+}
+
+static bool
+parse_general_time (const char *time,
+ size_t n_time,
+ struct tm *when,
+ int *offset)
+{
+ const char *p, *e;
+
+ assert (time != NULL);
+ assert (when != NULL);
+ assert (offset != NULL);
+
+ /* YYYYMMDDhhmmss.ffff Z | +0000 */
+ if (n_time < 8 || n_time >= 30)
+ return false;
+
+ /* Reset everything to default legal values */
+ memset (when, 0, sizeof (*when));
+ *offset = 0;
+ when->tm_mday = 1;
+
+ /* Select the digits part of it */
+ p = time;
+ for (e = p; *e >= '0' && *e <= '9'; ++e);
+
+ if (p + 4 <= e) {
+ when->tm_year = atoin (p, 4) - 1900;
+ p += 4;
+ }
+ if (p + 2 <= e) {
+ when->tm_mon = atoin (p, 2) - 1;
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when->tm_mday = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when->tm_hour = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when->tm_min = atoin (p, 2);
+ p += 2;
+ }
+ if (p + 2 <= e) {
+ when->tm_sec = atoin (p, 2);
+ p += 2;
+ }
+
+ if (when->tm_year < 0 || when->tm_year > 9999 ||
+ when->tm_mon < 0 || when->tm_mon > 11 ||
+ when->tm_mday < 1 || when->tm_mday > 31 ||
+ when->tm_hour < 0 || when->tm_hour > 23 ||
+ when->tm_min < 0 || when->tm_min > 59 ||
+ when->tm_sec < 0 || when->tm_sec > 59)
+ return false;
+
+ /* Make sure all that got parsed */
+ if (p != e)
+ return false;
+
+ /* Now the remaining optional stuff */
+ e = time + n_time;
+
+ /* See if there's a fraction, and discard it if so */
+ if (p < e && *p == '.' && p + 5 <= e)
+ p += 5;
+
+ /* See if it's UTC */
+ if (p < e && *p == 'Z') {
+ p += 1;
+
+ /* See if it has a timezone */
+ } else if ((*p == '-' || *p == '+') && p + 3 <= e) {
+ int off, neg;
+
+ neg = *p == '-';
+ ++p;
+
+ off = atoin (p, 2) * 3600;
+ if (off < 0 || off > 86400)
+ return false;
+ p += 2;
+
+ if (p + 2 <= e) {
+ off += atoin (p, 2) * 60;
+ p += 2;
+ }
+
+ /* Use TZ offset */
+ if (neg)
+ *offset = 0 - off;
+ else
+ *offset = off;
+ }
+
+ /* Make sure everything got parsed */
+ if (p != e)
+ return false;
+
+ return true;
+}
+
+static bool
+calc_date (node_asn *cert,
+ const char *field,
+ CK_DATE *date)
+{
+ node_asn *choice;
+ struct tm when;
+ int tz_offset;
+ char buf[64];
+ time_t timet;
+ char *sub;
+ int len;
+ int ret;
+
+ choice = asn1_find_node (cert, field);
+ return_val_if_fail (choice != NULL, false);
+
+ len = sizeof (buf) - 1;
+ ret = asn1_read_value (cert, field, buf, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+
+ sub = strconcat (field, ".", buf, NULL);
+
+ if (strcmp (buf, "generalTime") == 0) {
+ len = sizeof (buf) - 1;
+ ret = asn1_read_value (cert, sub, buf, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+ if (!parse_general_time (buf, len, &when, &tz_offset))
+ return_val_if_reached (false);
+
+ } else if (strcmp (buf, "utcTime") == 0) {
+ len = sizeof (buf) - 1;
+ ret = asn1_read_value (cert, sub, buf, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+ if (!parse_utc_time (buf, len - 1, &when, &tz_offset))
+ return_val_if_reached (false);
+
+ } else {
+ return_val_if_reached (false);
+ }
+
+ free (sub);
+
+ /* In order to work with 32 bit time_t. */
+ if (sizeof (time_t) <= 4 && when.tm_year >= 2038) {
+ timet = (time_t)2145914603; /* 2037-12-31 23:23:23 */
+
+ /* Convert to seconds since epoch */
+ } else {
+ timet = timegm (&when);
+ return_val_if_fail (timet >= 0, false);
+ timet += tz_offset;
+ }
+
+ if (!gmtime_r (&timet, &when))
+ return_val_if_reached (false);
+
+ assert (sizeof (date->year) == 4);
+ snprintf ((char *)buf, 5, "%04d", 1900 + when.tm_year);
+ memcpy (date->year, buf, 4);
+
+ assert (sizeof (date->month) == 2);
+ snprintf ((char *)buf, 3, "%02d", when.tm_mon + 1);
+ memcpy (date->month, buf, 2);
+
+ assert (sizeof (date->day) == 2);
+ snprintf ((char *)buf, 3, "%02d", when.tm_mday);
+ memcpy (date->day, buf, 2);
+
+ return true;
+}
+
+static bool
+calc_trusted (p11_parser *parser,
+ node_asn *cert,
+ CK_BBOOL *vtrusted)
+{
+ assert (parser != NULL);
+ assert (vtrusted != NULL);
+
+ /*
+ * This calculates CKA_TRUSTED, which is a silly attribute, don't
+ * read too much into this. The real trust mechinisms are elsewhere.
+ */
+
+ *vtrusted = CK_FALSE;
+ if (parser->flags & P11_PARSE_FLAG_ANCHOR) {
+ *vtrusted = CK_TRUE;
+ return true;
+ }
+
+ /* Don't add this attribute unless anchor */
+ return false;
+}
+
+static bool
+calc_element (node_asn *el,
+ const unsigned char *data,
+ size_t length,
+ const char *field,
+ CK_ATTRIBUTE *attr)
+{
+ int ret;
+ int start, end;
+
+ ret = asn1_der_decoding_startEnd (el, data, length, field, &start, &end);
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+ return_val_if_fail (end >= start, false);
+
+ attr->pValue = (void *)(data + start);
+ attr->ulValueLen = (end - start) + 1;
+ return true;
+}
+
+static CK_ATTRIBUTE *
+build_x509_certificate (p11_parser *parser,
+ CK_ATTRIBUTE *attrs,
+ node_asn *cert,
+ const unsigned char *data,
+ size_t length)
+{
+ CK_CERTIFICATE_TYPE vx509 = CKC_X_509;
+ CK_BYTE vchecksum[3];
+
+ /* TODO: Implement */
+ CK_ULONG vcategory = 0;
+ CK_BBOOL vtrusted = CK_FALSE;
+ CK_DATE vstart;
+ CK_DATE vend;
+
+ CK_ATTRIBUTE certificate_type = { CKA_CERTIFICATE_TYPE, &vx509, sizeof (vx509) };
+ CK_ATTRIBUTE certificate_category = { CKA_CERTIFICATE_CATEGORY, &vcategory, sizeof (vcategory) };
+ CK_ATTRIBUTE value = { CKA_VALUE, (void *)data, length };
+
+ CK_ATTRIBUTE check_value = { CKA_CHECK_VALUE, &vchecksum, sizeof (vchecksum) };
+ CK_ATTRIBUTE trusted = { CKA_TRUSTED, &vtrusted, sizeof (vtrusted) };
+ CK_ATTRIBUTE start_date = { CKA_START_DATE, &vstart, sizeof (vstart) };
+ CK_ATTRIBUTE end_date = { CKA_END_DATE, &vend, sizeof (vend) };
+ CK_ATTRIBUTE subject = { CKA_SUBJECT, };
+ CK_ATTRIBUTE issuer = { CKA_ISSUER, };
+ CK_ATTRIBUTE serial_number = { CKA_SERIAL_NUMBER, };
+
+ /*
+ * The following are not present:
+ * CKA_URL
+ * CKA_HASH_OF_SUBJECT_PUBLIC_KEY
+ * CKA_HASH_OF_ISSUER_PUBLIC_KEY
+ * CKA_JAVA_MIDP_SECURITY_DOMAIN
+ */
+
+ calc_check_value (data, length, vchecksum);
+
+ /* This is a silly trust flag, we set it if the cert is an anchor */
+ if (!calc_trusted (parser, cert, &vtrusted))
+ trusted.type = CKA_INVALID;
+
+ if (!calc_date (cert, "tbsCertificate.validity.notBefore", &vstart))
+ start_date.type = CKA_INVALID;
+ if (!calc_date (cert, "tbsCertificate.validity.notAfter", &vend))
+ end_date.type = CKA_INVALID;
+
+ if (!calc_element (cert, data, length, "tbsCertificate.issuer.rdnSequence", &issuer))
+ issuer.type = CKA_INVALID;
+ if (!calc_element (cert, data, length, "tbsCertificate.subject.rdnSequence", &subject))
+ subject.type = CKA_INVALID;
+ if (!calc_element (cert, data, length, "tbsCertificate.serialNumber", &serial_number))
+ serial_number.type = CKA_INVALID;
+
+ return p11_attrs_build (attrs, &certificate_type, &certificate_category,
+ &check_value, &trusted, &start_date, &end_date,
+ &subject, &issuer, &serial_number, &value,
+ NULL);
+}
+
+static unsigned char *
+find_extension (node_asn *cert,
+ const char *extension_oid,
+ size_t *length)
+{
+ unsigned char *data = NULL;
+ char field[128];
+ char oid[128];
+ int len;
+ int ret;
+ int i;
+
+ assert (extension_oid != NULL);
+ assert (strlen (extension_oid) < sizeof (oid));
+
+ for (i = 1; ; i++) {
+ if (snprintf (field, sizeof (field), "tbsCertificate.extensions.?%u.extnID", i) < 0)
+ return_val_if_reached (NULL);
+
+ len = sizeof (oid) - 1;
+ ret = asn1_read_value (cert, field, oid, &len);
+
+ /* No more extensions */
+ if (ret == ASN1_ELEMENT_NOT_FOUND)
+ break;
+
+ /* A really, really long extension oid, not looking for it */
+ else if (ret == ASN1_MEM_ERROR)
+ continue;
+
+ return_val_if_fail (ret == ASN1_SUCCESS, NULL);
+
+ /* The one we're lookin for? */
+ if (strcmp (oid, extension_oid) != 0)
+ continue;
+
+ if (snprintf (field, sizeof (field), "tbsCertificate.extensions.?%u.extnValue", i) < 0)
+ return_val_if_reached (NULL);
+
+ len = 0;
+ ret = asn1_read_value (cert, field, NULL, &len);
+ return_val_if_fail (ret == ASN1_MEM_ERROR, NULL);
+
+ data = malloc (len);
+ return_val_if_fail (data != NULL, NULL);
+
+ ret = asn1_read_value (cert, field, data, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, NULL);
+
+ *length = len;
+ break;
+ }
+
+ return data;
+}
+
+int
+p11_parse_key_usage (p11_parser *parser,
+ const unsigned char *data,
+ size_t length,
+ unsigned int *ku)
+{
+ char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, };
+ unsigned char buf[2];
+ node_asn *ext;
+ int len;
+ int ret;
+
+ ext = decode_asn1 (parser, "PKIX1.KeyUsage", data, length, message);
+ if (ext == NULL)
+ return P11_PARSE_UNRECOGNIZED;
+
+ len = sizeof (buf);
+ ret = asn1_read_value (ext, "", buf, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
+
+ /* A bit string, so combine into one set of flags */
+ *ku = buf[0] | (buf[1] << 8);
+
+ asn1_delete_structure (&ext);
+
+ return P11_PARSE_SUCCESS;
+}
+
+static unsigned int
+decode_ku (p11_parser *parser,
+ node_asn *cert)
+{
+ unsigned char *data;
+ size_t length;
+ unsigned int ku;
+
+ /*
+ * If the certificate extension was missing, then *all* key
+ * usages are to be set. If the extension was invalid, then
+ * fail safe to none of the key usages.
+ */
+
+ data = find_extension (cert, "2.5.29.15", &length);
+
+ if (!data)
+ return ~0U;
+
+ if (p11_parse_key_usage (parser, data, length, &ku) != P11_PARSE_SUCCESS) {
+ p11_message ("invalid key usage certificate extension");
+ ku = 0U;
+ }
+
+ free (data);
+
+ return ku;
+}
+
+int
+p11_parse_extended_key_usage (p11_parser *parser,
+ const unsigned char *data,
+ size_t length,
+ p11_dict *ekus)
+{
+ node_asn *ext;
+ char field[128];
+ char *eku;
+ int len;
+ int ret;
+ int i;
+
+ ext = decode_asn1 (parser, "PKIX1.ExtKeyUsageSyntax", data, length, NULL);
+ if (ext == NULL)
+ return P11_PARSE_UNRECOGNIZED;
+
+ for (i = 1; ; i++) {
+ if (snprintf (field, sizeof (field), "?%u", i) < 0)
+ return_val_if_reached (P11_PARSE_FAILURE);
+
+ len = 0;
+ ret = asn1_read_value (ext, field, NULL, &len);
+ if (ret == ASN1_ELEMENT_NOT_FOUND)
+ break;
+
+ return_val_if_fail (ret == ASN1_MEM_ERROR, P11_PARSE_FAILURE);
+
+ eku = malloc (len + 1);
+ return_val_if_fail (eku != NULL, P11_PARSE_FAILURE);
+
+ ret = asn1_read_value (ext, field, eku, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
+
+ if (!p11_dict_set (ekus, eku, eku))
+ return_val_if_reached (P11_PARSE_FAILURE);
+ }
+
+ asn1_delete_structure (&ext);
+
+ return P11_PARSE_SUCCESS;
+
+}
+
+static p11_dict *
+decode_eku (p11_parser *parser,
+ node_asn *cert)
+{
+ unsigned char *data;
+ p11_dict *ekus;
+ char *eku;
+ size_t length;
+
+ ekus = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL);
+ return_val_if_fail (ekus != NULL, NULL);
+
+ /*
+ * If the certificate extension was missing, then *all* extended key
+ * usages are to be set. If the extension was invalid, then
+ * fail safe to none of the extended key usages.
+ */
+
+ data = find_extension (cert, "2.5.29.37", &length);
+ if (data) {
+ if (p11_parse_extended_key_usage (parser, data, length, ekus) != P11_PARSE_SUCCESS) {
+ p11_message ("invalid extended key usage certificate extension");
+ p11_dict_free (ekus);
+ ekus = NULL;
+ }
+ } else {
+ /* A star means anything to has_eku() */
+ eku = strdup ("*");
+ if (!eku || !p11_dict_set (ekus, eku, eku))
+ return_val_if_reached (NULL);
+ }
+
+ free (data);
+
+ return ekus;
+}
+
+static int
+has_eku (p11_dict *ekus,
+ const char *eku)
+{
+ return ekus != NULL && /* If a "*" present, then any thing allowed */
+ (p11_dict_get (ekus, eku) || p11_dict_get (ekus, "*"));
+}
+
+static CK_ATTRIBUTE *
+build_nss_trust_object (p11_parser *parser,
+ CK_ATTRIBUTE *attrs,
+ node_asn *cert,
+ const unsigned char *data,
+ size_t length)
+{
+ CK_BYTE vsha1_hash[P11_CHECKSUM_SHA1_LENGTH];
+ CK_BYTE vmd5_hash[P11_CHECKSUM_MD5_LENGTH];
+ CK_BBOOL vfalse = CK_FALSE;
+
+ CK_TRUST vdigital_signature;
+ CK_TRUST vnon_repudiation;
+ CK_TRUST vkey_encipherment;
+ CK_TRUST vdata_encipherment;
+ CK_TRUST vkey_agreement;
+ CK_TRUST vkey_cert_sign;
+ CK_TRUST vcrl_sign;
+
+ CK_TRUST vserver_auth;
+ CK_TRUST vclient_auth;
+ CK_TRUST vcode_signing;
+ CK_TRUST vemail_protection;
+ CK_TRUST vipsec_end_system;
+ CK_TRUST vipsec_tunnel;
+ CK_TRUST vipsec_user;
+ CK_TRUST vtime_stamping;
+
+ CK_ATTRIBUTE subject = { CKA_SUBJECT, };
+ CK_ATTRIBUTE issuer = { CKA_ISSUER, };
+ CK_ATTRIBUTE serial_number = { CKA_SERIAL_NUMBER, };
+
+ CK_ATTRIBUTE md5_hash = { CKA_CERT_MD5_HASH, vmd5_hash, sizeof (vmd5_hash) };
+ CK_ATTRIBUTE sha1_hash = { CKA_CERT_SHA1_HASH, vsha1_hash, sizeof (vsha1_hash) };
+
+ CK_ATTRIBUTE digital_signature = { CKA_TRUST_DIGITAL_SIGNATURE, &vdigital_signature, sizeof (vdigital_signature) };
+ CK_ATTRIBUTE non_repudiation = { CKA_TRUST_NON_REPUDIATION, &vnon_repudiation, sizeof (vnon_repudiation) };
+ CK_ATTRIBUTE key_encipherment = { CKA_TRUST_KEY_ENCIPHERMENT, &vkey_encipherment, sizeof (vkey_encipherment) };
+ CK_ATTRIBUTE data_encipherment = { CKA_TRUST_DATA_ENCIPHERMENT, &vdata_encipherment, sizeof (vdata_encipherment) };
+ CK_ATTRIBUTE key_agreement = { CKA_TRUST_KEY_AGREEMENT, &vkey_agreement, sizeof (vkey_agreement) };
+ CK_ATTRIBUTE key_cert_sign = { CKA_TRUST_KEY_CERT_SIGN, &vkey_cert_sign, sizeof (vkey_cert_sign) };
+ CK_ATTRIBUTE crl_sign = { CKA_TRUST_CRL_SIGN, &vcrl_sign, sizeof (vcrl_sign) };
+
+ CK_ATTRIBUTE server_auth = { CKA_TRUST_SERVER_AUTH, &vserver_auth, sizeof (vserver_auth) };
+ CK_ATTRIBUTE client_auth = { CKA_TRUST_CLIENT_AUTH, &vclient_auth, sizeof (vclient_auth) };
+ CK_ATTRIBUTE code_signing = { CKA_TRUST_CODE_SIGNING, &vcode_signing, sizeof (vcode_signing) };
+ CK_ATTRIBUTE email_protection = { CKA_TRUST_EMAIL_PROTECTION, &vemail_protection, sizeof (vemail_protection) };
+ CK_ATTRIBUTE ipsec_end_system = { CKA_TRUST_IPSEC_END_SYSTEM, &vipsec_end_system, sizeof (vipsec_end_system) };
+ CK_ATTRIBUTE ipsec_tunnel = { CKA_TRUST_IPSEC_TUNNEL, &vipsec_tunnel, sizeof (vipsec_tunnel) };
+ CK_ATTRIBUTE ipsec_user = { CKA_TRUST_IPSEC_USER, &vipsec_user, sizeof (vipsec_user) };
+ CK_ATTRIBUTE time_stamping = { CKA_TRUST_TIME_STAMPING, &vtime_stamping, sizeof (vtime_stamping) };
+
+ CK_ATTRIBUTE step_up_approved = { CKA_TRUST_STEP_UP_APPROVED, &vfalse, sizeof (vfalse) };
+
+ p11_dict *ekus;
+ unsigned int ku;
+ CK_TRUST value;
+ CK_TRUST unknown;
+
+ if (!calc_element (cert, data, length, "tbsCertificate.issuer.rdnSequence", &issuer))
+ issuer.type = CKA_INVALID;
+ if (!calc_element (cert, data, length, "tbsCertificate.subject.rdnSequence", &subject))
+ subject.type = CKA_INVALID;
+ if (!calc_element (cert, data, length, "tbsCertificate.serialNumber", &serial_number))
+ serial_number.type = CKA_INVALID;
+
+ p11_checksum_md5 (vmd5_hash, data, length, NULL);
+ p11_checksum_sha1 (vsha1_hash, data, length, NULL);
+
+ unknown = CKT_NETSCAPE_TRUST_UNKNOWN;
+ if (parser->flags & P11_PARSE_FLAG_ANCHOR)
+ value = CKT_NETSCAPE_TRUSTED_DELEGATOR;
+ else
+ value = CKT_NETSCAPE_TRUSTED;
+
+ ku = decode_ku (parser, cert);
+ vdigital_signature = (ku & P11_KU_DIGITAL_SIGNATURE) ? value : unknown;
+ vnon_repudiation = (ku & P11_KU_NON_REPUDIATION) ? value : unknown;
+ vkey_encipherment = (ku & P11_KU_KEY_ENCIPHERMENT) ? value : unknown;
+ vkey_agreement = (ku & P11_KU_KEY_AGREEMENT) ? value : unknown;
+ vkey_cert_sign = (ku & P11_KU_KEY_CERT_SIGN) ? value : unknown;
+ vcrl_sign = (ku & P11_KU_CRL_SIGN) ? value : unknown;
+
+ ekus = decode_eku (parser, cert);
+ vserver_auth = has_eku (ekus, P11_EKU_SERVER_AUTH) ? value : unknown;
+ vclient_auth = has_eku (ekus, P11_EKU_CLIENT_AUTH) ? value : unknown;
+ vcode_signing = has_eku (ekus, P11_EKU_CODE_SIGNING) ? value : unknown;
+ vemail_protection = has_eku (ekus, P11_EKU_EMAIL) ? value : unknown;
+ vipsec_end_system = has_eku (ekus, P11_EKU_IPSEC_END_SYSTEM) ? value : unknown;
+ vipsec_tunnel = has_eku (ekus, P11_EKU_IPSEC_TUNNEL) ? value : unknown;
+ vipsec_user = has_eku (ekus, P11_EKU_IPSEC_USER) ? value : unknown;
+ vtime_stamping = has_eku (ekus, P11_EKU_TIME_STAMPING) ? value : unknown;
+ p11_dict_free (ekus);
+
+ return p11_attrs_build (attrs, &subject, &issuer, &serial_number, &md5_hash, &sha1_hash,
+ &digital_signature, &non_repudiation, &key_encipherment,
+ &data_encipherment, &key_agreement, &key_cert_sign, &crl_sign,
+ &server_auth, &client_auth, &code_signing, &email_protection,
+ &ipsec_end_system, &ipsec_tunnel, &ipsec_user, &time_stamping,
+ &step_up_approved, NULL);
+
+}
+
+static int
+sink_nss_trust_object (p11_parser *parser,
+ CK_BYTE *vid,
+ node_asn *cert,
+ const unsigned char *data,
+ size_t length)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+
+ attrs = build_object (parser, attrs, CKO_NETSCAPE_TRUST, vid, NULL);
+ return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
+
+ attrs = build_nss_trust_object (parser, attrs, cert, data, length);
+ return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
+
+ sink_object (parser, attrs);
+ return P11_PARSE_SUCCESS;
+}
+
+static int
+sink_x509_certificate (p11_parser *parser,
+ CK_BYTE *vid,
+ node_asn *cert,
+ const unsigned char *data,
+ size_t length)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+
+ attrs = build_object (parser, attrs, CKO_CERTIFICATE, vid, NULL);
+ return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
+
+ attrs = build_x509_certificate (parser, attrs, cert, data, length);
+ return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
+
+ sink_object (parser, attrs);
+ return P11_PARSE_SUCCESS;
+}
+
+static int
+parse_der_x509_certificate (p11_parser *parser,
+ const unsigned char *data,
+ size_t length)
+{
+ CK_BYTE vid[ID_LENGTH];
+ node_asn *cert;
+ int ret;
+
+ cert = decode_asn1 (parser, "PKIX1.Certificate", data, length, NULL);
+ if (cert == NULL)
+ return P11_PARSE_UNRECOGNIZED;
+
+ /* The CKA_ID links related objects */
+ id_generate (parser, vid);
+
+ ret = sink_x509_certificate (parser, vid, cert, data, length);
+ return_val_if_fail (ret == P11_PARSE_SUCCESS, ret);
+
+ ret = sink_nss_trust_object (parser, vid, cert, data, length);
+ return_val_if_fail (ret == P11_PARSE_SUCCESS, ret);
+
+ asn1_delete_structure (&cert);
+ return P11_PARSE_SUCCESS;
+}
+
+static parser_func all_parsers[] = {
+ parse_der_x509_certificate,
+ NULL,
+};
+
+p11_parser *
+p11_parser_new (void)
+{
+ char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, };
+ node_asn *definitions = NULL;
+ p11_parser *parser;
+ int ret;
+
+ ret = asn1_array2tree (pkix_asn1_tab, &definitions, message);
+ if (ret != ASN1_SUCCESS) {
+ p11_debug_precond ("failed to load pkix_asn1_tab in %s: %d %s",
+ __func__, ret, message);
+ return NULL;
+ }
+
+ parser = calloc (1, sizeof (p11_parser));
+ return_val_if_fail (parser != NULL, NULL);
+
+ parser->pkix_definitions = definitions;
+ return parser;
+}
+
+void
+p11_parser_free (p11_parser *parser)
+{
+ if (!parser)
+ return;
+
+ asn1_delete_structure (&parser->pkix_definitions);
+ free (parser);
+}
+
+int
+p11_parse_memory (p11_parser *parser,
+ const char *filename,
+ int flags,
+ const unsigned char *data,
+ size_t length,
+ p11_parser_sink sink,
+ void *sink_data)
+{
+ int ret = P11_PARSE_UNRECOGNIZED;
+ char *base;
+ int i;
+
+ return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
+ return_val_if_fail (parser->sink == NULL, P11_PARSE_FAILURE);
+
+ base = basename (filename);
+ parser->probable_label = base;
+ parser->sink = sink;
+ parser->sink_data = sink_data;
+ parser->flags = flags;
+
+ for (i = 0; all_parsers[i] != NULL; i++) {
+ ret = (all_parsers[i]) (parser, data, length);
+ if (ret != P11_PARSE_UNRECOGNIZED)
+ break;
+ }
+
+ parser->probable_label = NULL;
+ parser->sink = NULL;
+ parser->sink_data = NULL;
+ parser->flags = 0;
+
+ return ret;
+}
+
+int
+p11_parse_file (p11_parser *parser,
+ const char *filename,
+ int flags,
+ p11_parser_sink sink,
+ void *sink_data)
+{
+ void *data;
+ struct stat sb;
+ int fd;
+ int ret;
+
+ fd = open (filename, O_RDONLY);
+ if (fd == -1) {
+ p11_message ("couldn't open file: %s: %s", filename, strerror (errno));
+ return P11_PARSE_FAILURE;
+ }
+
+ if (fstat (fd, &sb) < 0) {
+ p11_message ("couldn't stat file: %s: %s", filename, strerror (errno));
+ return P11_PARSE_FAILURE;
+ }
+
+ data = mmap (NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == NULL) {
+ p11_message ("couldn't map file: %s: %s", filename, strerror (errno));
+ return P11_PARSE_FAILURE;
+ }
+
+ ret = p11_parse_memory (parser, filename, flags, data, sb.st_size, sink, sink_data);
+
+ munmap (data, sb.st_size);
+ close (fd);
+
+ return ret;
+}
diff --git a/trust/parser.h b/trust/parser.h
new file mode 100644
index 0000000..44529ba
--- /dev/null
+++ b/trust/parser.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012 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 "dict.h"
+#include "pkcs11.h"
+
+#ifndef P11_PARSER_H_
+#define P11_PARSER_H_
+
+enum {
+ P11_PARSE_FAILURE = -1,
+ P11_PARSE_UNRECOGNIZED = 0,
+ P11_PARSE_SUCCESS = 1,
+};
+
+enum {
+ P11_PARSE_FLAG_NONE = 0,
+ P11_PARSE_FLAG_ANCHOR = 1 << 0,
+};
+
+#define P11_PARSER_FIRST_HANDLE 0xA0000000UL
+
+#define P11_EKU_SERVER_AUTH "1.3.6.1.5.5.7.3.1"
+#define P11_EKU_CLIENT_AUTH "1.3.6.1.5.5.7.3.2"
+#define P11_EKU_CODE_SIGNING "1.3.6.1.5.5.7.3.3"
+#define P11_EKU_EMAIL "1.3.6.1.5.5.7.3.4"
+#define P11_EKU_IPSEC_END_SYSTEM "1.3.6.1.5.5.7.3.5"
+#define P11_EKU_IPSEC_TUNNEL "1.3.6.1.5.5.7.3.6"
+#define P11_EKU_IPSEC_USER "1.3.6.1.5.5.7.3.7"
+#define P11_EKU_TIME_STAMPING "1.3.6.1.5.5.7.3.8"
+
+enum {
+ P11_KU_DIGITAL_SIGNATURE = 128,
+ P11_KU_NON_REPUDIATION = 64,
+ P11_KU_KEY_ENCIPHERMENT = 32,
+ P11_KU_DATA_ENCIPHERMENT = 16,
+ P11_KU_KEY_AGREEMENT = 8,
+ P11_KU_KEY_CERT_SIGN = 4,
+ P11_KU_CRL_SIGN = 2,
+ P11_KU_ENCIPHER_ONLY = 1,
+ P11_KU_DECIPHER_ONLY = 32768,
+};
+
+typedef struct _p11_parser p11_parser;
+
+p11_parser * p11_parser_new (void);
+
+void p11_parser_free (p11_parser *parser);
+
+typedef void (* p11_parser_sink) (CK_ATTRIBUTE *attrs,
+ void *user_data);
+
+int p11_parse_memory (p11_parser *parser,
+ const char *filename,
+ int flags,
+ const unsigned char *data,
+ size_t length,
+ p11_parser_sink sink,
+ void *sink_data);
+
+int p11_parse_file (p11_parser *parser,
+ const char *filename,
+ int flags,
+ p11_parser_sink sink,
+ void *sink_data);
+
+int p11_parse_key_usage (p11_parser *parser,
+ const unsigned char *data,
+ size_t length,
+ unsigned int *ku);
+
+int p11_parse_extended_key_usage (p11_parser *parser,
+ const unsigned char *data,
+ size_t length,
+ p11_dict *ekus);
+
+#endif
diff --git a/trust/session.c b/trust/session.c
new file mode 100644
index 0000000..070364e
--- /dev/null
+++ b/trust/session.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2012 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 "attrs.h"
+#define P11_DEBUG_FLAG P11_DEBUG_TRUST
+#include "debug.h"
+#include "dict.h"
+#include "library.h"
+#include "pkcs11.h"
+#include "module.h"
+#include "session.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+ CK_OBJECT_HANDLE handle;
+ CK_ATTRIBUTE *attrs;
+} Object;
+
+static void
+object_free (void *data)
+{
+ Object *object = data;
+ p11_attrs_free (object->attrs);
+ free (object);
+}
+
+p11_session *
+p11_session_new (p11_token *token)
+{
+ p11_session *session;
+
+ session = calloc (1, sizeof (p11_session));
+ return_val_if_fail (session != NULL, NULL);
+
+ session->handle = p11_module_next_id ();
+
+ session->objects = p11_dict_new (p11_dict_ulongptr_hash,
+ p11_dict_ulongptr_equal,
+ NULL, object_free);
+ return_val_if_fail (session->objects != NULL, NULL);
+
+ session->token = token;
+
+ return session;
+}
+
+void
+p11_session_free (void *data)
+{
+ p11_session *session = data;
+
+ p11_session_set_operation (session, NULL, NULL);
+ p11_dict_free (session->objects);
+
+ free (session);
+}
+
+CK_RV
+p11_session_add_object (p11_session *session,
+ CK_ATTRIBUTE *attrs,
+ CK_OBJECT_HANDLE *handle)
+{
+ Object *object;
+
+ assert (handle != NULL);
+ assert (session != NULL);
+
+ return_val_if_fail (attrs != NULL, CKR_GENERAL_ERROR);
+
+ object = malloc (sizeof (Object));
+ return_val_if_fail (object != NULL, CKR_HOST_MEMORY);
+
+ object->handle = p11_module_next_id ();
+ object->attrs = attrs;
+
+ if (!p11_dict_set (session->objects, &object->handle, object))
+ return_val_if_reached (CKR_HOST_MEMORY);
+
+ *handle = object->handle;
+ return CKR_OK;
+}
+
+CK_RV
+p11_session_del_object (p11_session *session,
+ CK_OBJECT_HANDLE handle)
+{
+ p11_dict *objects;
+
+ assert (session != NULL);
+
+ if (p11_dict_remove (session->objects, &handle))
+ return CKR_OK;
+
+ /* Look for in the global objects */
+ objects = p11_token_objects (session->token);
+ if (p11_dict_get (objects, &handle))
+ return CKR_TOKEN_WRITE_PROTECTED;
+
+ return CKR_OBJECT_HANDLE_INVALID;
+}
+
+CK_ATTRIBUTE *
+p11_session_get_object (p11_session *session,
+ CK_OBJECT_HANDLE handle,
+ CK_BBOOL *token)
+{
+ CK_ATTRIBUTE *attrs;
+ p11_dict *objects;
+ Object *object;
+
+ assert (session != NULL);
+
+ object = p11_dict_get (session->objects, &handle);
+ if (object) {
+ if (token)
+ *token = CK_FALSE;
+ return object->attrs;
+ }
+
+ objects = p11_token_objects (session->token);
+ attrs = p11_dict_get (objects, &handle);
+ if (attrs) {
+ if (token)
+ *token = CK_TRUE;
+ return attrs;
+ }
+
+ return NULL;
+}
+
+CK_RV
+p11_session_set_object (p11_session *session,
+ CK_OBJECT_HANDLE handle,
+ CK_ATTRIBUTE *template,
+ CK_ULONG count)
+{
+ CK_BBOOL token;
+ p11_dict *objects;
+ Object *object;
+
+ assert (session != NULL);
+
+ object = p11_dict_get (session->objects, &handle);
+ if (object == NULL) {
+ objects = p11_token_objects (session->token);
+ if (p11_dict_get (objects, &handle))
+ return CKR_TOKEN_WRITE_PROTECTED;
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ if (!p11_attrs_findn_bool (template, count, CKA_TOKEN, &token) && token)
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ object->attrs = p11_attrs_buildn (object->attrs, template, count);
+ return CKR_OK;
+}
+
+void
+p11_session_set_operation (p11_session *session,
+ p11_session_cleanup cleanup,
+ void *operation)
+{
+ assert (session != NULL);
+
+ if (session->cleanup)
+ (session->cleanup) (session->operation);
+ session->cleanup = cleanup;
+ session->operation = operation;
+}
diff --git a/trust/session.h b/trust/session.h
new file mode 100644
index 0000000..97aedb1
--- /dev/null
+++ b/trust/session.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 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 "pkcs11.h"
+#include "token.h"
+
+#ifndef P11_SESSION_H_
+#define P11_SESSION_H_
+
+typedef void (* p11_session_cleanup) (void *data);
+
+typedef struct {
+ CK_SESSION_HANDLE handle;
+ p11_dict *objects;
+ p11_token *token;
+ CK_BBOOL loaded;
+
+ /* Used by various operations */
+ p11_session_cleanup cleanup;
+ void *operation;
+} p11_session;
+
+p11_session * p11_session_new (p11_token *token);
+
+void p11_session_free (void *data);
+
+CK_RV p11_session_add_object (p11_session *session,
+ CK_ATTRIBUTE *attrs,
+ CK_OBJECT_HANDLE *handle);
+
+CK_RV p11_session_del_object (p11_session *session,
+ CK_OBJECT_HANDLE handle);
+
+CK_ATTRIBUTE * p11_session_get_object (p11_session *session,
+ CK_OBJECT_HANDLE handle,
+ CK_BBOOL *token);
+
+CK_RV p11_session_set_object (p11_session *session,
+ CK_OBJECT_HANDLE handle,
+ CK_ATTRIBUTE *template,
+ CK_ULONG count);
+
+void p11_session_set_operation (p11_session *session,
+ p11_session_cleanup cleanup,
+ void *operation);
+
+#endif /* P11_SESSION_H_ */
diff --git a/trust/tests/Makefile.am b/trust/tests/Makefile.am
new file mode 100644
index 0000000..2426f8a
--- /dev/null
+++ b/trust/tests/Makefile.am
@@ -0,0 +1,44 @@
+
+include $(top_srcdir)/build/Makefile.tests
+
+NULL =
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ -I$(srcdir)/.. \
+ -I$(top_srcdir)/common \
+ $(CUTEST_CFLAGS)
+
+noinst_LTLIBRARIES = \
+ libtestdata.la
+
+libtestdata_la_SOURCES = \
+ test-data.c test-data.h
+
+LDADD = \
+ $(top_builddir)/trust/libtrust-testable.la \
+ $(top_builddir)/common/libp11-data.la \
+ $(top_builddir)/common/libp11-library.la \
+ $(top_builddir)/common/libp11-compat.la \
+ $(builddir)/libtestdata.la \
+ $(LIBTASN1_LIBS) \
+ $(CUTEST_LIBS) \
+ $(NULL)
+
+CHECK_PROGS = \
+ test-parser \
+ test-token \
+ test-session \
+ test-module \
+ $(NULL)
+
+noinst_PROGRAMS = \
+ $(CHECK_PROGS)
+
+TESTS = $(CHECK_PROGS:=$(EXEEXT))
+
+EXTRA_DIST = \
+ anchors \
+ certificates \
+ files \
+ $(NULL)
diff --git a/trust/tests/anchors/cacert3.der b/trust/tests/anchors/cacert3.der
new file mode 100644
index 0000000..56f8c88
--- /dev/null
+++ b/trust/tests/anchors/cacert3.der
Binary files differ
diff --git a/trust/tests/anchors/testing-ca.der b/trust/tests/anchors/testing-ca.der
new file mode 100644
index 0000000..d3f70ea
--- /dev/null
+++ b/trust/tests/anchors/testing-ca.der
Binary files differ
diff --git a/trust/tests/certificates/cacert-ca.der b/trust/tests/certificates/cacert-ca.der
new file mode 100644
index 0000000..719b0ff
--- /dev/null
+++ b/trust/tests/certificates/cacert-ca.der
Binary files differ
diff --git a/trust/tests/certificates/self-signed-with-eku.der b/trust/tests/certificates/self-signed-with-eku.der
new file mode 100644
index 0000000..33e0760
--- /dev/null
+++ b/trust/tests/certificates/self-signed-with-eku.der
Binary files differ
diff --git a/trust/tests/certificates/self-signed-with-ku.der b/trust/tests/certificates/self-signed-with-ku.der
new file mode 100644
index 0000000..e6f36e3
--- /dev/null
+++ b/trust/tests/certificates/self-signed-with-ku.der
Binary files differ
diff --git a/trust/tests/files/cacert-ca.der b/trust/tests/files/cacert-ca.der
new file mode 100644
index 0000000..719b0ff
--- /dev/null
+++ b/trust/tests/files/cacert-ca.der
Binary files differ
diff --git a/trust/tests/files/cacert3.der b/trust/tests/files/cacert3.der
new file mode 100644
index 0000000..56f8c88
--- /dev/null
+++ b/trust/tests/files/cacert3.der
Binary files differ
diff --git a/trust/tests/files/self-server.der b/trust/tests/files/self-server.der
new file mode 100644
index 0000000..68fe9af
--- /dev/null
+++ b/trust/tests/files/self-server.der
Binary files differ
diff --git a/trust/tests/files/testing-server.der b/trust/tests/files/testing-server.der
new file mode 100644
index 0000000..cf2de65
--- /dev/null
+++ b/trust/tests/files/testing-server.der
Binary files differ
diff --git a/trust/tests/files/unrecognized-file.txt b/trust/tests/files/unrecognized-file.txt
new file mode 100644
index 0000000..4d5bac3
--- /dev/null
+++ b/trust/tests/files/unrecognized-file.txt
@@ -0,0 +1 @@
+# This file is not recognized by the parser \ No newline at end of file
diff --git a/trust/tests/test-data.c b/trust/tests/test-data.c
new file mode 100644
index 0000000..1decf2e
--- /dev/null
+++ b/trust/tests/test-data.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "attrs.h"
+#include "test-data.h"
+
+void
+test_check_object (CuTest *cu,
+ CK_ATTRIBUTE *attrs,
+ CK_OBJECT_CLASS klass,
+ const char *label)
+{
+ CK_BBOOL val;
+ CK_ULONG ulong;
+ CK_ATTRIBUTE *attr;
+
+ if (!p11_attrs_find_bool (attrs, CKA_TOKEN, &val))
+ CuFail (cu, "missing CKA_TOKEN");
+ CuAssertIntEquals (cu, CK_TRUE, val);
+
+ if (!p11_attrs_find_bool (attrs, CKA_PRIVATE, &val))
+ CuFail (cu, "missing CKA_PRIVATE");
+ CuAssertIntEquals (cu, CK_FALSE, val);
+
+ if (!p11_attrs_find_bool (attrs, CKA_MODIFIABLE, &val))
+ CuFail (cu, "missing CKA_MODIFIABLE");
+ CuAssertIntEquals (cu, CK_FALSE, val);
+
+ if (!p11_attrs_find_ulong (attrs, CKA_CLASS, &ulong))
+ CuFail (cu, "missing CKA_CLASS");
+ CuAssertIntEquals (cu, klass, ulong);
+
+ if (label) {
+ attr = p11_attrs_find_valid (attrs, CKA_LABEL);
+ CuAssertPtrNotNull (cu, attr);
+ CuAssertTrue (cu, p11_attr_match_value (attr, label, -1));
+ }
+}
+
+void
+test_check_cacert3_ca (CuTest *cu,
+ CK_ATTRIBUTE *attrs,
+ const char *label)
+{
+ CK_ATTRIBUTE *attr;
+ CK_ULONG ulong;
+
+ test_check_object (cu, attrs, CKO_CERTIFICATE, label);
+
+ if (!p11_attrs_find_ulong (attrs, CKA_CERTIFICATE_TYPE, &ulong))
+ CuFail (cu, "missing CKA_CERTIFICATE_TYPE");
+ CuAssertIntEquals (cu, CKC_X_509, ulong);
+
+ /* TODO: Implement */
+ if (!p11_attrs_find_ulong (attrs, CKA_CERTIFICATE_CATEGORY, &ulong))
+ CuFail (cu, "missing CKA_CERTIFICATE_CATEGORY");
+ CuAssertIntEquals (cu, 0, ulong);
+
+ attr = p11_attrs_find (attrs, CKA_VALUE);
+ CuAssertPtrNotNull (cu, attr);
+ CuAssertTrue (cu, p11_attr_match_value (attr, test_cacert3_ca_der,
+ sizeof (test_cacert3_ca_der)));
+
+ attr = p11_attrs_find_valid (attrs, CKA_CHECK_VALUE);
+ CuAssertPtrNotNull (cu, attr);
+ CuAssertTrue (cu, p11_attr_match_value (attr, "\xad\x7c\x3f", 3));
+
+ attr = p11_attrs_find (attrs, CKA_START_DATE);
+ CuAssertPtrNotNull (cu, attr);
+ CuAssertTrue (cu, p11_attr_match_value (attr, "20110523", -1));
+
+ attr = p11_attrs_find_valid (attrs, CKA_END_DATE);
+ CuAssertPtrNotNull (cu, attr);
+ CuAssertTrue (cu, p11_attr_match_value (attr, "20210520", -1));
+
+ attr = p11_attrs_find (attrs, CKA_SUBJECT);
+ CuAssertPtrNotNull (cu, attr);
+ CuAssertTrue (cu, p11_attr_match_value (attr, test_cacert3_ca_subject,
+ sizeof (test_cacert3_ca_subject)));
+
+ attr = p11_attrs_find (attrs, CKA_ISSUER);
+ CuAssertPtrNotNull (cu, attr);
+ CuAssertTrue (cu, p11_attr_match_value (attr, test_cacert3_ca_issuer,
+ sizeof (test_cacert3_ca_issuer)));
+
+ attr = p11_attrs_find (attrs, CKA_SERIAL_NUMBER);
+ CuAssertPtrNotNull (cu, attr);
+ CuAssertTrue (cu, p11_attr_match_value (attr, test_cacert3_ca_serial,
+ sizeof (test_cacert3_ca_serial)));
+}
diff --git a/trust/tests/test-data.h b/trust/tests/test-data.h
new file mode 100644
index 0000000..9789493
--- /dev/null
+++ b/trust/tests/test-data.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include <sys/types.h>
+
+#ifndef TEST_DATA_H_
+#define TEST_DATA_H_
+
+void test_check_object (CuTest *cu,
+ CK_ATTRIBUTE *attrs,
+ CK_OBJECT_CLASS klass,
+ const char *label);
+
+void test_check_cacert3_ca (CuTest *cu,
+ CK_ATTRIBUTE *attrs,
+ const char *label);
+
+static const unsigned char test_cacert3_ca_der[] = {
+ 0x30, 0x82, 0x07, 0x59, 0x30, 0x82, 0x05, 0x41, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x0a,
+ 0x41, 0x8a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
+ 0x00, 0x30, 0x79, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x52, 0x6f,
+ 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x61, 0x63, 0x65, 0x72,
+ 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19,
+ 0x43, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20,
+ 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72,
+ 0x74, 0x40, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x31, 0x30, 0x35, 0x32, 0x33, 0x31, 0x37, 0x34, 0x38, 0x30, 0x32, 0x5a, 0x17, 0x0d, 0x32,
+ 0x31, 0x30, 0x35, 0x32, 0x30, 0x31, 0x37, 0x34, 0x38, 0x30, 0x32, 0x5a, 0x30, 0x54, 0x31, 0x14,
+ 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x20,
+ 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x68,
+ 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74,
+ 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x43,
+ 0x41, 0x63, 0x65, 0x72, 0x74, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x52, 0x6f,
+ 0x6f, 0x74, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82,
+ 0x02, 0x01, 0x00, 0xab, 0x49, 0x35, 0x11, 0x48, 0x7c, 0xd2, 0x26, 0x7e, 0x53, 0x94, 0xcf, 0x43,
+ 0xa9, 0xdd, 0x28, 0xd7, 0x42, 0x2a, 0x8b, 0xf3, 0x87, 0x78, 0x19, 0x58, 0x7c, 0x0f, 0x9e, 0xda,
+ 0x89, 0x7d, 0xe1, 0xfb, 0xeb, 0x72, 0x90, 0x0d, 0x74, 0xa1, 0x96, 0x64, 0xab, 0x9f, 0xa0, 0x24,
+ 0x99, 0x73, 0xda, 0xe2, 0x55, 0x76, 0xc7, 0x17, 0x7b, 0xf5, 0x04, 0xac, 0x46, 0xb8, 0xc3, 0xbe,
+ 0x7f, 0x64, 0x8d, 0x10, 0x6c, 0x24, 0xf3, 0x61, 0x9c, 0xc0, 0xf2, 0x90, 0xfa, 0x51, 0xe6, 0xf5,
+ 0x69, 0x01, 0x63, 0xc3, 0x0f, 0x56, 0xe2, 0x4a, 0x42, 0xcf, 0xe2, 0x44, 0x8c, 0x25, 0x28, 0xa8,
+ 0xc5, 0x79, 0x09, 0x7d, 0x46, 0xb9, 0x8a, 0xf3, 0xe9, 0xf3, 0x34, 0x29, 0x08, 0x45, 0xe4, 0x1c,
+ 0x9f, 0xcb, 0x94, 0x04, 0x1c, 0x81, 0xa8, 0x14, 0xb3, 0x98, 0x65, 0xc4, 0x43, 0xec, 0x4e, 0x82,
+ 0x8d, 0x09, 0xd1, 0xbd, 0xaa, 0x5b, 0x8d, 0x92, 0xd0, 0xec, 0xde, 0x90, 0xc5, 0x7f, 0x0a, 0xc2,
+ 0xe3, 0xeb, 0xe6, 0x31, 0x5a, 0x5e, 0x74, 0x3e, 0x97, 0x33, 0x59, 0xe8, 0xc3, 0x03, 0x3d, 0x60,
+ 0x33, 0xbf, 0xf7, 0xd1, 0x6f, 0x47, 0xc4, 0xcd, 0xee, 0x62, 0x83, 0x52, 0x6e, 0x2e, 0x08, 0x9a,
+ 0xa4, 0xd9, 0x15, 0x18, 0x91, 0xa6, 0x85, 0x92, 0x47, 0xb0, 0xae, 0x48, 0xeb, 0x6d, 0xb7, 0x21,
+ 0xec, 0x85, 0x1a, 0x68, 0x72, 0x35, 0xab, 0xff, 0xf0, 0x10, 0x5d, 0xc0, 0xf4, 0x94, 0xa7, 0x6a,
+ 0xd5, 0x3b, 0x92, 0x7e, 0x4c, 0x90, 0x05, 0x7e, 0x93, 0xc1, 0x2c, 0x8b, 0xa4, 0x8e, 0x62, 0x74,
+ 0x15, 0x71, 0x6e, 0x0b, 0x71, 0x03, 0xea, 0xaf, 0x15, 0x38, 0x9a, 0xd4, 0xd2, 0x05, 0x72, 0x6f,
+ 0x8c, 0xf9, 0x2b, 0xeb, 0x5a, 0x72, 0x25, 0xf9, 0x39, 0x46, 0xe3, 0x72, 0x1b, 0x3e, 0x04, 0xc3,
+ 0x64, 0x27, 0x22, 0x10, 0x2a, 0x8a, 0x4f, 0x58, 0xa7, 0x03, 0xad, 0xbe, 0xb4, 0x2e, 0x13, 0xed,
+ 0x5d, 0xaa, 0x48, 0xd7, 0xd5, 0x7d, 0xd4, 0x2a, 0x7b, 0x5c, 0xfa, 0x46, 0x04, 0x50, 0xe4, 0xcc,
+ 0x0e, 0x42, 0x5b, 0x8c, 0xed, 0xdb, 0xf2, 0xcf, 0xfc, 0x96, 0x93, 0xe0, 0xdb, 0x11, 0x36, 0x54,
+ 0x62, 0x34, 0x38, 0x8f, 0x0c, 0x60, 0x9b, 0x3b, 0x97, 0x56, 0x38, 0xad, 0xf3, 0xd2, 0x5b, 0x8b,
+ 0xa0, 0x5b, 0xea, 0x4e, 0x96, 0xb8, 0x7c, 0xd7, 0xd5, 0xa0, 0x86, 0x70, 0x40, 0xd3, 0x91, 0x29,
+ 0xb7, 0xa2, 0x3c, 0xad, 0xf5, 0x8c, 0xbb, 0xcf, 0x1a, 0x92, 0x8a, 0xe4, 0x34, 0x7b, 0xc0, 0xd8,
+ 0x6c, 0x5f, 0xe9, 0x0a, 0xc2, 0xc3, 0xa7, 0x20, 0x9a, 0x5a, 0xdf, 0x2c, 0x5d, 0x52, 0x5c, 0xba,
+ 0x47, 0xd5, 0x9b, 0xef, 0x24, 0x28, 0x70, 0x38, 0x20, 0x2f, 0xd5, 0x7f, 0x29, 0xc0, 0xb2, 0x41,
+ 0x03, 0x68, 0x92, 0xcc, 0xe0, 0x9c, 0xcc, 0x97, 0x4b, 0x45, 0xef, 0x3a, 0x10, 0x0a, 0xab, 0x70,
+ 0x3a, 0x98, 0x95, 0x70, 0xad, 0x35, 0xb1, 0xea, 0x85, 0x2b, 0xa4, 0x1c, 0x80, 0x21, 0x31, 0xa9,
+ 0xae, 0x60, 0x7a, 0x80, 0x26, 0x48, 0x00, 0xb8, 0x01, 0xc0, 0x93, 0x63, 0x55, 0x22, 0x91, 0x3c,
+ 0x56, 0xe7, 0xaf, 0xdb, 0x3a, 0x25, 0xf3, 0x8f, 0x31, 0x54, 0xea, 0x26, 0x8b, 0x81, 0x59, 0xf9,
+ 0xa1, 0xd1, 0x53, 0x11, 0xc5, 0x7b, 0x9d, 0x03, 0xf6, 0x74, 0x11, 0xe0, 0x6d, 0xb1, 0x2c, 0x3f,
+ 0x2c, 0x86, 0x91, 0x99, 0x71, 0x9a, 0xa6, 0x77, 0x8b, 0x34, 0x60, 0xd1, 0x14, 0xb4, 0x2c, 0xac,
+ 0x9d, 0xaf, 0x8c, 0x10, 0xd3, 0x9f, 0xc4, 0x6a, 0xf8, 0x6f, 0x13, 0xfc, 0x73, 0x59, 0xf7, 0x66,
+ 0x42, 0x74, 0x1e, 0x8a, 0xe3, 0xf8, 0xdc, 0xd2, 0x6f, 0x98, 0x9c, 0xcb, 0x47, 0x98, 0x95, 0x40,
+ 0x05, 0xfb, 0xe9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x0d, 0x30, 0x82, 0x02, 0x09,
+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x75, 0xa8, 0x71, 0x60, 0x4c,
+ 0x88, 0x13, 0xf0, 0x78, 0xd9, 0x89, 0x77, 0xb5, 0x6d, 0xc5, 0x89, 0xdf, 0xbc, 0xb1, 0x7a, 0x30,
+ 0x81, 0xa3, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0x9b, 0x30, 0x81, 0x98, 0x80, 0x14, 0x16,
+ 0xb5, 0x32, 0x1b, 0xd4, 0xc7, 0xf3, 0xe0, 0xe6, 0x8e, 0xf3, 0xbd, 0xd2, 0xb0, 0x3a, 0xee, 0xb2,
+ 0x39, 0x18, 0xd1, 0xa1, 0x7d, 0xa4, 0x7b, 0x30, 0x79, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x07, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06,
+ 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
+ 0x2e, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x69,
+ 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12,
+ 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x40, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f,
+ 0x72, 0x67, 0x82, 0x01, 0x00, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
+ 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x5d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x01, 0x01, 0x04, 0x51, 0x30, 0x4f, 0x30, 0x23, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x30, 0x01, 0x86, 0x17, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e,
+ 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x30, 0x28, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x1c, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x63,
+ 0x61, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x4a, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x43, 0x30, 0x41,
+ 0x30, 0x3f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x90, 0x4a, 0x30, 0x33, 0x30, 0x31,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x25, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x70, 0x68, 0x70, 0x3f, 0x69, 0x64, 0x3d, 0x31,
+ 0x30, 0x30, 0x34, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x27,
+ 0x16, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41, 0x63,
+ 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x70, 0x68,
+ 0x70, 0x3f, 0x69, 0x64, 0x3d, 0x31, 0x30, 0x30, 0x50, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86,
+ 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x43, 0x16, 0x41, 0x54, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x79,
+ 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x46, 0x52, 0x45, 0x45, 0x2c, 0x20, 0x67, 0x6f,
+ 0x20, 0x74, 0x6f, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43,
+ 0x41, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x29, 0x28, 0x85,
+ 0xae, 0x44, 0xa9, 0xb9, 0xaf, 0xa4, 0x79, 0x13, 0xf0, 0xa8, 0xa3, 0x2b, 0x97, 0x60, 0xf3, 0x5c,
+ 0xee, 0xe3, 0x2f, 0xc1, 0xf6, 0xe2, 0x66, 0xa0, 0x11, 0xae, 0x36, 0x37, 0x3a, 0x76, 0x15, 0x04,
+ 0x53, 0xea, 0x42, 0xf5, 0xf9, 0xea, 0xc0, 0x15, 0xd8, 0xa6, 0x82, 0xd9, 0xe4, 0x61, 0xae, 0x72,
+ 0x0b, 0x29, 0x5c, 0x90, 0x43, 0xe8, 0x41, 0xb2, 0xe1, 0x77, 0xdb, 0x02, 0x13, 0x44, 0x78, 0x47,
+ 0x55, 0xaf, 0x58, 0xfc, 0xcc, 0x98, 0xf6, 0x45, 0xb9, 0xd1, 0x20, 0xf8, 0xd8, 0x21, 0x07, 0xfe,
+ 0x6d, 0xaa, 0x73, 0xd4, 0xb3, 0xc6, 0x07, 0xe9, 0x09, 0x85, 0xcc, 0x3b, 0xf2, 0xb6, 0xbe, 0x2c,
+ 0x1c, 0x25, 0xd5, 0x71, 0x8c, 0x39, 0xb5, 0x2e, 0xea, 0xbe, 0x18, 0x81, 0xba, 0xb0, 0x93, 0xb8,
+ 0x0f, 0xe3, 0xe6, 0xd7, 0x26, 0x8c, 0x31, 0x5a, 0x72, 0x03, 0x84, 0x52, 0xe6, 0xa6, 0xf5, 0x33,
+ 0x22, 0x45, 0x0a, 0xc8, 0x0b, 0x0d, 0x8a, 0xb8, 0x36, 0x6f, 0x90, 0x09, 0xa1, 0xab, 0xbd, 0xd7,
+ 0xd5, 0x4e, 0x2e, 0x71, 0xa2, 0xd4, 0xae, 0xfa, 0xa7, 0x54, 0x2b, 0xeb, 0x35, 0x8d, 0x5a, 0xb7,
+ 0x54, 0x88, 0x2f, 0xee, 0x74, 0x9f, 0xed, 0x48, 0x16, 0xca, 0x0d, 0x48, 0xd0, 0x94, 0xd3, 0xac,
+ 0xa4, 0xa2, 0xf6, 0x24, 0xdf, 0x92, 0xe3, 0xbd, 0xeb, 0x43, 0x40, 0x91, 0x6e, 0x1c, 0x18, 0x8e,
+ 0x56, 0xb4, 0x82, 0x12, 0xf3, 0xa9, 0x93, 0x9f, 0xd4, 0xbc, 0x9c, 0xad, 0x9c, 0x75, 0xee, 0x5a,
+ 0x97, 0x1b, 0x95, 0xe7, 0x74, 0x2d, 0x1c, 0x0f, 0xb0, 0x2c, 0x97, 0x9f, 0xfb, 0xa9, 0x33, 0x39,
+ 0x7a, 0xe7, 0x03, 0x3a, 0x92, 0x8e, 0x22, 0xf6, 0x8c, 0x0d, 0xe4, 0xd9, 0x7e, 0x0d, 0x76, 0x18,
+ 0xf7, 0x01, 0xf9, 0xef, 0x96, 0x96, 0xa2, 0x55, 0x73, 0xc0, 0x3c, 0x71, 0xb4, 0x1d, 0x1a, 0x56,
+ 0x43, 0xb7, 0xc3, 0x0a, 0x8d, 0x72, 0xfc, 0xe2, 0x10, 0x09, 0x0b, 0x41, 0xce, 0x8c, 0x94, 0xa0,
+ 0xf9, 0x03, 0xfd, 0x71, 0x73, 0x4b, 0x8a, 0x57, 0x33, 0xe5, 0x8e, 0x74, 0x7e, 0x15, 0x01, 0x00,
+ 0xe6, 0xcc, 0x4a, 0x1c, 0xe7, 0x7f, 0x95, 0x19, 0x2d, 0xc5, 0xa5, 0x0c, 0x8b, 0xbb, 0xb5, 0xed,
+ 0x85, 0xb3, 0x5c, 0xd3, 0xdf, 0xb8, 0xb9, 0xf2, 0xca, 0xc7, 0x0d, 0x01, 0x14, 0xac, 0x70, 0x58,
+ 0xc5, 0x8c, 0x8d, 0x33, 0xd4, 0x9d, 0x66, 0xa3, 0x1a, 0x50, 0x95, 0x23, 0xfc, 0x48, 0xe0, 0x06,
+ 0x43, 0x12, 0xd9, 0xcd, 0xa7, 0x86, 0x39, 0x2f, 0x36, 0x72, 0xa3, 0x80, 0x10, 0xe4, 0xe1, 0xf3,
+ 0xd1, 0xcb, 0x5b, 0x1a, 0xc0, 0xe4, 0x80, 0x9a, 0x7c, 0x13, 0x73, 0x06, 0x4f, 0xdb, 0xa3, 0x6b,
+ 0x24, 0x0a, 0xba, 0xb3, 0x1c, 0xbc, 0x4a, 0x78, 0xbb, 0xe5, 0xe3, 0x75, 0x38, 0xa5, 0x48, 0xa7,
+ 0xa2, 0x1e, 0xaf, 0x76, 0xd4, 0x5e, 0xf7, 0x38, 0x86, 0x56, 0x5a, 0x89, 0xce, 0xd6, 0xc3, 0xa7,
+ 0x79, 0xb2, 0x52, 0xa0, 0xc6, 0xf1, 0x85, 0xb4, 0x25, 0x8c, 0xf2, 0x3f, 0x96, 0xb3, 0x10, 0xd9,
+ 0x8d, 0x6c, 0x57, 0x3b, 0x9f, 0x6f, 0x86, 0x3a, 0x18, 0x82, 0x22, 0x36, 0xc8, 0xb0, 0x91, 0x38,
+ 0xdb, 0x2a, 0xa1, 0x93, 0xaa, 0x84, 0x3f, 0xf5, 0x27, 0x65, 0xae, 0x73, 0xd5, 0xc8, 0xd5, 0xd3,
+ 0x77, 0xea, 0x4b, 0x9d, 0xc7, 0x41, 0xbb, 0xc7, 0xc0, 0xe3, 0xa0, 0x3f, 0xe4, 0x7d, 0xa4, 0x8d,
+ 0x73, 0xe6, 0x12, 0x4b, 0xdf, 0xa1, 0x73, 0x73, 0x73, 0x3a, 0x80, 0xe8, 0xd5, 0xcb, 0x8e, 0x2f,
+ 0xcb, 0xea, 0x13, 0xa7, 0xd6, 0x41, 0x8b, 0xac, 0xfa, 0x3c, 0x89, 0xd7, 0x24, 0xf5, 0x4e, 0xb4,
+ 0xe0, 0x61, 0x92, 0xb7, 0xf3, 0x37, 0x98, 0xc4, 0xbe, 0x96, 0xa3, 0xb7, 0x8a,
+};
+
+static const char test_cacert3_ca_subject[] = {
+ 0x30, 0x54, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x43, 0x41, 0x63,
+ 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x13, 0x15, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41,
+ 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x13, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20,
+ 0x33, 0x20, 0x52, 0x6f, 0x6f, 0x74,
+};
+
+static const char test_cacert3_ca_issuer[] = {
+ 0x30, 0x79, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x52, 0x6f, 0x6f,
+ 0x74, 0x20, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x68,
+ 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74,
+ 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43,
+ 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x41,
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
+ 0x40, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67,
+};
+
+static const char test_cacert3_ca_serial[] = {
+ 0x02, 0x03, 0x0a, 0x41, 0x8a,
+};
+
+static const char test_ku_ds_and_np[] = {
+ 0x03, 0x03, 0x07, 0xc0, 0x00,
+};
+
+static const char test_ku_none[] = {
+ 0x03, 0x03, 0x07, 0x00, 0x00,
+};
+
+static const char test_ku_cert_crl_sign[] = {
+ 0x03, 0x03, 0x07, 0x06, 0x00,
+};
+
+static const 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 const char test_eku_none[] = {
+ 0x30, 0x00,
+};
+
+static const char test_eku_client_email_and_timestamp[] = {
+ 0x30, 0x1e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x03, 0x04, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08,
+};
+
+#endif /* TEST_DATA_H_ */
diff --git a/trust/tests/test-module.c b/trust/tests/test-module.c
new file mode 100644
index 0000000..8bd8e10
--- /dev/null
+++ b/trust/tests/test-module.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "attrs.h"
+#include "checksum.h"
+#include "debug.h"
+#include "library.h"
+#include "pkcs11x.h"
+#include "test-data.h"
+#include "token.h"
+
+struct {
+ CK_FUNCTION_LIST *module;
+ CK_SLOT_ID slot;
+ CK_SESSION_HANDLE session;
+} test;
+
+static void
+setup (CuTest *cu)
+{
+ CK_C_INITIALIZE_ARGS args;
+ const char *anchors;
+ const char *certs;
+ char *arguments;
+ CK_ULONG count;
+ CK_RV rv;
+
+ memset (&test, 0, sizeof (test));
+
+ /* This is the entry point of the trust module, linked to this test */
+ rv = C_GetFunctionList (&test.module);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ memset (&args, 0, sizeof (args));
+ anchors = SRCDIR "/anchors:" SRCDIR "/files/cacert-ca.der";
+ certs = SRCDIR "/certificates";
+ if (asprintf (&arguments, "anchors='%s' certificates='%s'", anchors, certs) < 0)
+ CuAssertTrue (cu, false && "not reached");
+ args.pReserved = arguments;
+ args.flags = CKF_OS_LOCKING_OK;
+
+ rv = test.module->C_Initialize (&args);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ free (arguments);
+
+ count = 1;
+ rv = test.module->C_GetSlotList (CK_TRUE, &test.slot, &count);
+ CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertTrue (cu, count == 1);
+
+ rv = test.module->C_OpenSession (test.slot, CKF_SERIAL_SESSION, NULL, NULL, &test.session);
+ CuAssertTrue (cu, rv == CKR_OK);
+}
+
+static void
+teardown (CuTest *cu)
+{
+ CK_RV rv;
+
+ rv = test.module->C_CloseSession (test.session);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ rv = test.module->C_Finalize (NULL);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ memset (&test, 0, sizeof (test));
+}
+
+static CK_ULONG
+find_objects (CuTest *cu,
+ CK_ATTRIBUTE *match,
+ CK_OBJECT_HANDLE *objects,
+ CK_ULONG num_objects)
+{
+ CK_RV rv;
+ CK_ULONG count;
+
+ count = p11_attrs_count (match);
+
+ rv = test.module->C_FindObjectsInit (test.session, match, count);
+ CuAssertTrue (cu, rv == CKR_OK);
+ rv = test.module->C_FindObjects (test.session, objects, num_objects, &num_objects);
+ CuAssertTrue (cu, rv == CKR_OK);
+ rv = test.module->C_FindObjectsFinal (test.session);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ return num_objects;
+}
+
+static void
+check_trust_object_equiv (CuTest *cu,
+ CK_OBJECT_HANDLE trust,
+ CK_ATTRIBUTE *cert)
+{
+ unsigned char subject[1024];
+ unsigned char issuer[1024];
+ unsigned char serial[128];
+ CK_BBOOL modifiable;
+ CK_BBOOL private;
+ CK_BBOOL token;
+ CK_RV rv;
+
+ /* The following attributes should be equivalent to the certificate */
+ CK_ATTRIBUTE equiv[] = {
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_PRIVATE, &private, sizeof (private) },
+ { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
+ { CKA_ISSUER, issuer, sizeof (issuer) },
+ { CKA_SUBJECT, subject, sizeof (subject) },
+ { CKA_SERIAL_NUMBER, serial, sizeof (serial) },
+ { CKA_INVALID, },
+ };
+
+ rv = test.module->C_GetAttributeValue (test.session, trust, equiv, 6);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ CuAssertTrue (cu, p11_attrs_match (cert, equiv));
+}
+
+static void
+check_trust_object_hashes (CuTest *cu,
+ CK_OBJECT_HANDLE trust,
+ CK_ATTRIBUTE *cert)
+{
+ unsigned char sha1[P11_CHECKSUM_SHA1_LENGTH];
+ unsigned char md5[P11_CHECKSUM_MD5_LENGTH];
+ unsigned char check[128];
+ CK_ATTRIBUTE *value;
+ CK_RV rv;
+
+ CK_ATTRIBUTE hashes[] = {
+ { CKA_CERT_SHA1_HASH, sha1, sizeof (sha1) },
+ { CKA_CERT_MD5_HASH, md5, sizeof (md5) },
+ { CKA_INVALID, },
+ };
+
+ rv = test.module->C_GetAttributeValue (test.session, trust, hashes, 2);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ value = p11_attrs_find (cert, CKA_VALUE);
+ CuAssertPtrNotNull (cu, value);
+
+ p11_checksum_md5 (check, value->pValue, value->ulValueLen, NULL);
+ CuAssertTrue (cu, memcmp (md5, check, sizeof (md5)) == 0);
+
+ p11_checksum_sha1 (check, value->pValue, value->ulValueLen, NULL);
+ CuAssertTrue (cu, memcmp (sha1, check, sizeof (sha1)) == 0);
+}
+
+static void
+check_has_trust_object (CuTest *cu,
+ CK_ATTRIBUTE *cert)
+{
+ CK_OBJECT_CLASS trust_object = CKO_NETSCAPE_TRUST;
+ CK_ATTRIBUTE klass = { CKA_CLASS, &trust_object, sizeof (trust_object) };
+ CK_OBJECT_HANDLE objects[2];
+ CK_ATTRIBUTE *match;
+ CK_ATTRIBUTE *attr;
+ CK_ULONG count;
+
+ attr = p11_attrs_find (cert, CKA_ID);
+ CuAssertPtrNotNull (cu, attr);
+
+ match = p11_attrs_build (NULL, &klass, attr, NULL);
+ count = find_objects (cu, match, objects, 2);
+ CuAssertIntEquals (cu, 1, count);
+
+ check_trust_object_equiv (cu, objects[0], cert);
+ check_trust_object_hashes (cu, objects[0], cert);
+}
+
+static void
+check_certificate (CuTest *cu,
+ CK_OBJECT_HANDLE handle)
+{
+ unsigned char label[4096]= { 0, };
+ CK_OBJECT_CLASS klass;
+ unsigned char value[4096];
+ unsigned char subject[1024];
+ unsigned char issuer[1024];
+ unsigned char serial[128];
+ unsigned char id[128];
+ CK_CERTIFICATE_TYPE type;
+ CK_BBOOL val;
+ CK_BYTE check[3];
+ CK_DATE start;
+ CK_DATE end;
+ CK_ULONG category;
+ CK_BBOOL modifiable;
+ CK_BBOOL private;
+ CK_BBOOL token;
+ CK_RV rv;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_PRIVATE, &private, sizeof (private) },
+ { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
+ { CKA_VALUE, value, sizeof (value) },
+ { CKA_ISSUER, issuer, sizeof (issuer) },
+ { CKA_SUBJECT, subject, sizeof (subject) },
+ { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+ { CKA_CERTIFICATE_CATEGORY, &category, sizeof (category) },
+ { CKA_START_DATE, &start, sizeof (start) },
+ { CKA_END_DATE, &end, sizeof (end) },
+ { CKA_SERIAL_NUMBER, serial, sizeof (serial) },
+ { CKA_CHECK_VALUE, check, sizeof (check) },
+ { CKA_ID, id, sizeof (id) },
+ { CKA_LABEL, label, sizeof (label) },
+ { CKA_INVALID, },
+ };
+
+ /* Note that we don't pass the CKA_INVALID attribute in */
+ rv = test.module->C_GetAttributeValue (test.session, handle, attrs, 15);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ /* If this is the cacert3 certificate, check its values */
+ if (memcmp (value, test_cacert3_ca_der, sizeof (test_cacert3_ca_der)) == 0) {
+ CK_BBOOL trusted;
+
+ CK_ATTRIBUTE anchor[] = {
+ { CKA_TRUSTED, &trusted, sizeof (trusted) },
+ { CKA_INVALID, },
+ };
+
+ test_check_cacert3_ca (cu, attrs, NULL);
+
+ /* Get anchor specific attributes */
+ rv = test.module->C_GetAttributeValue (test.session, handle, anchor, 1);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ /* It lives in the trusted directory */
+ if (!p11_attrs_find_bool (anchor, CKA_TRUSTED, &val))
+ CuFail (cu, "missing CKA_TRUSTED");
+ CuAssertIntEquals (cu, CK_TRUE, val);
+
+ /* Other certificates, we can't check the values */
+ } else {
+ test_check_object (cu, attrs, CKO_CERTIFICATE, NULL);
+ }
+
+ check_has_trust_object (cu, attrs);
+}
+
+static void
+test_find_certificates (CuTest *cu)
+{
+ CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
+
+ CK_ATTRIBUTE match[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_INVALID, }
+ };
+
+ CK_OBJECT_HANDLE objects[16];
+ CK_ULONG count;
+ CK_ULONG i;
+
+ setup (cu);
+
+ count = find_objects (cu, match, objects, 16);
+ CuAssertIntEquals (cu, 6, count);
+
+ for (i = 0; i < count; i++)
+ check_certificate (cu, objects[i]);
+
+ teardown (cu);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ setenv ("P11_KIT_STRICT", "1", 1);
+ p11_debug_init ();
+ /* p11_message_quiet (); */
+
+ SUITE_ADD_TEST (suite, test_find_certificates);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}
diff --git a/trust/tests/test-parser.c b/trust/tests/test-parser.c
new file mode 100644
index 0000000..c224669
--- /dev/null
+++ b/trust/tests/test-parser.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "array.h"
+#include "attrs.h"
+#include "debug.h"
+#include "library.h"
+#include "parser.h"
+#include "test-data.h"
+
+struct {
+ p11_parser *parser;
+ p11_array *objects;
+} test;
+
+static void
+setup (CuTest *cu)
+{
+ test.parser = p11_parser_new ();
+ CuAssertPtrNotNull (cu, test.parser);
+
+ test.objects = p11_array_new (p11_attrs_free);
+ CuAssertPtrNotNull (cu, test.objects);
+}
+
+static void
+teardown (CuTest *cu)
+{
+ p11_parser_free (test.parser);
+ p11_array_free (test.objects);
+ memset (&test, 0, sizeof (test));
+}
+
+static void
+on_parse_object (CK_ATTRIBUTE *attrs,
+ void *data)
+{
+ CuTest *cu = data;
+
+ CuAssertPtrNotNull (cu, attrs);
+ CuAssertTrue (cu, p11_attrs_count (attrs) > 0);
+
+ p11_array_push (test.objects, attrs);
+}
+
+static void
+test_parse_der_certificate (CuTest *cu)
+{
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *attr;
+ int ret;
+
+ setup (cu);
+
+ ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der",
+ 0, on_parse_object, cu);
+ CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
+
+ /* Should have gotten certificate and a trust object */
+ CuAssertIntEquals (cu, 2, test.objects->num);
+
+ attrs = test.objects->elem[0];
+ test_check_cacert3_ca (cu, attrs, NULL);
+
+ attr = p11_attrs_find (attrs, CKA_TRUSTED);
+ CuAssertPtrEquals (cu, NULL, attr);
+
+ teardown (cu);
+}
+
+static void
+test_parse_anchor (CuTest *cu)
+{
+ CK_ATTRIBUTE *attrs;
+ CK_BBOOL val;
+ int ret;
+
+ setup (cu);
+
+ ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der",
+ P11_PARSE_FLAG_ANCHOR, on_parse_object, cu);
+ CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
+
+ /* Should have gotten a certificate and a trust object */
+ CuAssertIntEquals (cu, 2, test.objects->num);
+
+ attrs = test.objects->elem[0];
+ test_check_cacert3_ca (cu, attrs, NULL);
+
+ if (!p11_attrs_find_bool (attrs, CKA_TRUSTED, &val))
+ CuFail (cu, "missing CKA_TRUSTED");
+ CuAssertIntEquals (cu, CK_TRUE, val);
+
+ teardown (cu);
+}
+
+/* TODO: A certificate that uses generalTime needs testing */
+
+static void
+test_parse_no_sink (CuTest *cu)
+{
+ int ret;
+
+ setup (cu);
+
+ ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der",
+ 0, NULL, NULL);
+ CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
+
+ teardown (cu);
+}
+
+static void
+test_parse_invalid_file (CuTest *cu)
+{
+ int ret;
+
+ setup (cu);
+
+ ret = p11_parse_file (test.parser, "/nonexistant", 0, on_parse_object, cu);
+ CuAssertIntEquals (cu, P11_PARSE_FAILURE, ret);
+
+ teardown (cu);
+}
+
+static void
+test_parse_unrecognized (CuTest *cu)
+{
+ int ret;
+
+ setup (cu);
+
+ ret = p11_parse_file (test.parser, SRCDIR "/files/unrecognized-file.txt",
+ 0, on_parse_object, cu);
+ CuAssertIntEquals (cu, P11_PARSE_UNRECOGNIZED, ret);
+
+ teardown (cu);
+}
+
+struct {
+ const char *eku;
+ size_t length;
+ const char *expected[16];
+} extended_key_usage_fixtures[] = {
+ { test_eku_server_and_client, sizeof (test_eku_server_and_client),
+ { P11_EKU_CLIENT_AUTH, P11_EKU_SERVER_AUTH, NULL }, },
+ { test_eku_none, sizeof (test_eku_none),
+ { NULL, }, },
+ { test_eku_client_email_and_timestamp, sizeof (test_eku_client_email_and_timestamp),
+ { P11_EKU_CLIENT_AUTH, P11_EKU_EMAIL, P11_EKU_TIME_STAMPING }, },
+ { NULL },
+};
+
+static void
+test_parse_extended_key_usage (CuTest *cu)
+{
+ p11_dict *ekus;
+ int i, j;
+ int ret;
+
+ setup (cu);
+
+ for (i = 0; extended_key_usage_fixtures[i].eku != NULL; i++) {
+ ekus = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL);
+
+ ret = p11_parse_extended_key_usage (test.parser,
+ (const unsigned char *)extended_key_usage_fixtures[i].eku,
+ extended_key_usage_fixtures[i].length, ekus);
+ CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
+
+ for (j = 0; extended_key_usage_fixtures[i].expected[j] != NULL; j++)
+ CuAssertTrue (cu, p11_dict_get (ekus, extended_key_usage_fixtures[i].expected[j]) != NULL);
+ CuAssertIntEquals (cu, j, p11_dict_size (ekus));
+
+ p11_dict_free (ekus);
+ }
+
+ teardown (cu);
+}
+
+static void
+test_bad_extended_key_usage (CuTest *cu)
+{
+ p11_dict *ekus;
+ int ret;
+
+ setup (cu);
+
+ ekus = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL);
+
+ ret = p11_parse_extended_key_usage (test.parser, (const unsigned char *)"blah", 4, ekus);
+ CuAssertIntEquals (cu, P11_PARSE_UNRECOGNIZED, ret);
+
+ p11_dict_free (ekus);
+
+ teardown (cu);
+}
+
+struct {
+ const char *ku;
+ size_t length;
+ unsigned int expected;
+} key_usage_fixtures[] = {
+ { test_ku_ds_and_np, sizeof (test_ku_ds_and_np), P11_KU_DIGITAL_SIGNATURE | P11_KU_NON_REPUDIATION },
+ { test_ku_none, sizeof (test_ku_none), 0 },
+ { test_ku_cert_crl_sign, sizeof (test_ku_cert_crl_sign), P11_KU_KEY_CERT_SIGN | P11_KU_CRL_SIGN },
+ { NULL },
+};
+
+static void
+test_parse_key_usage (CuTest *cu)
+{
+ unsigned int ku;
+ int i;
+ int ret;
+
+ setup (cu);
+
+ for (i = 0; key_usage_fixtures[i].ku != NULL; i++) {
+ ku = 0;
+
+ ret = p11_parse_key_usage (test.parser,
+ (const unsigned char *)key_usage_fixtures[i].ku,
+ key_usage_fixtures[i].length, &ku);
+ CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
+
+ CuAssertIntEquals (cu, key_usage_fixtures[i].expected, ku);
+ }
+
+ teardown (cu);
+}
+
+static void
+test_bad_key_usage (CuTest *cu)
+{
+ unsigned int ku;
+ int ret;
+
+ setup (cu);
+
+ ret = p11_parse_key_usage (test.parser, (const unsigned char *)"blah", 4, &ku);
+ CuAssertIntEquals (cu, P11_PARSE_UNRECOGNIZED, ret);
+
+ teardown (cu);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ setenv ("P11_KIT_STRICT", "1", 1);
+ p11_debug_init ();
+ p11_message_quiet ();
+
+ SUITE_ADD_TEST (suite, test_parse_der_certificate);
+ SUITE_ADD_TEST (suite, test_parse_anchor);
+ SUITE_ADD_TEST (suite, test_parse_no_sink);
+ SUITE_ADD_TEST (suite, test_parse_invalid_file);
+ SUITE_ADD_TEST (suite, test_parse_unrecognized);
+ SUITE_ADD_TEST (suite, test_bad_extended_key_usage);
+ SUITE_ADD_TEST (suite, test_parse_extended_key_usage);
+ SUITE_ADD_TEST (suite, test_bad_key_usage);
+ SUITE_ADD_TEST (suite, test_parse_key_usage);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}
diff --git a/trust/tests/test-session.c b/trust/tests/test-session.c
new file mode 100644
index 0000000..48c9146
--- /dev/null
+++ b/trust/tests/test-session.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "attrs.h"
+#include "debug.h"
+#include "library.h"
+#include "session.h"
+#include "token.h"
+
+struct {
+ p11_token *token;
+ p11_session *session;
+} test;
+
+static void
+setup (CuTest *cu)
+{
+ test.token = p11_token_new ("", "");
+ CuAssertPtrNotNull (cu, test.token);
+
+ test.session = p11_session_new (test.token);
+ CuAssertPtrNotNull (cu, test.session);
+}
+
+static void
+teardown (CuTest *cu)
+{
+ p11_session_free (test.session);
+ p11_token_free (test.token);
+ memset (&test, 0, sizeof (test));
+}
+
+static void
+test_session_add_get (CuTest *cu)
+{
+ CK_ATTRIBUTE original[] = {
+ { CKA_LABEL, "yay", 3 },
+ { CKA_VALUE, "eight", 5 },
+ { CKA_INVALID }
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *check;
+ CK_OBJECT_HANDLE handle;
+ CK_BBOOL token;
+
+ setup (cu);
+
+ attrs = p11_attrs_dup (original);
+ p11_session_add_object (test.session, attrs, &handle);
+
+ check = p11_session_get_object (test.session, handle, &token);
+
+ CuAssertPtrEquals (cu, attrs, check);
+ CuAssertTrue (cu, token == CK_FALSE);
+
+ check = p11_session_get_object (test.session, 1UL, &token);
+ CuAssertPtrEquals (cu, NULL, check);
+
+ teardown (cu);
+}
+
+static void
+test_session_del (CuTest *cu)
+{
+ CK_ATTRIBUTE original[] = {
+ { CKA_LABEL, "yay", 3 },
+ { CKA_VALUE, "eight", 5 },
+ { CKA_INVALID }
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *check;
+ CK_OBJECT_HANDLE handle;
+ CK_BBOOL token;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = p11_attrs_dup (original);
+ p11_session_add_object (test.session, attrs, &handle);
+
+ check = p11_session_get_object (test.session, handle, &token);
+ CuAssertPtrEquals (cu, attrs, check);
+ CuAssertTrue (cu, token == CK_FALSE);
+
+ rv = p11_session_del_object (test.session, 1UL);
+ CuAssertTrue (cu, rv == CKR_OBJECT_HANDLE_INVALID);
+
+ rv = p11_session_del_object (test.session, handle);
+ CuAssertTrue (cu, rv == CKR_OK);
+
+ check = p11_session_get_object (test.session, handle, &token);
+ CuAssertPtrEquals (cu, NULL, check);
+
+ teardown (cu);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ setenv ("P11_KIT_STRICT", "1", 1);
+ p11_debug_init ();
+ p11_message_quiet ();
+
+ SUITE_ADD_TEST (suite, test_session_add_get);
+ SUITE_ADD_TEST (suite, test_session_del);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}
diff --git a/trust/tests/test-token.c b/trust/tests/test-token.c
new file mode 100644
index 0000000..1d9228a
--- /dev/null
+++ b/trust/tests/test-token.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012 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@gnome.org>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "attrs.h"
+#include "debug.h"
+#include "library.h"
+#include "token.h"
+
+struct {
+ p11_token *token;
+} test;
+
+static void
+setup (CuTest *cu)
+{
+ test.token = p11_token_new (SRCDIR "/anchors:" SRCDIR "/files/cacert-ca.der",
+ SRCDIR "/files/self-server.der");
+ CuAssertPtrNotNull (cu, test.token);
+}
+
+static void
+teardown (CuTest *cu)
+{
+ p11_token_free (test.token);
+ memset (&test, 0, sizeof (test));
+}
+
+static void
+test_token_load (CuTest *cu)
+{
+ p11_dict *objects;
+ int count;
+
+ setup (cu);
+
+ count = p11_token_load (test.token);
+ CuAssertIntEquals (cu, 4, count);
+
+ /* A certificate and trust object for each parsed object */
+ objects = p11_token_objects (test.token);
+ CuAssertIntEquals (cu, count * 2, p11_dict_size (objects));
+
+ teardown (cu);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ setenv ("P11_KIT_STRICT", "1", 1);
+ p11_debug_init ();
+ p11_message_quiet ();
+
+ SUITE_ADD_TEST (suite, test_token_load);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}
diff --git a/trust/token.c b/trust/token.c
new file mode 100644
index 0000000..8a607f0
--- /dev/null
+++ b/trust/token.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2012 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 "attrs.h"
+#include "compat.h"
+#include "debug.h"
+#include "errno.h"
+#include "library.h"
+#include "module.h"
+#include "parser.h"
+#include "pkcs11.h"
+#include "token.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct _p11_token {
+ p11_parser *parser;
+ p11_dict *objects;
+ const char *anchor_paths;
+ const char *other_paths;
+ const char *certificate_paths;
+ int loaded;
+};
+
+static void
+on_parser_object (CK_ATTRIBUTE *attrs,
+ void *user_data)
+{
+ CK_OBJECT_HANDLE object;
+ CK_OBJECT_HANDLE *key;
+ p11_token *token = user_data;
+
+ object = p11_module_next_id ();
+
+ key = memdup (&object, sizeof (object));
+ return_if_fail (key != NULL);
+
+ if (!p11_dict_set (token->objects, key, attrs))
+ return_if_reached ();
+}
+
+static int
+loader_load_file (p11_token *token,
+ const char *filename,
+ struct stat *sb,
+ int flags)
+{
+ int ret;
+
+ ret = p11_parse_file (token->parser, filename, flags,
+ on_parser_object, token);
+
+ return ret == P11_PARSE_SUCCESS ? 1 : 0;
+}
+
+static int
+loader_load_directory (p11_token *token,
+ const char *directory,
+ int flags)
+{
+ struct dirent *dp;
+ struct stat sb;
+ char *path;
+ int total = 0;
+ int ret;
+ DIR *dir;
+
+ /* First we load all the modules */
+ dir = opendir (directory);
+ if (!dir) {
+ p11_message ("couldn't list directory: %s: %s",
+ directory, strerror (errno));
+ return 0;
+ }
+
+ /* We're within a global mutex, so readdir is safe */
+ while ((dp = readdir (dir)) != NULL) {
+ path = strconcat (directory, "/", dp->d_name, NULL);
+ return_val_if_fail (path != NULL, -1);
+
+ if (stat (path, &sb) < 0) {
+ p11_message ("couldn't stat path: %s", path);
+
+ } else if (!S_ISDIR (sb.st_mode)) {
+ ret = loader_load_file (token, path, &sb, flags);
+ return_val_if_fail (ret > 0, ret);
+ total += ret;
+ }
+
+ free (path);
+ }
+
+ closedir (dir);
+ return total;
+}
+
+static int
+loader_load_path (p11_token *token,
+ const char *path,
+ int flags)
+{
+ struct stat sb;
+
+ if (stat (path, &sb) < 0) {
+ if (errno == ENOENT) {
+ p11_message ("trust certificate path does not exist: %s",
+ path);
+ } else {
+ p11_message ("cannot access trust certificate path: %s: %s",
+ path, strerror (errno));
+ }
+
+ return 0;
+ }
+
+ if (S_ISDIR (sb.st_mode))
+ return loader_load_directory (token, path, flags);
+ else
+ return loader_load_file (token, path, &sb, flags);
+}
+
+static int
+loader_load_paths (p11_token *token,
+ const char *paths,
+ int flags)
+{
+ const char *pos;
+ int total = 0;
+ char *path;
+ int ret;
+
+ while (paths) {
+ pos = strchr (paths, ':');
+ if (pos == NULL) {
+ path = strdup (paths);
+ paths = NULL;
+ } else {
+ path = strndup (paths, pos - paths);
+ paths = pos + 1;
+ }
+
+ return_val_if_fail (path != NULL, -1);
+
+ if (path[0] != '\0') {
+ /* We don't expect this to fail except for in strange circumstances */
+ ret = loader_load_path (token, path, flags);
+ if (ret < 0)
+ return_val_if_reached (-1);
+ total += ret;
+ }
+
+ free (path);
+ }
+
+ return total;
+}
+
+int
+p11_token_load (p11_token *token)
+{
+ int anchors;
+ int other;
+
+ if (token->loaded)
+ return 0;
+ token->loaded = 1;
+
+ anchors = loader_load_paths (token, token->anchor_paths, P11_PARSE_FLAG_ANCHOR);
+ if (anchors < 0)
+ return anchors;
+
+ other = loader_load_paths (token, token->other_paths, P11_PARSE_FLAG_NONE);
+ if (other < 0)
+ return other;
+
+ return anchors + other;
+}
+
+p11_dict *
+p11_token_objects (p11_token *token)
+{
+ return token->objects;
+}
+
+void
+p11_token_free (p11_token *token)
+{
+ if (!token)
+ return;
+
+ p11_dict_free (token->objects);
+ p11_parser_free (token->parser);
+ free (token);
+}
+
+p11_token *
+p11_token_new (const char *anchor_paths,
+ const char *other_paths)
+{
+ p11_token *token;
+
+ token = calloc (1, sizeof (p11_token));
+ return_val_if_fail (token != NULL, NULL);
+
+ token->parser = p11_parser_new ();
+ return_val_if_fail (token->parser != NULL, NULL);
+
+ token->objects = p11_dict_new (p11_dict_ulongptr_hash,
+ p11_dict_ulongptr_equal,
+ free, p11_attrs_free);
+ return_val_if_fail (token->objects != NULL, NULL);
+
+ token->anchor_paths = anchor_paths;
+ token->other_paths = other_paths;
+ token->loaded = 0;
+
+ return token;
+}
diff --git a/trust/token.h b/trust/token.h
new file mode 100644
index 0000000..1152a68
--- /dev/null
+++ b/trust/token.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 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_TOKEN_H_
+#define P11_TOKEN_H_
+
+#include "dict.h"
+
+typedef struct _p11_token p11_token;
+
+p11_token * p11_token_new (const char *anchor_paths,
+ const char *other_paths);
+
+void p11_token_free (p11_token *token);
+
+int p11_token_load (p11_token *token);
+
+p11_dict * p11_token_objects (p11_token *token);
+
+#endif /* P11_TOKEN_H_ */