]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
PKCS#11 provider: add support for ciphers
authorZoltan Fridrich <zfridric@redhat.com>
Thu, 16 Jan 2025 14:00:44 +0000 (15:00 +0100)
committerZoltan Fridrich <zfridric@redhat.com>
Tue, 10 Jun 2025 06:50:04 +0000 (08:50 +0200)
Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
lib/crypto-backend.c
lib/pkcs11/Makefile.am
lib/pkcs11/p11_cipher.c [new file with mode: 0644]
lib/pkcs11/p11_cipher.h [new file with mode: 0644]
lib/pkcs11/p11_provider.c

index faa0989543bc18fac436ec2fb432576514344965..b07b2dcd312aab5eaaaf562747f8bbffc62be621 100644 (file)
 #include "random.h"
 #include "cipher_int.h"
 
+#ifdef ENABLE_PKCS11
+#include "pkcs11/p11_provider.h"
+#endif
+
 /* default values for priorities */
 int crypto_mac_prio = INT_MAX;
 int crypto_digest_prio = INT_MAX;
index ad6c783a9333c98693dfe31435dda9b0d94d5bc8..d2e75d49521995009409057fd29351870ff44708 100644 (file)
@@ -36,7 +36,8 @@ endif
 noinst_LTLIBRARIES = libgnutls_pkcs11.la
 
 libgnutls_pkcs11_la_SOURCES = \
-       p11_provider.c p11_provider.h
+       p11_provider.c p11_provider.h \
+       p11_cipher.c p11_cipher.h
 
 libgnutls_pkcs11_la_LIBADD = $(P11_KIT_LIBS) $(LIBPMULTITHREAD)
 
