diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-05-18 09:19:16 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2018-05-20 09:47:18 +0200 |
commit | bb9a06cf6757bd2ea4e9333e60e045b281a0d789 (patch) | |
tree | 927f2775e27fc888634c1cd9e4f6d635cf9cd99a | |
parent | 7f75d92eb2150a1b1cfb168fcf6d2c7d5c9bfd78 (diff) | |
download | gnutls-bb9a06cf6757bd2ea4e9333e60e045b281a0d789.tar.gz |
gnutls_pkcs11_token_get_ptr, gnutls_pkcs11_obj_get_ptr: introduced
This allows an application to open a PKCS#11 token using a URI,
and use it directly, bypassing gnutls. That is useful to take
advantage of PKCS#11 functionality not wrapped by gnutls but
still use PKCS#11 URIs to identify the token.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r-- | doc/cha-tokens.texi | 14 | ||||
-rw-r--r-- | lib/errors.c | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/pkcs11.h | 11 | ||||
-rw-r--r-- | lib/libgnutls.map | 2 | ||||
-rw-r--r-- | lib/pkcs11.c | 197 | ||||
-rw-r--r-- | lib/pkcs11_int.h | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 11 | ||||
-rw-r--r-- | tests/pkcs11/pkcs11-obj-raw.c | 188 | ||||
-rw-r--r-- | tests/pkcs11/pkcs11-token-raw.c | 138 |
10 files changed, 559 insertions, 6 deletions
diff --git a/doc/cha-tokens.texi b/doc/cha-tokens.texi index 5915965d47..d984afcc4d 100644 --- a/doc/cha-tokens.texi +++ b/doc/cha-tokens.texi @@ -281,6 +281,7 @@ available in @code{gnutls/pkcs11.h}. * Accessing objects that require a PIN:: * Reading objects:: * Writing objects:: +* PKCS11 Low Level Access:: * Using a PKCS11 token with TLS:: * Verifying certificates over PKCS11:: * p11tool Invocation:: @@ -466,6 +467,19 @@ entered before accessing the object (for operations or otherwise). @showfuncdesc{gnutls_pkcs11_delete_url} +@node PKCS11 Low Level Access +@subsection Low Level Access + +When it is needed to use PKCS#11 functionality which is not wrapped by +GnuTLS, it is possible to extract the PKCS#11 session, object or token pointers. +That allows an application to still access the low-level functionality, +while at the same time take advantage of the URI addressing scheme supported +by GnuTLS. + +@showfuncdesc{gnutls_pkcs11_token_get_ptr} +@showfuncdesc{gnutls_pkcs11_obj_get_ptr} + + @node Using a PKCS11 token with TLS @subsection Using a @acronym{PKCS} #11 token with TLS diff --git a/lib/errors.c b/lib/errors.c index 1e9a64922b..c4bc8c72b9 100644 --- a/lib/errors.c +++ b/lib/errors.c @@ -231,6 +231,8 @@ static const gnutls_error_entry error_entries[] = { GNUTLS_E_TOO_MANY_EMPTY_PACKETS), ERROR_ENTRY(N_("Too many handshake packets have been received."), GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS), + ERROR_ENTRY(N_("More than a single object matches the criteria."), + GNUTLS_E_TOO_MANY_MATCHES), ERROR_ENTRY(N_("The crypto library version is too old."), GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY), diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index fd3b07af78..dac1c505dd 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -3079,6 +3079,7 @@ void gnutls_fips140_set_mode(gnutls_fips_mode_t mode, unsigned flags); #define GNUTLS_E_NO_COMMON_KEY_SHARE -423 #define GNUTLS_E_REAUTH_REQUEST -424 +#define GNUTLS_E_TOO_MANY_MATCHES -425 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250 diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h index 630fb7d014..3a442c8284 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010-2012 Free Software Foundation, Inc. + * Copyright (C) 2016-2018 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -294,6 +295,12 @@ typedef enum { GNUTLS_PKCS11_OBJ_LIBRARY_MANUFACTURER } gnutls_pkcs11_obj_info_t; +int +gnutls_pkcs11_obj_get_ptr(gnutls_pkcs11_obj_t obj, void **ptr, + void **session, void **ohandle, + unsigned long *slot_id, + unsigned int flags); + int gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t obj, gnutls_pkcs11_obj_info_t itype, void *output, size_t * output_size); @@ -356,6 +363,10 @@ gnutls_pkcs11_token_init(const char *token_url, const char *so_pin, const char *label); int +gnutls_pkcs11_token_get_ptr(const char *url, void **ptr, unsigned long *slot_id, + unsigned int flags); + +int gnutls_pkcs11_token_get_mechanism(const char *url, unsigned int idx, unsigned long *mechanism); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 17cd8ff2b3..bcde6c177b 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1217,6 +1217,8 @@ GNUTLS_3_6_3 gnutls_ext_raw_parse; gnutls_x509_crt_list_import_url; gnutls_pcert_list_import_x509_file; + gnutls_pkcs11_token_get_ptr; + gnutls_pkcs11_obj_get_ptr; } GNUTLS_3_6_2; GNUTLS_FIPS140_3_4 { diff --git a/lib/pkcs11.c b/lib/pkcs11.c index b31c1a0a14..bb07b5cfe8 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -70,6 +70,14 @@ struct find_url_data_st { bool overwrite_exts; /* only valid if looking for a certificate */ }; +struct find_obj_session_st { + gnutls_pkcs11_obj_t obj; + struct ck_function_list *ptr; + ck_session_handle_t pks; + ck_object_handle_t ohandle; + unsigned long slot_id; +}; + struct find_obj_data_st { gnutls_pkcs11_obj_t *p_list; unsigned int current; @@ -87,6 +95,8 @@ struct find_token_num { struct find_token_modname { struct p11_kit_uri *info; char *modname; + void *ptr; + unsigned long slot_id; }; struct find_pkey_list_st { @@ -625,6 +635,129 @@ gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t obj, return pkcs11_get_info(obj->info, itype, output, output_size); } +static int +find_obj_session_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo, + struct ck_token_info *tinfo, struct ck_info *lib_info, + void *input) +{ + struct find_obj_session_st *find_data = input; + struct ck_attribute a[4]; + ck_rv_t rv; + ck_object_handle_t ctx = CK_INVALID_HANDLE; + unsigned long count; + unsigned a_vals; + ck_certificate_type_t type; + ck_object_class_t class; + int found = 0, ret; + + if (tinfo == NULL) { /* we don't support multiple calls */ + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + /* do not bother reading the token if basic fields do not match + */ + if (!p11_kit_uri_match_token_info + (find_data->obj->info, tinfo) + || !p11_kit_uri_match_module_info(find_data->obj->info, + lib_info)) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + ret = add_obj_attrs(find_data->obj->info, a, &a_vals, &class, &type); + if (ret < 0) + return gnutls_assert_val(ret); + + rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, + a_vals); + if (rv != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("p11: FindObjectsInit failed.\n"); + ret = pkcs11_rv_to_err(rv); + goto cleanup; + } + + if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK && + count == 1) { + find_data->ptr = sinfo->module; + find_data->pks = sinfo->pks; + find_data->slot_id = sinfo->sid; + find_data->ohandle = ctx; + found = 1; + } + + if (found == 0) { + gnutls_assert(); + if (count > 1) + ret = GNUTLS_E_TOO_MANY_MATCHES; + else + ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + + } else { + ret = 0; + } + + cleanup: + pkcs11_find_objects_final(sinfo); + + return ret; +} + + +/** + * gnutls_pkcs11_obj_get_ptr: + * @obj: should contain a #gnutls_pkcs11_obj_t type + * @ptr: will contain the CK_FUNCTION_LIST_PTR pointer (may be %NULL) + * @session: will contain the CK_SESSION_HANDLE of the object + * @ohandle: will contain the CK_OBJECT_HANDLE of the object + * @slot_id: the identifier of the slot (may be %NULL) + * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags + * + * Obtains the PKCS#11 session handles of an object. @session and @ohandle + * must be deinitialized by the caller. The returned pointers are + * independent of the @obj lifetime. + * + * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code + * on error. + * + * Since: 3.6.3 + **/ +int +gnutls_pkcs11_obj_get_ptr(gnutls_pkcs11_obj_t obj, void **ptr, + void **session, void **ohandle, + unsigned long *slot_id, + unsigned int flags) +{ + int ret; + struct find_obj_session_st find_data; + + PKCS11_CHECK_INIT; + memset(&find_data, 0, sizeof(find_data)); + + find_data.obj = obj; + + ret = + _pkcs11_traverse_tokens(find_obj_session_cb, &find_data, obj->info, + &obj->pin, + SESSION_NO_CLOSE|pkcs11_obj_flags_to_int(flags)); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (ptr) + *ptr = find_data.ptr; + + *ohandle = (void*)find_data.ohandle; + *session = (void*)find_data.pks; + + if (slot_id) + *slot_id = find_data.slot_id; + + return 0; +} + int pkcs11_get_info(struct p11_kit_uri *info, gnutls_pkcs11_obj_info_t itype, void *output, @@ -1515,7 +1648,8 @@ _pkcs11_traverse_tokens(find_func_t find_func, void *input, } if (pks != 0 && module != NULL) { - pkcs11_close_session(&sinfo); + if (ret != 0 || !(flags & SESSION_NO_CLOSE)) + pkcs11_close_session(&sinfo); } return ret; @@ -2061,10 +2195,8 @@ find_obj_url_cb(struct ck_function_list *module, struct pkcs11_session_info *sin } ret = add_obj_attrs(find_data->obj->info, a, &a_vals, &class, &type); - if (ret < 0) { - gnutls_assert(); - return ret; - } + if (ret < 0) + return gnutls_assert_val(ret); rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, a_vals); @@ -2230,6 +2362,8 @@ find_token_modname_cb(struct ck_function_list *module, struct pkcs11_session_inf } find_data->modname = p11_kit_config_option(module, "module"); + find_data->ptr = module; + find_data->slot_id = sinfo->sid; return 0; } @@ -2404,6 +2538,59 @@ gnutls_pkcs11_token_get_info(const char *url, } /** + * gnutls_pkcs11_token_get_ptr: + * @url: should contain a PKCS#11 URL identifying a token + * @ptr: will contain the CK_FUNCTION_LIST_PTR pointer + * @slot_id: will contain the slot_id (may be %NULL) + * @flags: should be zero + * + * This function will return the function pointer of the specified + * token by the URL. The returned pointers are valid until + * gnutls is deinitialized, c.f. _global_deinit(). + * + * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code + * on error. + * + * Since: 3.6.3 + **/ +int +gnutls_pkcs11_token_get_ptr(const char *url, void **ptr, unsigned long *slot_id, + unsigned int flags) +{ + struct p11_kit_uri *info = NULL; + int ret; + struct find_token_modname tn; + + PKCS11_CHECK_INIT; + + ret = pkcs11_url_to_info(url, &info, 0); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + memset(&tn, 0, sizeof(tn)); + tn.info = info; + + ret = _pkcs11_traverse_tokens(find_token_modname_cb, &tn, NULL, NULL, 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + if (ptr) + *ptr = tn.ptr; + if (slot_id) + *slot_id = tn.slot_id; + + ret = 0; + + cleanup: + p11_kit_uri_free(info); + return ret; +} + +/** * gnutls_pkcs11_obj_export_url: * @obj: Holds the PKCS 11 certificate * @detailed: non zero if a detailed URL is required diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h index 2b0b07ad2d..62831d89c2 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -173,6 +173,7 @@ _gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt, #define SESSION_TRUSTED (1<<3) /* session on a marked as trusted (p11-kit) module */ #define SESSION_FORCE_LOGIN (1<<4) /* force login even when CFK_LOGIN_REQUIRED is not set */ #define SESSION_CONTEXT_SPECIFIC (1<<5) +#define SESSION_NO_CLOSE (1<<6) /* don't close session on success */ int pkcs11_open_session(struct pkcs11_session_info *sinfo, struct pin_info_st *pin_info, diff --git a/tests/Makefile.am b/tests/Makefile.am index 290387bdac..a7e57ccea1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -288,6 +288,14 @@ pkcs11_import_url_privkey_SOURCES = pkcs11/pkcs11-import-url-privkey.c pkcs11_import_url_privkey_DEPENDENCIES = libpkcs11mock1.la libutils.la pkcs11_import_url_privkey_LDADD = $(LDADD) $(LIBDL) +pkcs11_token_raw_SOURCES = pkcs11/pkcs11-token-raw.c +pkcs11_token_raw_DEPENDENCIES = libpkcs11mock1.la libutils.la +pkcs11_token_raw_LDADD = $(LDADD) $(LIBDL) + +pkcs11_obj_raw_SOURCES = pkcs11/pkcs11-obj-raw.c +pkcs11_obj_raw_DEPENDENCIES = libpkcs11mock1.la libutils.la +pkcs11_obj_raw_LDADD = $(LDADD) $(LIBDL) + pkcs11_privkey_fork_SOURCES = pkcs11/pkcs11-privkey-fork.c pkcs11_privkey_fork_DEPENDENCIES = libpkcs11mock1.la libutils.la pkcs11_privkey_fork_LDADD = $(LDADD) $(LIBDL) @@ -322,7 +330,8 @@ ctests += pkcs11-cert-import-url-exts pkcs11-get-exts pkcs11-get-raw-issuer-exts pkcs11/pkcs11-privkey-pthread pkcs11/pkcs11-pin-func pkcs11/pkcs11-obj-import \ pkcs11-privkey-fork-reinit pkcs11-mechanisms pkcs11-privkey-safenet-always-auth \ pkcs11/pkcs11-rsa-pss-privkey-test pkcs11/tls-neg-pkcs11-key pkcs11/pkcs11-privkey-generate \ - pkcs11/gnutls_x509_crt_list_import_url pkcs11/gnutls_pcert_list_import_x509_file + pkcs11/gnutls_x509_crt_list_import_url pkcs11/gnutls_pcert_list_import_x509_file \ + pkcs11-token-raw pkcs11-obj-raw endif diff --git a/tests/pkcs11/pkcs11-obj-raw.c b/tests/pkcs11/pkcs11-obj-raw.c new file mode 100644 index 0000000000..f093928447 --- /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 <http://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-token-raw.c b/tests/pkcs11/pkcs11-token-raw.c new file mode 100644 index 0000000000..bbcb23eb81 --- /dev/null +++ b/tests/pkcs11/pkcs11-token-raw.c @@ -0,0 +1,138 @@ +/* + * 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 <http://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); +} + +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); + } + + 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 |