summaryrefslogtreecommitdiff
path: root/tests/pkcs11
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-06-23 23:06:29 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-06-23 23:37:55 +0200
commitb25ee830d6e94291de58af14c988c6dbc4e1643d (patch)
tree498b0721043f35efd63f6bdda0bb31b297a21b03 /tests/pkcs11
parentf11e5dfdcc9d1b0f19286c13cbc0977d9a793a9f (diff)
downloadgnutls-b25ee830d6e94291de58af14c988c6dbc4e1643d.tar.gz
tests: moved pkcs11-softhsm test suite into pkcs11/
Diffstat (limited to 'tests/pkcs11')
-rw-r--r--tests/pkcs11/pkcs11-chainverify.c327
-rw-r--r--tests/pkcs11/pkcs11-combo.c478
-rw-r--r--tests/pkcs11/pkcs11-get-issuer.c299
-rw-r--r--tests/pkcs11/pkcs11-is-known.c637
-rw-r--r--tests/pkcs11/pkcs11-privkey.c266
-rw-r--r--tests/pkcs11/pkcs11-pubkey-import-ecdsa.c47
-rw-r--r--tests/pkcs11/pkcs11-pubkey-import-rsa.c42
-rw-r--r--tests/pkcs11/pkcs11-pubkey-import.c216
-rw-r--r--tests/pkcs11/softhsm.h125
9 files changed, 2437 insertions, 0 deletions
diff --git a/tests/pkcs11/pkcs11-chainverify.c b/tests/pkcs11/pkcs11-chainverify.c
new file mode 100644
index 0000000000..ac2148b219
--- /dev/null
+++ b/tests/pkcs11/pkcs11-chainverify.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ *
+ * Author: Simon Josefsson, Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#include "../utils.h"
+#include "softhsm.h"
+#include "../test-chains.h"
+
+#define CONFIG "softhsm-chainverify.config"
+
+#define DEFAULT_THEN 1256803113
+static time_t then = DEFAULT_THEN;
+
+/* GnuTLS internally calls time() to find out the current time when
+ verifying certificates. To avoid a time bomb, we hard code the
+ current time. This should work fine on systems where the library
+ call to time is resolved at run-time. */
+static time_t mytime(time_t * t)
+{
+ if (t)
+ *t = then;
+
+ return then;
+}
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+static
+int pin_func(void* userdata, int attempt, const char* url, const char *label,
+ unsigned flags, char *pin, size_t pin_max)
+{
+ if (attempt == 0) {
+ strcpy(pin, "1234");
+ return 0;
+ }
+ return -1;
+}
+
+void doit(void)
+{
+ int exit_val = 0;
+ size_t i;
+ int ret;
+ const char *lib, *bin;
+ gnutls_typed_vdata_st vdata[2];
+ char buf[128];
+
+ /* The overloading of time() seems to work in linux (ELF?)
+ * systems only. Disable it on windows.
+ */
+#ifdef _WIN32
+ exit(77);
+#endif
+
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ gnutls_global_set_time_function(mytime);
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ set_softhsm_conf(CONFIG);
+ snprintf(buf, sizeof(buf), "%s --init-token --slot 0 --label test --so-pin 1234 --pin 1234", bin);
+ system(buf);
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ for (i = 0; chains[i].chain; i++) {
+ gnutls_x509_trust_list_t tl;
+ unsigned int verify_status;
+ gnutls_x509_crt_t certs[MAX_CHAIN];
+ gnutls_x509_crt_t ca;
+ gnutls_datum_t tmp;
+ size_t j;
+
+ gnutls_x509_trust_list_iter_t get_ca_iter;
+ gnutls_datum_t get_ca_datum_test;
+ gnutls_datum_t get_ca_datum;
+ gnutls_x509_crt_t get_ca_crt;
+
+ if (debug)
+ printf("Chain '%s' (%d)...\n", chains[i].name,
+ (int) i);
+
+ for (j = 0; chains[i].chain[j]; j++) {
+ if (debug > 2)
+ printf("\tAdding certificate %d...",
+ (int) j);
+
+ ret = gnutls_x509_crt_init(&certs[j]);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_init[%d,%d]: %s\n",
+ (int) i, (int) j,
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) chains[i].chain[j];
+ tmp.size = strlen(chains[i].chain[j]);
+
+ ret =
+ gnutls_x509_crt_import(certs[j], &tmp,
+ GNUTLS_X509_FMT_PEM);
+ if (debug > 2)
+ printf("done\n");
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_import[%s,%d]: %s\n",
+ chains[i].name, (int) j,
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_print(certs[j],
+ GNUTLS_CRT_PRINT_ONELINE,
+ &tmp);
+ if (debug)
+ printf("\tCertificate %d: %.*s\n", (int) j,
+ tmp.size, tmp.data);
+ gnutls_free(tmp.data);
+ }
+
+ if (debug > 2)
+ printf("\tAdding CA certificate...");
+
+ ret = gnutls_x509_crt_init(&ca);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) *chains[i].ca;
+ tmp.size = strlen(*chains[i].ca);
+
+ ret =
+ gnutls_x509_crt_import(ca, &tmp, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (debug > 2)
+ printf("done\n");
+
+ gnutls_x509_crt_print(ca, GNUTLS_CRT_PRINT_ONELINE, &tmp);
+ if (debug)
+ printf("\tCA Certificate: %.*s\n", tmp.size,
+ tmp.data);
+ gnutls_free(tmp.data);
+
+ if (debug)
+ printf("\tVerifying...");
+
+ /* initialize softhsm token */
+ ret = gnutls_pkcs11_token_init(SOFTHSM_URL, "1234", "test");
+ if (ret < 0) {
+ fail("gnutls_pkcs11_token_init\n");
+ exit(1);
+ }
+
+ /* write CA certificate to softhsm */
+ ret = gnutls_pkcs11_copy_x509_crt(SOFTHSM_URL, ca, "test-ca", GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED|
+ GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|
+ GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO);
+ if (ret < 0) {
+ /* FIXME: this is a known softhsm v2.0.0 bug - remove this once our testsuite is updated */
+ fail_ignore("gnutls_pkcs11_copy_x509_crt: %s\n", gnutls_strerror(ret));
+ }
+
+ gnutls_x509_trust_list_init(&tl, 0);
+
+ ret = gnutls_x509_trust_list_add_trust_file(tl, SOFTHSM_URL, NULL, 0, 0, 0);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_add_trust_file: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (ret < 1) {
+ fail("gnutls_x509_trust_list_add_trust_file returned zero!\n");
+ exit(1);
+ }
+
+ /* test trust list iteration */
+ get_ca_iter = NULL;
+ while (gnutls_x509_trust_list_iter_get_ca(tl, &get_ca_iter, &get_ca_crt) == 0) {
+ ret = gnutls_x509_crt_export2(get_ca_crt, GNUTLS_X509_FMT_PEM, &get_ca_datum_test);
+ if (ret < 0) {
+ fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_export2(ca, GNUTLS_X509_FMT_PEM, &get_ca_datum);
+ if (ret < 0) {
+ fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (get_ca_datum_test.size != get_ca_datum.size ||
+ memcmp(get_ca_datum_test.data, get_ca_datum.data, get_ca_datum.size) != 0) {
+ fail("gnutls_x509_trist_list_iter_get_ca: Unexpected certificate (%u != %u):\n\n%s\n\nvs.\n\n%s", get_ca_datum.size, get_ca_datum_test.size, get_ca_datum.data, get_ca_datum_test.data);
+ exit(1);
+ }
+
+ gnutls_free(get_ca_datum.data);
+ gnutls_free(get_ca_datum_test.data);
+ gnutls_x509_crt_deinit(get_ca_crt);
+ }
+
+ vdata[0].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ vdata[0].data = (void *)chains[i].purpose;
+
+ if (chains[i].expected_time != 0)
+ then = chains[i].expected_time;
+ else
+ then = DEFAULT_THEN;
+
+ /* make sure that the two functions don't diverge */
+ ret = gnutls_x509_trust_list_verify_crt2(tl, certs, j,
+ vdata,
+ chains[i].purpose==NULL?0:1,
+ chains[i].verify_flags,
+ &verify_status, NULL);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_list_verify[%d,%d]: %s\n",
+ (int) i, (int) j, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (verify_status != chains[i].expected_verify_result) {
+ gnutls_datum_t out1, out2;
+ gnutls_certificate_verification_status_print
+ (verify_status, GNUTLS_CRT_X509, &out1, 0);
+ gnutls_certificate_verification_status_print(chains
+ [i].
+ expected_verify_result,
+ GNUTLS_CRT_X509,
+ &out2,
+ 0);
+ fail("chain[%s]:\nverify_status: %d: %s\nexpected: %d: %s\n", chains[i].name, verify_status, out1.data, chains[i].expected_verify_result, out2.data);
+ gnutls_free(out1.data);
+ gnutls_free(out2.data);
+
+#if 0
+ j = 0;
+ do {
+ fprintf(stderr, "%s\n",
+ chains[i].chain[j]);
+ }
+ while (chains[i].chain[++j] != NULL);
+#endif
+
+ if (!debug)
+ exit(1);
+ } else if (debug)
+ printf("done\n");
+
+ if (debug)
+ printf("\tCleanup...");
+
+ gnutls_x509_trust_list_deinit(tl, 0);
+ gnutls_x509_crt_deinit(ca);
+ for (j = 0; chains[i].chain[j]; j++)
+ gnutls_x509_crt_deinit(certs[j]);
+
+ if (debug)
+ printf("done\n\n\n");
+ }
+
+ gnutls_global_deinit();
+
+ if (debug)
+ printf("Exit status...%d\n", exit_val);
+ remove(CONFIG);
+
+ exit(exit_val);
+}
diff --git a/tests/pkcs11/pkcs11-combo.c b/tests/pkcs11/pkcs11-combo.c
new file mode 100644
index 0000000000..f2effbd388
--- /dev/null
+++ b/tests/pkcs11/pkcs11-combo.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/x509-ext.h>
+
+/* Tests whether the combination of a trust module + additional CAs
+ * in a trust list would work.
+ */
+
+#include "../utils.h"
+#include "../test-chains.h"
+#include "softhsm.h"
+
+#define NAME "softhsm-combo"
+#define CONFIG NAME".config"
+
+/* These CAs have the same DN */
+static const char *ca_list[MAX_CHAIN] = {
+"-----BEGIN CERTIFICATE-----\n"
+"MIIHSjCCBjKgAwIBAgIKYRHt9wABAAAAFTANBgkqhkiG9w0BAQUFADBSMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIFBvbGljeSBDQTAeFw0xMzAyMDQyMTUyMThaFw0x\n"
+"ODA1MjQxOTU5MzlaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw\n"
+"b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgSW50cmFuZXQgQmFzaWMgSXNzdWluZyBD\n"
+"QSAyQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALn3ogjraWSmK5Wb\n"
+"/4e9mENA1F36FBVemaG7L93ZhRRXq4UV0PQM5/4TOe9KAaOlX+a2cuULeeUtN9Rk\n"
+"V/nHAVzSWlqc/NTMJfuI/1AD7ICNejQFYLxDMXGjR7eAHtiMz0iTMp9u6YTw4WXh\n"
+"WffqTPiqUZ6DEWsMic9dM9yw/JqzycKClLcTD1OCvtw7Fx4tNTu6/ngrYJcTo29e\n"
+"BBh/DupgtgnYPYuExEkHmucb4VIDdjfRkPo/BdNqrUSYfYqnUDj5mH+hPzIgppsZ\n"
+"Rw0S5PUZGuC1f+Zok+4vZPR+hGG3Pdm2LTUEWSnurlhyfBoM+0yxeHsmL9aHU7zt\n"
+"EIzVmKUCAwEAAaOCBBwwggQYMBIGCSsGAQQBgjcVAQQFAgMCAAIwIwYJKwYBBAGC\n"
+"NxUCBBYEFMqHyYZOx6LYwRwZ+5vjOyIl9hENMB0GA1UdDgQWBBQ4Y3b6tgU6qVlP\n"
+"SoeNoIO3fpE6CzAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC\n"
+"AYYwEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBRp6zCRHAOAgE4RFYhG\n"
+"pOJBmtNpHzCCAaIGA1UdHwSCAZkwggGVMIIBkaCCAY2gggGJhlFodHRwOi8vd3d3\n"
+"LmludGVsLmNvbS9yZXBvc2l0b3J5L0NSTC9JbnRlbCUyMEludHJhbmV0JTIwQmFz\n"
+"aWMlMjBQb2xpY3klMjBDQSgxKS5jcmyGWmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuaW50\n"
+"ZWwuY29tL3JlcG9zaXRvcnkvQ1JML0ludGVsJTIwSW50cmFuZXQlMjBCYXNpYyUy\n"
+"MFBvbGljeSUyMENBKDEpLmNybIaB12xkYXA6Ly8vQ049SW50ZWwlMjBJbnRyYW5l\n"
+"dCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSksQ049bWNzaWJwY2EsQ049Q0RQLENO\n"
+"PVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3Vy\n"
+"YXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y2VydGlmaWNhdGVSZXZvY2F0\n"
+"aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MIIB\n"
+"uQYIKwYBBQUHAQEEggGrMIIBpzBmBggrBgEFBQcwAoZaaHR0cDovL3d3dy5pbnRl\n"
+"bC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJbnRyYW5ldCUy\n"
+"MEJhc2ljJTIwUG9saWN5JTIwQ0EoMSkuY3J0MG8GCCsGAQUFBzAChmNodHRwOi8v\n"
+"Y2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L2NlcnRpZmljYXRlcy9J\n"
+"bnRlbCUyMEludHJhbmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgxKS5jcnQwgcsG\n"
+"CCsGAQUFBzAChoG+bGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0JTIwQmFzaWMl\n"
+"MjBQb2xpY3klMjBDQSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMs\n"
+"Q049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jb3JwLERDPWludGVsLERD\n"
+"PWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNhdGlv\n"
+"bkF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAQEAsj8cHt2jSAmnIGulE9jXooAc\n"
+"qH2xehlI+ko/al+nDnBzbjDYYjVS52XitYg8JGo6j72ijiGlGb/03FcQJRBZmUH6\n"
+"znktx2rGTm4IdjL8quhvHthlzXXCozL8GMeeOuZ5rzHlhapKx764a5RuZtyx89uS\n"
+"9cECon6oLGesXjFJ8Xrq6ecHZrQwJUpmvZalwvloKACAWqBh8yV12WDnUNZhtp8N\n"
+"8rqeJZoy/lXGnTxsSSodO/5Y/CxYJM4W6u4WgvXNJSjO/0qWvb64S+pVLjBzwI+Y\n"
+"X6oLqmBovRp1lGPOLjkXZi3EKDR8DmzhtpJq2677RtYowewnFedQ+exH9cXoJw==\n"
+"-----END CERTIFICATE-----",
+"-----BEGIN CERTIFICATE-----\n"
+"MIIHSjCCBjKgAwIBAgIKYRXxrQABAAAAETANBgkqhkiG9w0BAQUFADBSMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIFBvbGljeSBDQTAeFw0wOTA1MTUxODQyNDVaFw0x\n"
+"NTA1MTUxODUyNDVaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw\n"
+"b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgSW50cmFuZXQgQmFzaWMgSXNzdWluZyBD\n"
+"QSAyQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbJOXtXYgfyoch6\n"
+"ip5SSjijOXvpIjBxbTl5EGH/VYHmpM2O6SRlKh/uy77QS9m84sRWCJLr8cWwX9oH\n"
+"qSmIylgcWvDpVNHx4v506DTTrbK0sbYRQYXRajOzJKeTt7NLeLrngyl45FrI9VAT\n"
+"3yqp/2BCG1dUwcBha3dB2UbTkFOMt9o/gqoL6KvgswYMs/oGc/OIjeozdYuhnBT2\n"
+"YlT9Ge5pfhOJWXh4DJbxnTmWwRUKq0MXFn0S00KQ/BZOTkc/5DibUmbmMrYi8ra4\n"
+"Z2bpnoTq0WNA99O2Lk8IgmkqPdi6HwZwKCE/x01qwP8zo76rvN8sbW9pj2WzS1WF\n"
+"tSDPeZECAwEAAaOCBBwwggQYMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE\n"
+"FPwbdyds7Cm03lobLKmI6q59npi+MAsGA1UdDwQEAwIBhjASBgkrBgEEAYI3FQEE\n"
+"BQIDAQABMCMGCSsGAQQBgjcVAgQWBBRT1n27C6cZL4QFHaUX2nFSCPxhtTAZBgkr\n"
+"BgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAfBgNVHSMEGDAWgBRp6zCRHAOAgE4RFYhG\n"
+"pOJBmtNpHzCCAaIGA1UdHwSCAZkwggGVMIIBkaCCAY2gggGJhlFodHRwOi8vd3d3\n"
+"LmludGVsLmNvbS9yZXBvc2l0b3J5L0NSTC9JbnRlbCUyMEludHJhbmV0JTIwQmFz\n"
+"aWMlMjBQb2xpY3klMjBDQSgxKS5jcmyGWmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuaW50\n"
+"ZWwuY29tL3JlcG9zaXRvcnkvQ1JML0ludGVsJTIwSW50cmFuZXQlMjBCYXNpYyUy\n"
+"MFBvbGljeSUyMENBKDEpLmNybIaB12xkYXA6Ly8vQ049SW50ZWwlMjBJbnRyYW5l\n"
+"dCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSksQ049bWNzaWJwY2EsQ049Q0RQLENO\n"
+"PVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3Vy\n"
+"YXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y2VydGlmaWNhdGVSZXZvY2F0\n"
+"aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MIIB\n"
+"uQYIKwYBBQUHAQEEggGrMIIBpzBmBggrBgEFBQcwAoZaaHR0cDovL3d3dy5pbnRl\n"
+"bC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJbnRyYW5ldCUy\n"
+"MEJhc2ljJTIwUG9saWN5JTIwQ0EoMSkuY3J0MG8GCCsGAQUFBzAChmNodHRwOi8v\n"
+"Y2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L2NlcnRpZmljYXRlcy9J\n"
+"bnRlbCUyMEludHJhbmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgxKS5jcnQwgcsG\n"
+"CCsGAQUFBzAChoG+bGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0JTIwQmFzaWMl\n"
+"MjBQb2xpY3klMjBDQSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMs\n"
+"Q049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jb3JwLERDPWludGVsLERD\n"
+"PWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNhdGlv\n"
+"bkF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAQEArlAkrJXyMCssqAJT3PqnY7wt\n"
+"sirq1fTMrVrHdmkpBKDXBQnDcTW1zfZtOPV/QDm3UsFwDBbGq+j/7U9qZ1zYHkv+\n"
+"wrBpeFM6dlca/sgegGGAhYnQQwmlSzNXCKHMBltMjT61X8rVjyt1XJnucgat9rnT\n"
+"2j8pztqoViVnORsGfT6DDB/bz/6bFKw4FMp1wDaJI7dKh5NUggvH36owTWI7JUvq\n"
+"yJ8OI2qmjXrlqGexfwvltIkEk8xzuMIHWQoR8sERL2qf3nb2VYq1s1LbH5uCkZ0l\n"
+"w/xgwFbbwjaGJ3TFOmkVKYU77nXSkfK9EXae0UZRU0WmX4t5NNt8jiL56TPpsw==\n"
+"-----END CERTIFICATE-----\n",
+"-----BEGIN CERTIFICATE-----\n"
+"MIIHIzCCBgugAwIBAgIKYRok3wABAAAADDANBgkqhkiG9w0BAQUFADBSMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIFBvbGljeSBDQTAeFw0wNjA1MjQxOTU2MDFaFw0x\n"
+"MjA1MjQyMDA2MDFaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw\n"
+"b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgSW50cmFuZXQgQmFzaWMgSXNzdWluZyBD\n"
+"QSAyQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANE2pFSB0XqXoRWF\n"
+"N7bzDesBAcTGEqcr6GVA+sMcJ5Vt17S8vGesmO2RgP6I49Q58nIhUnT054arUlOx\n"
+"NKYbAEiVyGOK5zV2mZS4oW2UazfcpsV1uuO3j02UbzX+qcxQdNqoAHxwoB4nRJuU\n"
+"Ijio45jWAssDbD8IKHZpmqRI5wUzbibkWnTZEc0YFO6iF40sNtqVr+uInP07PkQn\n"
+"1Ttkyw6isa5Dhcyq6lTVOjnlj29bFYbZxN1uuDnTpUMVeov8oQv5wLyLrDVd1sMg\n"
+"Njr2oofepZ8KjF3DKCkfsUekCHA9Pr2K/4hStd/nSwvIdNjCjfznqYadkB6wQ99a\n"
+"hTX4uJkCAwEAAaOCA/UwggPxMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE\n"
+"FJunwCR+/af8p76CGTyhUZc3l/4DMAsGA1UdDwQEAwIBhjAQBgkrBgEEAYI3FQEE\n"
+"AwIBADAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAfBgNVHSMEGDAWgBRp6zCR\n"
+"HAOAgE4RFYhGpOJBmtNpHzCCAaIGA1UdHwSCAZkwggGVMIIBkaCCAY2gggGJhlFo\n"
+"dHRwOi8vd3d3LmludGVsLmNvbS9yZXBvc2l0b3J5L0NSTC9JbnRlbCUyMEludHJh\n"
+"bmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgxKS5jcmyGWmh0dHA6Ly9jZXJ0aWZp\n"
+"Y2F0ZXMuaW50ZWwuY29tL3JlcG9zaXRvcnkvQ1JML0ludGVsJTIwSW50cmFuZXQl\n"
+"MjBCYXNpYyUyMFBvbGljeSUyMENBKDEpLmNybIaB12xkYXA6Ly8vQ049SW50ZWwl\n"
+"MjBJbnRyYW5ldCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSksQ049bWNzaWJwY2Es\n"
+"Q049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENO\n"
+"PUNvbmZpZ3VyYXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y2VydGlmaWNh\n"
+"dGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlv\n"
+"blBvaW50MIIBuQYIKwYBBQUHAQEEggGrMIIBpzBmBggrBgEFBQcwAoZaaHR0cDov\n"
+"L3d3dy5pbnRlbC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJ\n"
+"bnRyYW5ldCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSkuY3J0MG8GCCsGAQUFBzAC\n"
+"hmNodHRwOi8vY2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L2NlcnRp\n"
+"ZmljYXRlcy9JbnRlbCUyMEludHJhbmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgx\n"
+"KS5jcnQwgcsGCCsGAQUFBzAChoG+bGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0\n"
+"JTIwQmFzaWMlMjBQb2xpY3klMjBDQSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIw\n"
+"U2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jb3JwLERD\n"
+"PWludGVsLERDPWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2Vy\n"
+"dGlmaWNhdGlvbkF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAQEAe3SmN0lsGF0h\n"
+"zq+NANnUD4YJS31UqreVm4kJv07+9CTBtlB0AVqJ2RcjRosdQmrbhx7R0WwcXSdR\n"
+"QnRGhaoDVRNehKiz3Grp6ehJr9LInhCp6WtOeKRlOSb2xgRDJCtzCi07TuAb9h2I\n"
+"urpmndeA4NEbPYL1GYEBpKYawUcFCq5yTv0YgZXy53DdBDv9ygRWYGEk7/gPgvCu\n"
+"2O1GNs9n25goy+3/aMkHnUyl3MOtiooXJR7eKOEgTPHNe42LQ9KuUz5SoZQN8vSL\n"
+"r49IRDC4dgMkGvsC5h0+ftixQ66ni6QJe6SNcpSZrpW5vBE9J+vtDI0gTyq2SYPo\n"
+"0fiS3V8p4g==\n"
+"-----END CERTIFICATE-----\n",
+NULL};
+
+/* this certificate is issued by one of the above */
+static const char intermediate_str[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIIH4DCCBsigAwIBAgIKFpIKYgACAAJ8lTANBgkqhkiG9w0BAQUFADBWMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xKzApBgNVBAMTIklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIElzc3VpbmcgQ0EgMkIwHhcNMTQwMTA4MTc0MTM5\n"
+"WhcNMTcwMTA3MTc0MTM5WjB1MQswCQYDVQQGEwJJRTELMAkGA1UEBxMCSVIxGjAY\n"
+"BgNVBAoTEUludGVsIENvcnBvcmF0aW9uMQswCQYDVQQLEwJJVDEWMBQGA1UEAxMN\n"
+"dnBuLmludGVsLmNvbTEYMBYGA1UEAxMPc2NzaXIuaW50ZWwuY29tMIIBIjANBgkq\n"
+"hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi3WoORH5ITJ2lpcgCHex1HBUnmN/bb6s\n"
+"sS1Arm50NEHMlqGfbsdCxq2iodMvrGWvdRAPaf/7Ii1UwUhEzxyKYAXC3KRAgioh\n"
+"C0pvGmAFq1ciDYRhANPlW92lIgkt83WwGtOcES2u36VmUxBfdQe6rO3ldoZHVofY\n"
+"uIG/ubBVLz0NhWMaRYSUzTv/4PKJ4paIS7COUROYsyKwc5wNjTcR2PB7RRW+YHgM\n"
+"FkvqPpLjLAGpHdN+wuPNLlUcyzkZVhhXxvQJ9gc5hw/LLQvbmeiGIZCvOVy3ZSfi\n"
+"cGw2jkbqKcFttVV52Wild3ZigALZtkKuFnGw5DEIfk4EAZhG8eHfFQIDAQABo4IE\n"
+"jzCCBIswCwYDVR0PBAQDAgWgMB0GA1UdDgQWBBR4EAIG7OggvIFAhrB8m0eyhCKV\n"
+"GzAfBgNVHSMEGDAWgBQ4Y3b6tgU6qVlPSoeNoIO3fpE6CzCCAbkGA1UdHwSCAbAw\n"
+"ggGsMIIBqKCCAaSgggGghoHibGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0JTIw\n"
+"QmFzaWMlMjBJc3N1aW5nJTIwQ0ElMjAyQigyKSxDTj1BWlNNQ1NJQkVDQTAyLENO\n"
+"PUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1D\n"
+"b25maWd1cmF0aW9uLERDPWNvcnAsREM9aW50ZWwsREM9Y29tP2NlcnRpZmljYXRl\n"
+"UmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Q\n"
+"b2ludIZXaHR0cDovL3d3dy5pbnRlbC5jb20vcmVwb3NpdG9yeS9DUkwvSW50ZWwl\n"
+"MjBJbnRyYW5ldCUyMEJhc2ljJTIwSXNzdWluZyUyMENBJTIwMkIoMikuY3JshmBo\n"
+"dHRwOi8vY2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L0NSTC9JbnRl\n"
+"bCUyMEludHJhbmV0JTIwQmFzaWMlMjBJc3N1aW5nJTIwQ0ElMjAyQigyKS5jcmww\n"
+"ggHLBggrBgEFBQcBAQSCAb0wggG5MIHRBggrBgEFBQcwAoaBxGxkYXA6Ly8vQ049\n"
+"SW50ZWwlMjBJbnRyYW5ldCUyMEJhc2ljJTIwSXNzdWluZyUyMENBJTIwMkIsQ049\n"
+"QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNv\n"
+"bmZpZ3VyYXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y0FDZXJ0aWZpY2F0\n"
+"ZT9iYXNlP29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwbAYIKwYB\n"
+"BQUHMAKGYGh0dHA6Ly93d3cuaW50ZWwuY29tL3JlcG9zaXRvcnkvY2VydGlmaWNh\n"
+"dGVzL0ludGVsJTIwSW50cmFuZXQlMjBCYXNpYyUyMElzc3VpbmclMjBDQSUyMDJC\n"
+"KDIpLmNydDB1BggrBgEFBQcwAoZpaHR0cDovL2NlcnRpZmljYXRlcy5pbnRlbC5j\n"
+"b20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJbnRyYW5ldCUyMEJh\n"
+"c2ljJTIwSXNzdWluZyUyMENBJTIwMkIoMikuY3J0MD0GCSsGAQQBgjcVBwQwMC4G\n"
+"JisGAQQBgjcVCIbDjHWEmeVRg/2BKIWOn1OCkcAJZ4eC0UGC37J5AgFkAgERMB0G\n"
+"A1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAnBgkrBgEEAYI3FQoEGjAYMAoG\n"
+"CCsGAQUFBwMCMAoGCCsGAQUFBwMBMCkGA1UdEQQiMCCCD3Njc2lyLmludGVsLmNv\n"
+"bYINdnBuLmludGVsLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEALjO591IHOTt28HZ9\n"
+"+Vm2TJp8EJSgWW3luKFAAPUOxix5FgK7mqNQk1052qV8NCQKqChO64f6kl3R29Pp\n"
+"yv0ALYaxdYZXkxPuts05gwu9caeH9fK6vGTRk5pWygVIsobS2MypCYFs9VftFw5d\n"
+"EPUAOsigQmkBC+k+icYzZDjm4HBGd0mTHwniNsKkkjxSnF4UGH9OYp4+hs9/pWly\n"
+"19X4gVWwuxKB59TOe/tVxHBt57zZA3zYyXG+VPzVmklmYLPxVFcmeUDOjWU3x3Wp\n"
+"0D5YUmvQlsd4+73IYw0BrvB42bQEFDUU/v0u6mwluk1m0LEdm+jlM/YCbrAgA3O8\n"
+"eV1xMQ==\n"
+"-----END CERTIFICATE-----\n";
+
+
+
+/* GnuTLS internally calls time() to find out the current time when
+ verifying certificates. To avoid a time bomb, we hard code the
+ current time. This should work fine on systems where the library
+ call to time is resolved at run-time. */
+static time_t mytime(time_t * t)
+{
+ time_t then = 1256803113;
+
+ if (t)
+ *t = then;
+
+ return then;
+}
+
+#define PIN "1234"
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+static
+int pin_func(void* userdata, int attempt, const char* url, const char *label,
+ unsigned flags, char *pin, size_t pin_max)
+{
+ if (attempt == 0) {
+ strcpy(pin, PIN);
+ return 0;
+ }
+ return -1;
+}
+
+void doit(void)
+{
+ char buf[128];
+ int exit_val = 0;
+ int ret;
+ unsigned j;
+ const char *lib, *bin;
+ gnutls_x509_crt_t issuer = NULL;
+ gnutls_x509_trust_list_t tl;
+ gnutls_x509_crt_t certs[MAX_CHAIN];
+ gnutls_x509_crt_t end, ca;
+ unsigned verify_status = 0;
+ gnutls_datum_t tmp;
+
+ /* The overloading of time() seems to work in linux (ELF?)
+ * systems only. Disable it on windows.
+ */
+#ifdef _WIN32
+ exit(77);
+#endif
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ gnutls_global_set_time_function(mytime);
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ set_softhsm_conf(CONFIG);
+ snprintf(buf, sizeof(buf), "%s --init-token --slot 0 --label test --so-pin "PIN" --pin "PIN, bin);
+ system(buf);
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ for (j = 0; ca_list[j]; j++) {
+ if (debug > 2)
+ printf("\tAdding certificate %d...",
+ (int) j);
+
+ ret = gnutls_x509_crt_init(&certs[j]);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_init[%d,%d]: %s\n",
+ (int) 3, (int) j,
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) ca_list[j];
+ tmp.size = strlen(ca_list[j]);
+
+ ret =
+ gnutls_x509_crt_import(certs[j], &tmp,
+ GNUTLS_X509_FMT_PEM);
+ if (debug > 2)
+ printf("done\n");
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_import[%d]: %s\n",
+ (int) j,
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_print(certs[j],
+ GNUTLS_CRT_PRINT_ONELINE,
+ &tmp);
+ if (debug)
+ printf("\tCertificate %d: %.*s\n", (int) j,
+ tmp.size, tmp.data);
+ gnutls_free(tmp.data);
+ }
+
+ if (debug > 2)
+ printf("\tAdding end certificate...");
+
+ ret = gnutls_x509_crt_init(&end);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) v1_root_check[0];
+ tmp.size = strlen(v1_root_check[0]);
+
+ ret =
+ gnutls_x509_crt_import(end, &tmp, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_print(end, GNUTLS_CRT_PRINT_ONELINE, &tmp);
+ if (debug)
+ printf("\tEnd Certificate: %.*s\n", tmp.size,
+ tmp.data);
+ gnutls_free(tmp.data);
+
+ ret = gnutls_x509_crt_init(&ca);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) v1_root_check[1];
+ tmp.size = strlen(v1_root_check[1]);
+
+ ret =
+ gnutls_x509_crt_import(ca, &tmp, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_print(end, GNUTLS_CRT_PRINT_ONELINE, &tmp);
+ if (debug)
+ printf("\tCA Certificate: %.*s\n", tmp.size,
+ tmp.data);
+ gnutls_free(tmp.data);
+
+ if (debug > 2)
+ printf("done\n");
+
+
+ if (debug)
+ printf("\tChecking presence and verification...");
+
+ /* initialize softhsm token */
+ ret = gnutls_pkcs11_token_init(SOFTHSM_URL, PIN, "test");
+ if (ret < 0) {
+ fail("gnutls_pkcs11_token_init\n");
+ exit(1);
+ }
+
+ /* write CA certificate to softhsm */
+ for (j = 0; ca_list[j]; j++) {
+ char name[64];
+ snprintf(name, sizeof(name), "test-ca%d", j);
+ ret = gnutls_pkcs11_copy_x509_crt(SOFTHSM_URL, certs[j], name, GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED|GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_x509_crt: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+ }
+
+ gnutls_x509_trust_list_init(&tl, 0);
+
+ ret = gnutls_x509_trust_list_add_trust_file(tl, SOFTHSM_URL, NULL, 0, 0, 0);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_add_trust_file\n");
+ exit(1);
+ }
+
+ ret = gnutls_x509_trust_list_add_cas(tl, &ca, 1, 0);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_add_cas\n");
+ exit(1);
+ }
+
+ /* extract the issuer of the certificate */
+ ret = gnutls_x509_trust_list_get_issuer(tl, end, &issuer, GNUTLS_TL_GET_COPY);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_get_issuer should have succeeded\n");
+ exit(1);
+ }
+ gnutls_x509_crt_deinit(issuer);
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, ca, GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret != 0) {
+ fail("gnutls_pkcs11_crt_is_known should have failed!\n");
+ exit(1);
+ }
+
+ ret = gnutls_x509_trust_list_verify_crt2(tl, &end, 1,
+ NULL, 0,
+ GNUTLS_VERIFY_DISABLE_TIME_CHECKS, &verify_status, NULL);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_verify_crt2 should have succeeded\n");
+ exit(1);
+ }
+
+ if (verify_status != 0) {
+ fail("verification should have succeeded: %.2x\n", verify_status);
+ exit(1);
+ }
+
+ if (debug)
+ printf("\tCleanup...");
+
+ gnutls_x509_trust_list_deinit(tl, 0);
+ gnutls_x509_crt_deinit(ca);
+ gnutls_x509_crt_deinit(end);
+ for (j = 0; ca_list[j]; j++) {
+ gnutls_x509_crt_deinit(certs[j]);
+ }
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_global_deinit();
+
+ if (debug)
+ printf("Exit status...%d\n", exit_val);
+ remove(CONFIG);
+
+ exit(exit_val);
+}
diff --git a/tests/pkcs11/pkcs11-get-issuer.c b/tests/pkcs11/pkcs11-get-issuer.c
new file mode 100644
index 0000000000..fd65f3d82b
--- /dev/null
+++ b/tests/pkcs11/pkcs11-get-issuer.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ *
+ * Author: Simon Josefsson, Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/x509-ext.h>
+
+#include "../utils.h"
+#include "../test-chains.h"
+#include "softhsm.h"
+
+#define CONFIG "softhsm-issuer.config"
+
+/* GnuTLS internally calls time() to find out the current time when
+ verifying certificates. To avoid a time bomb, we hard code the
+ current time. This should work fine on systems where the library
+ call to time is resolved at run-time. */
+static time_t mytime(time_t * t)
+{
+ time_t then = 1256803113;
+
+ if (t)
+ *t = then;
+
+ return then;
+}
+
+#define PIN "1234"
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+static
+int pin_func(void* userdata, int attempt, const char* url, const char *label,
+ unsigned flags, char *pin, size_t pin_max)
+{
+ if (attempt == 0) {
+ strcpy(pin, PIN);
+ return 0;
+ }
+ return -1;
+}
+
+void doit(void)
+{
+ char buf[128];
+ int exit_val = 0;
+ int ret;
+ unsigned j;
+ const char *lib, *bin;
+ gnutls_x509_crt_t issuer = NULL;
+ gnutls_x509_trust_list_t tl;
+ gnutls_x509_crt_t certs[MAX_CHAIN];
+ gnutls_x509_crt_t ca;
+ gnutls_datum_t tmp;
+ int idx = -1;
+
+ /* The overloading of time() seems to work in linux (ELF?)
+ * systems only. Disable it on windows.
+ */
+#ifdef _WIN32
+ exit(77);
+#endif
+ for (j=0;;j++) {
+ if (chains[j].name == NULL)
+ break;
+ if (strcmp(chains[j].name, "verisign.com v1 ok") == 0) {
+ idx = j;
+ break;
+ }
+ }
+
+ if (idx == -1) {
+ fail("could not find proper chain\n");
+ exit(1);
+ }
+
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ gnutls_global_set_time_function(mytime);
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ /* write softhsm.config */
+
+ set_softhsm_conf(CONFIG);
+ snprintf(buf, sizeof(buf), "%s --init-token --slot 0 --label test --so-pin "PIN" --pin "PIN, bin);
+ system(buf);
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ for (j = 0; chains[idx].chain[j]; j++) {
+ if (debug > 2)
+ printf("\tAdding certificate %d...",
+ (int) j);
+
+ ret = gnutls_x509_crt_init(&certs[j]);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_init[%d,%d]: %s\n",
+ (int) 3, (int) j,
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) chains[idx].chain[j];
+ tmp.size = strlen(chains[idx].chain[j]);
+
+ ret =
+ gnutls_x509_crt_import(certs[j], &tmp,
+ GNUTLS_X509_FMT_PEM);
+ if (debug > 2)
+ printf("done\n");
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_import[%s,%d]: %s\n",
+ chains[idx].name, (int) j,
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_print(certs[j],
+ GNUTLS_CRT_PRINT_ONELINE,
+ &tmp);
+ if (debug)
+ printf("\tCertificate %d: %.*s\n", (int) j,
+ tmp.size, tmp.data);
+ gnutls_free(tmp.data);
+ }
+
+ if (debug > 2)
+ printf("\tAdding CA certificate...");
+
+ ret = gnutls_x509_crt_init(&ca);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) *chains[idx].ca;
+ tmp.size = strlen(*chains[idx].ca);
+
+ ret =
+ gnutls_x509_crt_import(ca, &tmp, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (debug > 2)
+ printf("done\n");
+
+ gnutls_x509_crt_print(ca, GNUTLS_CRT_PRINT_ONELINE, &tmp);
+ if (debug)
+ printf("\tCA Certificate: %.*s\n", tmp.size,
+ tmp.data);
+ gnutls_free(tmp.data);
+
+ if (debug)
+ printf("\tVerifying...");
+
+ /* initialize softhsm token */
+ ret = gnutls_pkcs11_token_init(SOFTHSM_URL, PIN, "test");
+ if (ret < 0) {
+ fail("gnutls_pkcs11_token_init\n");
+ exit(1);
+ }
+
+ /* write CA certificate to softhsm */
+ ret = gnutls_pkcs11_copy_x509_crt(SOFTHSM_URL, ca, "test-ca", GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED|GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_x509_crt: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_trust_list_init(&tl, 0);
+
+ ret = gnutls_x509_trust_list_add_trust_file(tl, SOFTHSM_URL, NULL, 0, 0, 0);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_add_trust_file\n");
+ exit(1);
+ }
+
+ /* extract the issuer of the certificate */
+ issuer = NULL;
+ ret = gnutls_x509_trust_list_get_issuer(tl, certs[2], &issuer, GNUTLS_TL_GET_COPY);
+ if (ret < 0) {
+ fail("error in gnutls_x509_trust_list_get_issuer\n");
+ exit(1);
+ }
+ if (issuer == NULL) {
+ fail("error in gnutls_x509_trust_list_get_issuer return value\n");
+ exit(1);
+ }
+ gnutls_x509_crt_deinit(issuer);
+
+ /* extract the issuer of the certificate using the non-thread-safe approach */
+ issuer = NULL;
+ ret = gnutls_x509_trust_list_get_issuer(tl, certs[2], &issuer, 0);
+ if (ret < 0) {
+ fail("error in gnutls_x509_trust_list_get_issuer\n");
+ exit(1);
+ }
+ if (issuer == NULL) {
+ fail("error in gnutls_x509_trust_list_get_issuer return value\n");
+ exit(1);
+ }
+
+ /* extract (again) the issuer of the certificate - check for any leaks */
+ ret = gnutls_x509_trust_list_get_issuer(tl, certs[2], &issuer, 0);
+ if (ret < 0) {
+ fail("error in gnutls_x509_trust_list_get_issuer\n");
+ exit(1);
+ }
+
+ /* Check gnutls_x509_trust_list_get_raw_issuer_by_dn */
+ ret = gnutls_x509_crt_get_raw_issuer_dn(certs[2], &tmp);
+ if (ret < 0) {
+ fail("error in gnutls_x509_crt_get_raw_issuer_dn: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_trust_list_get_issuer_by_dn(tl, &tmp, &issuer, 0);
+ gnutls_free(tmp.data);
+ if (ret < 0) {
+ fail("error in gnutls_x509_trust_list_get_issuer\n");
+ exit(1);
+ }
+ if (issuer == NULL) {
+ fail("error in gnutls_x509_trust_list_get_issuer_by_dn return value\n");
+ exit(1);
+ }
+ gnutls_x509_crt_deinit(issuer);
+
+ if (debug)
+ printf("\tCleanup...");
+
+ gnutls_x509_trust_list_deinit(tl, 0);
+ gnutls_x509_crt_deinit(ca);
+ for (j = 0; chains[idx].chain[j]; j++)
+ gnutls_x509_crt_deinit(certs[j]);
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_global_deinit();
+
+ if (debug)
+ printf("Exit status...%d\n", exit_val);
+ remove(CONFIG);
+
+ exit(exit_val);
+}
diff --git a/tests/pkcs11/pkcs11-is-known.c b/tests/pkcs11/pkcs11-is-known.c
new file mode 100644
index 0000000000..99e946aab7
--- /dev/null
+++ b/tests/pkcs11/pkcs11-is-known.c
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ *
+ * Author: Simon Josefsson, Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/x509-ext.h>
+#include <assert.h>
+
+#include "../utils.h"
+#include "softhsm.h"
+
+#define MAX_CHAIN 16
+
+#define OBJ_URL SOFTHSM_URL";object=test-ca0;object-type=cert"
+#define CONFIG "softhsm-issuer2.config"
+
+/* These CAs have the same DN */
+static const char *ca_list[MAX_CHAIN] = {
+"-----BEGIN CERTIFICATE-----\n"
+"MIIHSjCCBjKgAwIBAgIKYRHt9wABAAAAFTANBgkqhkiG9w0BAQUFADBSMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIFBvbGljeSBDQTAeFw0xMzAyMDQyMTUyMThaFw0x\n"
+"ODA1MjQxOTU5MzlaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw\n"
+"b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgSW50cmFuZXQgQmFzaWMgSXNzdWluZyBD\n"
+"QSAyQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALn3ogjraWSmK5Wb\n"
+"/4e9mENA1F36FBVemaG7L93ZhRRXq4UV0PQM5/4TOe9KAaOlX+a2cuULeeUtN9Rk\n"
+"V/nHAVzSWlqc/NTMJfuI/1AD7ICNejQFYLxDMXGjR7eAHtiMz0iTMp9u6YTw4WXh\n"
+"WffqTPiqUZ6DEWsMic9dM9yw/JqzycKClLcTD1OCvtw7Fx4tNTu6/ngrYJcTo29e\n"
+"BBh/DupgtgnYPYuExEkHmucb4VIDdjfRkPo/BdNqrUSYfYqnUDj5mH+hPzIgppsZ\n"
+"Rw0S5PUZGuC1f+Zok+4vZPR+hGG3Pdm2LTUEWSnurlhyfBoM+0yxeHsmL9aHU7zt\n"
+"EIzVmKUCAwEAAaOCBBwwggQYMBIGCSsGAQQBgjcVAQQFAgMCAAIwIwYJKwYBBAGC\n"
+"NxUCBBYEFMqHyYZOx6LYwRwZ+5vjOyIl9hENMB0GA1UdDgQWBBQ4Y3b6tgU6qVlP\n"
+"SoeNoIO3fpE6CzAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC\n"
+"AYYwEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBRp6zCRHAOAgE4RFYhG\n"
+"pOJBmtNpHzCCAaIGA1UdHwSCAZkwggGVMIIBkaCCAY2gggGJhlFodHRwOi8vd3d3\n"
+"LmludGVsLmNvbS9yZXBvc2l0b3J5L0NSTC9JbnRlbCUyMEludHJhbmV0JTIwQmFz\n"
+"aWMlMjBQb2xpY3klMjBDQSgxKS5jcmyGWmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuaW50\n"
+"ZWwuY29tL3JlcG9zaXRvcnkvQ1JML0ludGVsJTIwSW50cmFuZXQlMjBCYXNpYyUy\n"
+"MFBvbGljeSUyMENBKDEpLmNybIaB12xkYXA6Ly8vQ049SW50ZWwlMjBJbnRyYW5l\n"
+"dCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSksQ049bWNzaWJwY2EsQ049Q0RQLENO\n"
+"PVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3Vy\n"
+"YXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y2VydGlmaWNhdGVSZXZvY2F0\n"
+"aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MIIB\n"
+"uQYIKwYBBQUHAQEEggGrMIIBpzBmBggrBgEFBQcwAoZaaHR0cDovL3d3dy5pbnRl\n"
+"bC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJbnRyYW5ldCUy\n"
+"MEJhc2ljJTIwUG9saWN5JTIwQ0EoMSkuY3J0MG8GCCsGAQUFBzAChmNodHRwOi8v\n"
+"Y2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L2NlcnRpZmljYXRlcy9J\n"
+"bnRlbCUyMEludHJhbmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgxKS5jcnQwgcsG\n"
+"CCsGAQUFBzAChoG+bGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0JTIwQmFzaWMl\n"
+"MjBQb2xpY3klMjBDQSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMs\n"
+"Q049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jb3JwLERDPWludGVsLERD\n"
+"PWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNhdGlv\n"
+"bkF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAQEAsj8cHt2jSAmnIGulE9jXooAc\n"
+"qH2xehlI+ko/al+nDnBzbjDYYjVS52XitYg8JGo6j72ijiGlGb/03FcQJRBZmUH6\n"
+"znktx2rGTm4IdjL8quhvHthlzXXCozL8GMeeOuZ5rzHlhapKx764a5RuZtyx89uS\n"
+"9cECon6oLGesXjFJ8Xrq6ecHZrQwJUpmvZalwvloKACAWqBh8yV12WDnUNZhtp8N\n"
+"8rqeJZoy/lXGnTxsSSodO/5Y/CxYJM4W6u4WgvXNJSjO/0qWvb64S+pVLjBzwI+Y\n"
+"X6oLqmBovRp1lGPOLjkXZi3EKDR8DmzhtpJq2677RtYowewnFedQ+exH9cXoJw==\n"
+"-----END CERTIFICATE-----",
+"-----BEGIN CERTIFICATE-----\n"
+"MIIHSjCCBjKgAwIBAgIKYRXxrQABAAAAETANBgkqhkiG9w0BAQUFADBSMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIFBvbGljeSBDQTAeFw0wOTA1MTUxODQyNDVaFw0x\n"
+"NTA1MTUxODUyNDVaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw\n"
+"b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgSW50cmFuZXQgQmFzaWMgSXNzdWluZyBD\n"
+"QSAyQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbJOXtXYgfyoch6\n"
+"ip5SSjijOXvpIjBxbTl5EGH/VYHmpM2O6SRlKh/uy77QS9m84sRWCJLr8cWwX9oH\n"
+"qSmIylgcWvDpVNHx4v506DTTrbK0sbYRQYXRajOzJKeTt7NLeLrngyl45FrI9VAT\n"
+"3yqp/2BCG1dUwcBha3dB2UbTkFOMt9o/gqoL6KvgswYMs/oGc/OIjeozdYuhnBT2\n"
+"YlT9Ge5pfhOJWXh4DJbxnTmWwRUKq0MXFn0S00KQ/BZOTkc/5DibUmbmMrYi8ra4\n"
+"Z2bpnoTq0WNA99O2Lk8IgmkqPdi6HwZwKCE/x01qwP8zo76rvN8sbW9pj2WzS1WF\n"
+"tSDPeZECAwEAAaOCBBwwggQYMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE\n"
+"FPwbdyds7Cm03lobLKmI6q59npi+MAsGA1UdDwQEAwIBhjASBgkrBgEEAYI3FQEE\n"
+"BQIDAQABMCMGCSsGAQQBgjcVAgQWBBRT1n27C6cZL4QFHaUX2nFSCPxhtTAZBgkr\n"
+"BgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAfBgNVHSMEGDAWgBRp6zCRHAOAgE4RFYhG\n"
+"pOJBmtNpHzCCAaIGA1UdHwSCAZkwggGVMIIBkaCCAY2gggGJhlFodHRwOi8vd3d3\n"
+"LmludGVsLmNvbS9yZXBvc2l0b3J5L0NSTC9JbnRlbCUyMEludHJhbmV0JTIwQmFz\n"
+"aWMlMjBQb2xpY3klMjBDQSgxKS5jcmyGWmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuaW50\n"
+"ZWwuY29tL3JlcG9zaXRvcnkvQ1JML0ludGVsJTIwSW50cmFuZXQlMjBCYXNpYyUy\n"
+"MFBvbGljeSUyMENBKDEpLmNybIaB12xkYXA6Ly8vQ049SW50ZWwlMjBJbnRyYW5l\n"
+"dCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSksQ049bWNzaWJwY2EsQ049Q0RQLENO\n"
+"PVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3Vy\n"
+"YXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y2VydGlmaWNhdGVSZXZvY2F0\n"
+"aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MIIB\n"
+"uQYIKwYBBQUHAQEEggGrMIIBpzBmBggrBgEFBQcwAoZaaHR0cDovL3d3dy5pbnRl\n"
+"bC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJbnRyYW5ldCUy\n"
+"MEJhc2ljJTIwUG9saWN5JTIwQ0EoMSkuY3J0MG8GCCsGAQUFBzAChmNodHRwOi8v\n"
+"Y2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L2NlcnRpZmljYXRlcy9J\n"
+"bnRlbCUyMEludHJhbmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgxKS5jcnQwgcsG\n"
+"CCsGAQUFBzAChoG+bGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0JTIwQmFzaWMl\n"
+"MjBQb2xpY3klMjBDQSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMs\n"
+"Q049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jb3JwLERDPWludGVsLERD\n"
+"PWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNhdGlv\n"
+"bkF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAQEArlAkrJXyMCssqAJT3PqnY7wt\n"
+"sirq1fTMrVrHdmkpBKDXBQnDcTW1zfZtOPV/QDm3UsFwDBbGq+j/7U9qZ1zYHkv+\n"
+"wrBpeFM6dlca/sgegGGAhYnQQwmlSzNXCKHMBltMjT61X8rVjyt1XJnucgat9rnT\n"
+"2j8pztqoViVnORsGfT6DDB/bz/6bFKw4FMp1wDaJI7dKh5NUggvH36owTWI7JUvq\n"
+"yJ8OI2qmjXrlqGexfwvltIkEk8xzuMIHWQoR8sERL2qf3nb2VYq1s1LbH5uCkZ0l\n"
+"w/xgwFbbwjaGJ3TFOmkVKYU77nXSkfK9EXae0UZRU0WmX4t5NNt8jiL56TPpsw==\n"
+"-----END CERTIFICATE-----\n",
+"-----BEGIN CERTIFICATE-----\n"
+"MIIHIzCCBgugAwIBAgIKYRok3wABAAAADDANBgkqhkiG9w0BAQUFADBSMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIFBvbGljeSBDQTAeFw0wNjA1MjQxOTU2MDFaFw0x\n"
+"MjA1MjQyMDA2MDFaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw\n"
+"b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgSW50cmFuZXQgQmFzaWMgSXNzdWluZyBD\n"
+"QSAyQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANE2pFSB0XqXoRWF\n"
+"N7bzDesBAcTGEqcr6GVA+sMcJ5Vt17S8vGesmO2RgP6I49Q58nIhUnT054arUlOx\n"
+"NKYbAEiVyGOK5zV2mZS4oW2UazfcpsV1uuO3j02UbzX+qcxQdNqoAHxwoB4nRJuU\n"
+"Ijio45jWAssDbD8IKHZpmqRI5wUzbibkWnTZEc0YFO6iF40sNtqVr+uInP07PkQn\n"
+"1Ttkyw6isa5Dhcyq6lTVOjnlj29bFYbZxN1uuDnTpUMVeov8oQv5wLyLrDVd1sMg\n"
+"Njr2oofepZ8KjF3DKCkfsUekCHA9Pr2K/4hStd/nSwvIdNjCjfznqYadkB6wQ99a\n"
+"hTX4uJkCAwEAAaOCA/UwggPxMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE\n"
+"FJunwCR+/af8p76CGTyhUZc3l/4DMAsGA1UdDwQEAwIBhjAQBgkrBgEEAYI3FQEE\n"
+"AwIBADAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAfBgNVHSMEGDAWgBRp6zCR\n"
+"HAOAgE4RFYhGpOJBmtNpHzCCAaIGA1UdHwSCAZkwggGVMIIBkaCCAY2gggGJhlFo\n"
+"dHRwOi8vd3d3LmludGVsLmNvbS9yZXBvc2l0b3J5L0NSTC9JbnRlbCUyMEludHJh\n"
+"bmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgxKS5jcmyGWmh0dHA6Ly9jZXJ0aWZp\n"
+"Y2F0ZXMuaW50ZWwuY29tL3JlcG9zaXRvcnkvQ1JML0ludGVsJTIwSW50cmFuZXQl\n"
+"MjBCYXNpYyUyMFBvbGljeSUyMENBKDEpLmNybIaB12xkYXA6Ly8vQ049SW50ZWwl\n"
+"MjBJbnRyYW5ldCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSksQ049bWNzaWJwY2Es\n"
+"Q049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENO\n"
+"PUNvbmZpZ3VyYXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y2VydGlmaWNh\n"
+"dGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlv\n"
+"blBvaW50MIIBuQYIKwYBBQUHAQEEggGrMIIBpzBmBggrBgEFBQcwAoZaaHR0cDov\n"
+"L3d3dy5pbnRlbC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJ\n"
+"bnRyYW5ldCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSkuY3J0MG8GCCsGAQUFBzAC\n"
+"hmNodHRwOi8vY2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L2NlcnRp\n"
+"ZmljYXRlcy9JbnRlbCUyMEludHJhbmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgx\n"
+"KS5jcnQwgcsGCCsGAQUFBzAChoG+bGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0\n"
+"JTIwQmFzaWMlMjBQb2xpY3klMjBDQSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIw\n"
+"U2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jb3JwLERD\n"
+"PWludGVsLERDPWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2Vy\n"
+"dGlmaWNhdGlvbkF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAQEAe3SmN0lsGF0h\n"
+"zq+NANnUD4YJS31UqreVm4kJv07+9CTBtlB0AVqJ2RcjRosdQmrbhx7R0WwcXSdR\n"
+"QnRGhaoDVRNehKiz3Grp6ehJr9LInhCp6WtOeKRlOSb2xgRDJCtzCi07TuAb9h2I\n"
+"urpmndeA4NEbPYL1GYEBpKYawUcFCq5yTv0YgZXy53DdBDv9ygRWYGEk7/gPgvCu\n"
+"2O1GNs9n25goy+3/aMkHnUyl3MOtiooXJR7eKOEgTPHNe42LQ9KuUz5SoZQN8vSL\n"
+"r49IRDC4dgMkGvsC5h0+ftixQ66ni6QJe6SNcpSZrpW5vBE9J+vtDI0gTyq2SYPo\n"
+"0fiS3V8p4g==\n"
+"-----END CERTIFICATE-----\n",
+NULL};
+
+/* this certificate has the same CN as one of the CAs above */
+static const char same_dn_cert_str[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIIHSjCCBjKgAwIBAgIKYRHt9wABAAAAFTANBgkqhkiG9w0BAQUFADBSMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu\n"
+"dGVsIEludHJhbmV0IEJvc2FjIFBvbGljeSBDQTAeFw0xMzAyMDQyMTUyMThaFw0x\n"
+"ODA1MjQxOTU5MzlaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw\n"
+"b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgSW50cmFuZXQgQmFzaWMgSXNzdWluZyBD\n"
+"QSAyQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALn3ogjraWSmK5Wb\n"
+"/4e9mENA1F36FBVemaG7L93ZhRRXq4UV0PQM5/4TOe9KAaOlX+a2cuULeeUtN9Rk\n"
+"V/nHAVzSWlqc/NTMJfuI/1AD7ICNejQFYLxDMXGjR7eAHtiMz0iTMp9u6YTw4WXh\n"
+"WffqTPiqUZ6DEWsMic9dM9yw/JqzycKClLcTD1OCvtw7Fx4tNTu6/ngrYJcTo29e\n"
+"BBh/DupgtgnYPYuExEkHmucb4VIDdjfRkPo/BdNqrUSYfYqnUDj5mH+hPzIgppsZ\n"
+"Rw0S5PUZGuC1f+Zok+4vZPR+hGG3Pdm2LTUEWSnurlhyfBoM+0yxeHsmL9aHU7zt\n"
+"EIzVmKUCAwEAAaOCBBwwggQYMBIGCSsGAQQBgjcVAQQFAgMCAAIwIwYJKwYBBAGC\n"
+"NxUCBBYEFMqHyYZOx6LYwRwZ+5vjOyIl9hENMB0GA1UdDgQWBBQ4Y3b6tgU6qVlP\n"
+"SoeNoIO3fpE6CzAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC\n"
+"AYYwEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBRp6zCRHAOAgE4RFYhG\n"
+"pOJBmtNpHzCCAaIGA1UdHwSCAZkwggGVMIIBkaCCAY2gggGJhlFodHRwOi8vd3d3\n"
+"LmludGVsLmNvbS9yZXBvc2l0b3J5L1hYWC9JbnRlbCUyMEludHJhbmV0JTIwQmFz\n"
+"aWMlMjBQb2xpY3klMjBDQSgxKS5jcmyGWmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuaW50\n"
+"ZWwuY29tL3JlcG9zaXRvcnkvQ1JML0ludGVsJTIwSW50cmFuZXQlMjBCYXNpYyUy\n"
+"MFBvbGljeSUyMENBKDEpLmNybIaB12xkYXA6Ly8vQ049SW50ZWwlMjBJbnRyYW5l\n"
+"dCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSksQ049bWNzaWJwY2EsQ049Q0RQLENO\n"
+"PVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3Vy\n"
+"YXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y2VydGlmaWNhdGVSZXZvY2F0\n"
+"aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MIIB\n"
+"uQYIKwYBBQUHAQEEggGrMIIBpzBmBggrBgEFBQcwAoZaaHR0cDovL3d3dy5pbnRl\n"
+"bC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJbnRyYW5ldCUy\n"
+"MEJhc2ljJTIwUG9saWN5JTIwQ0EoMSkuY3J0MG8GCCsGAQUFBzAChmNodHRwOi8v\n"
+"Y2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L2NlcnRpZmljYXRlcy9J\n"
+"bnRlbCUyMEludHJhbmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgxKS5jcnQwgcsG\n"
+"CCsGAQUFBzAChoG+bGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0JTIwQmFzaWMl\n"
+"MjBQb2xpY3klMjBDQSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMs\n"
+"Q049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jb3JwLERDPWludGVsLERD\n"
+"PWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNhdGlv\n"
+"bkF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAQEAsj8cHt2jSAmnIGulE9jXooAc\n"
+"qH2xehlI+ko/al+nDnBzbjDYYjVS52XitYg8JGo6j72ijiGlGb/03FcQJRBZmUH6\n"
+"znktx2rGTm4IdjL8quhvHthlzXXCozL8GMeeOuZ5rzHlhapKx764a5RuZtyx89uS\n"
+"9cECon6oLGesXjFJ8Xrq6ecHZrQwJUpmvZalwvloKACAWqBh8yV12WDnUNZhtp8N\n"
+"8rqeJZoy/lXGnTxsSSodO/5Y/CxYJM4W6u4WgvXNJSjO/0qWvb64S+pVLjBzwI+Y\n"
+"X6oLqmBovRp1lGPOLjkXZi3EKDR8DmzhtpJq2677RtYowewnFedQ+exH9cXoJw==\n"
+"-----END CERTIFICATE-----\n";
+
+/* this certificate has the same subject and issuer DNs and serial as one of the CAs above */
+static const char same_issuer_cert_str[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIIHSjCCBjKgAwIBAgIKYRHt9wABAAAAFTANBgkqhkiG9w0BAQUFADBSMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIFBvbGljeSBDQTAeFw0xMzAyMDQyMTUyMThaFw0x\n"
+"ODA1MjQxOTU5MzlaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw\n"
+"b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgSW50cmFuZXQgQmFzaWMgSXNzdWluZyBD\n"
+"QSAyQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALn3ogjraWSmK5Wb\n"
+"/4e9mENA1F36FBVemaG7L93ZhRRXq4UV0PQM5/4TOe9KAaOlX+a2cuULeeUtN9Rk\n"
+"V/nHAVzSWlqc/NTMJfuI/1AD7ICNejQFYLxDMXGjR7eAHtiMz0iTMp9u6YTw4WXh\n"
+"WffqTPiqUZ6DEWsMic9dM9yw/JqzycKClLcTD1OCvtw7Fx4tNTu6/ngrYJcTo29e\n"
+"BBh/DupgtgnYPYuExEkHmucb4VIDdjfRkPo/BdNqrUSYfYqnUDj5mH+hPzIgppsZ\n"
+"Rw0S5PUZGuC1f+Zok+4vZPR+hGG3Pdm2LTUEWSnurlhyfBoM+0yxeHsmL9aHU7zt\n"
+"EIzVmKUCAwEAAaOCBBwwggQYMBIGCSsGAQQBgjcVAQQFAgMCAAIwIwYJKwYBBAGC\n"
+"NxUCBBYEFMqHyYZOx6LYwRwZ+5vjOyIl9hENMB0GA1UdDgQWBBQ4Y3b6tgU6qVlP\n"
+"SoeNoIO3fpE6CzAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC\n"
+"AYYwEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBRp6zCRHAOAgE4RFYhG\n"
+"pOJBmtNpHzCCAaIGA1UdHwSCAZkwggGVMIIBkaCCAY2gggGJhlFodHRwOi8vd3d3\n"
+"LmludGVsLmNvbS9yZXBvc2l0b3J5L1hYWC9JbnRlbCUyMEludHJhbmV0JTIwQmFz\n"
+"aWMlMjBQb2xpY3klMjBDQSgxKS5jcmyGWmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuaW50\n"
+"ZWwuY29tL3JlcG9zaXRvcnkvQ1JML0ludGVsJTIwSW50cmFuZXQlMjBCYXNpYyUy\n"
+"MFBvbGljeSUyMENBKDEpLmNybIaB12xkYXA6Ly8vQ049SW50ZWwlMjBJbnRyYW5l\n"
+"dCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EoMSksQ049bWNzaWJwY2EsQ049Q0RQLENO\n"
+"PVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3Vy\n"
+"YXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y2VydGlmaWNhdGVSZXZvY2F0\n"
+"aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MIIB\n"
+"uQYIKwYBBQUHAQEEggGrMIIBpzBmBggrBgEFBQcwAoZaaHR0cDovL3d3dy5pbnRl\n"
+"bC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJbnRyYW5ldCUy\n"
+"MEJhc2ljJTIwUG9saWN5JTIwQ0EoMSkuY3J0MG8GCCsGAQUFBzAChmNodHRwOi8v\n"
+"Y2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L2NlcnRpZmljYXRlcy9J\n"
+"bnRlbCUyMEludHJhbmV0JTIwQmFzaWMlMjBQb2xpY3klMjBDQSgxKS5jcnQwgcsG\n"
+"CCsGAQUFBzAChoG+bGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0JTIwQmFzaWMl\n"
+"MjBQb2xpY3klMjBDQSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMs\n"
+"Q049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jb3JwLERDPWludGVsLERD\n"
+"PWNvbT9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNhdGlv\n"
+"bkF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAQEAsj8cHt2jSAmnIGulE9jXooAc\n"
+"qH2xehlI+ko/al+nDnBzbjDYYjVS52XitYg8JGo6j72ijiGlGb/03FcQJRBZmUH6\n"
+"znktx2rGTm4IdjL8quhvHthlzXXCozL8GMeeOuZ5rzHlhapKx764a5RuZtyx89uS\n"
+"9cECon6oLGesXjFJ8Xrq6ecHZrQwJUpmvZalwvloKACAWqBh8yV12WDnUNZhtp8N\n"
+"8rqeJZoy/lXGnTxsSSodO/5Y/CxYJM4W6u4WgvXNJSjO/0qWvb64S+pVLjBzwI+Y\n"
+"X6oLqmBovRp1lGPOLjkXZi3EKDR8DmzhtpJq2677RtYowewnFedQ+exH9cXoJw==\n"
+"-----END CERTIFICATE-----\n";
+
+/* this certificate is issued by one of the above */
+static const char intermediate_str[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIIH4DCCBsigAwIBAgIKFpIKYgACAAJ8lTANBgkqhkiG9w0BAQUFADBWMQswCQYD\n"
+"VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xKzApBgNVBAMTIklu\n"
+"dGVsIEludHJhbmV0IEJhc2ljIElzc3VpbmcgQ0EgMkIwHhcNMTQwMTA4MTc0MTM5\n"
+"WhcNMTcwMTA3MTc0MTM5WjB1MQswCQYDVQQGEwJJRTELMAkGA1UEBxMCSVIxGjAY\n"
+"BgNVBAoTEUludGVsIENvcnBvcmF0aW9uMQswCQYDVQQLEwJJVDEWMBQGA1UEAxMN\n"
+"dnBuLmludGVsLmNvbTEYMBYGA1UEAxMPc2NzaXIuaW50ZWwuY29tMIIBIjANBgkq\n"
+"hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi3WoORH5ITJ2lpcgCHex1HBUnmN/bb6s\n"
+"sS1Arm50NEHMlqGfbsdCxq2iodMvrGWvdRAPaf/7Ii1UwUhEzxyKYAXC3KRAgioh\n"
+"C0pvGmAFq1ciDYRhANPlW92lIgkt83WwGtOcES2u36VmUxBfdQe6rO3ldoZHVofY\n"
+"uIG/ubBVLz0NhWMaRYSUzTv/4PKJ4paIS7COUROYsyKwc5wNjTcR2PB7RRW+YHgM\n"
+"FkvqPpLjLAGpHdN+wuPNLlUcyzkZVhhXxvQJ9gc5hw/LLQvbmeiGIZCvOVy3ZSfi\n"
+"cGw2jkbqKcFttVV52Wild3ZigALZtkKuFnGw5DEIfk4EAZhG8eHfFQIDAQABo4IE\n"
+"jzCCBIswCwYDVR0PBAQDAgWgMB0GA1UdDgQWBBR4EAIG7OggvIFAhrB8m0eyhCKV\n"
+"GzAfBgNVHSMEGDAWgBQ4Y3b6tgU6qVlPSoeNoIO3fpE6CzCCAbkGA1UdHwSCAbAw\n"
+"ggGsMIIBqKCCAaSgggGghoHibGRhcDovLy9DTj1JbnRlbCUyMEludHJhbmV0JTIw\n"
+"QmFzaWMlMjBJc3N1aW5nJTIwQ0ElMjAyQigyKSxDTj1BWlNNQ1NJQkVDQTAyLENO\n"
+"PUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1D\n"
+"b25maWd1cmF0aW9uLERDPWNvcnAsREM9aW50ZWwsREM9Y29tP2NlcnRpZmljYXRl\n"
+"UmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Q\n"
+"b2ludIZXaHR0cDovL3d3dy5pbnRlbC5jb20vcmVwb3NpdG9yeS9DUkwvSW50ZWwl\n"
+"MjBJbnRyYW5ldCUyMEJhc2ljJTIwSXNzdWluZyUyMENBJTIwMkIoMikuY3JshmBo\n"
+"dHRwOi8vY2VydGlmaWNhdGVzLmludGVsLmNvbS9yZXBvc2l0b3J5L0NSTC9JbnRl\n"
+"bCUyMEludHJhbmV0JTIwQmFzaWMlMjBJc3N1aW5nJTIwQ0ElMjAyQigyKS5jcmww\n"
+"ggHLBggrBgEFBQcBAQSCAb0wggG5MIHRBggrBgEFBQcwAoaBxGxkYXA6Ly8vQ049\n"
+"SW50ZWwlMjBJbnRyYW5ldCUyMEJhc2ljJTIwSXNzdWluZyUyMENBJTIwMkIsQ049\n"
+"QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNv\n"
+"bmZpZ3VyYXRpb24sREM9Y29ycCxEQz1pbnRlbCxEQz1jb20/Y0FDZXJ0aWZpY2F0\n"
+"ZT9iYXNlP29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwbAYIKwYB\n"
+"BQUHMAKGYGh0dHA6Ly93d3cuaW50ZWwuY29tL3JlcG9zaXRvcnkvY2VydGlmaWNh\n"
+"dGVzL0ludGVsJTIwSW50cmFuZXQlMjBCYXNpYyUyMElzc3VpbmclMjBDQSUyMDJC\n"
+"KDIpLmNydDB1BggrBgEFBQcwAoZpaHR0cDovL2NlcnRpZmljYXRlcy5pbnRlbC5j\n"
+"b20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMvSW50ZWwlMjBJbnRyYW5ldCUyMEJh\n"
+"c2ljJTIwSXNzdWluZyUyMENBJTIwMkIoMikuY3J0MD0GCSsGAQQBgjcVBwQwMC4G\n"
+"JisGAQQBgjcVCIbDjHWEmeVRg/2BKIWOn1OCkcAJZ4eC0UGC37J5AgFkAgERMB0G\n"
+"A1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAnBgkrBgEEAYI3FQoEGjAYMAoG\n"
+"CCsGAQUFBwMCMAoGCCsGAQUFBwMBMCkGA1UdEQQiMCCCD3Njc2lyLmludGVsLmNv\n"
+"bYINdnBuLmludGVsLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEALjO591IHOTt28HZ9\n"
+"+Vm2TJp8EJSgWW3luKFAAPUOxix5FgK7mqNQk1052qV8NCQKqChO64f6kl3R29Pp\n"
+"yv0ALYaxdYZXkxPuts05gwu9caeH9fK6vGTRk5pWygVIsobS2MypCYFs9VftFw5d\n"
+"EPUAOsigQmkBC+k+icYzZDjm4HBGd0mTHwniNsKkkjxSnF4UGH9OYp4+hs9/pWly\n"
+"19X4gVWwuxKB59TOe/tVxHBt57zZA3zYyXG+VPzVmklmYLPxVFcmeUDOjWU3x3Wp\n"
+"0D5YUmvQlsd4+73IYw0BrvB42bQEFDUU/v0u6mwluk1m0LEdm+jlM/YCbrAgA3O8\n"
+"eV1xMQ==\n"
+"-----END CERTIFICATE-----\n";
+
+
+
+/* GnuTLS internally calls time() to find out the current time when
+ verifying certificates. To avoid a time bomb, we hard code the
+ current time. This should work fine on systems where the library
+ call to time is resolved at run-time. */
+static time_t mytime(time_t * t)
+{
+ time_t then = 1412850586;
+
+ if (t)
+ *t = then;
+
+ return then;
+}
+
+#define PIN "1234"
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+static
+int pin_func(void* userdata, int attempt, const char* url, const char *label,
+ unsigned flags, char *pin, size_t pin_max)
+{
+ if (attempt == 0) {
+ strcpy(pin, PIN);
+ return 0;
+ }
+ return -1;
+}
+
+void doit(void)
+{
+ char buf[128];
+ int exit_val = 0;
+ int ret;
+ unsigned j;
+ const char *lib, *bin;
+ gnutls_x509_crt_t issuer = NULL;
+ gnutls_x509_trust_list_t tl;
+ gnutls_x509_crt_t certs[MAX_CHAIN];
+ gnutls_x509_crt_t intermediate, same_dn, same_issuer;
+ gnutls_datum_t tmp;
+
+ /* The overloading of time() seems to work in linux (ELF?)
+ * systems only. Disable it on windows.
+ */
+#ifdef _WIN32
+ exit(77);
+#endif
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ gnutls_global_set_time_function(mytime);
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ set_softhsm_conf(CONFIG);
+ snprintf(buf, sizeof(buf), "%s --init-token --slot 0 --label test --so-pin "PIN" --pin "PIN, bin);
+ system(buf);
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ for (j = 0; ca_list[j]; j++) {
+ if (debug > 2)
+ printf("\tAdding certificate %d...",
+ (int) j);
+
+ ret = gnutls_x509_crt_init(&certs[j]);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_init[%d,%d]: %s\n",
+ (int) 3, (int) j,
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) ca_list[j];
+ tmp.size = strlen(ca_list[j]);
+
+ ret =
+ gnutls_x509_crt_import(certs[j], &tmp,
+ GNUTLS_X509_FMT_PEM);
+ if (debug > 2)
+ printf("done\n");
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_import[%d]: %s\n",
+ (int) j,
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_print(certs[j],
+ GNUTLS_CRT_PRINT_ONELINE,
+ &tmp);
+ if (debug)
+ printf("\tCertificate %d: %.*s\n", (int) j,
+ tmp.size, tmp.data);
+ gnutls_free(tmp.data);
+ }
+
+ if (debug > 2)
+ printf("\tAdding intermediate certificate...");
+
+ ret = gnutls_x509_crt_init(&intermediate);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) intermediate_str;
+ tmp.size = strlen(intermediate_str);
+
+ ret =
+ gnutls_x509_crt_import(intermediate, &tmp, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (debug > 2)
+ printf("done\n");
+
+ gnutls_x509_crt_print(intermediate, GNUTLS_CRT_PRINT_ONELINE, &tmp);
+ if (debug)
+ printf("\tIntermediate Certificate: %.*s\n", tmp.size,
+ tmp.data);
+ gnutls_free(tmp.data);
+
+ assert(gnutls_x509_crt_init(&same_dn)>=0);
+ assert(gnutls_x509_crt_init(&same_issuer)>=0);
+
+ tmp.data = (unsigned char *) same_issuer_cert_str;
+ tmp.size = strlen(same_issuer_cert_str);
+
+ ret =
+ gnutls_x509_crt_import(same_dn, &tmp, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ tmp.data = (unsigned char *) same_dn_cert_str;
+ tmp.size = strlen(same_dn_cert_str);
+
+ ret =
+ gnutls_x509_crt_import(same_issuer, &tmp, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (debug)
+ printf("\tVerifying...");
+
+ /* initialize softhsm token */
+ ret = gnutls_pkcs11_token_init(SOFTHSM_URL, PIN, "test");
+ if (ret < 0) {
+ fail("gnutls_pkcs11_token_init\n");
+ exit(1);
+ }
+
+ /* write CA certificate to softhsm */
+ for (j = 0; ca_list[j]; j++) {
+ char name[64];
+ snprintf(name, sizeof(name), "test-ca%d", j);
+ ret = gnutls_pkcs11_copy_x509_crt(SOFTHSM_URL, certs[j], name, GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED|GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO);
+ if (ret < 0) {
+ /* FIXME: this is a known softhsm v2.0.0 bug - remove this once our testsuite is updated */
+ fail_ignore("gnutls_pkcs11_copy_x509_crt: %s\n", gnutls_strerror(ret));
+ }
+ }
+
+
+ /* try to extract an issuer when using an object URL
+ */
+ gnutls_x509_trust_list_init(&tl, 0);
+
+ ret = gnutls_x509_trust_list_add_trust_file(tl, OBJ_URL, NULL, 0, 0, 0);
+ if (ret != 1) {
+ fail("gnutls_x509_trust_list_add_trust_file (with expl. object 0): %d\n", ret);
+ exit(1);
+ }
+
+ /* extract the issuer of the certificate */
+ ret = gnutls_x509_trust_list_get_issuer(tl, intermediate, &issuer, GNUTLS_TL_GET_COPY);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_get_issuer (with expl. object) should have succeeded\n");
+ exit(1);
+ }
+ gnutls_x509_crt_deinit(issuer);
+
+ gnutls_x509_trust_list_deinit(tl, 1);
+
+
+
+ /* Try to extract issuers using PKCS #11 token URL
+ */
+ gnutls_x509_trust_list_init(&tl, 0);
+
+ ret = gnutls_x509_trust_list_add_trust_file(tl, SOFTHSM_URL, NULL, 0, 0, 0);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_add_trust_file\n");
+ exit(1);
+ }
+
+ /* extract the issuer of the certificate */
+ ret = gnutls_x509_trust_list_get_issuer(tl, intermediate, &issuer, GNUTLS_TL_GET_COPY);
+ if (ret < 0) {
+ fail("gnutls_x509_trust_list_get_issuer should have succeeded\n");
+ exit(1);
+ }
+ gnutls_x509_crt_deinit(issuer);
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, certs[2], GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - 0\n");
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, certs[0], GNUTLS_PKCS11_OBJ_FLAG_COMPARE|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - 0\n");
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, certs[1], GNUTLS_PKCS11_OBJ_FLAG_COMPARE|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - 0\n");
+ exit(1);
+ }
+
+ /* we should find a certificate with the same DN */
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_dn, 0);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - did not get a known cert\n");
+ exit(1);
+ }
+
+ /* we should find a certificate with the same issuer DN + serial number */
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_issuer, 0);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - did not get a known cert\n");
+ exit(1);
+ }
+
+ /* these are invalid certificates but their key matches existing keys, the following should work */
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_dn, GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - did not find a cert that does match key\n");
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_issuer, GNUTLS_PKCS11_OBJ_FLAG_COMPARE_KEY|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - did not find a cert that does match key\n");
+ exit(1);
+ }
+
+
+ /* The following check whether the RETRIEVE_TRUSTED implies compare of the certificate */
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_dn, GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret != 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - found a cert that doesn't match\n");
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_issuer, GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret != 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - found a cert that doesn't match\n");
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_dn, GNUTLS_PKCS11_OBJ_FLAG_COMPARE|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret != 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - found a cert that doesn't match\n");
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_issuer, GNUTLS_PKCS11_OBJ_FLAG_COMPARE|GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED);
+ if (ret != 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - found a cert that doesn't match\n");
+ exit(1);
+ }
+
+ gnutls_x509_trust_list_deinit(tl, 1);
+
+ /* deinit */
+ if (debug)
+ printf("\tCleanup...");
+
+ gnutls_x509_crt_deinit(intermediate);
+ gnutls_x509_crt_deinit(same_dn);
+ gnutls_x509_crt_deinit(same_issuer);
+ for (j = 0; ca_list[j]; j++) {
+ gnutls_x509_crt_deinit(certs[j]);
+ }
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_global_deinit();
+
+ if (debug)
+ printf("Exit status...%d\n", exit_val);
+ remove(CONFIG);
+
+ exit(exit_val);
+}
diff --git a/tests/pkcs11/pkcs11-privkey.c b/tests/pkcs11/pkcs11-privkey.c
new file mode 100644
index 0000000000..714614d997
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2014 Nikos Mavrogiannopoulos
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/x509-ext.h>
+
+#include "../utils.h"
+#include "softhsm.h"
+
+/* Tests whether gnutls_certificate_set_x509_key_file2() will utilize
+ * the provided password as PIN when PKCS #11 keys are imported */
+
+#define CONFIG_NAME "softhsm-privkey"
+#define CONFIG CONFIG_NAME".config"
+
+static unsigned char server_cert_pem[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICdDCCAd2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQDEwJDQTEL\n"
+"MAkGA1UEBhMCQ1owIhgPMjAxMzExMTAwODI1MjdaGA8yMDIwMTIxMzA4MjUyN1ow\n"
+"HjEPMA0GA1UEAxMGQ2xpZW50MQswCQYDVQQGEwJDWjCBnzANBgkqhkiG9w0BAQEF\n"
+"AAOBjQAwgYkCgYEAvQRIzvKyhr3tqmB4Pe+91DWSFayaNtcrDIT597bhxugVYW8o\n"
+"jB206kx5aknAMA3PQGYcGqkLrt+nsJcmOIXDZsC6P4zeOSsF1PPhDAoX3bkUr2lF\n"
+"MEt374eKdg1yvyhRxt4DOR6aD4gkC7fVtaYdgV6yXpJGMHV05LBIgQ7QtykCAwEA\n"
+"AaOBwTCBvjAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMCMBgGA1Ud\n"
+"EQQRMA+BDW5vbmVAbm9uZS5vcmcwDwYDVR0PAQH/BAUDAweAADAdBgNVHQ4EFgQU\n"
+"Dbinh11GaaJcTyOpmxPYuttsiGowHwYDVR0jBBgwFoAUEg7aURJAVq70HG3MobA9\n"
+"KGF+MwEwLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDovL3d3dy5nZXRjcmwuY3JsL2dl\n"
+"dGNybC8wDQYJKoZIhvcNAQELBQADgYEAN/Henso+5zzuFQWTpJXlUsWtRQAFhRY3\n"
+"WVt3xtnyPs4pF/LKBp3Ov0GLGBkz5YlyJGFNESSyUviMsH7g7rJM8i7Bph6BQTE9\n"
+"XdqbZPc0opfms4EHjmlXj5HQ0f0yoxHnLk43CR+vmbn0JPuurnEKAwjznAJR8GxI\n"
+"R2MRyMxdGqs=\n"
+"-----END CERTIFICATE-----\n";
+
+const gnutls_datum_t server_cert = { server_cert_pem,
+ sizeof(server_cert_pem)
+};
+
+static unsigned char server_key_pem[] =
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXQIBAAKBgQC9BEjO8rKGve2qYHg9773UNZIVrJo21ysMhPn3tuHG6BVhbyiM\n"
+"HbTqTHlqScAwDc9AZhwaqQuu36ewlyY4hcNmwLo/jN45KwXU8+EMChfduRSvaUUw\n"
+"S3fvh4p2DXK/KFHG3gM5HpoPiCQLt9W1ph2BXrJekkYwdXTksEiBDtC3KQIDAQAB\n"
+"AoGBAKXrseIAB5jh9lPeNQ7heXhjwiXGiuTjAkYOIMNDRXPuXH5YLna4yQv3L4mO\n"
+"zecg6DI2sCrzA29xoukP9ZweR4RUK2cS4/QggH9UgWP0QUpvj4nogyRkh7UrWyVV\n"
+"xbboHcmgqWgNLR8GrEZqlpOWFiT+f+QAx783/khvP5QLNp6BAkEA3YvvqfPpepdv\n"
+"UC/Uk/8LbVK0LGTSu2ynyl1fMbos9lkJNFdfPM31K6DHeqziIGSoWCSjAsN/e8V7\n"
+"MU7egWtI+QJBANppSlO+PTYHWKeOWE7NkM1yVHxAiav9Oott0JywAH8RarfyTuCB\n"
+"iyMJP8Rv920GsciDY4dyx0MBJF0tiH+5G7ECQQDQbU5UPbxyMPXwIo+DjHZbq2sG\n"
+"OPRoj5hrsdxVFCoouSsHqwtWUQ1Otjv1FaDHiOs3wX/6oaHV97wmb2S1rRFBAkAq\n"
+"prELFXVinaCkZ9m62c3TMOZqtTetTHAoVjOMxZnzNnV+omTg1qtTFjVLqQnKUqpZ\n"
+"G79N7g4XeZueTov/VSihAkAwGeDXvQ8NlrBlZACCKp1sUqaJptuJ438Qwztbl3Pq\n"
+"E6/8TD5yXtrLt9S2LNAFw1i7LVksUB8IbQNTuuwV7LYI\n"
+"-----END RSA PRIVATE KEY-----\n";
+
+const gnutls_datum_t server_key = { server_key_pem,
+ sizeof(server_key_pem)
+};
+
+
+/* GnuTLS internally calls time() to find out the current time when
+ verifying certificates. To avoid a time bomb, we hard code the
+ current time. This should work fine on systems where the library
+ call to time is resolved at run-time. */
+static time_t mytime(time_t * t)
+{
+ time_t then = 1412850586;
+
+ if (t)
+ *t = then;
+
+ return then;
+}
+
+#define PIN "1234"
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+static
+int pin_func(void* userdata, int attempt, const char* url, const char *label,
+ unsigned flags, char *pin, size_t pin_max)
+{
+ if (attempt == 0) {
+ strcpy(pin, PIN);
+ return 0;
+ }
+ return -1;
+}
+
+void doit(void)
+{
+ char buf[128];
+ int exit_val = 0;
+ int ret;
+ const char *lib, *bin;
+ gnutls_x509_crt_t crt;
+ gnutls_x509_privkey_t key;
+ gnutls_certificate_credentials_t cred;
+ gnutls_datum_t tmp;
+
+ /* The overloading of time() seems to work in linux (ELF?)
+ * systems only. Disable it on windows.
+ */
+#ifdef _WIN32
+ exit(77);
+#endif
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ gnutls_global_set_time_function(mytime);
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ set_softhsm_conf(CONFIG);
+ snprintf(buf, sizeof(buf), "%s --init-token --slot 0 --label test --so-pin "PIN" --pin "PIN, bin);
+ system(buf);
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret =
+ gnutls_x509_crt_import(crt, &server_cert,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (debug) {
+ gnutls_x509_crt_print(crt,
+ GNUTLS_CRT_PRINT_ONELINE,
+ &tmp);
+
+ printf("\tCertificate: %.*s\n",
+ tmp.size, tmp.data);
+ gnutls_free(tmp.data);
+ }
+
+ ret = gnutls_x509_privkey_init(&key);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_privkey_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret =
+ gnutls_x509_privkey_import(key, &server_key,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_privkey_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ /* initialize softhsm token */
+ ret = gnutls_pkcs11_token_init(SOFTHSM_URL, PIN, "test");
+ if (ret < 0) {
+ fail("gnutls_pkcs11_token_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_token_set_pin(SOFTHSM_URL, NULL, PIN, GNUTLS_PIN_USER);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_token_set_pin: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_copy_x509_crt(SOFTHSM_URL, crt, "cert",
+ GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE|GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_x509_crt: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_copy_x509_privkey(SOFTHSM_URL, key, "cert", GNUTLS_KEY_DIGITAL_SIGNATURE|GNUTLS_KEY_KEY_ENCIPHERMENT,
+ GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE|GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE|GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_x509_privkey: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_deinit(crt);
+ gnutls_x509_privkey_deinit(key);
+ gnutls_pkcs11_set_pin_function(NULL, NULL);
+
+ /* Test whether gnutls_certificate_set_x509_key_file2() would import the keys
+ * when the PIN is provided as parameter */
+
+ ret = gnutls_certificate_allocate_credentials(&cred);
+ if (ret < 0) {
+ fail("gnutls_certificate_allocate_credentials: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_certificate_set_x509_key_file2(cred, SOFTHSM_URL";object=cert;object-type=cert", SOFTHSM_URL";object=cert;object-type=private", 0, PIN, 0);
+ if (ret < 0) {
+ fail("gnutls_certificate_set_x509_key_file2: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_certificate_free_credentials(cred);
+
+ gnutls_global_deinit();
+
+ if (debug)
+ printf("Exit status...%d\n", exit_val);
+ remove(CONFIG);
+
+ exit(exit_val);
+}
diff --git a/tests/pkcs11/pkcs11-pubkey-import-ecdsa.c b/tests/pkcs11/pkcs11-pubkey-import-ecdsa.c
new file mode 100644
index 0000000000..38465c7885
--- /dev/null
+++ b/tests/pkcs11/pkcs11-pubkey-import-ecdsa.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 Nikos Mavrogiannopoulos
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include "softhsm.h"
+
+#define CONFIG_NAME "softhsm-pubkey-import-ecdsa"
+#define CONFIG CONFIG_NAME".config"
+
+#include "pkcs11-pubkey-import.c"
+
+void doit(void)
+{
+#ifdef SOFTHSM_V1
+ exit(77);
+#else
+ success("Testing ECDSA key\n");
+ return try(0);
+#endif
+}
diff --git a/tests/pkcs11/pkcs11-pubkey-import-rsa.c b/tests/pkcs11/pkcs11-pubkey-import-rsa.c
new file mode 100644
index 0000000000..ad0596f3f3
--- /dev/null
+++ b/tests/pkcs11/pkcs11-pubkey-import-rsa.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Nikos Mavrogiannopoulos
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+
+#define CONFIG_NAME "softhsm-pubkey-import-rsa"
+#define CONFIG CONFIG_NAME".config"
+
+#include "pkcs11-pubkey-import.c"
+
+void doit(void)
+{
+ success("Testing RSA key\n");
+ return try(1);
+}
diff --git a/tests/pkcs11/pkcs11-pubkey-import.c b/tests/pkcs11/pkcs11-pubkey-import.c
new file mode 100644
index 0000000000..c286652b20
--- /dev/null
+++ b/tests/pkcs11/pkcs11-pubkey-import.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2015 Nikos Mavrogiannopoulos
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+#include "../utils.h"
+#include "softhsm.h"
+
+/* Tests whether gnutls_pubkey_import_privkey works well for
+ * RSA keys under PKCS #11 */
+
+
+#include "../cert-common.h"
+
+#define PIN "1234"
+
+static const gnutls_datum_t testdata = {(void*)"test test", 9};
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+static
+int pin_func(void* userdata, int attempt, const char* url, const char *label,
+ unsigned flags, char *pin, size_t pin_max)
+{
+ if (attempt == 0) {
+ strcpy(pin, PIN);
+ return 0;
+ }
+ return -1;
+}
+
+void try(int rsa)
+{
+ char buf[128];
+ int ret, pk;
+ const char *lib, *bin;
+ gnutls_x509_crt_t crt;
+ gnutls_x509_privkey_t key;
+ gnutls_datum_t tmp, sig;
+ gnutls_privkey_t pkey;
+ gnutls_pubkey_t pubkey;
+ gnutls_pubkey_t pubkey2;
+
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ set_softhsm_conf(CONFIG);
+ snprintf(buf, sizeof(buf), "%s --init-token --slot 0 --label test --so-pin "PIN" --pin "PIN, bin);
+ system(buf);
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret =
+ gnutls_x509_crt_import(crt, rsa?&server_cert:&server_ecc_cert,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (debug) {
+ gnutls_x509_crt_print(crt,
+ GNUTLS_CRT_PRINT_ONELINE,
+ &tmp);
+
+ printf("\tCertificate: %.*s\n",
+ tmp.size, tmp.data);
+ gnutls_free(tmp.data);
+ }
+
+ ret = gnutls_x509_privkey_init(&key);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_privkey_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret =
+ gnutls_x509_privkey_import(key, rsa?&server_key:&server_ecc_key,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_privkey_import: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ /* initialize softhsm token */
+ ret = gnutls_pkcs11_token_init(SOFTHSM_URL, PIN, "test");
+ if (ret < 0) {
+ fail("gnutls_pkcs11_token_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_token_set_pin(SOFTHSM_URL, NULL, PIN, GNUTLS_PIN_USER);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_token_set_pin: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_copy_x509_crt(SOFTHSM_URL, crt, "cert",
+ GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE|GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_x509_crt: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_copy_x509_privkey(SOFTHSM_URL, key, "cert", GNUTLS_KEY_DIGITAL_SIGNATURE|GNUTLS_KEY_KEY_ENCIPHERMENT,
+ GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE|GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE|GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_x509_privkey: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_deinit(crt);
+ gnutls_x509_privkey_deinit(key);
+ gnutls_pkcs11_set_pin_function(NULL, NULL);
+
+ assert(gnutls_privkey_init(&pkey) == 0);
+
+ ret = gnutls_privkey_import_pkcs11_url(pkey, SOFTHSM_URL";object=cert;object-type=private;pin-value="PIN);
+ if (ret < 0) {
+ fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_pubkey_init(&pubkey) == 0);
+ assert(gnutls_pubkey_import_privkey(pubkey, pkey, 0, 0) == 0);
+
+ pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
+
+ /* check whether privkey and pubkey are operational
+ * by signing and verifying */
+ assert(gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA256, 0, &testdata, &sig) == 0);
+
+ /* verify against the raw pubkey */
+ assert(gnutls_pubkey_init(&pubkey2) == 0);
+ assert(gnutls_pubkey_import_x509_raw(pubkey2, rsa?&server_cert:&server_ecc_cert, GNUTLS_X509_FMT_PEM, 0) == 0);
+ assert(gnutls_pubkey_verify_data2(pubkey2, gnutls_pk_to_sign(pk, GNUTLS_DIG_SHA256), 0, &testdata, &sig) == 0);
+
+ /* verify against the pubkey in PKCS #11 */
+ assert(gnutls_pubkey_verify_data2(pubkey, gnutls_pk_to_sign(pk, GNUTLS_DIG_SHA256), 0, &testdata, &sig) == 0);
+
+ gnutls_free(sig.data);
+
+ gnutls_pubkey_deinit(pubkey2);
+ gnutls_pubkey_deinit(pubkey);
+ gnutls_privkey_deinit(pkey);
+
+ gnutls_global_deinit();
+
+ remove(CONFIG);
+}
+
diff --git a/tests/pkcs11/softhsm.h b/tests/pkcs11/softhsm.h
new file mode 100644
index 0000000000..3ac8167d74
--- /dev/null
+++ b/tests/pkcs11/softhsm.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2014 Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef SOFTHSM_H
+# define SOFTHSM_H
+
+#include <sys/stat.h>
+
+#define SOFTHSM_V2
+
+#ifdef SOFTHSM_V1
+# define SOFTHSM_URL "pkcs11:model=SoftHSM;manufacturer=SoftHSM;serial=1;token=test"
+# define LIB1 "/usr/lib64/pkcs11/libsofthsm.so"
+# define LIB2 "/usr/lib/pkcs11/libsofthsm.so"
+# define LIB3 "/usr/lib/softhsm/libsofthsm.so"
+# define LIB4 "/usr/local/lib/softhsm/libsofthsm.so"
+# define SOFTHSM_BIN1 "/usr/bin/softhsm"
+# define SOFTHSM_BIN2 "/usr/local/bin/softhsm"
+# define SOFTHSM_ENV "SOFTHSM_CONF"
+#else
+# define SOFTHSM_URL "pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;token=test"
+# define LIB1 "/usr/lib64/pkcs11/libsofthsm2.so"
+# define LIB2 "/usr/lib/pkcs11/libsofthsm2.so"
+# define LIB3 "/usr/lib/softhsm/libsofthsm2.so"
+# define LIB4 "/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so"
+# define SOFTHSM_BIN1 "/usr/bin/softhsm2-util"
+# define SOFTHSM_BIN2 "/usr/local/bin/softhsm2-util"
+# define SOFTHSM_ENV "SOFTHSM2_CONF"
+#endif
+
+
+inline static const char *softhsm_lib(void)
+{
+ const char *lib;
+
+ if (access(LIB1, R_OK) == 0) {
+ lib = LIB1;
+ } else if (access(LIB2, R_OK) == 0) {
+ lib = LIB2;
+ } else if (access(LIB3, R_OK) == 0) {
+ lib = LIB3;
+ } else if (access(LIB4, R_OK) == 0) {
+ lib = LIB4;
+ } else {
+ fprintf(stderr, "cannot find softhsm module\n");
+ exit(77);
+ }
+
+ return lib;
+}
+
+inline static const char *softhsm_bin(void)
+{
+ const char *bin;
+
+ if (access(SOFTHSM_BIN1, X_OK) == 0) {
+ bin = SOFTHSM_BIN1;
+ } else if (access(SOFTHSM_BIN2, X_OK) == 0) {
+ bin = SOFTHSM_BIN2;
+ } else {
+ fprintf(stderr, "cannot find softhsm bin\n");
+ exit(77);
+ }
+
+ return bin;
+}
+
+static
+void set_softhsm_conf(const char *config)
+{
+ char buf[128];
+ char db_dir[128];
+ FILE *fp;
+
+ snprintf(db_dir, sizeof(db_dir), "%s.db", config);
+
+ unsetenv(SOFTHSM_ENV);
+ remove(config);
+ fp = fopen(config, "w");
+ if (fp == NULL) {
+ fprintf(stderr, "error writing %s\n", config);
+ exit(1);
+ }
+
+#ifdef SOFTHSM_V1
+ remove(db_dir);
+ snprintf(buf, sizeof(buf), "0:./%s\n", db_dir);
+ fputs(buf, fp);
+#else
+ fputs("directories.tokendir = ", fp);
+ fputs(db_dir, fp);
+ fputs("\n", fp);
+ fputs("objectstore.backend = file\n", fp);
+
+ if (strlen(db_dir) < 6) {
+ fprintf(stderr, "too short name for db: %s\n", db_dir);
+ exit(1);
+ }
+ snprintf(buf, sizeof(buf), "rm -rf %s\n", db_dir);
+ system(buf);
+ mkdir(db_dir, 0755);
+#endif
+ fclose(fp);
+
+ setenv(SOFTHSM_ENV, config, 0);
+}
+
+#endif