diff --git a/lib/pkcs11/p11_cipher.c b/lib/pkcs11/p11_cipher.c
new file mode 100644 (file)
index 0000000..8837aa8
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * 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 "gnutls_int.h"
+#include "cipher_int.h"
+#include "p11_cipher.h"
+#include "p11_provider.h"
+
+#include <minmax.h>
+
+#define P11_KIT_FUTURE_UNSTABLE_API
+#include <p11-kit/iter.h>
+#include <p11-kit/pkcs11.h>
+
+struct p11_cipher_ctx;
+typedef int (*init_params_func)(struct p11_cipher_ctx *ctx);
+typedef int (*set_params_func)(struct p11_cipher_ctx *ctx, const void *iv,
+                              size_t iv_size, const void *auth,
+                              size_t auth_size, size_t tag_size);
+typedef void (*free_params_func)(struct p11_cipher_ctx *ctx);
+typedef int (*get_iv_func)(struct p11_cipher_ctx *ctx, void *iv,
+                          size_t iv_size);
+typedef int (*set_key_func)(struct p11_cipher_ctx *ctx, const void *key,
+                           size_t key_size);
+
+struct p11_cipher_st {
+       gnutls_cipher_algorithm_t alg;
+       CK_MECHANISM_TYPE mech;
+
+       size_t key_size;
+       size_t max_iv_size;
+
+       init_params_func init_params;
+       set_params_func set_params;
+       free_params_func free_params;
+       get_iv_func get_iv;
+       set_key_func set_encrypt_key;
+       set_key_func set_decrypt_key;
+
+       bool available;
+};
+
+union p11_cipher_params {
+       uint8_t iv[MAX_CIPHER_IV_SIZE];
+       CK_GCM_PARAMS gcm;
+};
+
+struct p11_cipher_ctx {
+       const struct p11_cipher_st *cipher;
+       CK_SESSION_HANDLE session;
+       bool enc;
+       union p11_cipher_params params;
+       size_t params_size;
+       CK_OBJECT_HANDLE key;
+};
+
+/*************************************************/
+/****** PKCS#11 Cipher specific functions ********/
+/*************************************************/
+
+static int init_iv_params(struct p11_cipher_ctx *ctx)
+{
+       gnutls_memset(&ctx->params, 0, sizeof(ctx->params));
+       ctx->params_size = 0;
+       return 0;
+}
+
+static void free_iv_params(struct p11_cipher_ctx *ctx)
+{
+       init_iv_params(ctx);
+}
+
+static int set_iv_params(struct p11_cipher_ctx *ctx, const void *iv,
+                        size_t iv_size, const void *auth, size_t auth_size,
+                        size_t tag_size)
+{
+       if (iv_size != ctx->cipher->max_iv_size)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       memcpy(ctx->params.iv, iv, iv_size);
+       ctx->params_size = iv_size;
+       return 0;
+}
+
+static int get_iv_params(struct p11_cipher_ctx *ctx, void *iv, size_t iv_size)
+{
+       if (iv_size < ctx->params_size)
+               return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+
+       memcpy(iv, ctx->params.iv, ctx->params_size);
+       return (int)ctx->params_size;
+}
+
+static int init_gcm_params(struct p11_cipher_ctx *ctx)
+{
+       gnutls_memset(&ctx->params, 0, sizeof(ctx->params));
+       ctx->params_size = sizeof(CK_GCM_PARAMS);
+       return 0;
+}
+
+static void free_gcm_params(struct p11_cipher_ctx *ctx)
+{
+       gnutls_free(ctx->params.gcm.pIv);
+       gnutls_free(ctx->params.gcm.pAAD);
+       init_gcm_params(ctx);
+}
+
+static int set_gcm_params(struct p11_cipher_ctx *ctx, const void *iv,
+                         size_t iv_size, const void *auth, size_t auth_size,
+                         size_t tag_size)
+{
+       uint8_t *_iv = NULL;
+       uint8_t *_auth = NULL;
+
+       if (iv_size == 0 || iv_size > ctx->cipher->max_iv_size || tag_size > 16)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       _iv = gnutls_malloc(iv_size);
+       if (_iv == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+       memcpy(_iv, iv, iv_size);
+
+       if (auth_size != 0) {
+               _auth = gnutls_malloc(auth_size);
+               if (_auth == NULL) {
+                       gnutls_free(_iv);
+                       return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+               }
+               memcpy(_auth, auth, auth_size);
+       }
+
+       free_gcm_params(ctx);
+       ctx->params.gcm.pIv = _iv;
+       ctx->params.gcm.ulIvLen = iv_size;
+       ctx->params.gcm.pAAD = _auth;
+       ctx->params.gcm.ulAADLen = auth_size;
+       ctx->params.gcm.ulTagBits = tag_size * 8;
+       return 0;
+}
+
+static int get_gcm_iv_params(struct p11_cipher_ctx *ctx, void *iv,
+                            size_t iv_size)
+{
+       if (ctx->params.gcm.pIv == NULL)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       if (iv_size < ctx->params.gcm.ulIvLen)
+               return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+
+       memcpy(iv, ctx->params.gcm.pIv, ctx->params.gcm.ulIvLen);
+       return (int)ctx->params.gcm.ulIvLen;
+}
+
+static int aes_set_key(struct p11_cipher_ctx *ctx, const void *key,
+                      size_t key_size)
+{
+       CK_RV rv;
+       CK_FUNCTION_LIST *module = _p11_provider_get_module();
+       CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE;
+       CK_OBJECT_CLASS attr_class = CKO_SECRET_KEY;
+       CK_KEY_TYPE attr_key_type = CKK_AES;
+       CK_BBOOL attr_true = CK_TRUE;
+       CK_UTF8CHAR label[] = "AES secret key";
+       CK_ATTRIBUTE attrs[] = { { CKA_CLASS, &attr_class, sizeof(attr_class) },
+                                { CKA_KEY_TYPE, &attr_key_type,
+                                  sizeof(attr_key_type) },
+                                { CKA_TOKEN, &attr_true, sizeof(attr_true) },
+                                { CKA_ENCRYPT, &attr_true, sizeof(attr_true) },
+                                { CKA_DECRYPT, &attr_true, sizeof(attr_true) },
+                                { CKA_LABEL, label, sizeof(label) - 1 },
+                                { CKA_VALUE, (CK_BYTE *)key, key_size } };
+       CK_ULONG n_attrs = sizeof(attrs) / sizeof(attrs[0]);
+
+       if (key_size != ctx->cipher->key_size)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       rv = module->C_CreateObject(ctx->session, attrs, n_attrs, &obj);
+       if (rv != CKR_OK)
+               return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+
+       ctx->key = obj;
+       return 0;
+}
+
+#define P11_CIPHERS_COUNT (sizeof(p11_ciphers) / sizeof(p11_ciphers[0]))
+static struct p11_cipher_st p11_ciphers[] = {
+       {
+               .alg = GNUTLS_CIPHER_AES_128_CBC,
+               .mech = CKM_AES_CBC,
+               .key_size = 16,
+               .max_iv_size = 16,
+               .init_params = init_iv_params,
+               .set_params = set_iv_params,
+               .free_params = free_iv_params,
+               .get_iv = get_iv_params,
+               .set_encrypt_key = aes_set_key,
+               .set_decrypt_key = aes_set_key,
+       },
+       {
+               .alg = GNUTLS_CIPHER_AES_192_CBC,
+               .mech = CKM_AES_CBC,
+               .key_size = 24,
+               .max_iv_size = 16,
+               .init_params = init_iv_params,
+               .set_params = set_iv_params,
+               .free_params = free_iv_params,
+               .get_iv = get_iv_params,
+               .set_encrypt_key = aes_set_key,
+               .set_decrypt_key = aes_set_key,
+       },
+       {
+               .alg = GNUTLS_CIPHER_AES_256_CBC,
+               .mech = CKM_AES_CBC,
+               .key_size = 32,
+               .max_iv_size = 16,
+               .init_params = init_iv_params,
+               .set_params = set_iv_params,
+               .free_params = free_iv_params,
+               .get_iv = get_iv_params,
+               .set_encrypt_key = aes_set_key,
+               .set_decrypt_key = aes_set_key,
+       },
+       {
+               .alg = GNUTLS_CIPHER_AES_128_GCM,
+               .mech = CKM_AES_GCM,
+               .key_size = 16,
+               .max_iv_size = 12,
+               .init_params = init_gcm_params,
+               .set_params = set_gcm_params,
+               .free_params = free_gcm_params,
+               .get_iv = get_gcm_iv_params,
+               .set_encrypt_key = aes_set_key,
+               .set_decrypt_key = aes_set_key,
+       },
+       {
+               .alg = GNUTLS_CIPHER_AES_192_GCM,
+               .mech = CKM_AES_GCM,
+               .key_size = 24,
+               .max_iv_size = 12,
+               .init_params = init_gcm_params,
+               .set_params = set_gcm_params,
+               .free_params = free_gcm_params,
+               .get_iv = get_gcm_iv_params,
+               .set_encrypt_key = aes_set_key,
+               .set_decrypt_key = aes_set_key,
+       },
+       {
+               .alg = GNUTLS_CIPHER_AES_256_GCM,
+               .mech = CKM_AES_GCM,
+               .key_size = 32,
+               .max_iv_size = 12,
+               .init_params = init_gcm_params,
+               .set_params = set_gcm_params,
+               .free_params = free_gcm_params,
+               .get_iv = get_gcm_iv_params,
+               .set_encrypt_key = aes_set_key,
+               .set_decrypt_key = aes_set_key,
+       },
+};
+
+int _p11_ciphers_init(CK_FUNCTION_LIST *module, CK_SLOT_ID slot)
+{
+       unsigned i, j;
+       CK_RV rv;
+       CK_MECHANISM_TYPE *mechs = NULL;
+       CK_ULONG mech_count = 0;
+       CK_MECHANISM_INFO *infos = NULL;
+
+       rv = module->C_GetMechanismList(slot, NULL, &mech_count);
+       if (rv != CKR_OK)
+               return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+
+       if (mech_count == 0)
+               return 0;
+
+       mechs = _gnutls_reallocarray(NULL, mech_count,
+                                    sizeof(CK_MECHANISM_TYPE));
+       if (mechs == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+       rv = module->C_GetMechanismList(slot, mechs, &mech_count);
+       if (rv != CKR_OK) {
+               gnutls_free(mechs);
+               return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+       }
+
+       infos = _gnutls_reallocarray(NULL, mech_count,
+                                    sizeof(CK_MECHANISM_INFO));
+       if (infos == NULL) {
+               gnutls_free(mechs);
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+       }
+
+       for (i = 0; i < mech_count; ++i) {
+               rv = module->C_GetMechanismInfo(slot, mechs[i], infos + i);
+               if (rv != CKR_OK) {
+                       gnutls_free(mechs);
+                       gnutls_free(infos);
+                       return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+               }
+       }
+
+       for (i = 0; i < P11_CIPHERS_COUNT; ++i) {
+               for (j = 0; j < mech_count; ++j) {
+                       if (mechs[j] == p11_ciphers[i].mech &&
+                           infos[j].ulMinKeySize <= p11_ciphers[i].key_size &&
+                           infos[j].ulMaxKeySize >= p11_ciphers[i].key_size) {
+                               p11_ciphers[i].available = true;
+                               break;
+                       }
+               }
+       }
+
+       gnutls_free(mechs);
+       gnutls_free(infos);
+       return 0;
+}
+
+void _p11_ciphers_deinit(void)
+{
+       unsigned i;
+
+       for (i = 0; i < P11_CIPHERS_COUNT; ++i)
+               p11_ciphers[i].available = false;
+}
+
+/*************************************************/
+/*************** Wrapper functions ***************/
+/*************************************************/
+
+static int wrap_p11_cipher_init(gnutls_cipher_algorithm_t alg, void **_ctx,
+                               int enc)
+{
+       unsigned i;
+       struct p11_cipher_ctx *ctx = NULL;
+       const struct p11_cipher_st *cipher = NULL;
+       CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
+
+       for (i = 0; i < P11_CIPHERS_COUNT; ++i) {
+               if (p11_ciphers[i].alg == alg && p11_ciphers[i].available) {
+                       cipher = p11_ciphers + i;
+                       break;
+               }
+       }
+       if (cipher == NULL)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       ctx = gnutls_calloc(1, sizeof(*ctx));
+       if (ctx == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+       if (cipher->init_params(ctx) < 0) {
+               gnutls_free(ctx);
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+       }
+
+       session = _p11_provider_open_session();
+       if (session == CK_INVALID_HANDLE) {
+               cipher->free_params(ctx);
+               gnutls_free(ctx);
+               return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+       }
+
+       ctx->cipher = cipher;
+       ctx->session = session;
+       ctx->enc = enc;
+       *_ctx = ctx;
+
+       return 0;
+}
+
+static int wrap_p11_cipher_exists(gnutls_cipher_algorithm_t alg)
+{
+       unsigned i;
+
+       for (i = 0; i < P11_CIPHERS_COUNT; ++i)
+               if (p11_ciphers[i].alg == alg)
+                       return p11_ciphers[i].available;
+
+       return 0;
+}
+
+static int wrap_p11_cipher_setiv(void *_ctx, const void *iv, size_t iv_size)
+{
+       struct p11_cipher_ctx *ctx = _ctx;
+
+       return ctx->cipher->set_params(ctx, iv, iv_size, NULL, 0, 0);
+}
+
+static int wrap_p11_cipher_getiv(void *_ctx, void *iv, size_t iv_size)
+{
+       struct p11_cipher_ctx *ctx = _ctx;
+
+       return ctx->cipher->get_iv(ctx, iv, iv_size);
+}
+
+static int wrap_p11_cipher_setkey(void *_ctx, const void *key, size_t key_size)
+{
+       struct p11_cipher_ctx *ctx = _ctx;
+
+       return ctx->enc ? ctx->cipher->set_encrypt_key(ctx, key, key_size) :
+                         ctx->cipher->set_decrypt_key(ctx, key, key_size);
+}
+
+static int wrap_p11_cipher_encrypt(void *_ctx, const void *plain,
+                                  size_t plain_size, void *enc,
+                                  size_t enc_size)
+{
+       struct p11_cipher_ctx *ctx = _ctx;
+       CK_RV rv;
+       CK_FUNCTION_LIST *module = _p11_provider_get_module();
+       CK_MECHANISM m = { ctx->cipher->mech, &ctx->params, ctx->params_size };
+
+       rv = module->C_EncryptInit(ctx->session, &m, ctx->key);
+       if (rv != CKR_OK)
+               return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+
+       rv = module->C_Encrypt(ctx->session, (CK_BYTE_PTR)plain, plain_size,
+                              enc, (CK_ULONG_PTR)&enc_size);
+       if (rv != CKR_OK)
+               return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+
+       return 0;
+}
+
+static int wrap_p11_cipher_decrypt(void *_ctx, const void *enc, size_t enc_size,
+                                  void *plain, size_t plain_size)
+{
+       struct p11_cipher_ctx *ctx = _ctx;
+       CK_RV rv;
+       uint8_t *tmp = NULL;
+       uint32_t is_err;
+       size_t copy_size;
+       CK_ULONG expected_size = 0;
+       CK_FUNCTION_LIST *module = _p11_provider_get_module();
+       CK_MECHANISM m = { ctx->cipher->mech, &ctx->params, ctx->params_size };
+
+       rv = module->C_DecryptInit(ctx->session, &m, ctx->key);
+       if (rv != CKR_OK)
+               return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+
+       rv = module->C_Decrypt(ctx->session, (CK_BYTE_PTR)enc, enc_size, NULL,
+                              &expected_size);
+       if (rv != CKR_OK)
+               return gnutls_assert_val(GNUTLS_E_PKCS11_ERROR);
+
+       tmp = gnutls_malloc(expected_size);
+       if (tmp == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+       copy_size = MIN(plain_size, expected_size);
+       rv = module->C_Decrypt(ctx->session, (CK_BYTE_PTR)enc, enc_size, tmp,
+                              &expected_size);
+       memcpy(plain, tmp, copy_size);
+       gnutls_free(tmp);
+
+       is_err = rv != CKR_OK;
+       return (int)((is_err * UINT_MAX) & GNUTLS_E_PKCS11_ERROR);
+}
+
+static int wrap_p11_cipher_aead_encrypt(void *_ctx, const void *iv,
+                                       size_t iv_size, const void *auth,
+                                       size_t auth_size, size_t tag_size,
+                                       const void *plain, size_t plain_size,
+                                       void *enc, size_t enc_size)
+{
+       struct p11_cipher_ctx *ctx = _ctx;
+
+       ctx->cipher->set_params(ctx, iv, iv_size, auth, auth_size, tag_size);
+       return wrap_p11_cipher_encrypt(_ctx, plain, plain_size, enc, enc_size);
+}
+
+static int wrap_p11_cipher_aead_decrypt(void *_ctx, const void *iv,
+                                       size_t iv_size, const void *auth,
+                                       size_t auth_size, size_t tag_size,
+                                       const void *enc, size_t enc_size,
+                                       void *plain, size_t plain_size)
+{
+       struct p11_cipher_ctx *ctx = _ctx;
+
+       ctx->cipher->set_params(ctx, iv, iv_size, auth, auth_size, tag_size);
+       return wrap_p11_cipher_decrypt(_ctx, enc, enc_size, plain, plain_size);
+}
+
+static void wrap_p11_cipher_deinit(void *_ctx)
+{
+       struct p11_cipher_ctx *ctx = _ctx;
+
+       _p11_provider_close_session(ctx->session);
+       ctx->cipher->free_params(ctx);
+       gnutls_memset(ctx, 0, sizeof(*ctx));
+       gnutls_free(ctx);
+}
+
+static int wrap_p11_cipher_auth(void *_ctx, const void *plain,
+                               size_t plain_size)
+{
+       return 0;
+}
+
+static void wrap_p11_cipher_tag(void *_ctx, void *tag, size_t tag_size)
+{
+}
+
+gnutls_crypto_cipher_st _gnutls_p11_cipher_ops = {
+       .init = wrap_p11_cipher_init,
+       .exists = wrap_p11_cipher_exists,
+       .setiv = wrap_p11_cipher_setiv,
+       .getiv = wrap_p11_cipher_getiv,
+       .setkey = wrap_p11_cipher_setkey,
+       .encrypt = wrap_p11_cipher_encrypt,
+       .decrypt = wrap_p11_cipher_decrypt,
+       .aead_encrypt = wrap_p11_cipher_aead_encrypt,
+       .aead_decrypt = wrap_p11_cipher_aead_decrypt,
+       .deinit = wrap_p11_cipher_deinit,
+       .auth = wrap_p11_cipher_auth,
+       .tag = wrap_p11_cipher_tag,
+};
diff --git a/lib/pkcs11/p11_cipher.h b/lib/pkcs11/p11_cipher.h
new file mode 100644 (file)
index 0000000..f9fd600
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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_CIPHER_H
+#define GNUTLS_LIB_P11_CIPHER_H
+
+#include <p11-kit/pkcs11.h>
+
+int _p11_ciphers_init(CK_FUNCTION_LIST *module, CK_SLOT_ID slot);
+void _p11_ciphers_deinit(void);
+
+#endif /* GNUTLS_LIB_P11_CIPHER_H */
index 2c8e1ba591ef3a9cbf6d4b1c60fbe79e4a5c551d..7fc5b047826b89b49899ad6f072a9aec9d838c13 100644 (file)
@@ -23,6 +23,7 @@
 #include "errors.h"
 #include "gnutls_int.h"
 #include "cipher_int.h"
+#include "p11_cipher.h"
 #include "p11_provider.h"
 
 #define P11_KIT_FUTURE_UNSTABLE_API
@@ -84,6 +85,12 @@ int _p11_provider_init(const char *module_path, const uint8_t *pin,
        }
        memcpy(_pin, pin, pin_size);
 
+       ret = _p11_ciphers_init(modules[0], slot);
+       if (ret < 0) {
+               gnutls_assert();
+               goto error;
+       }
+
        p11_provider.module = modules[0];
        p11_provider.slot = slot;
        p11_provider.pin = _pin;
@@ -97,6 +104,7 @@ error:
        gnutls_free(_pin);
        p11_kit_module_finalize(modules[0]);
        p11_kit_module_release(modules[0]);
+       _p11_ciphers_deinit();
        return ret;
 }
 
@@ -109,6 +117,7 @@ void _p11_provider_deinit(void)
        p11_kit_module_finalize(p11_provider.module);
        p11_kit_module_release(p11_provider.module);
        memset(&p11_provider, 0, sizeof(p11_provider));
+       _p11_ciphers_deinit();
 }
 
 bool _p11_provider_is_initialized(void)