linuxkm: support DRBG in LKCAPI shim set:

* Implement --enable-linuxkm-lkcapi-register=stdrng and =stdrng-default,
  LINUXKM_LKCAPI_REGISTER_HASH_DRBG, and
  LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT.  With "_DEFAULT", the DRBG is
  installed as the systemwide default stdrng, necessitating
  deregister-on-command, described below.  Note that get_random_bytes() and the
  associated /dev/random and /dev/urandom do not use the default stdrng, and
  their back end cannot currently be replaced by a module.

* Add control nodes /sys/module/libwolfssl/install_algs and
  /sys/module/libwolfssl/deinstall_algs.

* Add configure option --enable-linuxkm-lkcapi-register=sysfs-nodes-only, and
  macro LINUXKM_LKCAPI_REGISTER_ONLY_ON_COMMAND, to inhibit registration at
  module load time.

In configure.ac ENABLED_LINUXKM_LKCAPI_REGISTER setup, don't define
  WOLFSSL_DH_GEN_PUB in old FIPS, but do define it for =all.
This commit is contained in:
Daniel Pouzzner
2025-04-29 00:42:15 -05:00
parent 4450167ab0
commit 273b7fc0da
7 changed files with 534 additions and 98 deletions

View File

@@ -868,6 +868,8 @@ _ABIO64
_ARCH_PPC64
_COMPILER_VERSION
_INTPTR_T_DECLARED
_LINUX_REFCOUNT_H
_LINUX_REFCOUNT_TYPES_H
_LP64
_MSC_VER
_MSVC_LANG

View File

@@ -9405,7 +9405,10 @@ then
for lkcapi_alg in $(echo "$ENABLED_LINUXKM_LKCAPI_REGISTER" | tr ',' ' ')
do
case "$lkcapi_alg" in
all) AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_ALL -DWC_RSA_NO_PADDING" ;;
all) AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_ALL -DWC_RSA_NO_PADDING -DWOLFSSL_DH_EXTRA"
ENABLED_LINUXKM_LKCAPI_REGISTER_DH=yes
;;
sysfs-nodes-only) ENABLED_LINUXKM_LKCAPI_REGISTER_ONLY_ON_COMMAND=yes ;;
'cbc(aes)') test "$ENABLED_AESCBC" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-CBC implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESCBC" ;;
'cfb(aes)') test "$ENABLED_AESCFB" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-CFB implementation not enabled.])
@@ -9436,12 +9439,18 @@ then
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_SHA2_HMAC" ;;
'hmac(sha3)') test "$ENABLED_SHA3" != "no" && test "$ENABLED_HMAC" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: SHA-3 HMAC implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_SHA3_HMAC" ;;
'stdrng') test "$ENABLED_HASHDRBG" != "no" && AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: HASHDRBG implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_HASH_DRBG" ;;
'stdrng-default') test "$ENABLED_HASHDRBG" != "no" && AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: HASHDRBG implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_HASH_DRBG -DLINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT" ;;
'ecdsa') test "$ENABLED_ECC" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: ECDSA implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_ECDSA" ;;
'ecdh') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_ECDH" ;;
'rsa') test "$ENABLED_RSA" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: RSA implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_RSA -DWC_RSA_NO_PADDING" ;;
'dh') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_DH -DWOLFSSL_DH_EXTRA -DWOLFSSL_DH_GEN_PUB" ;;
'dh') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_DH -DWOLFSSL_DH_EXTRA"
ENABLED_LINUXKM_LKCAPI_REGISTER_DH=yes
;;
# disable options
'-cbc(aes)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESCBC" ;;
'-cfb(aes)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESCFB" ;;
@@ -9458,6 +9467,8 @@ then
'-hmac(sha1)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_SHA1_HMAC" ;;
'-hmac(sha2)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_SHA2_HMAC" ;;
'-hmac(sha3)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_SHA3_HMAC" ;;
'-stdrng') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG" ;;
'-stdrng-default') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG_DEFAULT" ;;
'-ecdsa') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_ECDSA" ;;
'-ecdh') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_ECDH" ;;
'-rsa') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_RSA" ;;
@@ -9465,6 +9476,17 @@ then
*) AC_MSG_ERROR([Unsupported LKCAPI algorithm "$lkcapi_alg".]) ;;
esac
done
if test "$ENABLED_LINUXKM_LKCAPI_REGISTER_DH" = "yes" &&
(test "$ENABLED_FIPS" = "no" || test $HAVE_FIPS_VERSION -ge 7)
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DH_GEN_PUB"
fi
if test "$ENABLED_LINUXKM_LKCAPI_REGISTER_ONLY_ON_COMMAND" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_ONLY_ON_COMMAND"
fi
fi
AC_SUBST([ENABLED_LINUXKM_LKCAPI_REGISTER])

View File

