lib/openpgp/Makefile
lib/openpgp/Makefile.in
lib/openpgp/pgp-api.texi
+lib/pkcs11/libgnutls_pkcs11.la
+lib/pkcs11/Makefile
+lib/pkcs11/Makefile.in
lib/priority_options.h
.libs
libtool
lib/includes/gnutls/gnutls.h
lib/minitasn1/Makefile
lib/nettle/Makefile
+ lib/pkcs11/Makefile
lib/x509/Makefile
lib/unistring/Makefile
po/Makefile.in
SUBDIRS = includes x509 auth ext algorithms extras accelerated
+if ENABLE_PKCS11
+SUBDIRS += pkcs11
+endif
+
if ENABLE_MINITASN1
SUBDIRS += minitasn1
endif
thirdparty_libadd += $(LTLIBINTL) $(LIBSOCKET) $(LTLIBNSL) \
$(P11_KIT_LIBS) $(LIB_SELECT) $(GNUTLS_LIBS_PRIVATE)
+if ENABLE_PKCS11
+libgnutls_la_LIBADD += pkcs11/libgnutls_pkcs11.la
+endif
+
if HAVE_LIBIDN2
thirdparty_libadd += $(LIBIDN2_LIBS)
endif
#include <leancrypto.h>
#endif
+#ifdef ENABLE_PKCS11
+#include "pkcs11/p11_provider.h"
+#endif
+
/* Minimum library versions we accept. */
#define GNUTLS_MIN_LIBTASN1_VERSION "0.3.4"
int ret = 0, res;
int level;
const char *e;
+#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
+ const char *p11_provider_path = NULL;
+ const char *p11_provider_pin = NULL;
+#endif
if (!constructor) {
ret = gnutls_static_mutex_lock(&global_init_mutex);
_gnutls_fips_mode_reset_zombie();
}
#endif
+
_gnutls_prepare_to_load_system_priorities();
+
+#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
+ p11_provider_path = _gnutls_config_get_p11_provider_path();
+ p11_provider_pin = _gnutls_config_get_p11_provider_pin();
+
+ if (res == 1 && p11_provider_path != NULL) {
+ ret = _p11_provider_init(p11_provider_path,
+ (const uint8_t *)p11_provider_pin,
+ strlen(p11_provider_pin));
+ if (ret < 0) {
+ gnutls_assert();
+ goto out;
+ }
+ }
+#endif
+
_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
ret = 0;
_gnutls_supplemental_deinit();
_gnutls_unload_system_priorities();
+#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
+ _p11_provider_deinit();
+#endif
+
#ifdef ENABLE_PKCS11
/* Do not try to deinitialize the PKCS #11 libraries
* from the destructor. If we do and the PKCS #11 modules
bool _gnutls_config_is_ktls_enabled(void);
bool _gnutls_config_is_rsa_pkcs1_encrypt_allowed(void);
int _gnutls_config_set_certificate_compression_methods(gnutls_session_t session);
+const char *_gnutls_config_get_p11_provider_path(void);
+const char *_gnutls_config_get_p11_provider_pin(void);
#endif /* GNUTLS_LIB_GNUTLS_INT_H */
--- /dev/null
+## Process this file with automake to produce Makefile.in
+# Copyright (C) 2025 Red Hat, Inc.
+#
+# Author: Zoltan Fridrich
+#
+# This file is part of GnuTLS.
+#
+# The GnuTLS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser 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/>
+
+include $(top_srcdir)/lib/common.mk
+
+AM_CPPFLAGS += \
+ -I$(srcdir)/../../gl \
+ -I$(builddir)/../../gl \
+ -I$(srcdir)/../includes \
+ -I$(builddir)/../includes \
+ -I$(srcdir)/.. \
+ $(LIBTASN1_CFLAGS) \
+ $(P11_KIT_CFLAGS)
+
+if ENABLE_MINITASN1
+AM_CPPFLAGS += -I$(srcdir)/../minitasn1
+endif
+
+noinst_LTLIBRARIES = libgnutls_pkcs11.la
+
+libgnutls_pkcs11_la_SOURCES = \
+ p11_provider.c p11_provider.h
+
+libgnutls_pkcs11_la_LIBADD = $(P11_KIT_LIBS) $(LIBPMULTITHREAD)
+
+if ENABLE_MINITASN1
+libgnutls_pkcs11_la_LIBADD += ../minitasn1/libminitasn1.la
+else
+libgnutls_pkcs11_la_LIBADD += $(LIBTASN1_LIBS)
+endif
--- /dev/null
+/*
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Author: Zoltan Fridrich
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser 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/>
+ *
+ */
+
+#include "errors.h"
+#include "gnutls_int.h"
+#include "cipher_int.h"
+#include "p11_provider.h"
+
+#define P11_KIT_FUTURE_UNSTABLE_API
+#include <p11-kit/iter.h>
+#include <p11-kit/pkcs11.h>
+
+static struct {
+ CK_FUNCTION_LIST *module;
+ CK_SLOT_ID slot;
+ uint8_t *pin;
+ size_t pin_size;
+ bool initialized;
+} p11_provider;
+
+int _p11_provider_init(const char *module_path, const uint8_t *pin,
+ size_t pin_size)
+{
+ int ret;
+ CK_RV rv;
+ P11KitIter *iter = NULL;
+ CK_FUNCTION_LIST *modules[2] = { 0 };
+ CK_SLOT_ID slot = 0;
+ uint8_t *_pin = NULL;
+
+ if (p11_provider.initialized)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ modules[0] = p11_kit_module_load(module_path, 0);
+ if (modules[0] == NULL)
+ return gnutls_assert_val(GNUTLS_E_PKCS11_LOAD_ERROR);
+
+ rv = p11_kit_module_initialize(modules[0]);
+ if (rv != CKR_OK) {
+ p11_kit_module_release(modules[0]);
+ return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+ }
+
+ iter = p11_kit_iter_new(NULL, P11_KIT_ITER_WITH_TOKENS |
+ P11_KIT_ITER_WITHOUT_OBJECTS);
+ if (iter == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ goto error;
+ }
+
+ p11_kit_iter_begin(iter, modules);
+ rv = p11_kit_iter_next(iter);
+ if (rv != CKR_OK) {
+ ret = gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+ goto error;
+ }
+
+ slot = p11_kit_iter_get_slot(iter);
+ p11_kit_iter_free(iter);
+
+ _pin = gnutls_malloc(pin_size);
+ if (_pin == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ goto error;
+ }
+ memcpy(_pin, pin, pin_size);
+
+ p11_provider.module = modules[0];
+ p11_provider.slot = slot;
+ p11_provider.pin = _pin;
+ p11_provider.pin_size = pin_size;
+ p11_provider.initialized = true;
+ return 0;
+
+error:
+ if (iter != NULL)
+ p11_kit_iter_free(iter);
+ gnutls_free(_pin);
+ p11_kit_module_finalize(modules[0]);
+ p11_kit_module_release(modules[0]);
+ return ret;
+}
+
+void _p11_provider_deinit(void)
+{
+ if (!p11_provider.initialized)
+ return;
+
+ gnutls_free(p11_provider.pin);
+ p11_kit_module_finalize(p11_provider.module);
+ p11_kit_module_release(p11_provider.module);
+ memset(&p11_provider, 0, sizeof(p11_provider));
+}
+
+bool _p11_provider_is_initialized(void)
+{
+ return p11_provider.initialized;
+}
+
+CK_SESSION_HANDLE _p11_provider_open_session(void)
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
+
+ rv = p11_provider.module->C_OpenSession(
+ p11_provider.slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL,
+ NULL, &session);
+ if (rv != CKR_OK)
+ return CK_INVALID_HANDLE;
+
+ rv = p11_provider.module->C_Login(session, CKU_USER, p11_provider.pin,
+ p11_provider.pin_size);
+ if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
+ p11_provider.module->C_CloseSession(session);
+ return CK_INVALID_HANDLE;
+ }
+
+ return session;
+}
+
+void _p11_provider_close_session(CK_SESSION_HANDLE session)
+{
+ if (session == CK_INVALID_HANDLE)
+ return;
+
+ p11_provider.module->C_Logout(session);
+ p11_provider.module->C_CloseSession(session);
+}
+
+CK_FUNCTION_LIST *_p11_provider_get_module(void)
+{
+ return p11_provider.module;
+}
+
+CK_SLOT_ID _p11_provider_get_slot(void)
+{
+ return p11_provider.slot;
+}
--- /dev/null
+/*
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Author: Zoltan Fridrich
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser 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/>
+ *
+ */
+
+#ifndef GNUTLS_LIB_P11_PROVIDER_H
+#define GNUTLS_LIB_P11_PROVIDER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <p11-kit/pkcs11.h>
+
+int _p11_provider_init(const char *module_path, const uint8_t *pin,
+ size_t pin_size);
+void _p11_provider_deinit(void);
+bool _p11_provider_is_initialized(void);
+CK_SESSION_HANDLE _p11_provider_open_session(void);
+void _p11_provider_close_session(CK_SESSION_HANDLE session);
+CK_FUNCTION_LIST *_p11_provider_get_module(void);
+CK_SLOT_ID _p11_provider_get_slot(void);
+
+#endif /* GNUTLS_LIB_P11_PROVIDER_H */
gnutls_compression_method_t
cert_comp_algs[MAX_COMPRESS_CERTIFICATE_METHODS + 1];
+ char *p11_provider_path;
+ char *p11_provider_pin;
+
ext_master_secret_t force_ext_master_secret;
bool force_ext_master_secret_set;
};
}
gnutls_free(cfg->priority_string);
gnutls_free(cfg->default_priority_string);
+ gnutls_free(cfg->p11_provider_path);
+ gnutls_free(cfg->p11_provider_pin);
}
/* Lock for reading and writing system_wide_config */
#define GLOBAL_SECTION "global"
#define CUSTOM_PRIORITY_SECTION "priorities"
+#define PROVIDER_SECTION "provider"
#define OVERRIDES_SECTION "overrides"
#define MAX_ALGO_NAME 2048
dst->default_priority_string = src->default_priority_string;
src->default_priority_string = NULL;
+ dst->p11_provider_path = src->p11_provider_path;
+ src->p11_provider_path = NULL;
+
+ dst->p11_provider_pin = src->p11_provider_pin;
+ src->p11_provider_pin = NULL;
+
dst->allowlisting = src->allowlisting;
dst->ktls_enabled = src->ktls_enabled;
dst->allow_rsa_pkcs1_encrypt = src->allow_rsa_pkcs1_encrypt;
value);
if (ret < 0)
return 0;
+ } else if (c_strcasecmp(section, PROVIDER_SECTION) == 0) {
+ if (c_strcasecmp(name, "path") == 0) {
+ gnutls_free(cfg->p11_provider_path);
+ cfg->p11_provider_path = NULL;
+ p = clear_spaces(value, str);
+ _gnutls_debug_log(
+ "cfg: adding pkcs11 provider path %s\n", p);
+ if (strlen(p) > 0) {
+ cfg->p11_provider_path = gnutls_strdup(p);
+ if (cfg->p11_provider_path == NULL) {
+ _gnutls_debug_log(
+ "cfg: failed setting pkcs11 provider path\n");
+ return 0;
+ }
+ } else {
+ _gnutls_debug_log(
+ "cfg: empty pkcs11 provider path, using default\n");
+ if (fail_on_invalid_config)
+ return 0;
+ }
+ } else if (c_strcasecmp(name, "pin") == 0) {
+ gnutls_free(cfg->p11_provider_pin);
+ cfg->p11_provider_pin = NULL;
+ p = clear_spaces(value, str);
+ _gnutls_debug_log("cfg: adding pkcs11 provider pin\n");
+ if (strlen(p) > 0) {
+ cfg->p11_provider_pin = gnutls_strdup(p);
+ if (cfg->p11_provider_pin == NULL) {
+ _gnutls_debug_log(
+ "cfg: failed setting pkcs11 provider pin\n");
+ return 0;
+ }
+ } else {
+ _gnutls_debug_log(
+ "cfg: empty pkcs11 provider pin, using default\n");
+ if (fail_on_invalid_config)
+ return 0;
+ }
+ } else {
+ _gnutls_debug_log("unknown parameter %s\n", name);
+ if (fail_on_invalid_config)
+ return 0;
+ }
} else if (c_strcasecmp(section, OVERRIDES_SECTION) == 0) {
if (!override_allowed(cfg->allowlisting, name)) {
_gnutls_debug_log(
return 0;
}
+const char *_gnutls_config_get_p11_provider_path(void)
+{
+ return system_wide_config.p11_provider_path;
+}
+
+const char *_gnutls_config_get_p11_provider_pin(void)
+{
+ return system_wide_config.p11_provider_pin;
+}
+
/*
* high-level interface for overriding configuration files
*/