summaryrefslogtreecommitdiffstats
path: root/tests/pkcs11
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 07:33:12 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 07:33:12 +0000
commit36082a2fe36ecd800d784ae44c14f1f18c66a7e9 (patch)
tree6c68e0c0097987aff85a01dabddd34b862309a7c /tests/pkcs11
parentInitial commit. (diff)
downloadgnutls28-upstream.tar.xz
gnutls28-upstream.zip
Adding upstream version 3.7.9.upstream/3.7.9upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--tests/pkcs11/gnutls_pcert_list_import_x509_file.c247
-rw-r--r--tests/pkcs11/gnutls_x509_crt_list_import_url.c202
-rw-r--r--tests/pkcs11/list-objects.c150
-rw-r--r--tests/pkcs11/list-tokens.c167
-rw-r--r--tests/pkcs11/pkcs11-cert-import-url-exts.c140
-rw-r--r--tests/pkcs11/pkcs11-cert-import-url4-exts.c165
-rw-r--r--tests/pkcs11/pkcs11-chainverify.c335
-rw-r--r--tests/pkcs11/pkcs11-combo.c431
-rw-r--r--tests/pkcs11/pkcs11-ec-privkey-test.c284
-rw-r--r--tests/pkcs11/pkcs11-eddsa-privkey-test.c299
-rw-r--r--tests/pkcs11/pkcs11-get-exts.c150
-rw-r--r--tests/pkcs11/pkcs11-get-issuer.c302
-rw-r--r--tests/pkcs11/pkcs11-get-raw-issuer-exts.c150
-rw-r--r--tests/pkcs11/pkcs11-import-url-privkey.c132
-rw-r--r--tests/pkcs11/pkcs11-import-with-pin.c220
-rw-r--r--tests/pkcs11/pkcs11-is-known.c656
-rw-r--r--tests/pkcs11/pkcs11-mechanisms.c120
-rw-r--r--tests/pkcs11/pkcs11-mock-ext.h33
-rw-r--r--tests/pkcs11/pkcs11-mock.c2819
-rw-r--r--tests/pkcs11/pkcs11-mock.h99
-rw-r--r--tests/pkcs11/pkcs11-mock2.c108
-rw-r--r--tests/pkcs11/pkcs11-obj-import.c254
-rw-r--r--tests/pkcs11/pkcs11-obj-raw.c188
-rw-r--r--tests/pkcs11/pkcs11-pin-func.c59
-rw-r--r--tests/pkcs11/pkcs11-privkey-always-auth.c200
-rw-r--r--tests/pkcs11/pkcs11-privkey-export.c157
-rw-r--r--tests/pkcs11/pkcs11-privkey-fork-reinit.c166
-rw-r--r--tests/pkcs11/pkcs11-privkey-fork.c162
-rw-r--r--tests/pkcs11/pkcs11-privkey-generate.c173
-rw-r--r--tests/pkcs11/pkcs11-privkey-pthread.c195
-rw-r--r--tests/pkcs11/pkcs11-privkey-safenet-always-auth.c182
-rw-r--r--tests/pkcs11/pkcs11-privkey.c269
-rw-r--r--tests/pkcs11/pkcs11-pubkey-import-ecdsa.c46
-rw-r--r--tests/pkcs11/pkcs11-pubkey-import-rsa.c41
-rw-r--r--tests/pkcs11/pkcs11-pubkey-import.c219
-rw-r--r--tests/pkcs11/pkcs11-rsa-pss-privkey-test.c274
-rw-r--r--tests/pkcs11/pkcs11-token-raw.c175
-rw-r--r--tests/pkcs11/softhsm.h125
-rw-r--r--tests/pkcs11/tls-neg-pkcs11-key.c488
-rw-r--r--tests/pkcs11/tls-neg-pkcs11-no-key.c378
40 files changed, 10960 insertions, 0 deletions
diff --git a/tests/pkcs11/gnutls_pcert_list_import_x509_file.c b/tests/pkcs11/gnutls_pcert_list_import_x509_file.c
new file mode 100644
index 0000000..a4602a4
--- /dev/null
+++ b/tests/pkcs11/gnutls_pcert_list_import_x509_file.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2018 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#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_x509_crt_list_import_url() will return a well
+ * sorted chain, out of values written to softhsm token.
+ */
+
+#define CONFIG_NAME "softhsm-import-url"
+#define CONFIG CONFIG_NAME".config"
+
+#include "../test-chains.h"
+
+#define PIN "123456"
+
+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;
+}
+
+static int comp_cert(gnutls_pcert_st *pcert, unsigned i)
+{
+ int ret;
+ gnutls_datum_t data;
+ gnutls_x509_crt_t crt2;
+
+ if (debug)
+ success("comparing cert %d\n", i);
+
+ ret = gnutls_x509_crt_init(&crt2);
+ if (ret < 0)
+ return -1;
+
+ data.data = (void*)nc_good2[i];
+ data.size = strlen(nc_good2[i]);
+ ret = gnutls_x509_crt_import(crt2, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ return -1;
+
+ if (!gnutls_x509_crt_equals2(crt2, &pcert->cert)) {
+ return -1;
+ }
+
+ gnutls_x509_crt_deinit(crt2);
+
+ return 0;
+}
+
+static void load_cert(const char *url, unsigned i)
+{
+ int ret;
+ gnutls_datum_t data;
+ gnutls_x509_crt_t crt;
+ char name[64];
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0)
+ fail("error: %s\n", gnutls_strerror(ret));
+
+ data.data = (void*)nc_good2[i];
+ data.size = strlen(nc_good2[i]);
+ ret = gnutls_x509_crt_import(crt, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ fail("error[%d]: %s\n", i, gnutls_strerror(ret));
+
+ snprintf(name, sizeof(name), "cert-%d", i);
+ ret = gnutls_pkcs11_copy_x509_crt(url, crt, name, GNUTLS_PKCS11_OBJ_FLAG_LOGIN|GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE);
+ if (ret < 0)
+ fail("error[%d]: %s\n", i, gnutls_strerror(ret));
+
+ success("written cert-%d\n", i);
+
+ gnutls_x509_crt_deinit(crt);
+}
+
+static void load_chain(const char *url)
+{
+ load_cert(url, 1);
+ load_cert(url, 0);
+ load_cert(url, 4);
+ load_cert(url, 2);
+ load_cert(url, 3);
+}
+
+static void write_certs(const char *file)
+{
+ FILE *fp = fopen(file, "w");
+ assert(fp != NULL);
+ fwrite(nc_good2[0], strlen(nc_good2[0]), 1, fp);
+ fwrite(nc_good2[4], strlen(nc_good2[4]), 1, fp);
+ fwrite(nc_good2[1], strlen(nc_good2[1]), 1, fp);
+ fwrite(nc_good2[2], strlen(nc_good2[2]), 1, fp);
+ fwrite(nc_good2[3], strlen(nc_good2[3]), 1, fp);
+ fclose(fp);
+}
+
+void doit(void)
+{
+ char buf[512];
+ int ret;
+ const char *lib, *bin;
+ unsigned int i;
+ gnutls_pcert_st pcerts[16];
+ unsigned int pcerts_size;
+ char file[TMPNAME_SIZE];
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ track_temp_files();
+ 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, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "add_provider: %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));
+ }
+
+ 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));
+ }
+
+ load_chain(SOFTHSM_URL);
+ gnutls_pkcs11_set_pin_function(NULL, NULL);
+
+ success("import from URI\n");
+ pcerts_size = 2;
+ ret = gnutls_pcert_list_import_x509_file(pcerts, &pcerts_size, SOFTHSM_URL";object=cert-0",
+ GNUTLS_X509_FMT_PEM, pin_func, NULL, 0);
+ assert(ret == GNUTLS_E_SHORT_MEMORY_BUFFER);
+
+ pcerts_size = sizeof(pcerts)/sizeof(pcerts[0]);
+ ret = gnutls_pcert_list_import_x509_file(pcerts, &pcerts_size, SOFTHSM_URL";object=cert-0",
+ GNUTLS_X509_FMT_PEM, pin_func, NULL, 0);
+ if (ret < 0)
+ fail("cannot load certs: %s\n", gnutls_strerror(ret));
+
+ assert(pcerts_size == 5);
+
+ for (i=0;i<pcerts_size;i++)
+ assert(comp_cert(&pcerts[i], i)>=0);
+
+ for (i=0;i<pcerts_size;i++)
+ gnutls_pcert_deinit(&pcerts[i]);
+
+ /* Try testing importing from file
+ */
+ success("import from file\n");
+ get_tmpname(file);
+
+ write_certs(file);
+
+ pcerts_size = 2;
+ ret = gnutls_pcert_list_import_x509_file(pcerts, &pcerts_size, file,
+ GNUTLS_X509_FMT_PEM, pin_func, NULL, 0);
+ assert(ret == GNUTLS_E_SHORT_MEMORY_BUFFER);
+
+ pcerts_size = sizeof(pcerts)/sizeof(pcerts[0]);
+ ret = gnutls_pcert_list_import_x509_file(pcerts, &pcerts_size, file,
+ GNUTLS_X509_FMT_PEM, pin_func, NULL, 0);
+ if (ret < 0)
+ fail("cannot load certs: %s\n", gnutls_strerror(ret));
+
+ assert(pcerts_size == 5);
+
+ for (i=0;i<pcerts_size;i++)
+ assert(comp_cert(&pcerts[i], i)>=0);
+
+ for (i=0;i<pcerts_size;i++)
+ gnutls_pcert_deinit(&pcerts[i]);
+
+ gnutls_global_deinit();
+ delete_temp_files();
+
+ remove(CONFIG);
+}
+
diff --git a/tests/pkcs11/gnutls_x509_crt_list_import_url.c b/tests/pkcs11/gnutls_x509_crt_list_import_url.c
new file mode 100644
index 0000000..e395180
--- /dev/null
+++ b/tests/pkcs11/gnutls_x509_crt_list_import_url.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2018 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#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_x509_crt_list_import_url() will return a well
+ * sorted chain, out of values written to softhsm token.
+ */
+
+#define CONFIG_NAME "x509-crt-list-import-url"
+#define CONFIG CONFIG_NAME".config"
+
+#include "../test-chains.h"
+
+#define PIN "123456"
+
+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;
+}
+
+static void comp_cert(gnutls_x509_crt_t crt1, unsigned i)
+{
+ int ret;
+ gnutls_datum_t data;
+ gnutls_x509_crt_t crt2;
+
+ ret = gnutls_x509_crt_init(&crt2);
+ if (ret < 0)
+ fail("error: %s\n", gnutls_strerror(ret));
+
+ data.data = (void*)nc_good2[i];
+ data.size = strlen(nc_good2[i]);
+ ret = gnutls_x509_crt_import(crt2, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ fail("error[%d]: %s\n", i, gnutls_strerror(ret));
+
+ if (!gnutls_x509_crt_equals(crt1, crt2)) {
+ fail("certificate doesn't match chain at %d\n", i);
+ }
+
+ gnutls_x509_crt_deinit(crt2);
+}
+
+static void load_cert(const char *url, unsigned i)
+{
+ int ret;
+ gnutls_datum_t data;
+ gnutls_x509_crt_t crt;
+ char name[64];
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0)
+ fail("error: %s\n", gnutls_strerror(ret));
+
+ data.data = (void*)nc_good2[i];
+ data.size = strlen(nc_good2[i]);
+ ret = gnutls_x509_crt_import(crt, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ fail("error[%d]: %s\n", i, gnutls_strerror(ret));
+
+ snprintf(name, sizeof(name), "cert-%d", i);
+ ret = gnutls_pkcs11_copy_x509_crt(url, crt, name, GNUTLS_PKCS11_OBJ_FLAG_LOGIN|GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE);
+ if (ret < 0)
+ fail("error[%d]: %s\n", i, gnutls_strerror(ret));
+
+ success("written cert-%d\n", i);
+
+ gnutls_x509_crt_deinit(crt);
+}
+
+static void load_chain(const char *url)
+{
+ load_cert(url, 1);
+ load_cert(url, 0);
+ load_cert(url, 4);
+ load_cert(url, 2);
+ load_cert(url, 3);
+}
+
+void doit(void)
+{
+ char buf[512];
+ int ret;
+ const char *lib, *bin;
+ gnutls_x509_crt_t *crts;
+ unsigned int crts_size, i;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ 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, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "add_provider: %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));
+ }
+
+ 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));
+ }
+
+ load_chain(SOFTHSM_URL);
+ gnutls_pkcs11_set_pin_function(NULL, NULL);
+
+ /* try importing without login */
+ ret = gnutls_x509_crt_list_import_url(&crts, &crts_size, SOFTHSM_URL";object=cert-0",
+ pin_func, NULL, 0);
+ if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+ fail("cannot load certs: %s\n", gnutls_strerror(ret));
+
+ /* try importing with login */
+ ret = gnutls_x509_crt_list_import_url(&crts, &crts_size, SOFTHSM_URL";object=cert-0",
+ pin_func, NULL, GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0)
+ fail("cannot load certs: %s\n", gnutls_strerror(ret));
+
+ assert(crts_size == 5);
+
+ for (i=0;i<crts_size;i++)
+ comp_cert(crts[i], i);
+
+ for (i=0;i<crts_size;i++)
+ gnutls_x509_crt_deinit(crts[i]);
+ gnutls_free(crts);
+
+ gnutls_global_deinit();
+ delete_temp_files();
+
+ remove(CONFIG);
+}
+
diff --git a/tests/pkcs11/list-objects.c b/tests/pkcs11/list-objects.c
new file mode 100644
index 0000000..ab30cd5
--- /dev/null
+++ b/tests/pkcs11/list-objects.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016-2017 Red Hat, Inc.
+ *
+ * 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include <getopt.h>
+#define P11_KIT_FUTURE_UNSTABLE_API
+#include <p11-kit/p11-kit.h>
+#include "cert-common.h"
+
+/* lists the registered PKCS#11 modules by p11-kit.
+ */
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+static const char *opt_pin;
+
+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, opt_pin);
+ return 0;
+ }
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ unsigned i;
+ int opt;
+ char *url, *mod;
+ unsigned flags;
+ unsigned obj_flags = 0;
+ int attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL;
+ gnutls_pkcs11_obj_t *crt_list;
+ unsigned int crt_list_size = 0;
+ const char *envvar;
+
+ ret = gnutls_global_init();
+ if (ret != 0) {
+ fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+
+ while((opt = getopt(argc, argv, "o:t:")) != -1) {
+ switch(opt) {
+ case 'o':
+ mod = strdup(optarg);
+ p11_kit_override_system_files(NULL, NULL, mod, mod, NULL);
+ break;
+ case 't':
+ /* specify the object type to list */
+ if (strcmp(optarg, "all") == 0)
+ attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL;
+ else if (strcmp(optarg, "privkey") == 0)
+ attrs = GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY;
+ else {
+ fprintf(stderr, "Unknown object type %s\n", optarg);
+ exit(1);
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown option %c\n", (char)opt);
+ exit(1);
+ }
+ }
+
+ if (optind == argc) {
+ fprintf(stderr, "specify URL\n");
+ exit(1);
+ }
+ url = argv[optind];
+
+ envvar = getenv("GNUTLS_PIN");
+ if (envvar && *envvar != '\0') {
+ opt_pin = envvar;
+ obj_flags |= GNUTLS_PKCS11_OBJ_FLAG_LOGIN;
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ }
+
+ ret = gnutls_pkcs11_token_get_flags(url, &flags);
+ if (ret < 0) {
+ flags = 0;
+ }
+
+ ret =
+ gnutls_pkcs11_obj_list_import_url2(&crt_list, &crt_list_size,
+ url, attrs, obj_flags);
+ if (ret != 0) {
+ fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ for (i = 0; i < crt_list_size; i++) {
+ char *output;
+
+ ret =
+ gnutls_pkcs11_obj_export_url(crt_list[i], 0,
+ &output);
+ if (ret != 0) {
+ fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ fprintf(stdout, "%s\n", output);
+ gnutls_free(output);
+ gnutls_pkcs11_obj_deinit(crt_list[i]);
+ }
+ gnutls_free(crt_list);
+
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/list-tokens.c b/tests/pkcs11/list-tokens.c
new file mode 100644
index 0000000..39cd730
--- /dev/null
+++ b/tests/pkcs11/list-tokens.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2016-2017 Red Hat, Inc.
+ *
+ * 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include <getopt.h>
+#include <assert.h>
+#define P11_KIT_FUTURE_UNSTABLE_API
+#include <p11-kit/p11-kit.h>
+#include "cert-common.h"
+
+/* lists the registered PKCS#11 modules by p11-kit.
+ */
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+int
+_gnutls_pkcs11_token_get_url(unsigned int seq,
+ gnutls_pkcs11_url_type_t detailed, char **url,
+ unsigned flags);
+
+int main(int argc, char **argv)
+{
+ int ret;
+ unsigned i;
+ int opt;
+ char *url, *mod;
+ gnutls_x509_trust_list_t tl;
+ gnutls_x509_crt_t crt;
+ gnutls_pkcs11_privkey_t key;
+ unsigned flag = 1;
+ unsigned int status;
+
+ ret = gnutls_global_init();
+ if (ret != 0) {
+ fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ //gnutls_global_set_log_level(4711);
+
+ while((opt = getopt(argc, argv, "s:o:mvatdp")) != -1) {
+ switch(opt) {
+ case 'o':
+ mod = strdup(optarg);
+ p11_kit_override_system_files(NULL, NULL, mod, mod, NULL);
+ break;
+ case 'm':
+ /* initialize manually - i.e., do no module loading */
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+ break;
+ case 's':
+ /* load module */
+ ret = gnutls_pkcs11_add_provider(optarg, NULL);
+ if (ret != 0) {
+ fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+ break;
+ case 'd':
+ /* when call _gnutls_pkcs11_token_get_url() do proper initialization
+ * if none done */
+ flag = 0;
+ break;
+ case 'p':
+ /* do private key operations */
+ assert(gnutls_pkcs11_privkey_init(&key) >= 0);
+ gnutls_pkcs11_privkey_import_url(key, "pkcs11:", 0);
+ gnutls_pkcs11_privkey_deinit(key);
+ break;
+ case 'a':
+ /* initialize auto - i.e., do module loading */
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
+ if (ret != 0) {
+ fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+ break;
+ case 't':
+ /* do trusted module loading */
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO_TRUSTED, NULL);
+ if (ret != 0) {
+ fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+ break;
+ case 'v':
+ /* do verification which should trigger trusted module loading */
+ assert(gnutls_x509_crt_init(&crt) >= 0);
+ assert(gnutls_x509_crt_import(crt, &ca3_cert, GNUTLS_X509_FMT_PEM) >= 0);
+
+ assert(gnutls_x509_trust_list_init(&tl, 0) >= 0);
+ assert(gnutls_x509_trust_list_add_system_trust(tl, 0, 0) >= 0);
+ gnutls_x509_trust_list_verify_crt2(tl, &crt, 1, NULL, 0, 0, &status, NULL);
+ gnutls_x509_trust_list_deinit(tl, 1);
+ gnutls_x509_crt_deinit(crt);
+ break;
+ default:
+ fprintf(stderr, "Unknown option %c\n", (char)opt);
+ exit(1);
+ }
+ }
+
+
+ for (i=0;;i++) {
+ ret = _gnutls_pkcs11_token_get_url(i, 0, &url, flag);
+ if (ret < 0)
+ break;
+ printf("%s\n", url);
+ free(url);
+ }
+
+ /* try whether these URIs are operational */
+ for (i=0;;i++) {
+ unsigned tflags;
+
+ ret = _gnutls_pkcs11_token_get_url(i, 0, &url, flag);
+ if (ret < 0)
+ break;
+ ret = gnutls_pkcs11_token_get_flags(url, &tflags);
+ if (ret < 0) {
+ fprintf(stderr, "cannot get token %s flags: %s\n", url, gnutls_strerror(ret));
+ exit(1);
+ }
+ free(url);
+ }
+
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/pkcs11-cert-import-url-exts.c b/tests/pkcs11/pkcs11-cert-import-url-exts.c
new file mode 100644
index 0000000..bf806b1
--- /dev/null
+++ b/tests/pkcs11/pkcs11-cert-import-url-exts.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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 <assert.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/x509-ext.h>
+
+#include "utils.h"
+
+/* Tests the certificate extension override in "trusted" PKCS#11 modules */
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+static time_t mytime(time_t * t)
+{
+ time_t then = 1424466893;
+
+ if (t)
+ *t = then;
+
+ return then;
+}
+
+void doit(void)
+{
+ int ret;
+ gnutls_x509_crt_t crt, ocrt;
+ unsigned keyusage;
+ const char *lib;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ gnutls_global_set_time_function(mytime);
+ if (debug) {
+ gnutls_global_set_log_level(4711);
+ success("loading lib %s\n", lib);
+ }
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_x509_crt_init(&crt)>=0);
+ assert(gnutls_x509_crt_init(&ocrt)>=0);
+
+ /* check high level certificate functions */
+ ret = gnutls_x509_crt_import_url(crt, "pkcs11:type=cert;object=cert1", 0);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_import_url(ocrt, "pkcs11:type=cert;object=cert1", GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_equals(crt, ocrt);
+ if (ret != 0) {
+ fail("exported certificates are equal!\n");
+ }
+
+ ret = gnutls_x509_crt_get_ca_status(ocrt, NULL);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (ret == 0) {
+ fail("overridden cert is not a CA!\n");
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_get_key_usage(ocrt, &keyusage, NULL);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (keyusage != (GNUTLS_KEY_KEY_ENCIPHERMENT|GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_KEY_CERT_SIGN)) {
+ fail("Extension does not have the expected key usage!\n");
+ }
+
+ gnutls_x509_crt_deinit(crt);
+ gnutls_x509_crt_deinit(ocrt);
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/pkcs11-cert-import-url4-exts.c b/tests/pkcs11/pkcs11-cert-import-url4-exts.c
new file mode 100644
index 0000000..f9fe82f
--- /dev/null
+++ b/tests/pkcs11/pkcs11-cert-import-url4-exts.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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 <assert.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/x509-ext.h>
+
+#include "utils.h"
+
+/* Tests the certificate extension override in "trusted" PKCS#11 modules */
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+static time_t mytime(time_t * t)
+{
+ time_t then = 1424466893;
+
+ if (t)
+ *t = then;
+
+ return then;
+}
+
+void doit(void)
+{
+ int ret;
+ gnutls_x509_crt_t crt, ocrt;
+ unsigned keyusage;
+ const char *lib;
+ gnutls_pkcs11_obj_t *plist;
+ unsigned int plist_size;
+ gnutls_pkcs11_obj_t *plist2;
+ unsigned int plist2_size, i;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ gnutls_global_set_time_function(mytime);
+ if (debug) {
+ gnutls_global_set_log_level(4711);
+ success("loading lib %s\n", lib);
+ }
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_x509_crt_init(&crt)>=0);
+ assert(gnutls_x509_crt_init(&ocrt)>=0);
+
+ /* check low level certificate import functions */
+ ret = gnutls_pkcs11_obj_list_import_url4(&plist, &plist_size, "pkcs11:type=cert;object=cert1", 0);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_obj_list_import_url4(&plist2, &plist2_size, "pkcs11:type=cert;object=cert1", GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (plist2_size != 1 || plist_size != 1) {
+ fail("could not import certs %d, %d\n", plist_size, plist2_size);
+ }
+
+ ret = gnutls_x509_crt_import_pkcs11(crt, plist[0]);
+ if (ret != 0) {
+ fail("could not import cert!\n");
+ }
+
+ ret = gnutls_x509_crt_import_pkcs11(ocrt, plist2[0]);
+ if (ret != 0) {
+ fail("could not import cert!\n");
+ }
+
+ for (i=0;i<plist_size;i++)
+ gnutls_pkcs11_obj_deinit(plist[i]);
+ for (i=0;i<plist2_size;i++)
+ gnutls_pkcs11_obj_deinit(plist2[i]);
+ gnutls_free(plist);
+ gnutls_free(plist2);
+
+ ret = gnutls_x509_crt_equals(crt, ocrt);
+ if (ret != 0) {
+ fail("exported certificates are equal!\n");
+ }
+
+ ret = gnutls_x509_crt_get_ca_status(ocrt, NULL);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (ret == 0) {
+ fail("overridden cert is not a CA!\n");
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_get_key_usage(ocrt, &keyusage, NULL);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (keyusage != (GNUTLS_KEY_KEY_ENCIPHERMENT|GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_KEY_CERT_SIGN)) {
+ fail("Extension does not have the expected key usage!\n");
+ }
+
+ gnutls_x509_crt_deinit(crt);
+ gnutls_x509_crt_deinit(ocrt);
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/pkcs11-chainverify.c b/tests/pkcs11/pkcs11-chainverify.c
new file mode 100644
index 0000000..0ad2efe
--- /dev/null
+++ b/tests/pkcs11/pkcs11-chainverify.c
@@ -0,0 +1,335 @@
+/*
+ * 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];
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ /* 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);
+
+ if (chains[i].notfips && gnutls_fips140_mode_enabled()) {
+ if (debug)
+ printf("Skipping in FIPS mode...\n");
+ continue;
+ }
+
+ 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) {
+ fail("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 0000000..43189c4
--- /dev/null
+++ b/tests/pkcs11/pkcs11-combo.c
@@ -0,0 +1,431 @@
+/*
+ * 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};
+
+/* 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;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ /* 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-ec-privkey-test.c b/tests/pkcs11/pkcs11-ec-privkey-test.c
new file mode 100644
index 0000000..782ba00
--- /dev/null
+++ b/tests/pkcs11/pkcs11-ec-privkey-test.c
@@ -0,0 +1,284 @@
+/*
+ * 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"
+
+#define CONFIG_NAME "softhsm-privkey-ecdsa-test"
+#define CONFIG CONFIG_NAME".config"
+
+/* Tests whether signing with PKCS#11 may produce signed (invalid)
+ * INTEGER values in DSASignatureValue. */
+
+
+#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;
+}
+
+int _gnutls_decode_ber_rs_raw(const gnutls_datum_t * sig_value, gnutls_datum_t *r, gnutls_datum_t *s);
+
+void doit(void)
+{
+ 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;
+ gnutls_pubkey_t pubkey3;
+ gnutls_pubkey_t pubkey4;
+ unsigned i;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ 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, &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, &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);
+ }
+
+ /* Write pubkey to the card too */
+ assert(gnutls_pubkey_init(&pubkey) == 0);
+ assert(gnutls_pubkey_import_x509(pubkey, crt, 0) == 0);
+
+ ret = gnutls_pkcs11_copy_pubkey(SOFTHSM_URL, pubkey, "cert", NULL,
+ GNUTLS_KEY_DIGITAL_SIGNATURE |
+ GNUTLS_KEY_KEY_ENCIPHERMENT, 0);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_pubkey: %s\n",
+ gnutls_strerror(ret));
+ }
+
+ gnutls_x509_crt_deinit(crt);
+ gnutls_x509_privkey_deinit(key);
+ gnutls_pubkey_deinit(pubkey);
+ 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);
+ }
+
+ /* Try to read the public key with public key URI */
+ assert(gnutls_pubkey_init(&pubkey3) == 0);
+
+
+ ret =
+ gnutls_pubkey_import_pkcs11_url(pubkey3,
+ SOFTHSM_URL
+ ";object=cert;object-type=public;pin-value="
+ PIN, 0);
+ if (ret < 0) {
+ fail("error in gnutls_pubkey_import_pkcs11_url: %s\n", gnutls_strerror(ret));
+ }
+
+ /* Try to read the public key with certificate URI */
+ assert(gnutls_pubkey_init(&pubkey4) == 0);
+
+ ret =
+ gnutls_pubkey_import_pkcs11_url(pubkey4,
+ SOFTHSM_URL
+ ";object=cert;object-type=cert;pin-value="
+ PIN, 0);
+ if (ret < 0) {
+ fail("error in gnutls_pubkey_import_pkcs11_url: %s\n", gnutls_strerror(ret));
+ }
+
+ assert(gnutls_pubkey_init(&pubkey) == 0);
+ assert(gnutls_pubkey_import_privkey(pubkey, pkey, 0, 0) == 0);
+
+ pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
+
+ assert(gnutls_pubkey_init(&pubkey2) == 0);
+ assert(gnutls_pubkey_import_x509_raw(pubkey2, &server_ecc_cert, GNUTLS_X509_FMT_PEM, 0) == 0);
+
+ for (i=0;i<100;i++) {
+ gnutls_datum_t r = {NULL, 0};
+ gnutls_datum_t s = {NULL, 0};
+
+ /* check whether privkey and pubkey are operational
+ * by signing and verifying */
+ assert(gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA256, 0, &testdata, &sig) == 0);
+
+ assert(_gnutls_decode_ber_rs_raw(&sig, &r, &s) == 0);
+ if (r.data[0] >= 0x80) {
+ fail("gnutls_privkey_sign_data resulted to a signed value for R\n");
+ }
+
+ if (s.data[0] >= 0x80) {
+ fail("gnutls_privkey_sign_data resulted to a signed value for S\n");
+ }
+
+ /* verify against the raw pubkey */
+ 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_free(r.data);
+ gnutls_free(s.data);
+ }
+
+ gnutls_pubkey_deinit(pubkey4);
+ gnutls_pubkey_deinit(pubkey3);
+ gnutls_pubkey_deinit(pubkey2);
+ gnutls_pubkey_deinit(pubkey);
+ gnutls_privkey_deinit(pkey);
+
+ gnutls_global_deinit();
+
+ remove(CONFIG);
+}
+
diff --git a/tests/pkcs11/pkcs11-eddsa-privkey-test.c b/tests/pkcs11/pkcs11-eddsa-privkey-test.c
new file mode 100644
index 0000000..ebbfe52
--- /dev/null
+++ b/tests/pkcs11/pkcs11-eddsa-privkey-test.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos, Simo Sorce
+ *
+ * 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#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"
+
+#define CONFIG_NAME "softhsm-privkey-eddsa-test"
+#define CONFIG CONFIG_NAME".config"
+
+/* Tests whether signing with PKCS#11 and EDDSA would
+ * generate valid signatures */
+
+#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;
+}
+
+#define myfail(fmt, ...) \
+ fail("%s (iter %d): "fmt, gnutls_sign_get_name(sigalgo), i, ##__VA_ARGS__)
+
+static unsigned verify_eddsa_presence(void)
+{
+ unsigned i;
+ unsigned long mechanism;
+ int ret;
+
+ i = 0;
+ do {
+ ret = gnutls_pkcs11_token_get_mechanism("pkcs11:", i++, &mechanism);
+ if (ret >= 0 && mechanism == 0x1057 /* CKM_EDDSA */)
+ return 1;
+ } while(ret>=0);
+
+ return 0;
+}
+
+void doit(void)
+{
+ char buf[128];
+ int ret;
+ 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;
+ gnutls_pubkey_t pubkey3;
+ gnutls_pubkey_t pubkey4;
+ unsigned i, sigalgo;
+
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ }
+
+ if (gnutls_fips140_mode_enabled()) {
+ gnutls_global_deinit();
+ return;
+ }
+
+ 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, NULL);
+ if (ret < 0) {
+ fail("gnutls_x509_crt_init: %s\n", gnutls_strerror(ret));
+ }
+
+ if (verify_eddsa_presence() == 0) {
+ fprintf(stderr, "Skipping test as no EDDSA mech is supported\n");
+ exit(77);
+ }
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0)
+ fail("gnutls_x509_crt_init: %s\n", gnutls_strerror(ret));
+
+ ret =
+ gnutls_x509_crt_import(crt, &server_ca3_eddsa_cert,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret));
+
+ 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) {
+ fail("gnutls_x509_privkey_init: %s\n", gnutls_strerror(ret));
+ }
+
+ ret =
+ gnutls_x509_privkey_import(key, &server_ca3_eddsa_key,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fail("gnutls_x509_privkey_import: %s\n", gnutls_strerror(ret));
+ }
+
+ /* 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));
+ }
+
+ 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));
+ }
+
+ 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));
+ }
+
+ 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));
+ }
+
+ /* Write pubkey to the card too */
+ assert(gnutls_pubkey_init(&pubkey) == 0);
+ assert(gnutls_pubkey_import_x509(pubkey, crt, 0) == 0);
+
+ ret = gnutls_pkcs11_copy_pubkey(SOFTHSM_URL, pubkey, "cert", NULL,
+ GNUTLS_KEY_DIGITAL_SIGNATURE |
+ GNUTLS_KEY_KEY_ENCIPHERMENT, 0);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_pubkey: %s\n",
+ gnutls_strerror(ret));
+ }
+
+ gnutls_x509_crt_deinit(crt);
+ gnutls_x509_privkey_deinit(key);
+ gnutls_pubkey_deinit(pubkey);
+ 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) {
+ fail("error in gnutls_privkey_import_pkcs11_url: %s\n", gnutls_strerror(ret));
+ }
+
+ /* Try to read the public key with public key URI */
+ assert(gnutls_pubkey_init(&pubkey3) == 0);
+
+
+ ret =
+ gnutls_pubkey_import_pkcs11_url(pubkey3,
+ SOFTHSM_URL
+ ";object=cert;object-type=public;pin-value="
+ PIN, 0);
+ if (ret < 0) {
+ fail("error in gnutls_pubkey_import_pkcs11_url: %s\n", gnutls_strerror(ret));
+ }
+
+ /* Try to read the public key with certificate URI */
+ assert(gnutls_pubkey_init(&pubkey4) == 0);
+
+ ret =
+ gnutls_pubkey_import_pkcs11_url(pubkey4,
+ SOFTHSM_URL
+ ";object=cert;object-type=cert;pin-value="
+ PIN, 0);
+ if (ret < 0) {
+ fail("error in gnutls_pubkey_import_pkcs11_url: %s\n", gnutls_strerror(ret));
+ }
+
+ assert(gnutls_pubkey_init(&pubkey) == 0);
+ assert(gnutls_pubkey_import_privkey(pubkey, pkey, 0, 0) == 0);
+
+ assert(gnutls_pubkey_init(&pubkey2) == 0);
+ assert(gnutls_pubkey_import_x509_raw
+ (pubkey2, &server_ca3_eddsa_cert, GNUTLS_X509_FMT_PEM, 0) == 0);
+
+ /* this is the algorithm supported by the certificate */
+ sigalgo = GNUTLS_SIGN_EDDSA_ED25519;
+
+ for (i = 0; i < 20; i++) {
+ /* check whether privkey and pubkey are operational
+ * by signing and verifying */
+ ret =
+ gnutls_privkey_sign_data2(pkey, sigalgo, 0,
+ &testdata, &sig);
+ if (ret < 0)
+ myfail("Error signing data %s\n", gnutls_strerror(ret));
+
+ /* verify against the pubkey in PKCS #11 */
+ ret =
+ gnutls_pubkey_verify_data2(pubkey, sigalgo, 0,
+ &testdata, &sig);
+ if (ret < 0)
+ myfail("Error verifying data1: %s\n",
+ gnutls_strerror(ret));
+
+ /* verify against the raw pubkey */
+ ret =
+ gnutls_pubkey_verify_data2(pubkey2, sigalgo, 0,
+ &testdata, &sig);
+ if (ret < 0)
+ myfail("Error verifying data2: %s\n",
+ gnutls_strerror(ret));
+
+ gnutls_free(sig.data);
+ }
+
+ /* TODO is there any sensible way to check the pubkeys are the same? */
+ gnutls_pubkey_deinit(pubkey4);
+ gnutls_pubkey_deinit(pubkey3);
+ gnutls_pubkey_deinit(pubkey2);
+ gnutls_pubkey_deinit(pubkey);
+ gnutls_privkey_deinit(pkey);
+
+ gnutls_global_deinit();
+
+ remove(CONFIG);
+}
diff --git a/tests/pkcs11/pkcs11-get-exts.c b/tests/pkcs11/pkcs11-get-exts.c
new file mode 100644
index 0000000..1d236a6
--- /dev/null
+++ b/tests/pkcs11/pkcs11-get-exts.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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 <assert.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/x509-ext.h>
+
+#include "utils.h"
+
+/* Tests the gnutls_pkcs11_obj_get_exts API */
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+void doit(void)
+{
+ int ret;
+ const char *lib;
+ gnutls_x509_ext_st *exts;
+ unsigned int exts_size, i;
+ gnutls_pkcs11_obj_t obj;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ if (debug) {
+ gnutls_global_set_log_level(4711);
+ success("loading lib %s\n", lib);
+ }
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_pkcs11_obj_init(&obj)>=0);
+
+ /* check extensions */
+ ret = gnutls_pkcs11_obj_import_url(obj, "pkcs11:type=cert;object=cert1", 0);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_obj_get_exts(obj, &exts, &exts_size, 0);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (exts_size != 2) {
+ fail("the expected extensions were not found (found %d)!\n", exts_size);
+ exit(1);
+ }
+
+ if (strcmp(exts[0].oid, "2.5.29.19") != 0) {
+ fail("Found OID for %d: %s\n", 0, exts[0].oid);
+ }
+
+ {
+ unsigned ca;
+ int pathlen;
+ ret = gnutls_x509_ext_import_basic_constraints(&exts[0].data, &ca, &pathlen);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (debug)
+ success("ca: %d/%d\n", ca, pathlen);
+ if (ca != 1) {
+ fail("Extension does not set the CA constraint!\n");
+ }
+ }
+
+ if (strcmp(exts[1].oid, "2.5.29.15") != 0) {
+ fail("Found OID for %d: %s\n", 1, exts[1].oid);
+ }
+
+ {
+ unsigned keyusage;
+ ret = gnutls_x509_ext_import_key_usage(&exts[1].data, &keyusage);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (debug)
+ success("usage: %x\n", keyusage);
+ if (keyusage != (GNUTLS_KEY_KEY_ENCIPHERMENT|GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_KEY_CERT_SIGN)) {
+ fail("Extension does not have the expected key usage!\n");
+ }
+ }
+
+ for (i=0;i<exts_size;i++)
+ gnutls_x509_ext_deinit(&exts[i]);
+ gnutls_free(exts);
+
+ gnutls_pkcs11_obj_deinit(obj);
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/pkcs11-get-issuer.c b/tests/pkcs11/pkcs11-get-issuer.c
new file mode 100644
index 0000000..b4df717
--- /dev/null
+++ b/tests/pkcs11/pkcs11-get-issuer.c
@@ -0,0 +1,302 @@
+/*
+ * 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;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ /* 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-get-raw-issuer-exts.c b/tests/pkcs11/pkcs11-get-raw-issuer-exts.c
new file mode 100644
index 0000000..dec3088
--- /dev/null
+++ b/tests/pkcs11/pkcs11-get-raw-issuer-exts.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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 <assert.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/x509-ext.h>
+
+#include "utils.h"
+
+/* Tests the certificate extension override in "trusted" PKCS#11 modules
+ * when used with gnutls_pkcs11_get_raw_issuer().
+ */
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+static time_t mytime(time_t * t)
+{
+ time_t then = 1424466893;
+
+ if (t)
+ *t = then;
+
+ return then;
+}
+
+void doit(void)
+{
+ int ret;
+ gnutls_x509_crt_t crt, ocrt;
+ unsigned keyusage;
+ const char *lib;
+ gnutls_datum_t issuer = {NULL, 0};
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ gnutls_global_set_time_function(mytime);
+ if (debug) {
+ gnutls_global_set_log_level(4711);
+ success("loading lib %s\n", lib);
+ }
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, "trusted");
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_x509_crt_init(&crt)>=0);
+ assert(gnutls_x509_crt_init(&ocrt)>=0);
+
+ /* check high level certificate functions */
+ ret = gnutls_x509_crt_import_url(crt, "pkcs11:type=cert;object=cert1", 0);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_get_raw_issuer("pkcs11:", crt, &issuer, GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_equals2(crt, &issuer);
+ if (ret != 0) {
+ fail("exported certificates are equal!\n");
+ }
+
+ ret = gnutls_x509_crt_import(ocrt, &issuer, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_get_ca_status(ocrt, NULL);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (ret == 0) {
+ fail("overridden cert is not a CA!\n");
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_get_key_usage(ocrt, &keyusage, NULL);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (keyusage != (GNUTLS_KEY_KEY_ENCIPHERMENT|GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_KEY_CERT_SIGN)) {
+ fail("Extension does not have the expected key usage!\n");
+ }
+
+ gnutls_x509_crt_deinit(crt);
+ gnutls_x509_crt_deinit(ocrt);
+ gnutls_free(issuer.data);
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/pkcs11-import-url-privkey.c b/tests/pkcs11/pkcs11-import-url-privkey.c
new file mode 100644
index 0000000..ded8c9a
--- /dev/null
+++ b/tests/pkcs11/pkcs11-import-url-privkey.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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 "pkcs11-mock-ext.h"
+
+/* Tests the private key import for sensitive keys in the common case and in
+ * some problematic cases. */
+
+#ifdef ALL_CAPS_URI
+#define PURI "PKCS11:"
+#else
+#define PURI "pkcs11:"
+#endif
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+void doit(void)
+{
+ int ret;
+ const char *lib;
+ gnutls_pkcs11_obj_t *obj_list;
+ unsigned int obj_list_size = 0;
+ unsigned int i;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_obj_list_import_url4(&obj_list, &obj_list_size, PURI, GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ for (i=0;i<obj_list_size;i++)
+ gnutls_pkcs11_obj_deinit(obj_list[i]);
+ gnutls_free(obj_list);
+ obj_list_size = 0;
+
+#ifndef _WIN32
+ {
+ void *dl;
+ unsigned int *pflags;
+
+ dl = dlopen(lib, RTLD_NOW);
+ if (dl == NULL) {
+ fail("could not dlopen %s\n", lib);
+ exit(1);
+ }
+
+ pflags = dlsym(dl, "pkcs11_mock_flags");
+ if (pflags == NULL) {
+ fail("could find pkcs11_mock_flags\n");
+ exit(1);
+ }
+
+ *pflags = MOCK_FLAG_BROKEN_GET_ATTRIBUTES;
+
+ ret = gnutls_pkcs11_obj_list_import_url4(&obj_list, &obj_list_size, PURI, GNUTLS_PKCS11_OBJ_FLAG_PRIVKEY);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ for (i=0;i<obj_list_size;i++)
+ gnutls_pkcs11_obj_deinit(obj_list[i]);
+ gnutls_free(obj_list);
+ obj_list_size = 0;
+ }
+#endif
+
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/pkcs11-import-with-pin.c b/tests/pkcs11/pkcs11-import-with-pin.c
new file mode 100644
index 0000000..79cf187
--- /dev/null
+++ b/tests/pkcs11/pkcs11-import-with-pin.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * 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 a protected object is imported with PIN obtained using
+ * pin-value or pin-source. */
+
+#define CONFIG_NAME "softhsm-import-with-pin"
+#define CONFIG CONFIG_NAME".config"
+
+#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;
+}
+
+static void write_pin(const char *file, const char *pin)
+{
+ FILE *fp = fopen(file, "w");
+ assert(fp != NULL);
+ fputs(pin, fp);
+ fclose(fp);
+}
+
+void doit(void)
+{
+ char buf[512];
+ int ret;
+ const char *lib, *bin;
+ gnutls_x509_privkey_t key;
+ gnutls_datum_t sig;
+ gnutls_privkey_t pkey;
+ char file[TMPNAME_SIZE];
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ 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, "add_provider: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ 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_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_privkey_deinit(key);
+ gnutls_pkcs11_set_pin_function(NULL, NULL);
+
+ assert(gnutls_privkey_init(&pkey) == 0);
+
+ /* Test 1
+ * Try importing with wrong pin-value */
+ ret = gnutls_privkey_import_pkcs11_url(pkey, SOFTHSM_URL";object=cert;object-type=private;pin-value=XXXX");
+ if (ret != GNUTLS_E_PKCS11_PIN_ERROR) {
+ fprintf(stderr, "unexpected error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+ gnutls_privkey_deinit(pkey);
+ assert(gnutls_privkey_init(&pkey) == 0);
+
+ /* Test 2
+ * Try importing with pin-value */
+ 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);
+ }
+
+ /* check whether privkey is operational by signing */
+ assert(gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA256, 0, &testdata, &sig) == 0);
+ gnutls_free(sig.data);
+ gnutls_privkey_deinit(pkey);
+
+ /* Test 3
+ * Try importing with wrong pin-source */
+ track_temp_files();
+ get_tmpname(file);
+
+ write_pin(file, "XXXX");
+
+ assert(gnutls_privkey_init(&pkey) == 0);
+ snprintf(buf, sizeof(buf), "%s;object=cert;object-type=private;pin-source=%s", SOFTHSM_URL, file);
+ ret = gnutls_privkey_import_pkcs11_url(pkey, buf);
+ if (ret != GNUTLS_E_PKCS11_PIN_ERROR) {
+ fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_privkey_deinit(pkey);
+
+ /* Test 4
+ * Try importing with pin-source */
+ write_pin(file, PIN);
+
+ assert(gnutls_privkey_init(&pkey) == 0);
+ snprintf(buf, sizeof(buf), "%s;object=cert;object-type=private;pin-source=%s", SOFTHSM_URL, file);
+ ret = gnutls_privkey_import_pkcs11_url(pkey, buf);
+ if (ret < 0) {
+ fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ /* check whether privkey is operational by signing */
+ assert(gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA256, 0, &testdata, &sig) == 0);
+ gnutls_free(sig.data);
+ gnutls_privkey_deinit(pkey);
+
+ gnutls_global_deinit();
+ delete_temp_files();
+
+ remove(CONFIG);
+}
+
diff --git a/tests/pkcs11/pkcs11-is-known.c b/tests/pkcs11/pkcs11-is-known.c
new file mode 100644
index 0000000..95b9c56
--- /dev/null
+++ b/tests/pkcs11/pkcs11-is-known.c
@@ -0,0 +1,656 @@
+/*
+ * 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;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ /* 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) {
+ fail("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);
+ }
+
+#if 0
+ /* test searching invalid certs. the distrusted flag disables any validity check except DN and serial number
+ * matching so it should work - unfortunately works only under p11-kit */
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_dn, GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - did not get a known cert\n");
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_crt_is_known(SOFTHSM_URL, same_issuer, GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_DISTRUSTED);
+ if (ret == 0) {
+ fail("error in gnutls_pkcs11_crt_is_known - did not get a known cert\n");
+ exit(1);
+ }
+#endif
+
+ /* 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 - found a cert that doesn't match\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 - found a cert that doesn't match\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-mechanisms.c b/tests/pkcs11/pkcs11-mechanisms.c
new file mode 100644
index 0000000..c38f6ac
--- /dev/null
+++ b/tests/pkcs11/pkcs11-mechanisms.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2016-2017 Red Hat, Inc.
+ *
+ * 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 <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+#include "utils.h"
+
+/* Tests whether a gnutls_privkey_t will continue to work after
+ * a fork(), when gnutls_pkcs11_reinit() is manually called. */
+
+#if defined(HAVE___REGISTER_ATFORK)
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+void doit(void)
+{
+ int ret;
+ const char *lib;
+ unsigned long mech;
+ unsigned i;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ for (i=0;;i++) {
+ ret = gnutls_pkcs11_token_get_mechanism("pkcs11:", i, &mech);
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+ break;
+ success("mech: %lu\n", mech);
+ ret = gnutls_pkcs11_token_check_mechanism("pkcs11:", mech, NULL, 0, 0);
+ if (ret == 0) {
+ fail("mechanism %ld was reported are supported, but is not found!\n", mech);
+ }
+ }
+ if (debug)
+ printf("done\n\n\n");
+
+ ret = gnutls_pkcs11_token_check_mechanism("pkcs11:", -1, NULL, 0, 0);
+ if (ret != 0)
+ fail("found invalid mechanism1\n");
+
+ ret = gnutls_pkcs11_token_check_mechanism("pkcs11:", -3, NULL, 0, 0);
+ if (ret != 0)
+ fail("found invalid mechanism2\n");
+
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+}
+#else
+void doit(void)
+{
+ exit(77);
+}
+#endif
diff --git a/tests/pkcs11/pkcs11-mock-ext.h b/tests/pkcs11/pkcs11-mock-ext.h
new file mode 100644
index 0000000..277e4a7
--- /dev/null
+++ b/tests/pkcs11/pkcs11-mock-ext.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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
+ */
+
+#ifndef PKCS11_MOCK_EXT_H
+# define PKCS11_MOCK_EXT_H
+
+/* This flag instructs the module to return CKR_OK on sensitive
+ * objects */
+#define MOCK_FLAG_BROKEN_GET_ATTRIBUTES 1
+#define MOCK_FLAG_ALWAYS_AUTH (1<<1)
+/* simulate the safenet HSMs always auth behavior */
+#define MOCK_FLAG_SAFENET_ALWAYS_AUTH (1<<2)
+
+#endif
diff --git a/tests/pkcs11/pkcs11-mock.c b/tests/pkcs11/pkcs11-mock.c
new file mode 100644
index 0000000..0645187
--- /dev/null
+++ b/tests/pkcs11/pkcs11-mock.c
@@ -0,0 +1,2819 @@
+/*
+ * Copyright 2011-2016 The Pkcs11Interop Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Written originally for the Pkcs11Interop project by:
+ * Jaroslav IMRICH <jimrich@jimrich.sk>
+ */
+
+#include "pkcs11-mock.h"
+#include "pkcs11-mock-ext.h"
+#include <string.h>
+#include <stdlib.h>
+
+unsigned int pkcs11_mock_flags = 0;
+
+/* This is a very basic mock PKCS #11 module that will return a given fixed
+ * certificate, and public key for all searches. It will also provide a
+ * CKO_X_CERTIFICATE_EXTENSION so that it can be used as a p11-kit trust
+ * module. */
+
+const char mock_certificate[] =
+ "\x30\x82\x03\x97\x30\x82\x02\x4f\xa0\x03\x02\x01\x02\x02\x04\x4d"
+ "\xa7\x54\x21\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b"
+ "\x05\x00\x30\x32\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42"
+ "\x45\x31\x0f\x30\x0d\x06\x03\x55\x04\x0a\x13\x06\x47\x6e\x75\x54"
+ "\x4c\x53\x31\x12\x30\x10\x06\x03\x55\x04\x03\x13\x09\x6c\x6f\x63"
+ "\x61\x6c\x68\x6f\x73\x74\x30\x1e\x17\x0d\x31\x31\x30\x34\x31\x34"
+ "\x32\x30\x30\x38\x30\x32\x5a\x17\x0d\x33\x38\x30\x38\x32\x39\x32"
+ "\x30\x30\x38\x30\x34\x5a\x30\x32\x31\x0b\x30\x09\x06\x03\x55\x04"
+ "\x06\x13\x02\x42\x45\x31\x0f\x30\x0d\x06\x03\x55\x04\x0a\x13\x06"
+ "\x47\x6e\x75\x54\x4c\x53\x31\x12\x30\x10\x06\x03\x55\x04\x03\x13"
+ "\x09\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x30\x82\x01\x52\x30\x0d"
+ "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01"
+ "\x3f\x00\x30\x82\x01\x3a\x02\x82\x01\x31\x00\xdd\xcf\x97\xd2\xa5"
+ "\x1d\x95\xdd\x86\x18\xd8\xc4\xb9\xad\xa6\x0c\xb4\x9d\xb6\xdc\xfa"
+ "\xdc\x21\xe1\x3a\x62\x34\x07\xe8\x33\xb2\xe8\x97\xee\x2c\x41\xd2"
+ "\x12\xf1\x5f\xed\xe4\x76\xff\x65\x26\x1e\x0c\xc7\x41\x15\x69\x5f"
+ "\x0d\xf9\xad\x89\x14\x8d\xea\xd7\x16\x52\x9a\x47\xc1\xbb\x00\x02"
+ "\xe4\x88\x45\x73\x78\xa4\xae\xdb\x38\xc3\xc6\x07\xd2\x64\x0e\x87"
+ "\xed\x74\x8c\x6b\xc4\xc0\x02\x50\x7c\x4e\xa6\xd1\x58\xe9\xe5\x13"
+ "\x09\xa9\xdb\x5a\xea\xeb\x0f\x06\x80\x5c\x09\xef\x94\xc8\xe9\xfb"
+ "\x37\x2e\x75\xe1\xac\x93\xad\x9b\x37\x13\x4b\x66\x3a\x76\x33\xd8"
+ "\xc4\xd7\x4c\xfb\x61\xc8\x92\x21\x07\xfc\xdf\xa9\x88\x54\xe4\xa3"
+ "\xa9\x47\xd2\x6c\xb8\xe3\x39\x89\x11\x88\x38\x2d\xa2\xdc\x3e\x5e"
+ "\x4a\xa9\xa4\x8e\xd5\x1f\xb2\xd0\xdd\x41\x3c\xda\x10\x68\x9e\x47"
+ "\x1b\x65\x02\xa2\xc5\x28\x73\x02\x83\x03\x09\xfd\xf5\x29\x7e\x97"
+ "\xdc\x2a\x4e\x4b\xaa\x79\x46\x46\x70\x86\x1b\x9b\xb8\xf6\x8a\xbe"
+ "\x29\x87\x7d\x5f\xda\xa5\x97\x6b\xef\xc8\x43\x09\x43\xe2\x1f\x8a"
+ "\x16\x7e\x1d\x50\x5d\xf5\xda\x02\xee\xf2\xc3\x2a\x48\xe6\x6b\x30"
+ "\xea\x02\xd7\xef\xac\x8b\x0c\xb8\xc1\x85\xd8\xbf\x7c\x85\xa8\x1e"
+ "\x83\xbe\x5c\x26\x2e\x79\x7b\x47\xf5\x4a\x3f\x66\x62\x92\xfd\x41"
+ "\x20\xb6\x2c\x00\xf0\x52\xca\x26\x06\x2d\x7c\xcf\x7a\x50\x7d\x0f"
+ "\xcb\xdd\x97\x20\xc8\x6f\xe4\xe0\x50\xf4\xe3\x02\x03\x01\x00\x01"
+ "\xa3\x55\x30\x53\x30\x0c\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x02"
+ "\x30\x00\x30\x13\x06\x03\x55\x1d\x25\x04\x0c\x30\x0a\x06\x08\x2b"
+ "\x06\x01\x05\x05\x07\x03\x01\x30\x0f\x06\x03\x55\x1d\x0f\x01\x01"
+ "\xff\x04\x05\x03\x03\x07\xa0\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04"
+ "\x16\x04\x14\x92\x53\xd6\x71\xb9\xf8\x68\xaa\xb3\x53\xf6\x8d\xf5"
+ "\x39\x45\x66\x9c\xa7\xe5\x31\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7"
+ "\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x31\x00\x98\xbf\x48\x89\xc1"
+ "\xe6\xe6\x15\x13\xcc\xfc\xba\xed\xa0\x89\xe5\x86\x45\x30\x73\x68"
+ "\xb2\x79\x1f\x88\x02\x80\xfb\x2d\xc9\xb8\x21\x55\x8d\xc5\xb7\x56"
+ "\x1b\xcf\xc3\x76\xee\xd0\xf0\xd9\x22\x3a\x63\x92\xc5\x04\x86\x70"
+ "\x1e\x42\x33\x2a\x3b\xc4\x14\x08\xc5\x42\x92\x73\x7c\x3e\x39\xc0"
+ "\xee\x34\xc7\x33\x16\x5f\x93\xae\xcf\x1f\x9a\x30\x09\x51\xfe\x2d"
+ "\x94\x9c\x28\xad\x2a\x7e\xe4\x14\x81\x45\x6b\x0d\xd7\x11\x21\xfc"
+ "\xdb\x27\x17\x74\xb4\xcc\x94\x1a\x6e\x9e\x7b\x58\xa9\xe0\x06\x8d"
+ "\xda\x5f\x60\xe1\xb8\x6f\x28\x68\xb6\x58\xbe\xc5\xac\x36\x47\x37"
+ "\xf6\xa8\x38\x74\x23\x81\xf3\x22\xbe\x61\xff\x08\x08\x87\xeb\xc2"
+ "\x8f\x29\x25\x75\x5d\x4c\xeb\xd5\x09\x28\xab\x7b\x99\xf9\x69\x08"
+ "\xa2\xc6\x02\xd2\x2e\xcd\xfa\xf1\x19\xce\x3f\x44\x6a\xa1\x4b\xa8"
+ "\x56\xd5\x11\xae\x44\xe3\x68\x05\x50\x57\x8d\x72\x0f\xc7\x21\xdb"
+ "\x8f\xa3\x50\x78\x5d\x5a\x39\xcb\x90\x3d\x52\x43\x33\xbf\xea\x89"
+ "\x07\x1a\x92\xcc\x85\x27\xa8\x3d\x34\xb8\x5b\x52\xee\xef\x20\xb9"
+ "\xb6\xff\xea\xc5\x90\xd3\x47\xc5\x51\x90\xe2\xe6\x3e\x52\xb9\x1e"
+ "\x79\x18\xbe\xfd\xe2\x24\xbe\x47\x32\x5a\xb0\x03\x6b\xaa\xdb\xc3"
+ "\xdb\xf6\x60\x44\x08\xb6\x2c\x19\x47\xa2\xf0\x43\x7f\xf0\x07\x97"
+ "\x57\xab\xec\xa0\xb8\x6a\x49\xce\x08\xe6\xc3\x4d\xf2\xa4\xe9\xb8"
+ "\x43\xe7\xf0\x84\xd7\x1a\x72\x14\x5d\x82\x1a";
+
+/* ca == true */
+const char mock_cert_ext1[] = "\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff";
+/* GNUTLS_KEY_ENCIPHER_ONLY | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN */
+const char mock_cert_ext2[] = "\x30\x0f\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x05\x03\x03\x07\x25\x00";
+
+const char mock_pubkey[] =
+ "\x30\x82\x01\x52\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01"
+ "\x01\x05\x00\x03\x82\x01\x3f\x00\x30\x82\x01\x3a\x02\x82\x01\x31"
+ "\x00\xdd\xcf\x97\xd2\xa5\x1d\x95\xdd\x86\x18\xd8\xc4\xb9\xad\xa6"
+ "\x0c\xb4\x9d\xb6\xdc\xfa\xdc\x21\xe1\x3a\x62\x34\x07\xe8\x33\xb2"
+ "\xe8\x97\xee\x2c\x41\xd2\x12\xf1\x5f\xed\xe4\x76\xff\x65\x26\x1e"
+ "\x0c\xc7\x41\x15\x69\x5f\x0d\xf9\xad\x89\x14\x8d\xea\xd7\x16\x52"
+ "\x9a\x47\xc1\xbb\x00\x02\xe4\x88\x45\x73\x78\xa4\xae\xdb\x38\xc3"
+ "\xc6\x07\xd2\x64\x0e\x87\xed\x74\x8c\x6b\xc4\xc0\x02\x50\x7c\x4e"
+ "\xa6\xd1\x58\xe9\xe5\x13\x09\xa9\xdb\x5a\xea\xeb\x0f\x06\x80\x5c"
+ "\x09\xef\x94\xc8\xe9\xfb\x37\x2e\x75\xe1\xac\x93\xad\x9b\x37\x13"
+ "\x4b\x66\x3a\x76\x33\xd8\xc4\xd7\x4c\xfb\x61\xc8\x92\x21\x07\xfc"
+ "\xdf\xa9\x88\x54\xe4\xa3\xa9\x47\xd2\x6c\xb8\xe3\x39\x89\x11\x88"
+ "\x38\x2d\xa2\xdc\x3e\x5e\x4a\xa9\xa4\x8e\xd5\x1f\xb2\xd0\xdd\x41"
+ "\x3c\xda\x10\x68\x9e\x47\x1b\x65\x02\xa2\xc5\x28\x73\x02\x83\x03"
+ "\x09\xfd\xf5\x29\x7e\x97\xdc\x2a\x4e\x4b\xaa\x79\x46\x46\x70\x86"
+ "\x1b\x9b\xb8\xf6\x8a\xbe\x29\x87\x7d\x5f\xda\xa5\x97\x6b\xef\xc8"
+ "\x43\x09\x43\xe2\x1f\x8a\x16\x7e\x1d\x50\x5d\xf5\xda\x02\xee\xf2"
+ "\xc3\x2a\x48\xe6\x6b\x30\xea\x02\xd7\xef\xac\x8b\x0c\xb8\xc1\x85"
+ "\xd8\xbf\x7c\x85\xa8\x1e\x83\xbe\x5c\x26\x2e\x79\x7b\x47\xf5\x4a"
+ "\x3f\x66\x62\x92\xfd\x41\x20\xb6\x2c\x00\xf0\x52\xca\x26\x06\x2d"
+ "\x7c\xcf\x7a\x50\x7d\x0f\xcb\xdd\x97\x20\xc8\x6f\xe4\xe0\x50\xf4"
+ "\xe3\x02\x03\x01\x00\x01";
+const char mock_public_exponent[] = "\x01\x00\x01";
+const char mock_modulus[] =
+ "\xDD\xCF\x97\xD2\xA5\x1D\x95\xDD\x86\x18\xD8\xC4\xB9\xAD\xA6\x0C"
+ "\xB4\x9D\xB6\xDC\xFA\xDC\x21\xE1\x3A\x62\x34\x07\xE8\x33\xB2\xE8"
+ "\x97\xEE\x2C\x41\xD2\x12\xF1\x5F\xED\xE4\x76\xFF\x65\x26\x1E\x0C"
+ "\xC7\x41\x15\x69\x5F\x0D\xF9\xAD\x89\x14\x8D\xEA\xD7\x16\x52\x9A"
+ "\x47\xC1\xBB\x00\x02\xE4\x88\x45\x73\x78\xA4\xAE\xDB\x38\xC3\xC6"
+ "\x07\xD2\x64\x0E\x87\xED\x74\x8C\x6B\xC4\xC0\x02\x50\x7C\x4E\xA6"
+ "\xD1\x58\xE9\xE5\x13\x09\xA9\xDB\x5A\xEA\xEB\x0F\x06\x80\x5C\x09"
+ "\xEF\x94\xC8\xE9\xFB\x37\x2E\x75\xE1\xAC\x93\xAD\x9B\x37\x13\x4B"
+ "\x66\x3A\x76\x33\xD8\xC4\xD7\x4C\xFB\x61\xC8\x92\x21\x07\xFC\xDF"
+ "\xA9\x88\x54\xE4\xA3\xA9\x47\xD2\x6C\xB8\xE3\x39\x89\x11\x88\x38"
+ "\x2D\xA2\xDC\x3E\x5E\x4A\xA9\xA4\x8E\xD5\x1F\xB2\xD0\xDD\x41\x3C"
+ "\xDA\x10\x68\x9E\x47\x1B\x65\x02\xA2\xC5\x28\x73\x02\x83\x03\x09"
+ "\xFD\xF5\x29\x7E\x97\xDC\x2A\x4E\x4B\xAA\x79\x46\x46\x70\x86\x1B"
+ "\x9B\xB8\xF6\x8A\xBE\x29\x87\x7D\x5F\xDA\xA5\x97\x6B\xEF\xC8\x43"
+ "\x09\x43\xE2\x1F\x8A\x16\x7E\x1D\x50\x5D\xF5\xDA\x02\xEE\xF2\xC3"
+ "\x2A\x48\xE6\x6B\x30\xEA\x02\xD7\xEF\xAC\x8B\x0C\xB8\xC1\x85\xD8"
+ "\xBF\x7C\x85\xA8\x1E\x83\xBE\x5C\x26\x2E\x79\x7B\x47\xF5\x4A\x3F"
+ "\x66\x62\x92\xFD\x41\x20\xB6\x2C\x00\xF0\x52\xCA\x26\x06\x2D\x7C"
+ "\xCF\x7A\x50\x7D\x0F\xCB\xDD\x97\x20\xC8\x6F\xE4\xE0\x50\xF4\xE3";
+const char mock_subject[] =
+ "DN: C=US, O=Test Government, OU=Test Department, OU=Test Agency/serialNumber=";
+
+CK_BBOOL pkcs11_mock_initialized = CK_FALSE;
+CK_BBOOL pkcs11_mock_session_opened = CK_FALSE;
+CK_BBOOL pkcs11_mock_session_reauth = CK_FALSE;
+
+static session_ptr_st *mock_session = NULL;
+
+CK_FUNCTION_LIST pkcs11_mock_functions =
+{
+ {2, 20},
+ &C_Initialize,
+ &C_Finalize,
+ &C_GetInfo,
+ &C_GetFunctionList,
+ &C_GetSlotList,
+ &C_GetSlotInfo,
+ &C_GetTokenInfo,
+ &C_GetMechanismList,
+ &C_GetMechanismInfo,
+ &C_InitToken,
+ &C_InitPIN,
+ &C_SetPIN,
+ &C_OpenSession,
+ &C_CloseSession,
+ &C_CloseAllSessions,
+ &C_GetSessionInfo,
+ &C_GetOperationState,
+ &C_SetOperationState,
+ &C_Login,
+ &C_Logout,
+ &C_CreateObject,
+ &C_CopyObject,
+ &C_DestroyObject,
+ &C_GetObjectSize,
+ &C_GetAttributeValue,
+ &C_SetAttributeValue,
+ &C_FindObjectsInit,
+ &C_FindObjects,
+ &C_FindObjectsFinal,
+ &C_EncryptInit,
+ &C_Encrypt,
+ &C_EncryptUpdate,
+ &C_EncryptFinal,
+ &C_DecryptInit,
+ &C_Decrypt,
+ &C_DecryptUpdate,
+ &C_DecryptFinal,
+ &C_DigestInit,
+ &C_Digest,
+ &C_DigestUpdate,
+ &C_DigestKey,
+ &C_DigestFinal,
+ &C_SignInit,
+ &C_Sign,
+ &C_SignUpdate,
+ &C_SignFinal,
+ &C_SignRecoverInit,
+ &C_SignRecover,
+ &C_VerifyInit,
+ &C_Verify,
+ &C_VerifyUpdate,
+ &C_VerifyFinal,
+ &C_VerifyRecoverInit,
+ &C_VerifyRecover,
+ &C_DigestEncryptUpdate,
+ &C_DecryptDigestUpdate,
+ &C_SignEncryptUpdate,
+ &C_DecryptVerifyUpdate,
+ &C_GenerateKey,
+ &C_GenerateKeyPair,
+ &C_WrapKey,
+ &C_UnwrapKey,
+ &C_DeriveKey,
+ &C_SeedRandom,
+ &C_GenerateRandom,
+ &C_GetFunctionStatus,
+ &C_CancelFunction,
+ &C_WaitForSlotEvent
+};
+
+#if defined(HAVE___REGISTER_ATFORK)
+extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
+extern void *__dso_handle;
+static unsigned registered_fork_handler = 0;
+
+static void fork_handler(void)
+{
+ pkcs11_mock_initialized = CK_FALSE;
+ pkcs11_mock_session_opened = CK_FALSE;
+ if (mock_session) {
+ mock_session->state = CKS_RO_PUBLIC_SESSION;
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ free(mock_session->find_label);
+ }
+ free(mock_session);
+ mock_session = NULL;
+}
+#endif
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs)
+{
+ if (CK_TRUE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_ALREADY_INITIALIZED;
+
+ IGNORE(pInitArgs);
+#if defined(HAVE___REGISTER_ATFORK)
+ if (registered_fork_handler == 0) {
+ __register_atfork(NULL, NULL, fork_handler, __dso_handle);
+ registered_fork_handler = 1;
+ }
+#endif
+ pkcs11_mock_initialized = CK_TRUE;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Finalize)(CK_VOID_PTR pReserved)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ IGNORE(pReserved);
+
+ pkcs11_mock_initialized = CK_FALSE;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)(CK_INFO_PTR pInfo)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (NULL == pInfo)
+ return CKR_ARGUMENTS_BAD;
+
+ pInfo->cryptokiVersion.major = 0x02;
+ pInfo->cryptokiVersion.minor = 0x14;
+ memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
+ memcpy(pInfo->manufacturerID, PKCS11_MOCK_CK_INFO_MANUFACTURER_ID, strlen(PKCS11_MOCK_CK_INFO_MANUFACTURER_ID));
+ pInfo->flags = 0;
+ memset(pInfo->libraryDescription, ' ', sizeof(pInfo->libraryDescription));
+ memcpy(pInfo->libraryDescription, PKCS11_MOCK_CK_INFO_LIBRARY_DESCRIPTION, strlen(PKCS11_MOCK_CK_INFO_LIBRARY_DESCRIPTION));
+ pInfo->libraryVersion.major = 0x01;
+ pInfo->libraryVersion.minor = 0x00;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
+{
+ if (NULL == ppFunctionList)
+ return CKR_ARGUMENTS_BAD;
+
+ *ppFunctionList = &pkcs11_mock_functions;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ IGNORE(tokenPresent);
+
+ if (NULL == pulCount)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pSlotList)
+ {
+ *pulCount = 1;
+ }
+ else
+ {
+ if (0 == *pulCount)
+ return CKR_BUFFER_TOO_SMALL;
+
+ pSlotList[0] = PKCS11_MOCK_CK_SLOT_ID;
+ *pulCount = 1;
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_SLOT_ID != slotID)
+ return CKR_SLOT_ID_INVALID;
+
+ if (NULL == pInfo)
+ return CKR_ARGUMENTS_BAD;
+
+ memset(pInfo->slotDescription, ' ', sizeof(pInfo->slotDescription));
+ memcpy(pInfo->slotDescription, PKCS11_MOCK_CK_SLOT_INFO_SLOT_DESCRIPTION, strlen(PKCS11_MOCK_CK_SLOT_INFO_SLOT_DESCRIPTION));
+ memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
+ memcpy(pInfo->manufacturerID, PKCS11_MOCK_CK_SLOT_INFO_MANUFACTURER_ID, strlen(PKCS11_MOCK_CK_SLOT_INFO_MANUFACTURER_ID));
+ pInfo->flags = CKF_TOKEN_PRESENT;
+ pInfo->hardwareVersion.major = 0x01;
+ pInfo->hardwareVersion.minor = 0x00;
+ pInfo->firmwareVersion.major = 0x01;
+ pInfo->firmwareVersion.minor = 0x00;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_SLOT_ID != slotID)
+ return CKR_SLOT_ID_INVALID;
+
+ if (NULL == pInfo)
+ return CKR_ARGUMENTS_BAD;
+
+ memset(pInfo->label, ' ', sizeof(pInfo->label));
+ memcpy(pInfo->label, PKCS11_MOCK_CK_TOKEN_INFO_LABEL, strlen(PKCS11_MOCK_CK_TOKEN_INFO_LABEL));
+ memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
+ memcpy(pInfo->manufacturerID, PKCS11_MOCK_CK_TOKEN_INFO_MANUFACTURER_ID, strlen(PKCS11_MOCK_CK_TOKEN_INFO_MANUFACTURER_ID));
+ memset(pInfo->model, ' ', sizeof(pInfo->model));
+ memcpy(pInfo->model, PKCS11_MOCK_CK_TOKEN_INFO_MODEL, strlen(PKCS11_MOCK_CK_TOKEN_INFO_MODEL));
+ memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber));
+ memcpy(pInfo->serialNumber, PKCS11_MOCK_CK_TOKEN_INFO_SERIAL_NUMBER, strlen(PKCS11_MOCK_CK_TOKEN_INFO_SERIAL_NUMBER));
+ pInfo->flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED;
+
+ if (pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH)
+ pInfo->flags &= ~CKF_LOGIN_REQUIRED;
+
+ pInfo->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ pInfo->ulSessionCount = (CK_TRUE == pkcs11_mock_session_opened) ? 1 : 0;
+ pInfo->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
+ if ((CK_TRUE == pkcs11_mock_session_opened) && ((CKS_RO_PUBLIC_SESSION != mock_session->state) && (CKS_RO_USER_FUNCTIONS != mock_session->state)))
+ pInfo->ulRwSessionCount = 1;
+ else
+ pInfo->ulRwSessionCount = 0;
+ pInfo->ulMaxPinLen = PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN;
+ pInfo->ulMinPinLen = PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN;
+ pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
+ pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
+ pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ pInfo->hardwareVersion.major = 0x01;
+ pInfo->hardwareVersion.minor = 0x00;
+ pInfo->firmwareVersion.major = 0x01;
+ pInfo->firmwareVersion.minor = 0x00;
+ memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime));
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_SLOT_ID != slotID)
+ return CKR_SLOT_ID_INVALID;
+
+ if (NULL == pulCount)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pMechanismList)
+ {
+ *pulCount = 9;
+ }
+ else
+ {
+ if (9 > *pulCount)
+ return CKR_BUFFER_TOO_SMALL;
+
+ pMechanismList[0] = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ pMechanismList[1] = CKM_RSA_PKCS;
+ pMechanismList[2] = CKM_SHA1_RSA_PKCS;
+ pMechanismList[3] = CKM_RSA_PKCS_OAEP;
+ pMechanismList[4] = CKM_DES3_CBC;
+ pMechanismList[5] = CKM_DES3_KEY_GEN;
+ pMechanismList[6] = CKM_SHA_1;
+ pMechanismList[7] = CKM_XOR_BASE_AND_DATA;
+ pMechanismList[8] = CKM_AES_CBC;
+
+ *pulCount = 9;
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_SLOT_ID != slotID)
+ return CKR_SLOT_ID_INVALID;
+
+ if (NULL == pInfo)
+ return CKR_ARGUMENTS_BAD;
+
+ switch (type)
+ {
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ pInfo->ulMinKeySize = 1024;
+ pInfo->ulMaxKeySize = 1024;
+ pInfo->flags = CKF_GENERATE_KEY_PAIR;
+ break;
+
+ case CKM_RSA_PKCS:
+ pInfo->ulMinKeySize = 1024;
+ pInfo->ulMaxKeySize = 1024;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_SIGN_RECOVER | CKF_VERIFY | CKF_VERIFY_RECOVER | CKF_WRAP | CKF_UNWRAP;
+ break;
+
+ case CKM_SHA1_RSA_PKCS:
+ pInfo->ulMinKeySize = 1024;
+ pInfo->ulMaxKeySize = 1024;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+
+ case CKM_RSA_PKCS_OAEP:
+ pInfo->ulMinKeySize = 1024;
+ pInfo->ulMaxKeySize = 1024;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+
+ case CKM_DES3_CBC:
+ pInfo->ulMinKeySize = 192;
+ pInfo->ulMaxKeySize = 192;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+
+ case CKM_DES3_KEY_GEN:
+ pInfo->ulMinKeySize = 192;
+ pInfo->ulMaxKeySize = 192;
+ pInfo->flags = CKF_GENERATE;
+ break;
+
+ case CKM_SHA_1:
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_DIGEST;
+ break;
+
+ case CKM_XOR_BASE_AND_DATA:
+ pInfo->ulMinKeySize = 128;
+ pInfo->ulMaxKeySize = 256;
+ pInfo->flags = CKF_DERIVE;
+ break;
+
+ case CKM_AES_CBC:
+ pInfo->ulMinKeySize = 128;
+ pInfo->ulMaxKeySize = 256;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_SLOT_ID != slotID)
+ return CKR_SLOT_ID_INVALID;
+
+ if (NULL == pPin)
+ return CKR_ARGUMENTS_BAD;
+
+ if ((ulPinLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulPinLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN))
+ return CKR_PIN_LEN_RANGE;
+
+ if (NULL == pLabel)
+ return CKR_ARGUMENTS_BAD;
+
+ if (CK_TRUE == pkcs11_mock_session_opened)
+ return CKR_SESSION_EXISTS;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (CKS_RW_SO_FUNCTIONS != mock_session->state)
+ return CKR_USER_NOT_LOGGED_IN;
+
+ if (NULL == pPin)
+ return CKR_ARGUMENTS_BAD;
+
+ if ((ulPinLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulPinLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN))
+ return CKR_PIN_LEN_RANGE;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((CKS_RO_PUBLIC_SESSION == mock_session->state) || (CKS_RO_USER_FUNCTIONS == mock_session->state))
+ return CKR_SESSION_READ_ONLY;
+
+ if (NULL == pOldPin)
+ return CKR_ARGUMENTS_BAD;
+
+ if ((ulOldLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulOldLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN))
+ return CKR_PIN_LEN_RANGE;
+
+ if (NULL == pNewPin)
+ return CKR_ARGUMENTS_BAD;
+
+ if ((ulNewLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulNewLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN))
+ return CKR_PIN_LEN_RANGE;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (CK_TRUE == pkcs11_mock_session_opened)
+ return CKR_SESSION_COUNT;
+
+ if (PKCS11_MOCK_CK_SLOT_ID != slotID)
+ return CKR_SLOT_ID_INVALID;
+
+ if (!(flags & CKF_SERIAL_SESSION))
+ return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+
+ IGNORE(pApplication);
+
+ IGNORE(Notify);
+
+ if (NULL == phSession)
+ return CKR_ARGUMENTS_BAD;
+
+ pkcs11_mock_session_opened = CK_TRUE;
+
+ mock_session = calloc(1, sizeof(session_ptr_st));
+ if (mock_session == NULL)
+ return CKR_HOST_MEMORY;
+
+ mock_session->state = (flags & CKF_RW_SESSION) ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION;
+
+ mock_session->find_op.find_result = CKR_OBJECT_HANDLE_INVALID;
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ mock_session->state = CKS_RO_PUBLIC_SESSION;
+
+ *phSession = PKCS11_MOCK_CK_SESSION_ID;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)(CK_SESSION_HANDLE hSession)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ pkcs11_mock_session_opened = CK_FALSE;
+ mock_session->state = CKS_RO_PUBLIC_SESSION;
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ free(mock_session->find_label);
+ free(mock_session);
+ mock_session = NULL;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)(CK_SLOT_ID slotID)
+{
+ return C_CloseSession(PKCS11_MOCK_CK_SESSION_ID);
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pInfo)
+ return CKR_ARGUMENTS_BAD;
+
+ pInfo->slotID = PKCS11_MOCK_CK_SLOT_ID;
+ pInfo->state = mock_session->state;
+ pInfo->flags = CKF_SERIAL_SESSION;
+ if ((mock_session->state != CKS_RO_PUBLIC_SESSION) && (mock_session->state != CKS_RO_USER_FUNCTIONS))
+ pInfo->flags = pInfo->flags | CKF_RW_SESSION;
+ pInfo->ulDeviceError = 0;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pulOperationStateLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pOperationState)
+ {
+ *pulOperationStateLen = 256;
+ }
+ else
+ {
+ if (256 > *pulOperationStateLen)
+ return CKR_BUFFER_TOO_SMALL;
+
+ memset(pOperationState, 1, 256);
+ *pulOperationStateLen = 256;
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pOperationState)
+ return CKR_ARGUMENTS_BAD;
+
+ if (256 != ulOperationStateLen)
+ return CKR_ARGUMENTS_BAD;
+
+ IGNORE(hEncryptionKey);
+
+ IGNORE(hAuthenticationKey);
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ CK_RV rv = CKR_OK;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) && userType == CKU_CONTEXT_SPECIFIC) {
+ return CKR_USER_TYPE_INVALID;
+ }
+
+ if ((pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH) || (pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH)) {
+ if ((CKU_CONTEXT_SPECIFIC != userType) && (CKU_SO != userType) && (CKU_USER != userType))
+ return CKR_USER_TYPE_INVALID;
+ } else if ((CKU_SO != userType) && (CKU_USER != userType)) {
+ return CKR_USER_TYPE_INVALID;
+ }
+
+ if (NULL == pPin)
+ return CKR_ARGUMENTS_BAD;
+
+ if ((ulPinLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulPinLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN))
+ return CKR_PIN_LEN_RANGE;
+
+ switch (mock_session->state)
+ {
+ case CKS_RO_PUBLIC_SESSION:
+
+ if (CKU_SO == userType)
+ rv = CKR_SESSION_READ_ONLY_EXISTS;
+ else
+ mock_session->state = CKS_RO_USER_FUNCTIONS;
+
+ break;
+
+ case CKS_RO_USER_FUNCTIONS:
+ case CKS_RW_USER_FUNCTIONS:
+
+ rv = (CKU_SO == userType) ? CKR_USER_ANOTHER_ALREADY_LOGGED_IN : CKR_USER_ALREADY_LOGGED_IN;
+
+ break;
+
+ case CKS_RW_PUBLIC_SESSION:
+
+ mock_session->state = (CKU_SO == userType) ? CKS_RW_SO_FUNCTIONS : CKS_RW_USER_FUNCTIONS;
+
+ break;
+
+ case CKS_RW_SO_FUNCTIONS:
+
+ rv = (CKU_SO == userType) ? CKR_USER_ALREADY_LOGGED_IN : CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ break;
+ }
+
+ if ((pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) && rv == CKR_USER_ALREADY_LOGGED_IN) {
+ rv = 0;
+ }
+
+ pkcs11_mock_session_reauth = 1;
+ return rv;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Logout)(CK_SESSION_HANDLE hSession)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((mock_session->state == CKS_RO_PUBLIC_SESSION) || (mock_session->state == CKS_RW_PUBLIC_SESSION))
+ return CKR_USER_NOT_LOGGED_IN;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pTemplate)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulCount)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == phObject)
+ return CKR_ARGUMENTS_BAD;
+
+ for (i = 0; i < ulCount; i++)
+ {
+ if (NULL == pTemplate[i].pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (0 >= pTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ *phObject = PKCS11_MOCK_CK_OBJECT_HANDLE_DATA;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_CopyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_DATA != hObject)
+ return CKR_OBJECT_HANDLE_INVALID;
+
+ if (NULL == phNewObject)
+ return CKR_ARGUMENTS_BAD;
+
+ if ((NULL != pTemplate) && (0 >= ulCount))
+ {
+ for (i = 0; i < ulCount; i++)
+ {
+ if (NULL == pTemplate[i].pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (0 >= pTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ }
+
+ *phNewObject = PKCS11_MOCK_CK_OBJECT_HANDLE_DATA;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((PKCS11_MOCK_CK_OBJECT_HANDLE_DATA != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hObject))
+ return CKR_OBJECT_HANDLE_INVALID;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetObjectSize)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((PKCS11_MOCK_CK_OBJECT_HANDLE_DATA != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hObject))
+ return CKR_OBJECT_HANDLE_INVALID;
+
+ if (NULL == pulSize)
+ return CKR_ARGUMENTS_BAD;
+
+ *pulSize = PKCS11_MOCK_CK_OBJECT_SIZE;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((PKCS11_MOCK_CK_OBJECT_HANDLE_DATA != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE_EXTENSION != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hObject))
+ return CKR_OBJECT_HANDLE_INVALID;
+
+ if (NULL == pTemplate)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulCount)
+ return CKR_ARGUMENTS_BAD;
+
+ for (i = 0; i < ulCount; i++)
+ {
+ if (CKA_PUBLIC_KEY_INFO == pTemplate[i].type &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE == hObject || PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY == hObject))
+ {
+ if (pTemplate[i].ulValueLen < sizeof(mock_pubkey)-1) {
+ pTemplate[i].ulValueLen = sizeof(mock_pubkey)-1;
+ if (pTemplate[i].pValue == NULL)
+ return CKR_OK;
+ else
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ pTemplate[i].ulValueLen = (CK_ULONG) sizeof(mock_pubkey)-1;
+ memcpy(pTemplate[i].pValue, mock_pubkey, pTemplate[i].ulValueLen);
+ }
+ else if (CKA_CLASS == pTemplate[i].type)
+ {
+ if (NULL != pTemplate[i].pValue)
+ {
+ if (pTemplate[i].ulValueLen < sizeof(hObject))
+ return CKR_BUFFER_TOO_SMALL;
+ else
+ memcpy(pTemplate[i].pValue, &hObject, sizeof(hObject));
+ }
+
+ pTemplate[i].ulValueLen = sizeof(hObject);
+ }
+ else if (CKA_PUBLIC_EXPONENT == pTemplate[i].type &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY == hObject || PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY == hObject))
+ {
+ if (NULL != pTemplate[i].pValue)
+ {
+ if (pTemplate[i].ulValueLen < sizeof(mock_public_exponent)-1)
+ return CKR_BUFFER_TOO_SMALL;
+ else
+ memcpy(pTemplate[i].pValue, mock_public_exponent, sizeof(mock_public_exponent)-1);
+ }
+
+ pTemplate[i].ulValueLen = sizeof(mock_public_exponent)-1;
+ }
+ else if (CKA_MODULUS == pTemplate[i].type &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY == hObject || PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY == hObject))
+ {
+ if (NULL != pTemplate[i].pValue)
+ {
+ if (pTemplate[i].ulValueLen < sizeof(mock_modulus)-1)
+ return CKR_BUFFER_TOO_SMALL;
+ else
+ memcpy(pTemplate[i].pValue, mock_modulus, sizeof(mock_modulus)-1);
+ }
+
+ pTemplate[i].ulValueLen = sizeof(mock_modulus)-1;
+ }
+ else if (CKA_SUBJECT == pTemplate[i].type && PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE == hObject)
+ {
+ if (NULL != pTemplate[i].pValue)
+ {
+ if (pTemplate[i].ulValueLen < strlen(mock_subject))
+ return CKR_BUFFER_TOO_SMALL;
+ else
+ memcpy(pTemplate[i].pValue, mock_subject, strlen(mock_subject));
+ }
+
+ pTemplate[i].ulValueLen = strlen(mock_subject);
+ }
+ else if (CKA_LABEL == pTemplate[i].type)
+ {
+ if (NULL != pTemplate[i].pValue)
+ {
+ if (pTemplate[i].ulValueLen < strlen(PKCS11_MOCK_CK_OBJECT_CKA_LABEL))
+ return CKR_BUFFER_TOO_SMALL;
+ else
+ memcpy(pTemplate[i].pValue, PKCS11_MOCK_CK_OBJECT_CKA_LABEL, strlen(PKCS11_MOCK_CK_OBJECT_CKA_LABEL));
+ }
+
+ pTemplate[i].ulValueLen = strlen(PKCS11_MOCK_CK_OBJECT_CKA_LABEL);
+ }
+ else if (CKA_KEY_TYPE == pTemplate[i].type)
+ {
+ CK_KEY_TYPE t;
+ if (pTemplate[i].ulValueLen != sizeof(CK_KEY_TYPE))
+ return CKR_ARGUMENTS_BAD;
+
+ t = CKK_RSA;
+ memcpy(pTemplate[i].pValue, &t, sizeof(CK_KEY_TYPE));
+ }
+ else if (CKA_ALWAYS_AUTHENTICATE == pTemplate[i].type)
+ {
+ CK_BBOOL t;
+ if (pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH)
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+
+ if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL))
+ return CKR_ARGUMENTS_BAD;
+
+ if (!(pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH)) {
+ t = CK_FALSE;
+ } else {
+ t = CK_TRUE;
+ }
+ memcpy(pTemplate[i].pValue, &t, sizeof(CK_BBOOL));
+ }
+ else if (CKA_ID == pTemplate[i].type)
+ {
+ if (NULL != pTemplate[i].pValue)
+ {
+ if (pTemplate[i].ulValueLen < strlen(PKCS11_MOCK_CK_OBJECT_CKA_LABEL))
+ return CKR_BUFFER_TOO_SMALL;
+ else
+ memcpy(pTemplate[i].pValue, PKCS11_MOCK_CK_OBJECT_CKA_LABEL, strlen(PKCS11_MOCK_CK_OBJECT_CKA_LABEL));
+ }
+
+ pTemplate[i].ulValueLen = strlen(PKCS11_MOCK_CK_OBJECT_CKA_LABEL);
+ }
+ else if (CKA_CERTIFICATE_CATEGORY == pTemplate[i].type)
+ {
+ CK_ULONG t = 2; /* authority */
+ if (pTemplate[i].ulValueLen < sizeof(CK_ULONG))
+ return CKR_BUFFER_TOO_SMALL;
+ memcpy(pTemplate[i].pValue, &t, sizeof(CK_ULONG));
+ }
+ else if (CKA_VALUE == pTemplate[i].type)
+ {
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE_EXTENSION == hObject)
+ {
+ const void *obj;
+ unsigned obj_len;
+
+ if (mock_session->find_op.remaining_data == 1) {
+ obj = mock_cert_ext1;
+ obj_len = sizeof(mock_cert_ext1)-1;
+ } else {
+ obj = mock_cert_ext2;
+ obj_len = sizeof(mock_cert_ext2)-1;
+ }
+
+ if (pTemplate[i].ulValueLen < obj_len) {
+ pTemplate[i].ulValueLen = obj_len;
+ if (pTemplate[i].pValue == NULL)
+ return CKR_OK;
+ else
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ pTemplate[i].ulValueLen = (CK_ULONG) obj_len;
+ memcpy(pTemplate[i].pValue, obj, pTemplate[i].ulValueLen);
+ }
+ else if (PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE == hObject)
+ {
+ if (pTemplate[i].ulValueLen < sizeof(mock_certificate)-1) {
+ pTemplate[i].ulValueLen = sizeof(mock_certificate)-1;
+ if (pTemplate[i].pValue == NULL)
+ return CKR_OK;
+ else
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ pTemplate[i].ulValueLen = (CK_ULONG) sizeof(mock_certificate)-1;
+ memcpy(pTemplate[i].pValue, mock_certificate, pTemplate[i].ulValueLen);
+ }
+ else if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY == hObject)
+ {
+ if (pTemplate[i].ulValueLen < sizeof(mock_pubkey)-1) {
+ pTemplate[i].ulValueLen = sizeof(mock_pubkey)-1;
+ if (pTemplate[i].pValue == NULL)
+ return CKR_OK;
+ else
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ pTemplate[i].ulValueLen = (CK_ULONG) sizeof(mock_pubkey)-1;
+ memcpy(pTemplate[i].pValue, mock_pubkey, pTemplate[i].ulValueLen);
+ }
+ else if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY == hObject)
+ {
+ pTemplate[i].ulValueLen = (CK_ULONG) -1;
+ if (!(pkcs11_mock_flags & MOCK_FLAG_BROKEN_GET_ATTRIBUTES)) {
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+ }
+ else
+ {
+ if (NULL != pTemplate[i].pValue)
+ {
+ if (pTemplate[i].ulValueLen < strlen(PKCS11_MOCK_CK_OBJECT_CKA_VALUE))
+ return CKR_BUFFER_TOO_SMALL;
+ else
+ memcpy(pTemplate[i].pValue, PKCS11_MOCK_CK_OBJECT_CKA_VALUE, strlen(PKCS11_MOCK_CK_OBJECT_CKA_VALUE));
+ }
+
+ pTemplate[i].ulValueLen = strlen(PKCS11_MOCK_CK_OBJECT_CKA_VALUE);
+ }
+ }
+ else
+ {
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((PKCS11_MOCK_CK_OBJECT_HANDLE_DATA != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hObject) &&
+ (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hObject))
+ return CKR_OBJECT_HANDLE_INVALID;
+
+ if (NULL == pTemplate)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulCount)
+ return CKR_ARGUMENTS_BAD;
+
+ for (i = 0; i < ulCount; i++)
+ {
+ if ((CKA_LABEL == pTemplate[i].type) || (CKA_VALUE == pTemplate[i].type))
+ {
+ if (NULL == pTemplate[i].pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (0 >= pTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ else
+ {
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ CK_ULONG i = 0;
+ CK_ULONG_PTR cka_class_value = NULL;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation)
+ return CKR_OPERATION_ACTIVE;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pTemplate)
+ return CKR_ARGUMENTS_BAD;
+
+ IGNORE(ulCount);
+
+ mock_session->find_op.find_result = CK_INVALID_HANDLE;
+
+ for (i = 0; i < ulCount; i++)
+ {
+ if (NULL == pTemplate[i].pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (0 >= pTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (CKA_LABEL == pTemplate[i].type)
+ {
+ free(mock_session->find_label);
+ mock_session->find_label = strndup(pTemplate[i].pValue, pTemplate[i].ulValueLen);
+ }
+ else if (CKA_CLASS == pTemplate[i].type)
+ {
+ if (sizeof(CK_ULONG) != pTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ cka_class_value = (CK_ULONG_PTR) pTemplate[i].pValue;
+
+ switch (*cka_class_value)
+ {
+ case CKO_DATA:
+ mock_session->find_op.find_result = PKCS11_MOCK_CK_OBJECT_HANDLE_DATA;
+ mock_session->find_op.remaining_data = 2;
+ break;
+ case CKO_SECRET_KEY:
+ mock_session->find_op.find_result = PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY;
+ mock_session->find_op.remaining_data = 1;
+ break;
+ case CKO_CERTIFICATE:
+ mock_session->find_op.find_result = PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE;
+ mock_session->find_op.remaining_data = 1;
+ break;
+ case CKO_PUBLIC_KEY:
+ mock_session->find_op.find_result = PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY;
+ mock_session->find_op.remaining_data = 1;
+ break;
+ case CKO_PRIVATE_KEY:
+ mock_session->find_op.find_result = PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY;
+ mock_session->find_op.remaining_data = 1;
+ break;
+ case CKO_X_CERTIFICATE_EXTENSION:
+ mock_session->find_op.find_result = PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE_EXTENSION;
+ mock_session->find_op.remaining_data = 2;
+ break;
+ }
+ }
+ }
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_FIND;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_FIND != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((NULL == phObject) && (0 < ulMaxObjectCount))
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulObjectCount)
+ return CKR_ARGUMENTS_BAD;
+
+ if (mock_session->find_op.remaining_data <= 0) {
+ *pulObjectCount = 0;
+ return CKR_OK;
+ }
+
+ switch (mock_session->find_op.find_result)
+ {
+ case PKCS11_MOCK_CK_OBJECT_HANDLE_DATA:
+
+ if (ulMaxObjectCount >= 2)
+ {
+ phObject[0] = mock_session->find_op.find_result;
+ phObject[1] = mock_session->find_op.find_result;
+ }
+
+ *pulObjectCount = 2;
+ mock_session->find_op.remaining_data -= 2;
+
+ break;
+
+ case CK_INVALID_HANDLE:
+
+ *pulObjectCount = 0;
+
+ break;
+
+ default:
+
+ if (ulMaxObjectCount >= 1)
+ {
+ phObject[0] = mock_session->find_op.find_result;
+ }
+
+ *pulObjectCount = 1;
+ mock_session->find_op.remaining_data --;
+
+ break;
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)(CK_SESSION_HANDLE hSession)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_FIND != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_EncryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DIGEST != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_SIGN != mock_session->find_op.active_operation))
+ return CKR_OPERATION_ACTIVE;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ switch (pMechanism->mechanism)
+ {
+ case CKM_RSA_PKCS:
+
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ break;
+
+#if 0
+ case CKM_RSA_PKCS_OAEP:
+
+ if ((NULL == pMechanism->pParameter) || (sizeof(CK_RSA_PKCS_OAEP_PARAMS) != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ break;
+#endif
+ case CKM_DES3_CBC:
+
+ if ((NULL == pMechanism->pParameter) || (8 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ break;
+
+ case CKM_AES_CBC:
+
+ if ((NULL == pMechanism->pParameter) || (16 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ break;
+
+ default:
+
+ return CKR_MECHANISM_INVALID;
+ }
+
+ switch (mock_session->find_op.active_operation)
+ {
+ case PKCS11_MOCK_CK_OPERATION_NONE:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_ENCRYPT;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_DIGEST:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_SIGN:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT;
+ break;
+ default:
+ return CKR_FUNCTION_FAILED;
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Encrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_ENCRYPT != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pData)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulEncryptedDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pEncryptedData)
+ {
+ if (ulDataLen > *pulEncryptedDataLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulDataLen; i++)
+ pEncryptedData[i] = pData[i] ^ 0xAB;
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ }
+ }
+
+ *pulEncryptedDataLen = ulDataLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_EncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_ENCRYPT != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulEncryptedPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pEncryptedPart)
+ {
+ if (ulPartLen > *pulEncryptedPartLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulPartLen; i++)
+ pEncryptedPart[i] = pPart[i] ^ 0xAB;
+ }
+ }
+
+ *pulEncryptedPartLen = ulPartLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_EncryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((PKCS11_MOCK_CK_OPERATION_ENCRYPT != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT != mock_session->find_op.active_operation))
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pulLastEncryptedPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pLastEncryptedPart)
+ {
+ switch (mock_session->find_op.active_operation)
+ {
+ case PKCS11_MOCK_CK_OPERATION_ENCRYPT:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_SIGN;
+ break;
+ default:
+ return CKR_FUNCTION_FAILED;
+ }
+ }
+
+ *pulLastEncryptedPartLen = 0;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DIGEST != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_VERIFY != mock_session->find_op.active_operation))
+ return CKR_OPERATION_ACTIVE;
+
+ if (pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) {
+ mock_session->state = CKS_RO_PUBLIC_SESSION;
+ pkcs11_mock_session_reauth = 0;
+ }
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ switch (pMechanism->mechanism)
+ {
+ case CKM_RSA_PKCS:
+
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ break;
+#if 0
+ case CKM_RSA_PKCS_OAEP:
+
+ if ((NULL == pMechanism->pParameter) || (sizeof(CK_RSA_PKCS_OAEP_PARAMS) != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ break;
+#endif
+ case CKM_DES3_CBC:
+
+ if ((NULL == pMechanism->pParameter) || (8 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ break;
+
+ case CKM_AES_CBC:
+
+ if ((NULL == pMechanism->pParameter) || (16 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ break;
+
+ default:
+
+ return CKR_MECHANISM_INVALID;
+ }
+
+ switch (mock_session->find_op.active_operation)
+ {
+ case PKCS11_MOCK_CK_OPERATION_NONE:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_DIGEST:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_VERIFY:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY;
+ break;
+ default:
+ return CKR_FUNCTION_FAILED;
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) {
+ if (!pkcs11_mock_session_reauth) {
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+ if ((pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH) && pData != NULL) {
+ pkcs11_mock_session_reauth = 0;
+ }
+ }
+
+ if (NULL == pEncryptedData)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulEncryptedDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pData)
+ {
+ if (ulEncryptedDataLen > *pulDataLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulEncryptedDataLen; i++)
+ pData[i] = pEncryptedData[i] ^ 0xAB;
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ }
+ }
+
+ *pulDataLen = ulEncryptedDataLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (NULL == pEncryptedPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulEncryptedPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pPart)
+ {
+ if (ulEncryptedPartLen > *pulPartLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulEncryptedPartLen; i++)
+ pPart[i] = pEncryptedPart[i] ^ 0xAB;
+ }
+ }
+
+ *pulPartLen = ulEncryptedPartLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != mock_session->find_op.active_operation))
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (NULL == pulLastPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pLastPart)
+ {
+ switch (mock_session->find_op.active_operation)
+ {
+ case PKCS11_MOCK_CK_OPERATION_DECRYPT:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_VERIFY;
+ break;
+ default:
+ return CKR_FUNCTION_FAILED;
+ }
+ }
+
+ *pulLastPartLen = 0;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_ENCRYPT != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation))
+ return CKR_OPERATION_ACTIVE;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if (CKM_SHA_1 != pMechanism->mechanism)
+ return CKR_MECHANISM_INVALID;
+
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ switch (mock_session->find_op.active_operation)
+ {
+ case PKCS11_MOCK_CK_OPERATION_NONE:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_ENCRYPT:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_DECRYPT:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST;
+ break;
+ default:
+ return CKR_FUNCTION_FAILED;
+ }
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Digest)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ CK_BYTE hash[20] = { 0x7B, 0x50, 0x2C, 0x3A, 0x1F, 0x48, 0xC8, 0x60, 0x9A, 0xE2, 0x12, 0xCD, 0xFB, 0x63, 0x9D, 0xEE, 0x39, 0x67, 0x3F, 0x5E };
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_DIGEST != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pData)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulDigestLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pDigest)
+ {
+ if (sizeof(hash) > *pulDigestLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ memcpy(pDigest, hash, sizeof(hash));
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ }
+ }
+
+ *pulDigestLen = sizeof(hash);
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_DIGEST != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_DIGEST != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey)
+ return CKR_OBJECT_HANDLE_INVALID;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DigestFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ CK_BYTE hash[20] = { 0x7B, 0x50, 0x2C, 0x3A, 0x1F, 0x48, 0xC8, 0x60, 0x9A, 0xE2, 0x12, 0xCD, 0xFB, 0x63, 0x9D, 0xEE, 0x39, 0x67, 0x3F, 0x5E };
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((PKCS11_MOCK_CK_OPERATION_DIGEST != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != mock_session->find_op.active_operation))
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pulDigestLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pDigest)
+ {
+ if (sizeof(hash) > *pulDigestLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ memcpy(pDigest, hash, sizeof(hash));
+
+ switch (mock_session->find_op.active_operation)
+ {
+ case PKCS11_MOCK_CK_OPERATION_DIGEST:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_ENCRYPT;
+ break;
+ case PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST:
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT;
+ break;
+ default:
+ return CKR_FUNCTION_FAILED;
+ }
+ }
+ }
+
+ *pulDigestLen = sizeof(hash);
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_ENCRYPT != mock_session->find_op.active_operation))
+ return CKR_OPERATION_ACTIVE;
+
+ if (pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) {
+ mock_session->state = CKS_RO_PUBLIC_SESSION;
+ pkcs11_mock_session_reauth = 0;
+ }
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if ((CKM_RSA_PKCS == pMechanism->mechanism) || (CKM_SHA1_RSA_PKCS == pMechanism->mechanism))
+ {
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ if (PKCS11_MOCK_CK_OPERATION_NONE == mock_session->find_op.active_operation)
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_SIGN;
+ else
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ CK_BYTE signature[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_SIGN != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) {
+ if (!pkcs11_mock_session_reauth) {
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ if ((pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH) && pSignature != NULL) {
+ pkcs11_mock_session_reauth = 0;
+ }
+ }
+
+ if (NULL == pData)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulSignatureLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pSignature)
+ {
+ if (sizeof(signature) > *pulSignatureLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ memcpy(pSignature, signature, sizeof(signature));
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ }
+ }
+
+ *pulSignatureLen = sizeof(signature);
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_SIGN != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ CK_BYTE signature[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((PKCS11_MOCK_CK_OPERATION_SIGN != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT != mock_session->find_op.active_operation))
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pulSignatureLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pSignature)
+ {
+ if (sizeof(signature) > *pulSignatureLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ memcpy(pSignature, signature, sizeof(signature));
+
+ if (PKCS11_MOCK_CK_OPERATION_SIGN == mock_session->find_op.active_operation)
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ else
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_ENCRYPT;
+ }
+ }
+
+ *pulSignatureLen = sizeof(signature);
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation)
+ return CKR_OPERATION_ACTIVE;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if (CKM_RSA_PKCS == pMechanism->mechanism)
+ {
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_SIGN_RECOVER;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SignRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_SIGN_RECOVER != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pData)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulSignatureLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pSignature)
+ {
+ if (ulDataLen > *pulSignatureLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulDataLen; i++)
+ pSignature[i] = pData[i] ^ 0xAB;
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ }
+ }
+
+ *pulSignatureLen = ulDataLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if ((PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation))
+ return CKR_OPERATION_ACTIVE;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if ((CKM_RSA_PKCS == pMechanism->mechanism) || (CKM_SHA1_RSA_PKCS == pMechanism->mechanism))
+ {
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ if (PKCS11_MOCK_CK_OPERATION_NONE == mock_session->find_op.active_operation)
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_VERIFY;
+ else
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_Verify)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ CK_BYTE signature[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_VERIFY != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pData)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pSignature)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulSignatureLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (sizeof(signature) != ulSignatureLen)
+ return CKR_SIGNATURE_LEN_RANGE;
+
+ if (0 != memcmp(pSignature, signature, sizeof(signature)))
+ return CKR_SIGNATURE_INVALID;
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_VerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_VERIFY != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_VerifyFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ CK_BYTE signature[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((PKCS11_MOCK_CK_OPERATION_VERIFY != mock_session->find_op.active_operation) &&
+ (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != mock_session->find_op.active_operation))
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pSignature)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulSignatureLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (sizeof(signature) != ulSignatureLen)
+ return CKR_SIGNATURE_LEN_RANGE;
+
+ if (0 != memcmp(pSignature, signature, sizeof(signature)))
+ return CKR_SIGNATURE_INVALID;
+
+ if (PKCS11_MOCK_CK_OPERATION_VERIFY == mock_session->find_op.active_operation)
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ else
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation)
+ return CKR_OPERATION_ACTIVE;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if (CKM_RSA_PKCS == pMechanism->mechanism)
+ {
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hKey)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_VERIFY_RECOVER;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_VERIFY_RECOVER != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pSignature)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulSignatureLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulDataLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pData)
+ {
+ if (ulSignatureLen > *pulDataLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulSignatureLen; i++)
+ pData[i] = pSignature[i] ^ 0xAB;
+
+ mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE;
+ }
+ }
+
+ *pulDataLen = ulSignatureLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulEncryptedPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pEncryptedPart)
+ {
+ if (ulPartLen > *pulEncryptedPartLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulPartLen; i++)
+ pEncryptedPart[i] = pPart[i] ^ 0xAB;
+ }
+ }
+
+ *pulEncryptedPartLen = ulPartLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (NULL == pEncryptedPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulEncryptedPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pPart)
+ {
+ if (ulEncryptedPartLen > *pulPartLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulEncryptedPartLen; i++)
+ pPart[i] = pEncryptedPart[i] ^ 0xAB;
+ }
+ }
+
+ *pulPartLen = ulEncryptedPartLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (NULL == pPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulEncryptedPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pEncryptedPart)
+ {
+ if (ulPartLen > *pulEncryptedPartLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulPartLen; i++)
+ pEncryptedPart[i] = pPart[i] ^ 0xAB;
+ }
+ }
+
+ *pulEncryptedPartLen = ulPartLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != mock_session->find_op.active_operation)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (NULL == pEncryptedPart)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulEncryptedPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pulPartLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pPart)
+ {
+ if (ulEncryptedPartLen > *pulPartLen)
+ {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ for (i = 0; i < ulEncryptedPartLen; i++)
+ pPart[i] = pEncryptedPart[i] ^ 0xAB;
+ }
+ }
+
+ *pulPartLen = ulEncryptedPartLen;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if (CKM_DES3_KEY_GEN != pMechanism->mechanism)
+ return CKR_MECHANISM_INVALID;
+
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (NULL == pTemplate)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulCount)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == phKey)
+ return CKR_ARGUMENTS_BAD;
+
+ for (i = 0; i < ulCount; i++)
+ {
+ if (NULL == pTemplate[i].pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (0 >= pTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ *phKey = PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if (CKM_RSA_PKCS_KEY_PAIR_GEN != pMechanism->mechanism)
+ return CKR_MECHANISM_INVALID;
+
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (NULL == pPublicKeyTemplate)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulPublicKeyAttributeCount)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pPrivateKeyTemplate)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulPrivateKeyAttributeCount)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == phPublicKey)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == phPrivateKey)
+ return CKR_ARGUMENTS_BAD;
+
+ for (i = 0; i < ulPublicKeyAttributeCount; i++)
+ {
+ if (NULL == pPublicKeyTemplate[i].pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (0 >= pPublicKeyTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ for (i = 0; i < ulPrivateKeyAttributeCount; i++)
+ {
+ if (NULL == pPrivateKeyTemplate[i].pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (0 >= pPrivateKeyTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ *phPublicKey = PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY;
+ *phPrivateKey = PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
+{
+ CK_BYTE wrappedKey[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if (CKM_RSA_PKCS != pMechanism->mechanism)
+ return CKR_MECHANISM_INVALID;
+
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hWrappingKey)
+ return CKR_KEY_HANDLE_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey)
+ return CKR_KEY_HANDLE_INVALID;
+
+ if (NULL != pWrappedKey)
+ {
+ if (sizeof(wrappedKey) > *pulWrappedKeyLen)
+ return CKR_BUFFER_TOO_SMALL;
+ else
+ memcpy(pWrappedKey, wrappedKey, sizeof(wrappedKey));
+ }
+
+ *pulWrappedKeyLen = sizeof(wrappedKey);
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ CK_ULONG i = 0;
+
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pMechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if (CKM_RSA_PKCS != pMechanism->mechanism)
+ return CKR_MECHANISM_INVALID;
+
+ if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen))
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hUnwrappingKey)
+ return CKR_KEY_HANDLE_INVALID;
+
+ if (NULL == pWrappedKey)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulWrappedKeyLen)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pTemplate)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulAttributeCount)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == phKey)
+ return CKR_ARGUMENTS_BAD;
+
+ for (i = 0; i < ulAttributeCount; i++)
+ {
+ if (NULL == pTemplate[i].pValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ if (0 >= pTemplate[i].ulValueLen)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ *phKey = PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ return CKR_GENERAL_ERROR;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == pSeed)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulSeedLen)
+ return CKR_ARGUMENTS_BAD;
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (NULL == RandomData)
+ return CKR_ARGUMENTS_BAD;
+
+ if (0 >= ulRandomLen)
+ return CKR_ARGUMENTS_BAD;
+
+ memset(RandomData, 1, ulRandomLen);
+
+ return CKR_OK;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)(CK_SESSION_HANDLE hSession)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)(CK_SESSION_HANDLE hSession)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession))
+ return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+
+CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
+{
+ if (CK_FALSE == pkcs11_mock_initialized)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if ((0 != flags) && (CKF_DONT_BLOCK != flags))
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL == pSlot)
+ return CKR_ARGUMENTS_BAD;
+
+ if (NULL != pReserved)
+ return CKR_ARGUMENTS_BAD;
+
+ return CKR_NO_EVENT;
+}
+
diff --git a/tests/pkcs11/pkcs11-mock.h b/tests/pkcs11/pkcs11-mock.h
new file mode 100644
index 0000000..6764c02
--- /dev/null
+++ b/tests/pkcs11/pkcs11-mock.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011-2016 The Pkcs11Interop Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Written originally for the Pkcs11Interop project by:
+ * Jaroslav IMRICH <jimrich@jimrich.sk>
+ */
+
+#define _POSIX_C_SOURCE 200809
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+
+// PKCS#11 related stuff
+#define CK_PTR *
+#define CK_DEFINE_FUNCTION(returnType, name) returnType name
+#define CK_DECLARE_FUNCTION(returnType, name) returnType name
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
+#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
+
+#include <p11-kit/pkcs11.h>
+#include <p11-kit/pkcs11x.h>
+
+#ifndef NULL_PTR
+#define NULL_PTR 0
+#endif
+
+#define IGNORE(P) (void)(P)
+
+#define PKCS11_MOCK_CK_INFO_MANUFACTURER_ID "Pkcs11Interop Project"
+#define PKCS11_MOCK_CK_INFO_LIBRARY_DESCRIPTION "Mock module"
+
+#define PKCS11_MOCK_CK_SLOT_ID 1
+#define PKCS11_MOCK_CK_SLOT_INFO_SLOT_DESCRIPTION "Mock slot"
+#define PKCS11_MOCK_CK_SLOT_INFO_MANUFACTURER_ID "Pkcs11Interop Project"
+
+#define PKCS11_MOCK_CK_TOKEN_INFO_LABEL "Pkcs11Interop"
+#define PKCS11_MOCK_CK_TOKEN_INFO_MANUFACTURER_ID "Pkcs11Interop Project"
+#define PKCS11_MOCK_CK_TOKEN_INFO_MODEL "Mock token"
+#define PKCS11_MOCK_CK_TOKEN_INFO_SERIAL_NUMBER "0123456789A"
+#define PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN 256
+#define PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN 4
+
+#define PKCS11_MOCK_CK_SESSION_ID 1
+
+#define PKCS11_MOCK_CK_OBJECT_CKA_LABEL "Pkcs11Interop"
+#define PKCS11_MOCK_CK_OBJECT_CKA_VALUE "Hello world!"
+#define PKCS11_MOCK_CK_OBJECT_SIZE 256
+#define PKCS11_MOCK_CK_OBJECT_HANDLE_DATA 1
+#define PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY 2
+#define PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY 3
+#define PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY 4
+#define PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE_EXTENSION 5
+#define PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE 6
+
+typedef enum
+{
+ PKCS11_MOCK_CK_OPERATION_NONE,
+ PKCS11_MOCK_CK_OPERATION_FIND,
+ PKCS11_MOCK_CK_OPERATION_ENCRYPT,
+ PKCS11_MOCK_CK_OPERATION_DECRYPT,
+ PKCS11_MOCK_CK_OPERATION_DIGEST,
+ PKCS11_MOCK_CK_OPERATION_SIGN,
+ PKCS11_MOCK_CK_OPERATION_SIGN_RECOVER,
+ PKCS11_MOCK_CK_OPERATION_VERIFY,
+ PKCS11_MOCK_CK_OPERATION_VERIFY_RECOVER,
+ PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT,
+ PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST,
+ PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT,
+ PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY
+}
+PKCS11_MOCK_CK_OPERATION;
+
+struct find_ptr_st {
+ int remaining_data;
+ PKCS11_MOCK_CK_OPERATION active_operation;
+ CK_OBJECT_HANDLE find_result;
+};
+
+typedef struct session_ptr_st {
+ char *find_label;
+ CK_ULONG state;
+
+ struct find_ptr_st find_op;
+} session_ptr_st;
+
diff --git a/tests/pkcs11/pkcs11-mock2.c b/tests/pkcs11/pkcs11-mock2.c
new file mode 100644
index 0000000..44bf517
--- /dev/null
+++ b/tests/pkcs11/pkcs11-mock2.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Author: Daiki Ueno
+ *
+ * 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dlfcn.h>
+#include <p11-kit/pkcs11.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "softhsm.h"
+
+/* This provides a mock PKCS #11 module that delegates all the
+ * operations to SoftHSM except that it filters out CKM_RSA_PKCS_PSS
+ * mechanism.
+ */
+
+static void *dl;
+static CK_C_GetMechanismInfo base_C_GetMechanismInfo;
+static CK_FUNCTION_LIST override_funcs;
+
+#ifdef __sun
+# pragma fini(mock_deinit)
+# pragma init(mock_init)
+# define _CONSTRUCTOR
+# define _DESTRUCTOR
+#else
+# define _CONSTRUCTOR __attribute__((constructor))
+# define _DESTRUCTOR __attribute__((destructor))
+#endif
+
+static CK_RV
+override_C_GetMechanismInfo(CK_SLOT_ID slot_id,
+ CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO *info)
+{
+ if (type == CKM_RSA_PKCS_PSS)
+ return CKR_MECHANISM_INVALID;
+
+ return base_C_GetMechanismInfo(slot_id, type, info);
+}
+
+CK_RV
+C_GetFunctionList(CK_FUNCTION_LIST **function_list)
+{
+ CK_C_GetFunctionList func;
+ CK_FUNCTION_LIST *funcs;
+
+ assert(dl);
+
+ func = dlsym(dl, "C_GetFunctionList");
+ if (func == NULL) {
+ return CKR_GENERAL_ERROR;
+ }
+
+ func(&funcs);
+ base_C_GetMechanismInfo = funcs->C_GetMechanismInfo;
+
+ memcpy(&override_funcs, funcs, sizeof(CK_FUNCTION_LIST));
+ override_funcs.C_GetMechanismInfo = override_C_GetMechanismInfo;
+ *function_list = &override_funcs;
+
+ return CKR_OK;
+}
+
+static _CONSTRUCTOR void
+mock_init(void)
+{
+ const char *lib;
+
+ /* suppress compiler warning */
+ (void) set_softhsm_conf;
+
+ lib = softhsm_lib();
+
+ dl = dlopen(lib, RTLD_NOW);
+ if (dl == NULL)
+ exit(77);
+}
+
+static _DESTRUCTOR void
+mock_deinit(void)
+{
+ dlclose(dl);
+}
diff --git a/tests/pkcs11/pkcs11-obj-import.c b/tests/pkcs11/pkcs11-obj-import.c
new file mode 100644
index 0000000..17c75a7
--- /dev/null
+++ b/tests/pkcs11/pkcs11-obj-import.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * 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>
+
+#define CONFIG_NAME "softhsm-obj-import"
+#define CONFIG CONFIG_NAME".config"
+
+#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 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)
+{
+ static char buf[1024];
+ int ret;
+ const char *lib, *bin;
+ gnutls_x509_crt_t crt;
+ gnutls_pkcs11_obj_t obj;
+ char *url;
+ gnutls_datum_t tmp, tmp2;
+ size_t buf_size;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ 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, NULL);
+ 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);
+ }
+
+ /* 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_NOT_PRIVATE|GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_copy_x509_crt: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_set_pin_function(NULL, NULL);
+
+ assert(gnutls_pkcs11_obj_init(&obj) >= 0);
+
+ ret = gnutls_pkcs11_obj_import_url(obj, SOFTHSM_URL";object=cert", 0);
+ if (ret < 0) {
+ fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_pkcs11_obj_export_url(obj, GNUTLS_PKCS11_URL_GENERIC, &url) >= 0);
+ assert(url != NULL);
+
+ gnutls_free(url);
+
+ assert(gnutls_pkcs11_obj_export3(obj, GNUTLS_X509_FMT_DER, &tmp) >= 0);
+ assert(gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &tmp2) >= 0);
+
+ assert(tmp2.size == tmp.size);
+ assert(memcmp(tmp.data, tmp2.data, tmp.size) == 0);
+ gnutls_free(tmp2.data);
+
+ /* check gnutls_pkcs11_obj_export */
+ buf_size = 4;
+ assert(gnutls_pkcs11_obj_export(obj, buf, &buf_size) == GNUTLS_E_SHORT_MEMORY_BUFFER);
+
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_export(obj, buf, &buf_size)>=0);
+ assert(buf_size == tmp.size);
+ assert(memcmp(buf, tmp.data, tmp.size) == 0);
+
+ gnutls_free(tmp.data);
+
+ /* The ID is constant and copied from the certificate */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_ID_HEX, buf, &buf_size) >= 0);
+ assert(buf_size == 60);
+ assert(memcmp(buf, "95:d1:ad:a4:52:e4:c5:61:12:a6:91:13:8d:80:dd:2d:81:22:3e:d4", 60) == 0);
+
+ /* label */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_LABEL, buf, &buf_size) >= 0);
+ assert(buf_size == 4);
+ assert(memcmp(buf, "cert", 4) == 0);
+
+ /* token-label */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_TOKEN_LABEL, buf, &buf_size) >= 0);
+ assert(buf_size == 4);
+ assert(memcmp(buf, "test", 4) == 0);
+
+ /* token-serial */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_TOKEN_SERIAL, buf, &buf_size) >= 0);
+ assert(buf_size != 0);
+ assert(strlen(buf) != 0);
+
+ /* token-model */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_TOKEN_MODEL, buf, &buf_size) >= 0);
+ assert(buf_size != 0);
+ assert(strlen(buf) != 0);
+
+ /* token-manufacturer */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER, buf, &buf_size) >= 0);
+ assert(buf_size != 0);
+ assert(strlen(buf) != 0);
+
+ /* token-ID */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_ID, buf, &buf_size) >= 0);
+ assert(buf_size != 0);
+
+ /* library description */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_LIBRARY_DESCRIPTION, buf, &buf_size) >= 0);
+ assert(buf_size != 0);
+ assert(strlen(buf) != 0);
+
+ /* library manufacturer */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER, buf, &buf_size) >= 0);
+ assert(buf_size != 0);
+ assert(strlen(buf) != 0);
+
+ /* library version */
+ buf_size = sizeof(buf);
+ assert(gnutls_pkcs11_obj_get_info(obj, GNUTLS_PKCS11_OBJ_LIBRARY_VERSION, buf, &buf_size) >= 0);
+ assert(buf_size != 0);
+ assert(strlen(buf) != 0);
+
+ gnutls_pkcs11_obj_deinit(obj);
+ gnutls_x509_crt_deinit(crt);
+
+ gnutls_global_deinit();
+
+ remove(CONFIG);
+}
+
diff --git a/tests/pkcs11/pkcs11-obj-raw.c b/tests/pkcs11/pkcs11-obj-raw.c
new file mode 100644
index 0000000..a955272
--- /dev/null
+++ b/tests/pkcs11/pkcs11-obj-raw.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2016-2018 Red Hat, Inc.
+ *
+ * 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/pkcs11.h>
+#ifndef CRYPTOKI_GNU
+# define CRYPTOKI_GNU
+#endif
+#include <p11-kit/pkcs11.h>
+
+#include "utils.h"
+
+/* Tests whether a gnutls_pkcs11_obj_get_ptr returns valid handles. */
+
+#if defined(HAVE___REGISTER_ATFORK)
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+#define PIN "1234"
+
+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)
+{
+ int ret;
+ const char *lib;
+ unsigned long slot_id;
+ unsigned char sig[256];
+ unsigned long len;
+ struct ck_function_list *mod;
+ struct ck_info info;
+ struct ck_token_info tinfo;
+ ck_session_handle_t session;
+ ck_object_handle_t ohandle;
+ gnutls_pkcs11_obj_t obj;
+ struct ck_mechanism mech;
+ ck_rv_t rv;
+ gnutls_datum_t data;
+
+ data.data = (void*)"\x38\x17\x0c\x08\xcb\x45\x8f\xd4\x87\x9c\x34\xb6\xf6\x08\x29\x4c\x50\x31\x2b\xbb";
+ data.size = 20;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_pkcs11_obj_init(&obj)>=0);
+
+ gnutls_pkcs11_obj_set_pin_function(obj, pin_func, NULL);
+
+ /* unknown object */
+ ret = gnutls_pkcs11_obj_import_url(obj, "pkcs11:token=unknown;object=invalid;type=private", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ assert(ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
+ ret = gnutls_pkcs11_obj_import_url(obj, "pkcs11:object=test;type=private", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ assert(ret >= 0);
+
+ ret = gnutls_pkcs11_obj_get_ptr(obj, (void**)&mod, (void*)&session,
+ (void*)&ohandle,
+ &slot_id, GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_obj_deinit(obj);
+
+ rv = mod->C_GetInfo(&info);
+ if (rv != CKR_OK) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(info.cryptoki_version.major == 0x02);
+ assert(info.cryptoki_version.minor == 0x14);
+ assert(info.flags == 0);
+ assert(info.library_version.major == 0x01);
+ assert(info.library_version.minor == 0x00);
+
+ rv = mod->C_GetTokenInfo(slot_id, &tinfo);
+ if (rv != CKR_OK) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(tinfo.hardware_version.major == 0x01);
+ assert(tinfo.firmware_version.major == 0x01);
+
+ mech.mechanism = CKM_RSA_PKCS;
+ mech.parameter = NULL;
+ mech.parameter_len = 0;
+
+ rv = mod->C_SignInit(session, &mech, ohandle);
+ if (rv != CKR_OK) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ len = sizeof(sig);
+ rv = mod->C_Sign(session, data.data, data.size, sig, &len);
+ if (rv != CKR_OK) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ mod->C_CloseSession(session);
+
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+}
+#else
+void doit(void)
+{
+ exit(77);
+}
+#endif
diff --git a/tests/pkcs11/pkcs11-pin-func.c b/tests/pkcs11/pkcs11-pin-func.c
new file mode 100644
index 0000000..b6d707e
--- /dev/null
+++ b/tests/pkcs11/pkcs11-pin-func.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 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 <assert.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/pkcs11.h>
+
+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, "xxx");
+ return 0;
+ }
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ void *u;
+ gnutls_pin_callback_t cb;
+
+ gnutls_pkcs11_set_pin_function(pin_func, (void*)-1);
+
+ cb = gnutls_pkcs11_get_pin_function(&u);
+
+ assert(u==(void*)-1);
+ assert(cb == pin_func);
+
+ return 0;
+}
diff --git a/tests/pkcs11/pkcs11-privkey-always-auth.c b/tests/pkcs11/pkcs11-privkey-always-auth.c
new file mode 100644
index 0000000..441f637
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey-always-auth.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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 <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include <gnutls/pkcs11.h>
+
+#ifdef _WIN32
+
+void doit(void)
+{
+ exit(77);
+}
+
+#else
+
+# include "utils.h"
+# include "pkcs11-mock-ext.h"
+
+/* Tests whether a gnutls_privkey_t will work properly with a key marked
+ * as always authenticate */
+
+static unsigned pin_called = 0;
+static const char *_pin = "1234";
+
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+
+
+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 (_pin == NULL)
+ return -1;
+
+ strcpy(pin, _pin);
+ pin_called++;
+ return 0;
+}
+
+void doit(void)
+{
+ int ret;
+ const char *lib;
+ gnutls_privkey_t key;
+ gnutls_pkcs11_obj_t obj;
+ gnutls_datum_t sig = {NULL, 0}, data;
+ unsigned flags = 0;
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ {
+ void *dl;
+ unsigned int *pflags;
+
+ dl = dlopen(lib, RTLD_NOW);
+ if (dl == NULL) {
+ fail("could not dlopen %s\n", lib);
+ exit(1);
+ }
+
+ pflags = dlsym(dl, "pkcs11_mock_flags");
+ if (pflags == NULL) {
+ fail("could find pkcs11_mock_flags\n");
+ exit(1);
+ }
+
+ *pflags = MOCK_FLAG_ALWAYS_AUTH;
+ }
+
+ data.data = (void*)"\x38\x17\x0c\x08\xcb\x45\x8f\xd4\x87\x9c\x34\xb6\xf6\x08\x29\x4c\x50\x31\x2b\xbb";
+ data.size = 20;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_obj_init(&obj);
+ assert(ret>=0);
+
+ gnutls_pkcs11_obj_set_pin_function(obj, pin_func, NULL);
+
+ ret = gnutls_pkcs11_obj_import_url(obj, "pkcs11:object=test;type=private", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ assert(ret>=0);
+
+ ret = gnutls_pkcs11_obj_get_flags(obj, &flags);
+ assert(ret>=0);
+
+ if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH)) {
+ fail("key object doesn't have the always authenticate flag\n");
+ }
+ gnutls_pkcs11_obj_deinit(obj);
+
+
+ ret = gnutls_privkey_init(&key);
+ assert(ret>=0);
+
+ gnutls_privkey_set_pin_function(key, pin_func, NULL);
+
+ ret = gnutls_privkey_import_url(key, "pkcs11:object=test", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ pin_called = 0;
+
+ ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (pin_called == 0) {
+ fail("PIN function wasn't called!\n");
+ }
+ pin_called = 0;
+
+ gnutls_free(sig.data);
+
+ /* call again - should re-authenticate */
+ ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (pin_called == 0) {
+ fail("PIN function wasn't called twice!\n");
+ }
+ pin_called = 0;
+
+ gnutls_free(sig.data);
+
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_privkey_deinit(key);
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+}
+#endif
diff --git a/tests/pkcs11/pkcs11-privkey-export.c b/tests/pkcs11/pkcs11-privkey-export.c
new file mode 100644
index 0000000..ce22ea7
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey-export.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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 <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+#include "utils.h"
+
+/* This checks whether the public parts of RSA private and public keys
+ * can be properly extracted from a PKCS#11 module. */
+
+#define PIN "1234"
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+
+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)
+{
+ int ret;
+ const char *lib;
+ gnutls_privkey_t key;
+ gnutls_pubkey_t pub;
+ gnutls_datum_t m1, e1;
+ gnutls_datum_t m2, e2;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_privkey_init(&key);
+ assert(ret>=0);
+ ret = gnutls_pubkey_init(&pub);
+ assert(ret>=0);
+
+ gnutls_privkey_set_pin_function(key, pin_func, NULL);
+
+ ret = gnutls_privkey_import_url(key, "pkcs11:object=test", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pubkey_import_privkey(pub, key, 0, 0);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pubkey_export_rsa_raw(pub, &m1, &e1);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pubkey_deinit(pub);
+ gnutls_privkey_deinit(key);
+
+ /* try again using gnutls_pubkey_import_url */
+ ret = gnutls_pubkey_init(&pub);
+ assert(ret>=0);
+
+ ret = gnutls_pubkey_import_url(pub, "pkcs11:object=test;type=public", 0);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pubkey_export_rsa_raw(pub, &m2, &e2);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(m1.size == m2.size);
+ assert(e1.size == e2.size);
+ assert(memcmp(e1.data, e2.data, e2.size)==0);
+ assert(memcmp(m1.data, m2.data, m2.size)==0);
+
+ gnutls_pubkey_deinit(pub);
+ gnutls_free(m1.data);
+ gnutls_free(e1.data);
+ gnutls_free(m2.data);
+ gnutls_free(e2.data);
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/pkcs11-privkey-fork-reinit.c b/tests/pkcs11/pkcs11-privkey-fork-reinit.c
new file mode 100644
index 0000000..a725842
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey-fork-reinit.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2016-2017 Red Hat, Inc.
+ *
+ * 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 <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+#include "utils.h"
+
+/* Tests whether a gnutls_privkey_t will continue to work after
+ * a fork(), when gnutls_pkcs11_reinit() is manually called. */
+
+#if defined(HAVE___REGISTER_ATFORK)
+
+#define PIN "1234"
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+
+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)
+{
+ int ret;
+ const char *lib;
+ gnutls_privkey_t key;
+ gnutls_datum_t sig = {NULL, 0}, data;
+ pid_t pid;
+
+ data.data = (void*)"\x38\x17\x0c\x08\xcb\x45\x8f\xd4\x87\x9c\x34\xb6\xf6\x08\x29\x4c\x50\x31\x2b\xbb";
+ data.size = 20;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_privkey_init(&key);
+ assert(ret>=0);
+
+ gnutls_privkey_set_pin_function(key, pin_func, NULL);
+
+ ret = gnutls_privkey_import_url(key, "pkcs11:object=test", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_free(sig.data);
+
+ pid = fork();
+ if (pid != 0) {
+ int status;
+ assert(waitpid(pid, &status, 0) >= 0);
+
+ if (WEXITSTATUS(status) != 0) {
+ fail("child return status was unexpected: %d\n", WEXITSTATUS(status));
+ exit(1);
+ }
+ } else { /* child */
+
+ ret = gnutls_pkcs11_reinit();
+ assert(ret == 0);
+
+ ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_free(sig.data);
+ gnutls_privkey_deinit(key);
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+ exit(0);
+ }
+
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_privkey_deinit(key);
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+}
+#else
+void doit(void)
+{
+ exit(77);
+}
+#endif
diff --git a/tests/pkcs11/pkcs11-privkey-fork.c b/tests/pkcs11/pkcs11-privkey-fork.c
new file mode 100644
index 0000000..b99755c
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey-fork.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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 <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+#include "utils.h"
+
+/* Tests whether a gnutls_privkey_t will continue to work after
+ * a fork(). */
+
+#if defined(HAVE___REGISTER_ATFORK)
+
+#define PIN "1234"
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+
+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)
+{
+ int ret;
+ const char *lib;
+ gnutls_privkey_t key;
+ gnutls_datum_t sig = {NULL, 0}, data;
+ pid_t pid;
+
+ data.data = (void*)"\x38\x17\x0c\x08\xcb\x45\x8f\xd4\x87\x9c\x34\xb6\xf6\x08\x29\x4c\x50\x31\x2b\xbb";
+ data.size = 20;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_privkey_init(&key);
+ assert(ret>=0);
+
+ gnutls_privkey_set_pin_function(key, pin_func, NULL);
+
+ ret = gnutls_privkey_import_url(key, "pkcs11:object=test", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_free(sig.data);
+
+ pid = fork();
+ if (pid != 0) {
+ int status;
+ assert(waitpid(pid, &status, 0) >= 0);
+
+ if (WEXITSTATUS(status) != 0) {
+ fail("child return status was unexpected: %d\n", WEXITSTATUS(status));
+ exit(1);
+ }
+ } else { /* child */
+ ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_free(sig.data);
+ gnutls_privkey_deinit(key);
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+ exit(0);
+ }
+
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_privkey_deinit(key);
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+}
+#else
+void doit(void)
+{
+ exit(77);
+}
+#endif
diff --git a/tests/pkcs11/pkcs11-privkey-generate.c b/tests/pkcs11/pkcs11-privkey-generate.c
new file mode 100644
index 0000000..102cf4b
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey-generate.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2018 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include <gnutls/pkcs11.h>
+
+#ifdef _WIN32
+
+void doit(void)
+{
+ exit(77);
+}
+
+#else
+
+#include "../utils.h"
+#include "softhsm.h"
+#include <assert.h>
+
+#define CONFIG_NAME "softhsm-generate"
+#define CONFIG CONFIG_NAME".config"
+#define PIN "1234"
+/* Tests whether a gnutls_privkey_generate3 will work generate a key
+ * which is marked as sensitive.
+ */
+
+static unsigned pin_called = 0;
+static const char *_pin = PIN;
+
+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 (_pin == NULL)
+ return -1;
+
+ strcpy(pin, _pin);
+ pin_called++;
+ return 0;
+}
+
+void doit(void)
+{
+ char buf[128];
+ int ret;
+ const char *lib, *bin;
+ gnutls_datum_t out;
+ unsigned flags;
+ gnutls_pkcs11_obj_t obj;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ 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_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+
+ /* generate sensitive */
+ ret = gnutls_pkcs11_privkey_generate3("pkcs11:token=test", GNUTLS_PK_RSA, 2048,
+ "testkey", NULL, GNUTLS_X509_FMT_DER,
+ &out, 0, GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_pkcs11_obj_init(&obj) >= 0);
+ assert(out.size > 0);
+
+ gnutls_pkcs11_obj_set_pin_function(obj, pin_func, NULL);
+ assert(gnutls_pkcs11_obj_import_url(obj, "pkcs11:token=test;object=testkey;type=private", GNUTLS_PKCS11_OBJ_FLAG_LOGIN) >= 0);
+
+ assert(gnutls_pkcs11_obj_get_flags(obj, &flags) >= 0);
+
+ assert(!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE));
+ assert(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE);
+
+ gnutls_free(out.data);
+ gnutls_pkcs11_obj_deinit(obj);
+
+ /* generate non-sensitive */
+ ret = gnutls_pkcs11_privkey_generate3("pkcs11:token=test", GNUTLS_PK_RSA, 2048,
+ "testkey2", NULL, GNUTLS_X509_FMT_DER,
+ &out, 0, GNUTLS_PKCS11_OBJ_FLAG_LOGIN|GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_pkcs11_obj_init(&obj) >= 0);
+ assert(out.size > 0);
+
+ gnutls_pkcs11_obj_set_pin_function(obj, pin_func, NULL);
+ assert(gnutls_pkcs11_obj_import_url(obj, "pkcs11:token=test;object=testkey2;type=private", GNUTLS_PKCS11_OBJ_FLAG_LOGIN) >= 0);
+
+ assert(gnutls_pkcs11_obj_get_flags(obj, &flags) >= 0);
+
+ assert(!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE));
+ assert(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE);
+
+ gnutls_free(out.data);
+ gnutls_pkcs11_obj_deinit(obj);
+
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+ remove(CONFIG);
+}
+#endif
diff --git a/tests/pkcs11/pkcs11-privkey-pthread.c b/tests/pkcs11/pkcs11-privkey-pthread.c
new file mode 100644
index 0000000..8b23759
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey-pthread.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * 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 <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/abstract.h>
+#include <gnutls/crypto.h>
+#include <signal.h>
+#include <unistd.h>
+#include <assert.h>
+#ifndef _WIN32
+# include <netinet/in.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <sys/wait.h>
+# include <pthread.h>
+#endif
+#include "utils.h"
+
+#if !defined(HAVE___REGISTER_ATFORK)
+
+void doit(void)
+{
+ exit(77);
+}
+
+#else
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+/* Tests whether we can use gnutls_privkey_sign() under multiple threads
+ * with the same key when PKCS#11 is in use.
+ */
+
+#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;
+}
+
+typedef struct thread_data_st {
+ gnutls_privkey_t pkey;
+ pthread_t id;
+} thread_data_st;
+
+static void *start_thread(void *arg)
+{
+ thread_data_st *data = arg;
+ int ret;
+ gnutls_datum_t sig;
+
+ ret = gnutls_privkey_sign_data(data->pkey, GNUTLS_DIG_SHA256, 0, &testdata, &sig);
+ if (ret < 0)
+ pthread_exit((void*)-2);
+
+ gnutls_free(sig.data);
+
+ pthread_exit(0);
+}
+
+#define MAX_THREADS 48
+
+static
+void do_thread_stuff(gnutls_privkey_t pkey)
+{
+ int ret;
+ thread_data_st *data;
+ unsigned i;
+ void *retval;
+
+ data = calloc(1, sizeof(thread_data_st)*MAX_THREADS);
+ if (data == NULL)
+ abort();
+
+ for (i=0;i<MAX_THREADS;i++) {
+ data[i].pkey = pkey;
+ ret = pthread_create(&data[i].id, NULL, start_thread, &data[i]);
+ if (ret != 0) {
+ fail("Error creating thread\n");
+ }
+ }
+
+ for (i=0;i<MAX_THREADS;i++) {
+ ret = pthread_join(data[i].id, &retval);
+ if (ret != 0 || retval != NULL) {
+ fail("Error in %d: %p\n", (int)data[i].id, retval);
+ }
+ }
+ free(data);
+
+}
+
+void doit(void)
+{
+ int ret, status;
+ const char *lib;
+ gnutls_privkey_t pkey;
+ pid_t pid;
+
+ signal(SIGPIPE, SIG_IGN);
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(gnutls_privkey_init(&pkey) == 0);
+
+ ret = gnutls_privkey_import_url(pkey, "pkcs11:object=test", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ /* fork to force PKCS#11 reinitialization */
+ pid = fork();
+ if (pid == -1) {
+ exit(1);
+ } else if (pid) {
+ waitpid(pid, &status, 0);
+ check_wait_status(status);
+ goto cleanup;
+ }
+
+ do_thread_stuff(pkey);
+
+ cleanup:
+ gnutls_privkey_deinit(pkey);
+}
+
+#endif
diff --git a/tests/pkcs11/pkcs11-privkey-safenet-always-auth.c b/tests/pkcs11/pkcs11-privkey-safenet-always-auth.c
new file mode 100644
index 0000000..a4ab5b5
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey-safenet-always-auth.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2017 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 <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include <gnutls/pkcs11.h>
+
+#ifdef _WIN32
+
+void doit(void)
+{
+ exit(77);
+}
+
+#else
+
+# include "utils.h"
+# include "pkcs11-mock-ext.h"
+
+/* Tests whether a gnutls_privkey_t will work properly with a key marked
+ * as always authenticate, but on the safenet HSMs where CKA_ALWAYS_AUTHENTICATE
+ * is not supported */
+
+static unsigned pin_called = 0;
+static const char *_pin = "1234";
+
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+
+
+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 (_pin == NULL)
+ return -1;
+
+ strcpy(pin, _pin);
+ pin_called++;
+ return 0;
+}
+
+void doit(void)
+{
+ int ret;
+ const char *lib;
+ gnutls_privkey_t key;
+ gnutls_datum_t sig = {NULL, 0}, data;
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ {
+ void *dl;
+ unsigned int *pflags;
+
+ dl = dlopen(lib, RTLD_NOW);
+ if (dl == NULL) {
+ fail("could not dlopen %s\n", lib);
+ exit(1);
+ }
+
+ pflags = dlsym(dl, "pkcs11_mock_flags");
+ if (pflags == NULL) {
+ fail("could find pkcs11_mock_flags\n");
+ exit(1);
+ }
+
+ *pflags = MOCK_FLAG_SAFENET_ALWAYS_AUTH;
+ }
+
+ data.data = (void*)"\x38\x17\x0c\x08\xcb\x45\x8f\xd4\x87\x9c\x34\xb6\xf6\x08\x29\x4c\x50\x31\x2b\xbb";
+ data.size = 20;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_privkey_init(&key);
+ assert(ret>=0);
+
+ gnutls_privkey_set_pin_function(key, pin_func, NULL);
+
+ ret = gnutls_privkey_import_url(key, "pkcs11:object=test", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ pin_called = 0;
+
+ ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (pin_called == 0) {
+ fail("PIN function wasn't called!\n");
+ }
+ pin_called = 0;
+
+ gnutls_free(sig.data);
+
+ /* call again - should re-authenticate */
+ ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (pin_called == 0) {
+ fail("PIN function wasn't called twice!\n");
+ }
+ pin_called = 0;
+
+ gnutls_free(sig.data);
+
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_privkey_deinit(key);
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+}
+#endif
diff --git a/tests/pkcs11/pkcs11-privkey.c b/tests/pkcs11/pkcs11-privkey.c
new file mode 100644
index 0000000..a4217d4
--- /dev/null
+++ b/tests/pkcs11/pkcs11-privkey.c
@@ -0,0 +1,269 @@
+/*
+ * 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;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ /* 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 0000000..6ee42e8
--- /dev/null
+++ b/tests/pkcs11/pkcs11-pubkey-import-ecdsa.c
@@ -0,0 +1,46 @@
+/*
+ * 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 <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 0000000..f0d64ab
--- /dev/null
+++ b/tests/pkcs11/pkcs11-pubkey-import-rsa.c
@@ -0,0 +1,41 @@
+/*
+ * 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 <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 0000000..57d0d59
--- /dev/null
+++ b/tests/pkcs11/pkcs11-pubkey-import.c
@@ -0,0 +1,219 @@
+/*
+ * 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;
+}
+
+static 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;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ 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/pkcs11-rsa-pss-privkey-test.c b/tests/pkcs11/pkcs11-rsa-pss-privkey-test.c
new file mode 100644
index 0000000..2d1d093
--- /dev/null
+++ b/tests/pkcs11/pkcs11-rsa-pss-privkey-test.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#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"
+
+#define CONFIG_NAME "softhsm-privkey-rsa-pss-test"
+#define CONFIG CONFIG_NAME".config"
+
+/* Tests whether signing with PKCS#11 and RSA-PSS would
+ * generate valid signatures */
+
+#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;
+}
+
+#define myfail(fmt, ...) \
+ fail("%s (iter %d): "fmt, gnutls_sign_get_name(sigalgo), i, ##__VA_ARGS__)
+
+static unsigned verify_rsa_pss_presence(void)
+{
+ unsigned i;
+ unsigned long mechanism;
+ int ret;
+
+ i = 0;
+ do {
+ ret = gnutls_pkcs11_token_get_mechanism("pkcs11:", i++, &mechanism);
+ if (ret >= 0 && mechanism == 0xd /* CKM_RSA_PKCS_PSS*/)
+ return 1;
+ } while(ret>=0);
+
+ return 0;
+}
+
+void doit(void)
+{
+ char buf[128];
+ int ret;
+ 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;
+ unsigned i, sigalgo;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ 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, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (verify_rsa_pss_presence() == 0) {
+ fprintf(stderr, "Skipping test as no RSA-PSS mech is supported\n");
+ exit(77);
+ }
+
+ 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, &cli_ca3_rsa_pss_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, &cli_ca3_rsa_pss_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);
+
+ assert(gnutls_pubkey_init(&pubkey2) == 0);
+ assert(gnutls_pubkey_import_x509_raw
+ (pubkey2, &cli_ca3_rsa_pss_cert, GNUTLS_X509_FMT_PEM, 0) == 0);
+
+ /* this is the algorithm supported by the certificate */
+ sigalgo = GNUTLS_SIGN_RSA_PSS_SHA256;
+
+ for (i = 0; i < 20; i++) {
+ /* check whether privkey and pubkey are operational
+ * by signing and verifying */
+ ret =
+ gnutls_privkey_sign_data2(pkey, sigalgo, 0,
+ &testdata, &sig);
+ if (ret < 0)
+ myfail("Error signing data %s\n", gnutls_strerror(ret));
+
+ /* verify against the pubkey in PKCS #11 */
+ ret =
+ gnutls_pubkey_verify_data2(pubkey, sigalgo, 0,
+ &testdata, &sig);
+ if (ret < 0)
+ myfail("Error verifying data1: %s\n",
+ gnutls_strerror(ret));
+
+ /* verify against the raw pubkey */
+ ret =
+ gnutls_pubkey_verify_data2(pubkey2, sigalgo, 0,
+ &testdata, &sig);
+ if (ret < 0)
+ myfail("Error verifying data2: %s\n",
+ gnutls_strerror(ret));
+
+ 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/pkcs11-token-raw.c b/tests/pkcs11/pkcs11-token-raw.c
new file mode 100644
index 0000000..04ff12d
--- /dev/null
+++ b/tests/pkcs11/pkcs11-token-raw.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016-2018 Red Hat, Inc.
+ *
+ * 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/pkcs11.h>
+#ifndef CRYPTOKI_GNU
+# define CRYPTOKI_GNU
+#endif
+#include <p11-kit/pkcs11.h>
+
+#include "utils.h"
+
+/* Tests whether a gnutls_pkcs11_token_get_ptr returns valid handles. */
+
+#if defined(HAVE___REGISTER_ATFORK)
+
+#ifdef _WIN32
+# define P11LIB "libpkcs11mock1.dll"
+#else
+# include <dlfcn.h>
+# define P11LIB "libpkcs11mock1.so"
+#endif
+
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+
+#define TOKEN_NAME "whatever"
+void doit(void)
+{
+ int ret;
+ const char *lib;
+ unsigned long slot_id;
+ struct ck_function_list *mod;
+ struct ck_info info;
+ struct ck_token_info tinfo;
+ ck_rv_t rv;
+
+ ret = global_init();
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ lib = getenv("P11MOCKLIB1");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ {
+ static const char url[] = "pkcs11:token="TOKEN_NAME;
+
+ /* Testing a too small buffer */
+ size_t size = 1;
+ char *buf = gnutls_malloc(size);
+ assert(buf != NULL);
+ ret = gnutls_pkcs11_token_get_info(url,
+ GNUTLS_PKCS11_TOKEN_LABEL,
+ buf, &size);
+ assert(ret == GNUTLS_E_SHORT_MEMORY_BUFFER);
+ assert(size == strlen(TOKEN_NAME)+1);
+
+ /* Testing a too small buffer by one */
+ size -= 1;
+ buf = gnutls_realloc(buf, size);
+ assert(buf != NULL);
+ ret = gnutls_pkcs11_token_get_info(url,
+ GNUTLS_PKCS11_TOKEN_LABEL,
+ buf, &size);
+ assert(ret == GNUTLS_E_SHORT_MEMORY_BUFFER);
+ assert(size == strlen(TOKEN_NAME)+1);
+
+ /* Testing an exactly fitting buffer */
+ buf = gnutls_realloc(buf, size);
+ assert(buf != NULL);
+ ret = gnutls_pkcs11_token_get_info(url,
+ GNUTLS_PKCS11_TOKEN_LABEL,
+ buf, &size);
+ assert(ret == 0);
+ assert(strcmp(buf, TOKEN_NAME) == 0);
+ assert(size == strlen(TOKEN_NAME));
+
+ gnutls_free(buf);
+ }
+
+ ret = gnutls_pkcs11_token_get_ptr("pkcs11:token=invalid", (void**)&mod, &slot_id, 0);
+ assert(ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
+ ret = gnutls_pkcs11_token_get_ptr("pkcs11:", (void**)&mod, &slot_id, 0);
+ if (ret < 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ rv = mod->C_GetInfo(&info);
+ if (rv != CKR_OK) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(info.cryptoki_version.major == 0x02);
+ assert(info.cryptoki_version.minor == 0x14);
+ assert(info.flags == 0);
+ assert(info.library_version.major == 0x01);
+ assert(info.library_version.minor == 0x00);
+
+ rv = mod->C_GetTokenInfo(slot_id, &tinfo);
+ if (rv != CKR_OK) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ assert(tinfo.session_count == 0);
+ assert(tinfo.hardware_version.major == 0x01);
+ assert(tinfo.firmware_version.major == 0x01);
+
+ if (debug)
+ printf("done\n\n\n");
+
+ gnutls_pkcs11_deinit();
+ gnutls_global_deinit();
+}
+#else
+void doit(void)
+{
+ exit(77);
+}
+#endif
diff --git a/tests/pkcs11/softhsm.h b/tests/pkcs11/softhsm.h
new file mode 100644
index 0000000..725d29e
--- /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 (sizeof(long) == 8 && 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 (sizeof(long) == 8 && 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
diff --git a/tests/pkcs11/tls-neg-pkcs11-key.c b/tests/pkcs11/tls-neg-pkcs11-key.c
new file mode 100644
index 0000000..25f08ac
--- /dev/null
+++ b/tests/pkcs11/tls-neg-pkcs11-key.c
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2017 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+/* This tests TLS negotiation using the gnutls_privkey_import_ext2() APIs */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef _WIN32
+# include <netinet/in.h>
+# include <sys/socket.h>
+# include <arpa/inet.h>
+#endif
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include <assert.h>
+#include "cert-common.h"
+#include "eagain-common.h"
+#include "utils.h"
+#include "softhsm.h"
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "<%d> %s", level, str);
+}
+
+#define CONFIG_NAME "softhsm-neg"
+#define CONFIG CONFIG_NAME".config"
+#define PIN "1234"
+
+#define testfail(fmt, ...) \
+ fail("%s: "fmt, name, ##__VA_ARGS__)
+
+static unsigned verify_eddsa_presence(void)
+{
+ unsigned i;
+ unsigned long mechanism;
+ int ret;
+
+ i = 0;
+ do {
+ ret = gnutls_pkcs11_token_get_mechanism("pkcs11:", i++, &mechanism);
+ if (ret >= 0 && mechanism == 0x1057 /* CKM_EDDSA */)
+ return 1;
+ } while(ret>=0);
+
+ return 0;
+}
+
+static gnutls_privkey_t load_virt_privkey(const char *name, const gnutls_datum_t *txtkey,
+ int exp_key_err, unsigned needs_decryption)
+{
+ unsigned flags;
+ gnutls_privkey_t privkey;
+ gnutls_x509_privkey_t tmp;
+ int ret;
+
+ ret = gnutls_x509_privkey_init(&tmp);
+ if (ret < 0)
+ testfail("gnutls_privkey_init\n");
+
+ ret = gnutls_x509_privkey_import(tmp, txtkey, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ testfail("gnutls_privkey_import: %s\n", gnutls_strerror(ret));
+
+ if (needs_decryption)
+ flags = GNUTLS_KEY_KEY_ENCIPHERMENT;
+ else
+ flags = GNUTLS_KEY_DIGITAL_SIGNATURE;
+
+ ret = gnutls_pkcs11_copy_x509_privkey(SOFTHSM_URL, tmp, "key", flags,
+ GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE|GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE|GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ gnutls_x509_privkey_deinit(tmp);
+
+ if (ret < 0) {
+ if (ret == exp_key_err) {
+ return NULL;
+ }
+ fail("gnutls_pkcs11_copy_x509_privkey: %s\n", gnutls_strerror(ret));
+ }
+
+ ret = gnutls_privkey_init(&privkey);
+ if (ret < 0)
+ testfail("gnutls_privkey_init\n");
+
+ ret =
+ gnutls_privkey_import_url(privkey, SOFTHSM_URL";object=key", 0);
+ if (ret < 0) {
+ if (ret == exp_key_err) {
+ gnutls_privkey_deinit(privkey);
+ return NULL;
+ }
+ testfail("gnutls_privkey_import: %s\n", gnutls_strerror(ret));
+ }
+
+ if (exp_key_err) {
+ testfail("did not fail in key import, although expected\n");
+ }
+
+ return privkey;
+}
+
+static
+void try_with_key(const char *name, const char *client_prio,
+ gnutls_kx_algorithm_t client_kx,
+ gnutls_sign_algorithm_t server_sign_algo,
+ gnutls_sign_algorithm_t client_sign_algo,
+ const gnutls_datum_t *serv_cert,
+ gnutls_privkey_t key,
+ int exp_serv_err)
+{
+ int ret;
+ gnutls_pcert_st pcert_list[4];
+ unsigned pcert_list_size;
+ /* Server stuff. */
+ gnutls_certificate_credentials_t s_xcred;
+ gnutls_session_t server;
+ int sret = GNUTLS_E_AGAIN;
+ /* Client stuff. */
+ gnutls_certificate_credentials_t c_xcred;
+ gnutls_session_t client;
+ int cret = GNUTLS_E_AGAIN, version;
+ const char *err;
+
+ /* General init. */
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(6);
+
+ reset_buffers();
+ /* Init server */
+ gnutls_certificate_allocate_credentials(&s_xcred);
+
+ pcert_list_size = sizeof(pcert_list)/sizeof(pcert_list[0]);
+ ret = gnutls_pcert_list_import_x509_raw(pcert_list, &pcert_list_size,
+ serv_cert, GNUTLS_X509_FMT_PEM, 0);
+ if (ret < 0) {
+ testfail("error in gnutls_pcert_list_import_x509_raw: %s\n", gnutls_strerror(ret));
+ }
+
+ ret = gnutls_certificate_set_key(s_xcred, NULL, 0, pcert_list,
+ pcert_list_size, key);
+ if (ret < 0) {
+ testfail("Could not set key/cert: %s\n", gnutls_strerror(ret));
+ }
+
+ gnutls_init(&server, GNUTLS_SERVER);
+ gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
+ s_xcred);
+
+ assert(gnutls_priority_set_direct(server,
+ "NORMAL:+VERS-SSL3.0:+ANON-ECDH:+ANON-DH:+ECDHE-RSA:+DHE-RSA:+RSA:+ECDHE-ECDSA:+CURVE-X25519:+SIGN-EDDSA-ED25519",
+ NULL) >= 0);
+ gnutls_transport_set_push_function(server, server_push);
+ gnutls_transport_set_pull_function(server, server_pull);
+ gnutls_transport_set_ptr(server, server);
+
+ /* Init client */
+
+ ret = gnutls_certificate_allocate_credentials(&c_xcred);
+ if (ret < 0)
+ exit(1);
+
+ ret = gnutls_init(&client, GNUTLS_CLIENT);
+ if (ret < 0)
+ exit(1);
+
+ ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
+ c_xcred);
+ if (ret < 0)
+ exit(1);
+
+ gnutls_transport_set_push_function(client, client_push);
+ gnutls_transport_set_pull_function(client, client_pull);
+ gnutls_transport_set_ptr(client, client);
+
+ ret = gnutls_priority_set_direct(client, client_prio, &err);
+ if (ret < 0) {
+ if (ret == GNUTLS_E_INVALID_REQUEST)
+ fprintf(stderr, "Error in %s\n", err);
+ exit(1);
+ }
+ if (exp_serv_err) {
+ HANDSHAKE_EXPECT(client, server, GNUTLS_E_AGAIN, exp_serv_err);
+ goto cleanup;
+ } else {
+ HANDSHAKE(client, server);
+ }
+
+ if (gnutls_kx_get(client) != client_kx) {
+ testfail("%s: got unexpected key exchange algorithm: %s (expected %s)\n", name, gnutls_kx_get_name(gnutls_kx_get(client)),
+ gnutls_kx_get_name(client_kx));
+ exit(1);
+ }
+
+ /* test signature algorithm match */
+ version = gnutls_protocol_get_version(client);
+ if (version >= GNUTLS_TLS1_2) {
+ ret = gnutls_sign_algorithm_get(server);
+ if (ret != (int)server_sign_algo && server_sign_algo != 0) {
+ testfail("%s: got unexpected server signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret));
+ exit(1);
+ }
+
+ ret = gnutls_sign_algorithm_get_client(server);
+ if (ret != (int)client_sign_algo && client_sign_algo != 0) {
+ testfail("%s: got unexpected client signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret));
+ exit(1);
+ }
+
+ ret = gnutls_sign_algorithm_get(client);
+ if (ret != (int)server_sign_algo && server_sign_algo != 0) {
+ testfail("%s: cl: got unexpected server signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret));
+ exit(1);
+ }
+
+ ret = gnutls_sign_algorithm_get_client(client);
+ if (ret != (int)client_sign_algo && client_sign_algo != 0) {
+ testfail("%s: cl: got unexpected client signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret));
+ exit(1);
+ }
+ }
+
+ gnutls_bye(client, GNUTLS_SHUT_RDWR);
+ gnutls_bye(server, GNUTLS_SHUT_RDWR);
+
+ cleanup:
+ gnutls_deinit(client);
+ gnutls_deinit(server);
+
+ gnutls_certificate_free_credentials(s_xcred);
+ gnutls_certificate_free_credentials(c_xcred);
+}
+
+typedef struct test_st {
+ const char *name;
+ gnutls_pk_algorithm_t pk;
+ const char *prio;
+ const gnutls_datum_t *cert;
+ const gnutls_datum_t *key;
+ gnutls_kx_algorithm_t exp_kx;
+ int exp_key_err;
+ int exp_serv_err;
+ int needs_eddsa;
+ int needs_decryption;
+ int nofips;
+ unsigned requires_pkcs11_pss;
+} test_st;
+
+static const test_st tests[] = {
+ {.name = "tls1.2: rsa-decryption key",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:-KX-ALL:+RSA:-VERS-TLS-ALL:+VERS-TLS1.2",
+ .cert = &server_ca3_localhost_rsa_decrypt_cert,
+ .key = &server_ca3_key,
+ .exp_kx = GNUTLS_KX_RSA,
+ .needs_decryption = 1
+ },
+ {.name = "tls1.2: rsa-decryption key, signatures prioritized",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:-KX-ALL:+ECDHE-RSA:+RSA:-VERS-TLS-ALL:+VERS-TLS1.2:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA256",
+ .cert = &server_ca3_localhost_cert,
+ .key = &server_ca3_key,
+ .exp_kx = GNUTLS_KX_RSA,
+ .needs_decryption = 1
+ },
+ {.name = "tls1.2: ecc key",
+ .pk = GNUTLS_PK_ECDSA,
+ .prio = "NORMAL:-KX-ALL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.2",
+ .cert = &server_ca3_localhost_ecc_cert,
+ .key = &server_ca3_ecc_key,
+ .exp_kx = GNUTLS_KX_ECDHE_ECDSA
+ },
+ {.name = "tls1.2: rsa-sign key",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.2",
+ .cert = &server_ca3_localhost_cert,
+ .key = &server_ca3_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA
+ },
+ {.name = "tls1.2: rsa-sign key with rsa-pss sigs prioritized",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512:+SIGN-RSA-SHA256:+SIGN-RSA-SHA384:+SIGN-RSA-SHA512:-VERS-TLS-ALL:+VERS-TLS1.2",
+ .cert = &server_ca3_localhost_cert,
+ .key = &server_ca3_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA
+ },
+ {.name = "tls1.2: rsa-pss-sign key",
+ .pk = GNUTLS_PK_RSA_PSS,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.2",
+ .cert = &server_ca3_rsa_pss2_cert,
+ .key = &server_ca3_rsa_pss2_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA,
+ .requires_pkcs11_pss = 1,
+ },
+ {.name = "tls1.2: rsa-pss cert, rsa-sign key",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.2",
+ .cert = &server_ca3_rsa_pss_cert,
+ .key = &server_ca3_rsa_pss_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA,
+ .requires_pkcs11_pss = 1,
+ },
+ {.name = "tls1.2: rsa-pss cert, rsa-sign key no PSS signatures",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.2:-SIGN-RSA-PSS-SHA256:-SIGN-RSA-PSS-SHA384:-SIGN-RSA-PSS-SHA512:-SIGN-RSA-PSS-RSAE-SHA256:-SIGN-RSA-PSS-RSAE-SHA384:-SIGN-RSA-PSS-RSAE-SHA512",
+ .cert = &server_ca3_rsa_pss_cert,
+ .key = &server_ca3_rsa_pss_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA,
+ .exp_serv_err = GNUTLS_E_NO_CIPHER_SUITES
+ },
+ {.name = "tls1.2: ed25519 cert, ed25519 key",
+ .pk = GNUTLS_PK_EDDSA_ED25519,
+ .needs_eddsa = 1,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA",
+ .cert = &server_ca3_eddsa_cert,
+ .key = &server_ca3_eddsa_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA,
+ .nofips = 1
+ },
+ {.name = "tls1.3: ecc key",
+ .pk = GNUTLS_PK_ECDSA,
+ .prio = "NORMAL:-KX-ALL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.3",
+ .cert = &server_ca3_localhost_ecc_cert,
+ .key = &server_ca3_ecc_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA
+ },
+ {.name = "tls1.3: rsa-sign key",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.3",
+ .cert = &server_ca3_localhost_cert,
+ .key = &server_ca3_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA
+ },
+ {.name = "tls1.3: rsa-sign key with rsa-pss sigs prioritized",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512:+SIGN-RSA-PSS-RSAE-SHA256:+SIGN-RSA-PSS-RSAE-SHA384:+SIGN-RSA-PSS-RSAE-SHA512:-VERS-TLS-ALL:+VERS-TLS1.3",
+ .cert = &server_ca3_localhost_cert,
+ .key = &server_ca3_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA
+ },
+ {.name = "tls1.3: rsa-pss-sign key",
+ .pk = GNUTLS_PK_RSA_PSS,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.3",
+ .cert = &server_ca3_rsa_pss2_cert,
+ .key = &server_ca3_rsa_pss2_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA,
+ .requires_pkcs11_pss = 1,
+ },
+ {.name = "tls1.3: rsa-pss cert, rsa-sign key",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.3",
+ .cert = &server_ca3_rsa_pss_cert,
+ .key = &server_ca3_rsa_pss_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA,
+ .requires_pkcs11_pss = 1,
+ },
+ {.name = "tls1.3: rsa-pss cert, rsa-sign key no PSS signatures",
+ .pk = GNUTLS_PK_RSA,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.3:-SIGN-RSA-PSS-SHA256:-SIGN-RSA-PSS-SHA384:-SIGN-RSA-PSS-SHA512:-SIGN-RSA-PSS-RSAE-SHA256:-SIGN-RSA-PSS-RSAE-SHA384:-SIGN-RSA-PSS-RSAE-SHA512",
+ .cert = &server_ca3_rsa_pss_cert,
+ .key = &server_ca3_rsa_pss_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA,
+ .exp_serv_err = GNUTLS_E_NO_CIPHER_SUITES
+ },
+ {.name = "tls1.3: ed25519 cert, ed25519 key",
+ .needs_eddsa = 1,
+ .pk = GNUTLS_PK_EDDSA_ED25519,
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA",
+ .cert = &server_ca3_eddsa_cert,
+ .key = &server_ca3_eddsa_key,
+ .exp_kx = GNUTLS_KX_ECDHE_RSA,
+ .nofips = 1
+ }
+};
+
+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;
+}
+
+#ifndef CKM_RSA_PKCS_PSS
+# define CKM_RSA_PKCS_PSS (0xdUL)
+#endif
+
+void doit(void)
+{
+ gnutls_privkey_t privkey;
+ const char *bin, *lib;
+ char buf[512];
+ unsigned int i, have_eddsa;
+ int ret;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+#ifdef _WIN32
+ exit(77);
+#endif
+ bin = softhsm_bin();
+
+ lib = softhsm_lib();
+
+ global_init();
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(6);
+
+
+ /* initialize token */
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+ 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, NULL);
+ if (ret < 0) {
+ fail("gnutls_pkcs11_add_provider: %s\n",
+ gnutls_strerror(ret));
+ }
+
+ have_eddsa = verify_eddsa_presence();
+
+ for (i=0;i<sizeof(tests)/sizeof(tests[0]);i++) {
+ if (tests[i].nofips && gnutls_fips140_mode_enabled())
+ continue;
+
+ if (tests[i].needs_eddsa && !have_eddsa)
+ continue;
+
+ success("checking: %s\n", tests[i].name);
+
+ if (tests[i].requires_pkcs11_pss) {
+ ret = gnutls_pkcs11_token_check_mechanism("pkcs11:", CKM_RSA_PKCS_PSS, NULL, 0, 0);
+ if (ret == 0) {
+ fprintf(stderr, "softhsm2 doesn't support CKM_RSA_PKCS_PSS; skipping test\n");
+ continue;
+ }
+ }
+
+ privkey = load_virt_privkey(tests[i].name, tests[i].key, tests[i].exp_key_err, tests[i].needs_decryption);
+ if (privkey == NULL && tests[i].exp_key_err < 0)
+ continue;
+ assert(privkey != 0);
+
+ try_with_key(tests[i].name, tests[i].prio,
+ tests[i].exp_kx, 0, 0,
+ tests[i].cert, privkey,
+ tests[i].exp_serv_err);
+
+ gnutls_pkcs11_delete_url(SOFTHSM_URL";object=key", GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
+ remove(CONFIG);
+ }
+
+ gnutls_global_deinit();
+}
diff --git a/tests/pkcs11/tls-neg-pkcs11-no-key.c b/tests/pkcs11/tls-neg-pkcs11-no-key.c
new file mode 100644
index 0000000..124378d
--- /dev/null
+++ b/tests/pkcs11/tls-neg-pkcs11-no-key.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2017-2019 Red Hat, Inc.
+ *
+ * Author: Daiki Ueno
+ *
+ * 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 Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32)
+
+int main()
+{
+ exit(77);
+}
+
+#else
+
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/dtls.h>
+#include <signal.h>
+#include <assert.h>
+
+#include "cert-common.h"
+#include "tls13/ext-parse.h"
+#include "pkcs11/softhsm.h"
+#include "utils.h"
+
+/* This program tests that TLS 1.3 is disabled as expected.
+ */
+
+static void server_log_func(int level, const char *str)
+{
+ fprintf(stderr, "server|<%d>| %s", level, str);
+}
+
+static void client_log_func(int level, const char *str)
+{
+ fprintf(stderr, "client|<%d>| %s", level, str);
+}
+
+#define P11LIB "libpkcs11mock2.so"
+
+#define PIN "1234"
+
+#define CONFIG_NAME "softhsm-neg-no-key"
+#define CONFIG CONFIG_NAME".config"
+
+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;
+}
+
+static void client(int fd)
+{
+ int ret;
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t x509_cred;
+
+ global_init();
+
+ if (debug) {
+ gnutls_global_set_log_function(client_log_func);
+ gnutls_global_set_log_level(7);
+ }
+
+ ret = gnutls_certificate_allocate_credentials(&x509_cred);
+ if (ret < 0)
+ exit(1);
+
+ ret = gnutls_certificate_set_x509_trust_mem(x509_cred, &ca_cert, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ exit(1);
+
+ /* Initialize TLS session
+ */
+ assert(gnutls_init(&session, GNUTLS_CLIENT)>=0);
+
+ gnutls_handshake_set_timeout(session, get_timeout());
+
+ ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+ if (ret < 0)
+ fail("cannot set credentials\n");
+
+ ret = gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2", NULL);
+ if (ret < 0)
+ fail("cannot set priorities\n");
+
+
+ gnutls_transport_set_int(session, fd);
+
+ /* Perform the TLS handshake
+ */
+ do {
+ ret = gnutls_handshake(session);
+ }
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ if (ret != 0)
+ fail("handshake failed: %s\n", gnutls_strerror(ret));
+
+ if (debug)
+ success("client handshake completed\n");
+
+ if (gnutls_protocol_get_version(session) == GNUTLS_TLS1_2) {
+ if (debug)
+ success("session is downgraded to TLS 1.2\n");
+ } else
+ fail("session is NOT downgraded to TLS 1.2\n");
+
+ do {
+ ret = gnutls_bye(session, GNUTLS_SHUT_WR);
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+
+ close(fd);
+
+ gnutls_deinit(session);
+
+ gnutls_global_deinit();
+}
+
+static void server(int fd)
+{
+ int ret;
+ const char *lib;
+ gnutls_x509_crt_t crt;
+ gnutls_x509_privkey_t key;
+ gnutls_datum_t tmp;
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t x509_cred;
+
+ /* this must be called once in the program
+ */
+ global_init();
+
+ if (debug) {
+ gnutls_global_set_log_function(server_log_func);
+ gnutls_global_set_log_level(4711);
+ }
+
+ /* point to SoftHSM token that libpkcs11mock2.so internally uses */
+ setenv(SOFTHSM_ENV, CONFIG, 1);
+
+ gnutls_pkcs11_set_pin_function(pin_func, NULL);
+
+ lib = getenv("P11MOCKLIB2");
+ if (lib == NULL)
+ lib = P11LIB;
+
+ ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_add_provider(lib, NULL);
+ if (ret != 0) {
+ fail("%d: %s\n", ret, 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_ca3_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_ca3_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);
+
+ assert(gnutls_certificate_allocate_credentials(&x509_cred)>=0);
+
+ gnutls_init(&session, GNUTLS_SERVER);
+
+ gnutls_handshake_set_timeout(session, get_timeout());
+
+ assert(gnutls_certificate_set_x509_key_file(x509_cred,
+ SOFTHSM_URL
+ ";object=cert;object-type=cert",
+ SOFTHSM_URL
+ ";object=cert;object-type=private;pin-value="
+ PIN,
+ GNUTLS_X509_FMT_DER)>=0);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ /* avoid calling all the priority functions, since the defaults
+ * are adequate.
+ */
+ gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2", NULL);
+
+ gnutls_transport_set_int(session, fd);
+
+ do {
+ ret = gnutls_handshake(session);
+ } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ if (ret != 0)
+ fail("handshake failed: %s\n", gnutls_strerror(ret));
+
+ if (debug)
+ success("server handshake completed\n");
+
+ if (gnutls_protocol_get_version(session) == GNUTLS_TLS1_2) {
+ if (debug)
+ success("session is downgraded to TLS 1.2\n");
+ } else
+ fail("session is NOT downgraded to TLS 1.2\n");
+
+ do {
+ ret = gnutls_bye(session, GNUTLS_SHUT_RDWR);
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+
+ close(fd);
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+
+ if (debug)
+ success("server: client/server hello were verified\n");
+}
+
+void doit(void)
+{
+ const char *bin;
+ char buf[128];
+ int fd[2];
+ int ret;
+ pid_t child;
+ int status = 0;
+
+ if (gnutls_fips140_mode_enabled())
+ exit(77);
+
+ /* check if softhsm module is loadable */
+ (void) softhsm_lib();
+
+ /* initialize SoftHSM token that libpkcs11mock2.so internally uses */
+ bin = softhsm_bin();
+
+ set_softhsm_conf(CONFIG);
+ snprintf(buf, sizeof(buf),
+ "%s --init-token --slot 0 --label test --so-pin " PIN " --pin "
+ PIN, bin);
+ system(buf);
+
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+
+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
+ if (ret < 0) {
+ perror("socketpair");
+ exit(1);
+ }
+
+ child = fork();
+ if (child < 0) {
+ perror("fork");
+ fail("fork");
+ exit(1);
+ }
+
+ if (child) {
+ /* parent */
+ close(fd[1]);
+ server(fd[0]);
+ kill(child, SIGTERM);
+ wait(&status);
+ check_wait_status(status);
+ } else {
+ close(fd[0]);
+ client(fd[1]);
+ exit(0);
+ }
+
+}
+#endif /* _WIN32 */