@@ -294,6 +294,7 @@
#include <crypto/scatterwalk.h>
#include <crypto/internal/aead.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/rng.h>
#include <crypto/internal/skcipher.h>
#include <crypto/internal/akcipher.h>
#include <crypto/internal/kpp.h>
@@ -301,7 +302,7 @@
/* the LKCAPI assumes that expanded encrypt and decrypt keys will stay
* loaded simultaneously, and the Linux in-tree implementations have two
* AES key structs in each context, one for each direction. in
* linuxkm/lkcapi_glue.c (used for CBC, CFB, and GCM), we do the same
* linuxkm/lkcapi_aes_glue.c, we do the same
* thing with "struct km_AesCtx". however, wolfCrypt struct AesXts
* already has two AES expanded keys, the main and tweak, and the tweak
* is always used in the encrypt direction regardless of the main
@@ -314,6 +315,12 @@
#ifndef WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS
#define WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS
#endif
#if defined(_LINUX_REFCOUNT_H) || defined(_LINUX_REFCOUNT_TYPES_H)
#define WC_LKM_REFCOUNT_TO_INT(refcount) (atomic_read(&(refcount.refs)))
#else
#define WC_LKM_REFCOUNT_TO_INT(refcount) (atomic_read(&(refcount)))
#endif
#endif
#if defined(WOLFSSL_AESNI) || defined(USE_INTEL_SPEEDUP) || \
@@ -930,7 +937,7 @@
#define WC_LINUXKM_ROUND_UP_P_OF_2(x) ( \
{ \
size_t _alloc_sz = (x); \
if (_alloc_sz < 8192) \
if ((_alloc_sz < 8192) && (_alloc_sz != 0)) \
_alloc_sz = 1UL << \
((sizeof(_alloc_sz) * 8UL) - __builtin_clzl(_alloc_sz - 1)); \
_alloc_sz; \

View File

@@ -80,6 +80,13 @@
#define WOLFKM_DRIVER_SUFFIX_BASE "-wolfcrypt" WOLFKM_DRIVER_FIPS
#define WOLFKM_INSTALL_NOTICE(alg) \
pr_info("%s self-test OK -- " \
"registered for %s with priority %d.\n", \
(alg).base.cra_driver_name, \
(alg).base.cra_name, \
(alg).base.cra_priority); \
#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES
enum linux_errcodes {
my_EINVAL = EINVAL,
@@ -249,10 +256,10 @@ WC_MAYBE_UNUSED static int check_shash_driver_masking(struct crypto_shash *tfm,
#if defined (LINUXKM_LKCAPI_REGISTER_ECDSA)
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && \
defined(CONFIG_CRYPTO_FIPS) && defined(CONFIG_CRYPTO_MANAGER)
/**
/*
* note: ecdsa was not recognized as fips_allowed before linux v6.3
* in kernel crypto/testmgr.c, and will not pass the tests.
* */
*/
#undef LINUXKM_LKCAPI_REGISTER_ECDSA
#endif /* linux < 6.3.0 && CONFIG_CRYPTO_FIPS && CONFIG_CRYPTO_MANAGER */
@@ -271,7 +278,7 @@ WC_MAYBE_UNUSED static int check_shash_driver_masking(struct crypto_shash *tfm,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0)
/**
/*
* notes:
* - ecdsa supported with linux 6.12 and earlier for now, only.
* - pkcs1pad rsa supported both before and after linux 6.13, but
@@ -283,7 +290,7 @@ WC_MAYBE_UNUSED static int check_shash_driver_masking(struct crypto_shash *tfm,
*
* pkcs1pad rsa remained a struct akcipher_alg, but without sign/verify
* functionality.
* */
*/
#if defined (LINUXKM_LKCAPI_REGISTER_ECDSA)
#undef LINUXKM_LKCAPI_REGISTER_ECDSA
#endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */
@@ -307,10 +314,10 @@ WC_MAYBE_UNUSED static int check_shash_driver_masking(struct crypto_shash *tfm,
#if defined (LINUXKM_LKCAPI_REGISTER_DH) && defined(CONFIG_CRYPTO_FIPS) && \
defined(CONFIG_CRYPTO_MANAGER)
/**
* note: normal dh not fips_allowed in in kernel crypto/testmgr.c,
/*
* note: normal dh not fips_allowed in kernel crypto/testmgr.c,
* and will not pass the tests.
* */
*/
#undef LINUXKM_DH
#endif /* LINUXKM_LKCAPI_REGISTER_DH */
@@ -330,14 +337,100 @@ WC_MAYBE_UNUSED static int check_shash_driver_masking(struct crypto_shash *tfm,
#include "linuxkm/lkcapi_dh_glue.c"
#endif /* LINUXKM_LKCAPI_REGISTER_DH */
static int linuxkm_lkcapi_register(void);
static int linuxkm_lkcapi_unregister(void);
static ssize_t install_algs_handler(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
int arg;
int ret;
(void)kobj;
(void)attr;
if (kstrtoint(buf, 10, &arg) || arg != 1)
return -EINVAL;
pr_info("wolfCrypt: Installing algorithms");
ret = linuxkm_lkcapi_register();
if (ret != 0)
return ret;
return count;
}
static ssize_t deinstall_algs_handler(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
int arg;
int ret;
(void)kobj;
(void)attr;
if (kstrtoint(buf, 10, &arg) || arg != 1)
return -EINVAL;
pr_info("wolfCrypt: Deinstalling algorithms");
ret = linuxkm_lkcapi_unregister();
if (ret != 0)
return ret;
return count;
}
/* create control channels at /sys/module/libwolfssl/parameters/{install_algs,deinstall_algs} */
static struct kobj_attribute install_algs_attr = __ATTR(install_algs, 0220, NULL, install_algs_handler);
static struct kobj_attribute deinstall_algs_attr = __ATTR(deinstall_algs, 0220, NULL, deinstall_algs_handler);
static int installed_sysfs_files = 0;
static int linuxkm_lkcapi_sysfs_install(void) {
int ret;
if (! installed_sysfs_files) {
installed_sysfs_files = 1;
ret = sysfs_create_file(&THIS_MODULE->mkobj.kobj, &install_algs_attr.attr);
if (ret) {
pr_err("sysfs_create_file failed: %d\n", ret);
return ret;
}
ret = sysfs_create_file(&THIS_MODULE->mkobj.kobj, &deinstall_algs_attr.attr);
if (ret) {
pr_err("sysfs_create_file failed: %d\n", ret);
return ret;
}
}
return 0;
}
static int linuxkm_lkcapi_sysfs_deinstall(void) {
if (installed_sysfs_files) {
installed_sysfs_files = 0;
sysfs_remove_file(&THIS_MODULE->mkobj.kobj, &install_algs_attr.attr);
sysfs_remove_file(&THIS_MODULE->mkobj.kobj, &deinstall_algs_attr.attr);
}
return 0;
}
static int linuxkm_lkcapi_registered = 0;
static int linuxkm_lkcapi_register(void)
{
int ret = 0;
int ret = -1;
int seen_err = 0;
#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
int enabled_fips = 0;
#endif
ret = linuxkm_lkcapi_sysfs_install();
if (ret)
return ret;
#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
/* temporarily disable warnings around setkey failures, which are expected
* from the crypto fuzzer in FIPS configs, and potentially in others.
@@ -355,196 +448,191 @@ static int linuxkm_lkcapi_register(void)
}
#endif
#define REGISTER_ALG(alg, installer, tester) do { \
if (alg ## _loaded) { \
pr_err("ERROR: %s is already registered.\n", \
(alg).base.cra_driver_name); \
ret = -EEXIST; \
goto out; \
} \
\
ret = (installer)(&(alg)); \
\
if (ret) { \
pr_err("ERROR: " #installer " for %s failed " \
"with return code %d.\n", \
(alg).base.cra_driver_name, ret); \
goto out; \
} \
\
alg ## _loaded = 1; \
\
ret = (tester()); \
\
if (ret) { \
pr_err("ERROR: self-test for %s failed " \
"with return code %d.\n", \
(alg).base.cra_driver_name, ret); \
goto out; \
} \
pr_info("%s self-test OK -- " \
"registered for %s with priority %d.\n", \
(alg).base.cra_driver_name, \
(alg).base.cra_name, \
(alg).base.cra_priority); \
#define REGISTER_ALG(alg, alg_class, tester) do { \
if (! alg ## _loaded) { \
ret = (crypto_register_ ## alg_class)(&(alg)); \
if (ret) { \
seen_err = 1; \
pr_err("ERROR: crypto_register_" #alg_class " for %s failed "\
"with return code %d.\n", \
(alg).base.cra_driver_name, ret); \
} else { \
ret = (tester()); \
if (ret) { \
seen_err = 1; \
pr_err("ERROR: self-test for %s failed " \
"with return code %d.\n", \
(alg).base.cra_driver_name, ret); \
(crypto_unregister_ ## alg_class)(&(alg)); \
} else { \
alg ## _loaded = 1; \
WOLFKM_INSTALL_NOTICE(alg) \
} \
} \
} \
} while (0)
#ifdef LINUXKM_LKCAPI_REGISTER_AESCBC
REGISTER_ALG(cbcAesAlg, crypto_register_skcipher, linuxkm_test_aescbc);
REGISTER_ALG(cbcAesAlg, skcipher, linuxkm_test_aescbc);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESCFB
REGISTER_ALG(cfbAesAlg, crypto_register_skcipher, linuxkm_test_aescfb);
REGISTER_ALG(cfbAesAlg, skcipher, linuxkm_test_aescfb);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESGCM
REGISTER_ALG(gcmAesAead, crypto_register_aead, linuxkm_test_aesgcm);
REGISTER_ALG(gcmAesAead, aead, linuxkm_test_aesgcm);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106
REGISTER_ALG(gcmAesAead_rfc4106, crypto_register_aead, linuxkm_test_aesgcm_rfc4106);
REGISTER_ALG(gcmAesAead_rfc4106, aead, linuxkm_test_aesgcm_rfc4106);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESXTS
REGISTER_ALG(xtsAesAlg, crypto_register_skcipher, linuxkm_test_aesxts);
REGISTER_ALG(xtsAesAlg, skcipher, linuxkm_test_aesxts);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESCTR
REGISTER_ALG(ctrAesAlg, crypto_register_skcipher, linuxkm_test_aesctr);
REGISTER_ALG(ctrAesAlg, skcipher, linuxkm_test_aesctr);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESOFB
REGISTER_ALG(ofbAesAlg, crypto_register_skcipher, linuxkm_test_aesofb);
REGISTER_ALG(ofbAesAlg, skcipher, linuxkm_test_aesofb);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESECB
REGISTER_ALG(ecbAesAlg, crypto_register_skcipher, linuxkm_test_aesecb);
REGISTER_ALG(ecbAesAlg, skcipher, linuxkm_test_aesecb);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA1
REGISTER_ALG(sha1_alg, crypto_register_shash, linuxkm_test_sha1);
REGISTER_ALG(sha1_alg, shash, linuxkm_test_sha1);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2_224
REGISTER_ALG(sha2_224_alg, crypto_register_shash, linuxkm_test_sha2_224);
REGISTER_ALG(sha2_224_alg, shash, linuxkm_test_sha2_224);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2_256
REGISTER_ALG(sha2_256_alg, crypto_register_shash, linuxkm_test_sha2_256);
REGISTER_ALG(sha2_256_alg, shash, linuxkm_test_sha2_256);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2_384
REGISTER_ALG(sha2_384_alg, crypto_register_shash, linuxkm_test_sha2_384);
REGISTER_ALG(sha2_384_alg, shash, linuxkm_test_sha2_384);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2_512
REGISTER_ALG(sha2_512_alg, crypto_register_shash, linuxkm_test_sha2_512);
REGISTER_ALG(sha2_512_alg, shash, linuxkm_test_sha2_512);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA3_224
REGISTER_ALG(sha3_224_alg, crypto_register_shash, linuxkm_test_sha3_224);
REGISTER_ALG(sha3_224_alg, shash, linuxkm_test_sha3_224);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA3_256
REGISTER_ALG(sha3_256_alg, crypto_register_shash, linuxkm_test_sha3_256);
REGISTER_ALG(sha3_256_alg, shash, linuxkm_test_sha3_256);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA3_384
REGISTER_ALG(sha3_384_alg, crypto_register_shash, linuxkm_test_sha3_384);
REGISTER_ALG(sha3_384_alg, shash, linuxkm_test_sha3_384);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA3_512
REGISTER_ALG(sha3_512_alg, crypto_register_shash, linuxkm_test_sha3_512);
REGISTER_ALG(sha3_512_alg, shash, linuxkm_test_sha3_512);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA1_HMAC
REGISTER_ALG(sha1_hmac_alg, crypto_register_shash, linuxkm_test_sha1_hmac);
REGISTER_ALG(sha1_hmac_alg, shash, linuxkm_test_sha1_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2_224_HMAC
REGISTER_ALG(sha2_224_hmac_alg, crypto_register_shash, linuxkm_test_sha2_224_hmac);
REGISTER_ALG(sha2_224_hmac_alg, shash, linuxkm_test_sha2_224_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2_256_HMAC
REGISTER_ALG(sha2_256_hmac_alg, crypto_register_shash, linuxkm_test_sha2_256_hmac);
REGISTER_ALG(sha2_256_hmac_alg, shash, linuxkm_test_sha2_256_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2_384_HMAC
REGISTER_ALG(sha2_384_hmac_alg, crypto_register_shash, linuxkm_test_sha2_384_hmac);
REGISTER_ALG(sha2_384_hmac_alg, shash, linuxkm_test_sha2_384_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2_512_HMAC
REGISTER_ALG(sha2_512_hmac_alg, crypto_register_shash, linuxkm_test_sha2_512_hmac);
REGISTER_ALG(sha2_512_hmac_alg, shash, linuxkm_test_sha2_512_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA3_224_HMAC
REGISTER_ALG(sha3_224_hmac_alg, crypto_register_shash, linuxkm_test_sha3_224_hmac);
REGISTER_ALG(sha3_224_hmac_alg, shash, linuxkm_test_sha3_224_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA3_256_HMAC
REGISTER_ALG(sha3_256_hmac_alg, crypto_register_shash, linuxkm_test_sha3_256_hmac);
REGISTER_ALG(sha3_256_hmac_alg, shash, linuxkm_test_sha3_256_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA3_384_HMAC
REGISTER_ALG(sha3_384_hmac_alg, crypto_register_shash, linuxkm_test_sha3_384_hmac);
REGISTER_ALG(sha3_384_hmac_alg, shash, linuxkm_test_sha3_384_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA3_512_HMAC
REGISTER_ALG(sha3_512_hmac_alg, crypto_register_shash, linuxkm_test_sha3_512_hmac);
REGISTER_ALG(sha3_512_hmac_alg, shash, linuxkm_test_sha3_512_hmac);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG
/* special installation handler for wc_linuxkm_drbg, to conditionally
* install it as the system-wide default rng.
*/
if (! wc_linuxkm_drbg_loaded)
ret = wc_linuxkm_drbg_startup();
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_ECDSA
#if defined(LINUXKM_ECC192)
REGISTER_ALG(ecdsa_nist_p192, crypto_register_akcipher,
REGISTER_ALG(ecdsa_nist_p192, akcipher,
linuxkm_test_ecdsa_nist_p192);
#endif /* LINUXKM_ECC192 */
REGISTER_ALG(ecdsa_nist_p256, crypto_register_akcipher,
REGISTER_ALG(ecdsa_nist_p256, akcipher,
linuxkm_test_ecdsa_nist_p256);
REGISTER_ALG(ecdsa_nist_p384, crypto_register_akcipher,
REGISTER_ALG(ecdsa_nist_p384, akcipher,
linuxkm_test_ecdsa_nist_p384);
#if defined(HAVE_ECC521)
REGISTER_ALG(ecdsa_nist_p521, crypto_register_akcipher,
REGISTER_ALG(ecdsa_nist_p521, akcipher,
linuxkm_test_ecdsa_nist_p521);
#endif /* HAVE_ECC521 */
#endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */
#ifdef LINUXKM_LKCAPI_REGISTER_ECDH
#if defined(LINUXKM_ECC192)
REGISTER_ALG(ecdh_nist_p192, crypto_register_kpp,
REGISTER_ALG(ecdh_nist_p192, kpp,
linuxkm_test_ecdh_nist_p192);
#endif /* LINUXKM_ECC192 */
REGISTER_ALG(ecdh_nist_p256, crypto_register_kpp,
REGISTER_ALG(ecdh_nist_p256, kpp,
linuxkm_test_ecdh_nist_p256);
REGISTER_ALG(ecdh_nist_p384, crypto_register_kpp,
REGISTER_ALG(ecdh_nist_p384, kpp,
linuxkm_test_ecdh_nist_p384);
#endif /* LINUXKM_LKCAPI_REGISTER_ECDH */
#ifdef LINUXKM_LKCAPI_REGISTER_RSA
#if defined(LINUXKM_DIRECT_RSA)
REGISTER_ALG(direct_rsa, crypto_register_akcipher, linuxkm_test_rsa);
REGISTER_ALG(direct_rsa, akcipher, linuxkm_test_rsa);
#endif /* LINUXKM_DIRECT_RSA */
#ifndef NO_SHA256
REGISTER_ALG(pkcs1_sha256, crypto_register_akcipher,
REGISTER_ALG(pkcs1_sha256, akcipher,
linuxkm_test_pkcs1_sha256);
#endif /* !NO_SHA256 */
#ifdef WOLFSSL_SHA512
REGISTER_ALG(pkcs1_sha512, crypto_register_akcipher,
REGISTER_ALG(pkcs1_sha512, akcipher,
linuxkm_test_pkcs1_sha512);
#endif /* WOLFSSL_SHA512 */
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_DH
#ifdef LINUXKM_DH
REGISTER_ALG(dh, crypto_register_kpp, linuxkm_test_dh);
REGISTER_ALG(dh, kpp, linuxkm_test_dh);
#endif /* LINUXKM_DH */
#ifdef HAVE_FFDHE_2048
REGISTER_ALG(ffdhe2048, crypto_register_kpp, linuxkm_test_ffdhe2048);
REGISTER_ALG(ffdhe2048, kpp, linuxkm_test_ffdhe2048);
#endif /* HAVE_FFDHE_2048 */
#ifdef HAVE_FFDHE_3072
REGISTER_ALG(ffdhe3072, crypto_register_kpp, linuxkm_test_ffdhe3072);
REGISTER_ALG(ffdhe3072, kpp, linuxkm_test_ffdhe3072);
#endif /* HAVE_FFDHE_3072 */
#ifdef HAVE_FFDHE_4096
REGISTER_ALG(ffdhe4096, crypto_register_kpp, linuxkm_test_ffdhe4096);
REGISTER_ALG(ffdhe4096, kpp, linuxkm_test_ffdhe4096);
#endif /* HAVE_FFDHE_4096 */
#ifdef HAVE_FFDHE_6144
REGISTER_ALG(ffdhe6144, crypto_register_kpp, linuxkm_test_ffdhe6144);
REGISTER_ALG(ffdhe6144, kpp, linuxkm_test_ffdhe6144);
#endif /* HAVE_FFDHE_6144 */
#ifdef HAVE_FFDHE_8192
REGISTER_ALG(ffdhe8192, crypto_register_kpp, linuxkm_test_ffdhe8192);
REGISTER_ALG(ffdhe8192, kpp, linuxkm_test_ffdhe8192);
#endif /* HAVE_FFDHE_8192 */
#endif /* LINUXKM_LKCAPI_REGISTER_DH */
#undef REGISTER_ALG
out:
#if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \
!defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
if (enabled_fips)
@@ -554,16 +642,47 @@ static int linuxkm_lkcapi_register(void)
disable_setkey_warnings = 0;
#endif
return ret;
if (ret == -1) {
/* no installations occurred */
if (linuxkm_lkcapi_registered)
return -EEXIST;
else {
linuxkm_lkcapi_registered = 1;
return 0;
}
}
else {
/* flag that linuxkm_lkcapi_register has been called, even if an error
* occurred.
*/
linuxkm_lkcapi_registered = 1;
if (seen_err)
return -EINVAL;
else
return 0;
}
}
static void linuxkm_lkcapi_unregister(void)
static int linuxkm_lkcapi_unregister(void)
{
#define UNREGISTER_ALG(alg, uninstaller) do { \
if (alg ## _loaded) { \
(uninstaller)(&(alg)); \
alg ## _loaded = 0; \
} \
int seen_err = 0;
if (! linuxkm_lkcapi_registered)
return -ENOENT;
#define UNREGISTER_ALG(alg, uninstaller) do { \
if (alg ## _loaded) { \
int cur_refcnt = WC_LKM_REFCOUNT_TO_INT(alg.base.cra_refcnt);\
if (cur_refcnt == 1) { \
(uninstaller)(&(alg)); \
alg ## _loaded = 0; \
} \
else { \
pr_err("alg %s cannot be uninstalled (refcnt = %d)", \
alg.base.cra_driver_name, cur_refcnt); \
if (cur_refcnt > 0) { seen_err = 1; } \
} \
} \
} while (0)
#ifdef LINUXKM_LKCAPI_REGISTER_AESCBC
@@ -647,6 +766,16 @@ static void linuxkm_lkcapi_unregister(void)
UNREGISTER_ALG(sha3_512_hmac_alg, crypto_unregister_shash);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG
/* special deinstallation handler for wc_linuxkm_drbg, to deinstall it as
* the system-wide default rng.
*/
if (wc_linuxkm_drbg_loaded) {
if (wc_linuxkm_drbg_cleanup() != 0)
seen_err = 1;
}
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_ECDSA
#if defined(LINUXKM_ECC192)
UNREGISTER_ALG(ecdsa_nist_p192, crypto_unregister_akcipher);
@@ -705,4 +834,15 @@ static void linuxkm_lkcapi_unregister(void)
#endif /* LINUXKM_LKCAPI_REGISTER_DH */
#undef UNREGISTER_ALG
/* only clear linuxkm_lkcapi_registered if no errors occurred, to allow
* retries.
*/
if (seen_err == 0) {
linuxkm_lkcapi_registered = 0;
pr_info("wolfCrypt: All algorithms deregistered successfully.");
}
return seen_err ? -EINVAL : 0;
}

View File

@@ -33,6 +33,7 @@
#define WOLFKM_SHA3_256_NAME "sha3-256"
#define WOLFKM_SHA3_384_NAME "sha3-384"
#define WOLFKM_SHA3_512_NAME "sha3-512"
#define WOLFKM_SHA1_HMAC_NAME "hmac(sha1)"
#define WOLFKM_SHA2_224_HMAC_NAME "hmac(sha224)"
#define WOLFKM_SHA2_256_HMAC_NAME "hmac(sha256)"
@@ -43,6 +44,8 @@
#define WOLFKM_SHA3_384_HMAC_NAME "hmac(sha3-384)"
#define WOLFKM_SHA3_512_HMAC_NAME "hmac(sha3-512)"
#define WOLFKM_STDRNG_NAME "stdrng"
#if defined(USE_INTEL_SPEEDUP)
#define WOLFKM_SHA_DRIVER_ISA_EXT "-avx"
#else
@@ -72,6 +75,8 @@
#define WOLFKM_SHA3_384_HMAC_DRIVER ("hmac-sha3-384" WOLFKM_SHA_DRIVER_SUFFIX)
#define WOLFKM_SHA3_512_HMAC_DRIVER ("hmac-sha3-512" WOLFKM_SHA_DRIVER_SUFFIX)
#define WOLFKM_STDRNG_DRIVER ("sha2-256-drbg" WOLFKM_SHA_DRIVER_SUFFIX)
#ifdef LINUXKM_LKCAPI_REGISTER_SHA2
#define LINUXKM_LKCAPI_REGISTER_SHA2_224
#define LINUXKM_LKCAPI_REGISTER_SHA2_256
@@ -274,6 +279,19 @@
#error LINUXKM_LKCAPI_REGISTER for HMACs is supported only on Linux kernel versions >= 5.6.0.
#endif
#ifdef HAVE_HASHDRBG
#if (defined(LINUXKM_LKCAPI_REGISTER_ALL) && !defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG)) && \
!defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG)
#define LINUXKM_LKCAPI_REGISTER_HASH_DRBG
#endif
#if (defined(LINUXKM_LKCAPI_REGISTER_ALL) && !defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG_DEFAULT)) && \
!defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT)
#define LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
#endif
#else
#undef LINUXKM_LKCAPI_REGISTER_HASH_DRBG
#endif
struct km_sha_state {
union {
#ifdef LINUXKM_LKCAPI_REGISTER_SHA1
@@ -811,3 +829,238 @@ struct wc_swallow_the_semicolon
WC_SHA3_512_BLOCK_SIZE, WOLFKM_SHA3_512_HMAC_NAME,
WOLFKM_SHA3_512_HMAC_DRIVER, hmac_sha3_test_once);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG
#include <wolfssl/wolfcrypt/random.h>
struct wc_linuxkm_drbg_ctx {
wolfSSL_Mutex lock;
WC_RNG rng;
};
static int wc_linuxkm_drbg_init_tfm(struct crypto_tfm *tfm)
{
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_tfm_ctx(tfm);
int ret;
ret = wc_InitMutex(&ctx->lock);
if (ret != 0)
return -EINVAL;
/* Note the new DRBG instance is seeded, and later reseeded, from system
* get_random_bytes() via wc_GenerateSeed().
*/
ret = wc_InitRng(&ctx->rng);
if (ret != 0) {
(void)wc_FreeMutex(&ctx->lock);
return -EINVAL;
}
return 0;
}
static void wc_linuxkm_drbg_exit_tfm(struct crypto_tfm *tfm)
{
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_tfm_ctx(tfm);
wc_FreeRng(&ctx->rng);
(void)wc_FreeMutex(&ctx->lock);
return;
}
static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int dlen)
{
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm);
int ret;
(void)tfm;
wc_LockMutex(&ctx->lock);
if (slen > 0) {
ret = wc_RNG_DRBG_Reseed(&ctx->rng, src, slen);
if (ret != 0) {
ret = -EINVAL;
goto out;
}
}
ret = wc_RNG_GenerateBlock(&ctx->rng, dst, dlen);
if (ret != 0)
ret = -EINVAL;
out:
wc_UnLockMutex(&ctx->lock);
return ret;
}
static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm,
const u8 *seed, unsigned int slen)
{
struct wc_linuxkm_drbg_ctx *ctx = (struct wc_linuxkm_drbg_ctx *)crypto_rng_ctx(tfm);
int ret;
(void)tfm;
if (slen == 0)
return 0;
wc_LockMutex(&ctx->lock);
ret = wc_RNG_DRBG_Reseed(&ctx->rng, seed, slen);
if (ret != 0) {
ret = -EINVAL;
goto out;
}
out:
wc_UnLockMutex(&ctx->lock);
return ret;
}
static struct rng_alg wc_linuxkm_drbg = {
.generate = wc_linuxkm_drbg_generate,
.seed = wc_linuxkm_drbg_seed,
.seedsize = 0,
.base = {
.cra_name = WOLFKM_STDRNG_NAME,
.cra_driver_name = WOLFKM_STDRNG_DRIVER,
.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY,
.cra_ctxsize = sizeof(struct wc_linuxkm_drbg_ctx),
.cra_init = wc_linuxkm_drbg_init_tfm,
.cra_exit = wc_linuxkm_drbg_exit_tfm,
.cra_module = THIS_MODULE
}
};
static int wc_linuxkm_drbg_loaded = 0;
static int wc_linuxkm_drbg_default_instance_registered = 0;
WC_MAYBE_UNUSED static int wc_linuxkm_drbg_startup(void) {
int ret;
int cur_refcnt;
if (wc_linuxkm_drbg_loaded) {
pr_err("wc_linuxkm_drbg_set_default called with wc_linuxkm_drbg_loaded.");
return -EBUSY;
}
ret = random_test();
if (ret) {
pr_err("ERROR: self-test for %s failed "
"with return code %d.\n",
wc_linuxkm_drbg.base.cra_driver_name, ret);
return -EINVAL;
}
ret = crypto_register_rng(&wc_linuxkm_drbg);
if (ret != 0) {
pr_err("crypto_register_rng: %d", ret);
return ret;
}
wc_linuxkm_drbg_loaded = 1;
WOLFKM_INSTALL_NOTICE(wc_linuxkm_drbg);
#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
ret = crypto_del_default_rng();
if (ret) {
pr_err("crypto_del_default_rng returned %d", ret);
return ret;
}
ret = crypto_get_default_rng();
if (ret) {
pr_err("crypto_get_default_rng returned %d", ret);
return ret;
}
cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt);
if (cur_refcnt < 2) {
pr_err("wc_linuxkm_drbg refcnt = %d after crypto_get_default_rng()", cur_refcnt);
crypto_put_default_rng();
return -EINVAL;
}
if (! crypto_default_rng) {
pr_err("crypto_default_rng is null");
crypto_put_default_rng();
return -EINVAL;
}
if (strcmp(crypto_tfm_alg_driver_name(&crypto_default_rng->base), wc_linuxkm_drbg.base.cra_driver_name) == 0) {
crypto_put_default_rng();
wc_linuxkm_drbg_default_instance_registered = 1;
pr_info("%s registered as systemwide default stdrng.", wc_linuxkm_drbg.base.cra_driver_name);
pr_info("to unload module, first echo 1 > /sys/module/libwolfssl/deinstall_algs");
}
else {
pr_err("%s NOT registered as systemwide default stdrng -- found \"%s\".", wc_linuxkm_drbg.base.cra_driver_name, crypto_tfm_alg_driver_name(&crypto_default_rng->base));
crypto_put_default_rng();
return -EINVAL;
}
#endif /* LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT */
return 0;
}
WC_MAYBE_UNUSED static int wc_linuxkm_drbg_cleanup(void) {
int cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt);
int ret;
if (! wc_linuxkm_drbg_loaded) {
pr_err("wc_linuxkm_drbg_cleanup called with ! wc_linuxkm_drbg_loaded");
return -EINVAL;
}
if (cur_refcnt - wc_linuxkm_drbg_default_instance_registered != 1) {
pr_err("wc_linuxkm_drbg_cleanup called with refcnt = %d, with wc_linuxkm_drbg %sset as default rng",
cur_refcnt, wc_linuxkm_drbg_default_instance_registered ? "" : "not ");
return -EBUSY;
}
/* The below is racey, but the kernel doesn't provide any other way. It's
* written to be retryable.
*/
#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
if (wc_linuxkm_drbg_default_instance_registered) {
ret = crypto_del_default_rng();
if (ret) {
pr_err("crypto_del_default_rng failed: %d", ret);
return ret;
}
cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt);
if (cur_refcnt != 1) {
pr_err("wc_linuxkm_drbg refcnt = %d after crypto_del_default_rng()", cur_refcnt);
return -EINVAL;
}
}
#endif /* LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT */
crypto_unregister_rng(&wc_linuxkm_drbg);
if (! (wc_linuxkm_drbg.base.cra_flags & CRYPTO_ALG_DEAD)) {
pr_err("wc_linuxkm_drbg_cleanup: after crypto_unregister_rng, wc_linuxkm_drbg isn't dead.");
return -EBUSY;
}
#ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
wc_linuxkm_drbg_default_instance_registered = 0;
#endif /* LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT */
wc_linuxkm_drbg_loaded = 0;
return 0;
}
#endif /* LINUXKM_LKCAPI_REGISTER_HASH_DRBG */

View File

@@ -316,6 +316,16 @@ static int wolfssl_init(void)
#endif
#ifdef LINUXKM_LKCAPI_REGISTER
#ifdef LINUXKM_LKCAPI_REGISTER_ONLY_ON_COMMAND
ret = linuxkm_lkcapi_sysfs_install();
if (ret) {
pr_err("linuxkm_lkcapi_sysfs_install() failed with return code %d.\n", ret);
(void)libwolfssl_cleanup();
msleep(10);
return -ECANCELED;
}
#else /* !LINUXKM_LKCAPI_REGISTER_ONLY_ON_COMMAND */
ret = linuxkm_lkcapi_register();
if (ret) {
@@ -325,7 +335,8 @@ static int wolfssl_init(void)
msleep(10);
return -ECANCELED;
}
#endif
#endif /* !LINUXKM_LKCAPI_REGISTER_ONLY_ON_COMMAND */
#endif /* LINUXKM_LKCAPI_REGISTER */
#ifdef WOLFSSL_LINUXKM_BENCHMARKS
wolfcrypt_benchmark_main(0, (char**)NULL);
@@ -365,7 +376,8 @@ static void wolfssl_exit(void)
#endif
{
#ifdef LINUXKM_LKCAPI_REGISTER
linuxkm_lkcapi_unregister();
(void)linuxkm_lkcapi_unregister();
(void)linuxkm_lkcapi_sysfs_deinstall();
#endif
(void)libwolfssl_cleanup();

View File

@@ -3676,7 +3676,7 @@ extern void uITRON4_free(void *p) ;
#if defined(LINUXKM_LKCAPI_REGISTER) && !defined(WOLFSSL_ASN_INT_LEAD_0_ANY)
/* kernel 5.10 crypto manager tests key(s) that fail unless leading
* bytes are tolerated in GetASN_Integer().
* zero bytes are tolerated in GetASN_Integer().
*/
#define WOLFSSL_ASN_INT_LEAD_0_ANY
#endif