From: Zoltan Fridrich Date: Thu, 16 Jan 2025 13:41:40 +0000 (+0100) Subject: Add support for multiple crypto backends X-Git-Tag: 3.8.10~20^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d2993dfb8cf4ad07f3f26cf65dd2000be0c4d036;p=thirdparty%2Fgnutls.git Add support for multiple crypto backends Signed-off-by: Zoltan Fridrich --- diff --git a/lib/cipher_int.c b/lib/cipher_int.c index 5c7c931d45..115f3b9528 100644 --- a/lib/cipher_int.c +++ b/lib/cipher_int.c @@ -30,6 +30,10 @@ #include "fips.h" #include "algorithms.h" +#ifdef ENABLE_PKCS11 +#include "pkcs11/p11_provider.h" +#endif + #define SR_FB(x, cleanup) \ ret = (x); \ if (ret < 0) { \ @@ -55,9 +59,6 @@ */ int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher) { - const gnutls_crypto_cipher_st *cc; - int ret; - if (!is_cipher_algo_allowed(cipher)) return 0; @@ -68,12 +69,10 @@ int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher) if (cipher == GNUTLS_CIPHER_NULL) return 1; - cc = _gnutls_get_crypto_cipher(cipher); - if (cc != NULL) + if (_gnutls_get_crypto_cipher(cipher) != NULL) return 1; - ret = _gnutls_cipher_ops.exists(cipher); - return ret; + return _gnutls_cipher_backend()->exists(cipher); } int _gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e, @@ -82,6 +81,7 @@ int _gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e, { int ret = GNUTLS_E_INTERNAL_ERROR; const gnutls_crypto_cipher_st *cc = NULL; + const gnutls_crypto_cipher_st *fallback_cc = _gnutls_cipher_backend(); if (unlikely(e == NULL || e->id == GNUTLS_CIPHER_NULL)) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); @@ -91,6 +91,12 @@ int _gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e, handle->e = e; handle->handle = NULL; +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + /* Prioritize crypto from pkcs11 provider */ + if (_p11_provider_is_initialized()) + goto fallback; +#endif + /* check if a cipher has been registered */ cc = _gnutls_get_crypto_cipher(e->id); @@ -130,34 +136,33 @@ int _gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e, } fallback: - handle->encrypt = _gnutls_cipher_ops.encrypt; - handle->decrypt = _gnutls_cipher_ops.decrypt; - handle->aead_encrypt = _gnutls_cipher_ops.aead_encrypt; - handle->aead_decrypt = _gnutls_cipher_ops.aead_decrypt; - handle->deinit = _gnutls_cipher_ops.deinit; - handle->auth = _gnutls_cipher_ops.auth; - handle->tag = _gnutls_cipher_ops.tag; - handle->setiv = _gnutls_cipher_ops.setiv; - handle->getiv = _gnutls_cipher_ops.getiv; - handle->setkey = _gnutls_cipher_ops.setkey; + handle->encrypt = fallback_cc->encrypt; + handle->decrypt = fallback_cc->decrypt; + handle->aead_encrypt = fallback_cc->aead_encrypt; + handle->aead_decrypt = fallback_cc->aead_decrypt; + handle->deinit = fallback_cc->deinit; + handle->auth = fallback_cc->auth; + handle->tag = fallback_cc->tag; + handle->setiv = fallback_cc->setiv; + handle->getiv = fallback_cc->getiv; + handle->setkey = fallback_cc->setkey; /* otherwise use generic cipher interface */ - ret = _gnutls_cipher_ops.init(e->id, &handle->handle, enc); + ret = fallback_cc->init(e->id, &handle->handle, enc); if (ret < 0) { gnutls_assert(); return ret; } - ret = _gnutls_cipher_ops.setkey(handle->handle, key->data, key->size); + ret = fallback_cc->setkey(handle->handle, key->data, key->size); if (ret < 0) { gnutls_assert(); goto cc_cleanup; } if (iv) { - ret = _gnutls_cipher_ops.setiv(handle->handle, iv->data, - iv->size); + ret = fallback_cc->setiv(handle->handle, iv->data, iv->size); if (ret < 0) { gnutls_assert(); goto cc_cleanup; diff --git a/lib/cipher_int.h b/lib/cipher_int.h index 707d608aa6..18d3d7463f 100644 --- a/lib/cipher_int.h +++ b/lib/cipher_int.h @@ -28,7 +28,6 @@ #include "crypto-backend.h" extern int crypto_cipher_prio; -extern gnutls_crypto_cipher_st _gnutls_cipher_ops; typedef int (*cipher_encrypt_func)(void *hd, const void *plaintext, size_t, void *ciphertext, size_t); diff --git a/lib/crypto-api.c b/lib/crypto-api.c index 0abbd7f69d..01539d5b52 100644 --- a/lib/crypto-api.c +++ b/lib/crypto-api.c @@ -2054,8 +2054,6 @@ void gnutls_aead_cipher_deinit(gnutls_aead_cipher_hd_t handle) gnutls_free(handle); } -extern gnutls_crypto_kdf_st _gnutls_kdf_ops; - /* Same as @gnutls_hkdf_extract but without changing FIPS context */ int _gnutls_hkdf_extract(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key, const gnutls_datum_t *salt, void *output) @@ -2069,9 +2067,10 @@ int _gnutls_hkdf_extract(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key, /* We don't check whether MAC is approved, because HKDF is * only approved in TLS, which is handled separately. */ - return _gnutls_kdf_ops.hkdf_extract(mac, key->data, key->size, - salt ? salt->data : NULL, - salt ? salt->size : 0, output); + return _gnutls_kdf_backend()->hkdf_extract(mac, key->data, key->size, + salt ? salt->data : NULL, + salt ? salt->size : 0, + output); } /** @@ -2115,9 +2114,9 @@ int _gnutls_hkdf_expand(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key, /* We don't check whether MAC is approved, because HKDF is * only approved in TLS, which is handled separately. */ - return _gnutls_kdf_ops.hkdf_expand(mac, key->data, key->size, - info->data, info->size, output, - length); + return _gnutls_kdf_backend()->hkdf_expand(mac, key->data, key->size, + info->data, info->size, + output, length); } /** @@ -2199,8 +2198,9 @@ int gnutls_pbkdf2(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key, not_approved = true; } - ret = _gnutls_kdf_ops.pbkdf2(mac, key->data, key->size, salt->data, - salt->size, iter_count, output, length); + ret = _gnutls_kdf_backend()->pbkdf2(mac, key->data, key->size, + salt->data, salt->size, iter_count, + output, length); if (ret < 0) { _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); } else if (not_approved) { diff --git a/lib/crypto-backend.c b/lib/crypto-backend.c index 63db24b907..faa0989543 100644 --- a/lib/crypto-backend.c +++ b/lib/crypto-backend.c @@ -148,6 +148,65 @@ void _gnutls_crypto_deregister(void) _deregister(&glob_dl); } +extern gnutls_crypto_cipher_st _gnutls_cipher_ops; +extern gnutls_crypto_pk_st _gnutls_pk_ops; +extern gnutls_crypto_mac_st _gnutls_mac_ops; +extern gnutls_crypto_digest_st _gnutls_digest_ops; +extern gnutls_crypto_kdf_st _gnutls_kdf_ops; + +#ifdef ENABLE_PKCS11 +extern gnutls_crypto_cipher_st _gnutls_p11_cipher_ops; +extern gnutls_crypto_pk_st _gnutls_p11_pk_ops; +extern gnutls_crypto_mac_st _gnutls_p11_mac_ops; +extern gnutls_crypto_digest_st _gnutls_p11_digest_ops; +extern gnutls_crypto_kdf_st _gnutls_p11_kdf_ops; +#endif + +const gnutls_crypto_cipher_st *_gnutls_cipher_backend(void) +{ +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + if (_p11_provider_is_initialized()) + return &_gnutls_p11_cipher_ops; +#endif + return &_gnutls_cipher_ops; +} + +const gnutls_crypto_pk_st *_gnutls_pk_backend(void) +{ +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + if (_p11_provider_is_initialized()) + return &_gnutls_p11_pk_ops; +#endif + return &_gnutls_pk_ops; +} + +const gnutls_crypto_mac_st *_gnutls_mac_backend(void) +{ +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + if (_p11_provider_is_initialized()) + return &_gnutls_p11_mac_ops; +#endif + return &_gnutls_mac_ops; +} + +const gnutls_crypto_digest_st *_gnutls_digest_backend(void) +{ +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + if (_p11_provider_is_initialized()) + return &_gnutls_p11_digest_ops; +#endif + return &_gnutls_digest_ops; +} + +const gnutls_crypto_kdf_st *_gnutls_kdf_backend(void) +{ +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + if (_p11_provider_is_initialized()) + return &_gnutls_p11_kdf_ops; +#endif + return &_gnutls_kdf_ops; +} + /*- * gnutls_crypto_single_cipher_register: * @algorithm: is the gnutls algorithm identifier diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h index f213a43dcf..585dffdc80 100644 --- a/lib/crypto-backend.h +++ b/lib/crypto-backend.h @@ -467,4 +467,10 @@ int _gnutls_rsa_pss_sign_pad(gnutls_x509_spki_st *params, size_t key_bits, const gnutls_datum_t *data, unsigned char *buffer, size_t buffer_size); +const gnutls_crypto_cipher_st *_gnutls_cipher_backend(void) ATTRIBUTE_PURE; +const gnutls_crypto_pk_st *_gnutls_pk_backend(void) ATTRIBUTE_PURE; +const gnutls_crypto_mac_st *_gnutls_mac_backend(void) ATTRIBUTE_PURE; +const gnutls_crypto_digest_st *_gnutls_digest_backend(void) ATTRIBUTE_PURE; +const gnutls_crypto_kdf_st *_gnutls_kdf_backend(void) ATTRIBUTE_PURE; + #endif /* GNUTLS_LIB_CRYPTO_BACKEND_H */ diff --git a/lib/hash_int.c b/lib/hash_int.c index 3cf34e58a1..69d50a4a1b 100644 --- a/lib/hash_int.c +++ b/lib/hash_int.c @@ -30,6 +30,10 @@ #include "algorithms.h" #include "fips.h" +#ifdef ENABLE_PKCS11 +#include "pkcs11/p11_provider.h" +#endif + int _gnutls_hash_init(digest_hd_st *dig, const mac_entry_st *e) { int result; @@ -45,7 +49,12 @@ int _gnutls_hash_init(digest_hd_st *dig, const mac_entry_st *e) /* check if a digest has been registered */ cc = _gnutls_get_crypto_digest((gnutls_digest_algorithm_t)e->id); - if (cc != NULL && cc->init) { + if ( +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + /* Prioritize crypto from pkcs11 provider */ + !_p11_provider_is_initialized() && +#endif + cc != NULL && cc->init) { if (cc->init((gnutls_digest_algorithm_t)e->id, &dig->handle) < 0) { gnutls_assert(); @@ -60,17 +69,17 @@ int _gnutls_hash_init(digest_hd_st *dig, const mac_entry_st *e) return 0; } - result = _gnutls_digest_ops.init((gnutls_digest_algorithm_t)e->id, - &dig->handle); + result = _gnutls_digest_backend()->init( + (gnutls_digest_algorithm_t)e->id, &dig->handle); if (result < 0) { gnutls_assert(); return result; } - dig->hash = _gnutls_digest_ops.hash; - dig->output = _gnutls_digest_ops.output; - dig->deinit = _gnutls_digest_ops.deinit; - dig->copy = _gnutls_digest_ops.copy; + dig->hash = _gnutls_digest_backend()->hash; + dig->output = _gnutls_digest_backend()->output; + dig->deinit = _gnutls_digest_backend()->deinit; + dig->copy = _gnutls_digest_backend()->copy; return 0; } @@ -86,10 +95,15 @@ int _gnutls_digest_exists(gnutls_digest_algorithm_t algo) return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM); cc = _gnutls_get_crypto_digest(algo); - if (cc != NULL) + if ( +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + /* Prioritize crypto from pkcs11 provider */ + !_p11_provider_is_initialized() && +#endif + cc != NULL) return 1; - return _gnutls_digest_ops.exists(algo); + return _gnutls_digest_backend()->exists(algo); } int _gnutls_hash_copy(const digest_hd_st *handle, digest_hd_st *dst) @@ -130,7 +144,12 @@ int _gnutls_hash_fast(gnutls_digest_algorithm_t algorithm, const void *text, /* check if a digest has been registered */ cc = _gnutls_get_crypto_digest(algorithm); - if (cc != NULL) { + if ( +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + /* Prioritize crypto from pkcs11 provider */ + !_p11_provider_is_initialized() && +#endif + cc != NULL) { if (cc->fast(algorithm, text, textlen, digest) < 0) { gnutls_assert(); return GNUTLS_E_HASH_FAILED; @@ -139,7 +158,7 @@ int _gnutls_hash_fast(gnutls_digest_algorithm_t algorithm, const void *text, return 0; } - ret = _gnutls_digest_ops.fast(algorithm, text, textlen, digest); + ret = _gnutls_digest_backend()->fast(algorithm, text, textlen, digest); if (ret < 0) { gnutls_assert(); return ret; @@ -173,7 +192,12 @@ int _gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key, /* check if a digest has been registered */ cc = _gnutls_get_crypto_mac(algorithm); - if (cc != NULL) { + if ( +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + /* Prioritize crypto from pkcs11 provider */ + !_p11_provider_is_initialized() && +#endif + cc != NULL) { if (cc->fast(algorithm, NULL, 0, key, keylen, text, textlen, digest) < 0) { gnutls_assert(); @@ -183,8 +207,8 @@ int _gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key, return 0; } - ret = _gnutls_mac_ops.fast(algorithm, NULL, 0, key, keylen, text, - textlen, digest); + ret = _gnutls_mac_backend()->fast(algorithm, NULL, 0, key, keylen, text, + textlen, digest); if (ret < 0) { gnutls_assert(); return ret; @@ -208,10 +232,15 @@ int _gnutls_mac_exists(gnutls_mac_algorithm_t algo) return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM); cc = _gnutls_get_crypto_mac(algo); - if (cc != NULL) + if ( +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + /* Prioritize crypto from pkcs11 provider */ + !_p11_provider_is_initialized() && +#endif + cc != NULL) return 1; - return _gnutls_mac_ops.exists(algo); + return _gnutls_mac_backend()->exists(algo); } int _gnutls_mac_init(mac_hd_st *mac, const mac_entry_st *e, const void *key, @@ -231,7 +260,13 @@ int _gnutls_mac_init(mac_hd_st *mac, const mac_entry_st *e, const void *key, /* check if a digest has been registered */ cc = _gnutls_get_crypto_mac(e->id); - if (cc != NULL && cc->init != NULL) { + if ( +#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140) + /* Prioritize crypto from pkcs11 provider */ + !_p11_provider_is_initialized() && +#endif + cc != NULL && cc->init != NULL) { + if (cc->init(e->id, &mac->handle) < 0) { gnutls_assert(); return GNUTLS_E_HASH_FAILED; @@ -253,20 +288,20 @@ int _gnutls_mac_init(mac_hd_st *mac, const mac_entry_st *e, const void *key, return 0; } - result = _gnutls_mac_ops.init(e->id, &mac->handle); + result = _gnutls_mac_backend()->init(e->id, &mac->handle); if (result < 0) { gnutls_assert(); return result; } - mac->hash = _gnutls_mac_ops.hash; - mac->setnonce = _gnutls_mac_ops.setnonce; - mac->output = _gnutls_mac_ops.output; - mac->deinit = _gnutls_mac_ops.deinit; - mac->copy = _gnutls_mac_ops.copy; - mac->setkey = _gnutls_mac_ops.setkey; + mac->hash = _gnutls_mac_backend()->hash; + mac->setnonce = _gnutls_mac_backend()->setnonce; + mac->output = _gnutls_mac_backend()->output; + mac->deinit = _gnutls_mac_backend()->deinit; + mac->copy = _gnutls_mac_backend()->copy; + mac->setkey = _gnutls_mac_backend()->setkey; - if (_gnutls_mac_ops.setkey(mac->handle, key, keylen) < 0) { + if (_gnutls_mac_backend()->setkey(mac->handle, key, keylen) < 0) { gnutls_assert(); mac->deinit(mac->handle); return GNUTLS_E_HASH_FAILED; diff --git a/lib/hash_int.h b/lib/hash_int.h index 340f182237..8a66d5c997 100644 --- a/lib/hash_int.h +++ b/lib/hash_int.h @@ -31,10 +31,7 @@ /* for message digests */ extern int crypto_mac_prio; -extern gnutls_crypto_mac_st _gnutls_mac_ops; - extern int crypto_digest_prio; -extern gnutls_crypto_digest_st _gnutls_digest_ops; typedef int (*hash_func)(void *handle, const void *text, size_t size); typedef int (*nonce_func)(void *handle, const void *text, size_t size); diff --git a/lib/pk.h b/lib/pk.h index eca4e02d73..6969b534de 100644 --- a/lib/pk.h +++ b/lib/pk.h @@ -23,50 +23,53 @@ #ifndef GNUTLS_LIB_PK_H #define GNUTLS_LIB_PK_H +#include "crypto-backend.h" + extern int crypto_pk_prio; -extern gnutls_crypto_pk_st _gnutls_pk_ops; #define _gnutls_pk_encrypt(algo, ciphertext, plaintext, params) \ - _gnutls_pk_ops.encrypt(algo, ciphertext, plaintext, params) + _gnutls_pk_backend()->encrypt(algo, ciphertext, plaintext, params) #define _gnutls_pk_decrypt(algo, ciphertext, plaintext, params) \ - _gnutls_pk_ops.decrypt(algo, ciphertext, plaintext, params) -#define _gnutls_pk_decrypt2(algo, ciphertext, plaintext, size, params) \ - _gnutls_pk_ops.decrypt2(algo, ciphertext, plaintext, size, params) + _gnutls_pk_backend()->decrypt(algo, ciphertext, plaintext, params) +#define _gnutls_pk_decrypt2(algo, ciphertext, plaintext, size, params) \ + _gnutls_pk_backend()->decrypt2(algo, ciphertext, plaintext, size, \ + params) #define _gnutls_pk_sign(algo, sig, data, params, sign_params) \ - _gnutls_pk_ops.sign(algo, sig, data, params, sign_params) + _gnutls_pk_backend()->sign(algo, sig, data, params, sign_params) #define _gnutls_pk_verify(algo, data, sig, params, sign_params) \ - _gnutls_pk_ops.verify(algo, data, sig, params, sign_params) + _gnutls_pk_backend()->verify(algo, data, sig, params, sign_params) #define _gnutls_pk_verify_priv_params(algo, params) \ - _gnutls_pk_ops.verify_priv_params(algo, params) + _gnutls_pk_backend()->verify_priv_params(algo, params) #define _gnutls_pk_verify_pub_params(algo, params) \ - _gnutls_pk_ops.verify_pub_params(algo, params) + _gnutls_pk_backend()->verify_pub_params(algo, params) #define _gnutls_pk_derive(algo, out, pub, priv) \ - _gnutls_pk_ops.derive(algo, out, pub, priv, NULL, 0) + _gnutls_pk_backend()->derive(algo, out, pub, priv, NULL, 0) #define _gnutls_pk_derive_nonce(algo, out, pub, priv, nonce) \ - _gnutls_pk_ops.derive(algo, out, pub, priv, nonce, 0) -#define _gnutls_pk_derive_tls13(algo, out, pub, priv) \ - _gnutls_pk_ops.derive(algo, out, pub, priv, NULL, PK_DERIVE_TLS13) + _gnutls_pk_backend()->derive(algo, out, pub, priv, nonce, 0) +#define _gnutls_pk_derive_tls13(algo, out, pub, priv) \ + _gnutls_pk_backend()->derive(algo, out, pub, priv, NULL, \ + PK_DERIVE_TLS13) #define _gnutls_pk_encaps(algo, ciphertext, shared_secret, pub) \ - _gnutls_pk_ops.encaps(algo, ciphertext, shared_secret, pub) + _gnutls_pk_backend()->encaps(algo, ciphertext, shared_secret, pub) #define _gnutls_pk_decaps(algo, shared_secret, ciphertext, priv) \ - _gnutls_pk_ops.decaps(algo, shared_secret, ciphertext, priv) + _gnutls_pk_backend()->decaps(algo, shared_secret, ciphertext, priv) #define _gnutls_pk_generate_keys(algo, bits, params, temporal) \ - _gnutls_pk_ops.generate_keys(algo, bits, params, temporal) + _gnutls_pk_backend()->generate_keys(algo, bits, params, temporal) #define _gnutls_pk_generate_params(algo, bits, priv) \ - _gnutls_pk_ops.generate_params(algo, bits, priv) + _gnutls_pk_backend()->generate_params(algo, bits, priv) #define _gnutls_pk_hash_algorithm(pk, sig, params, hash) \ - _gnutls_pk_ops.hash_algorithm(pk, sig, params, hash) -#define _gnutls_pk_curve_exists(curve) _gnutls_pk_ops.curve_exists(curve) -#define _gnutls_pk_exists(algo) _gnutls_pk_ops.pk_exists(algo) -#define _gnutls_pk_sign_exists(algo) _gnutls_pk_ops.sign_exists(algo) + _gnutls_pk_backend()->hash_algorithm(pk, sig, params, hash) +#define _gnutls_pk_curve_exists(curve) _gnutls_pk_backend()->curve_exists(curve) +#define _gnutls_pk_exists(algo) _gnutls_pk_backend()->pk_exists(algo) +#define _gnutls_pk_sign_exists(algo) _gnutls_pk_backend()->sign_exists(algo) inline static int _gnutls_pk_fixup(gnutls_pk_algorithm_t algo, gnutls_direction_t direction, gnutls_pk_params_st *params) { - if (_gnutls_pk_ops.pk_fixup_private_params) - return _gnutls_pk_ops.pk_fixup_private_params(algo, direction, - params); + if (_gnutls_pk_backend()->pk_fixup_private_params) + return _gnutls_pk_backend()->pk_fixup_private_params( + algo, direction, params); return 0; }