mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-08 17:00:49 +02:00
Merge pull request #10856 from douzzer/20260702-linuxkm-various
20260702-linuxkm-various
This commit is contained in:
@@ -137,6 +137,7 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
|
||||
CONFIG_MBEDTLS_PSA_CRYPTO_C
|
||||
CONFIG_MIPS
|
||||
CONFIG_MODULE_SIG
|
||||
CONFIG_MODULE_SIG_SHA1
|
||||
CONFIG_NET_SOCKETS_SOCKOPT_TLS
|
||||
CONFIG_NEWLIB_LIBC
|
||||
CONFIG_NEWLIB_NANO_FORMAT
|
||||
|
||||
+39
-32
@@ -35,28 +35,43 @@
|
||||
#error Unsupported kernel.
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FIPS) && defined(LINUXKM_LKCAPI_REGISTER_AESXTS) && defined(CONFIG_CRYPTO_MANAGER_EXTRA_TESTS)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0)
|
||||
#if defined(CONFIG_CRYPTO_MANAGER) && !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
|
||||
#define WC_LINUXKM_HAVE_SELFTEST
|
||||
#endif
|
||||
#if defined(WC_LINUXKM_HAVE_SELFTEST) && defined(CONFIG_CRYPTO_MANAGER_EXTRA_TESTS)
|
||||
#define WC_LINUXKM_HAVE_SELFTEST_FULL
|
||||
#endif
|
||||
#else
|
||||
/* see Linux 698de822780f */
|
||||
#if defined(CONFIG_CRYPTO_MANAGER) && defined(CONFIG_CRYPTO_SELFTESTS)
|
||||
#define WC_LINUXKM_HAVE_SELFTEST
|
||||
#endif
|
||||
/* see Linux ac90aad0e9 */
|
||||
#if defined(WC_LINUXKM_HAVE_SELFTEST) && defined(CONFIG_CRYPTO_SELFTESTS_FULL)
|
||||
#define WC_LINUXKM_HAVE_SELFTEST_FULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FIPS) && defined(LINUXKM_LKCAPI_REGISTER_AESXTS) && defined(WC_LINUXKM_HAVE_SELFTEST_FULL)
|
||||
/* CONFIG_CRYPTO_MANAGER_EXTRA_TESTS expects AES-XTS-384 to work, even when CONFIG_CRYPTO_FIPS, but FIPS 140-3 only allows AES-XTS-256 and AES-XTS-512. */
|
||||
#error CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is incompatible with FIPS wolfCrypt AES-XTS -- please reconfigure the target kernel to disable CONFIG_CRYPTO_MANAGER_EXTRA_TESTS.
|
||||
#error CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is incompatible with FIPS wolfCrypt AES-XTS -- please reconfigure the target kernel to disable CONFIG_CRYPTO_MANAGER_EXTRA_TESTS/CONFIG_CRYPTO_SELFTESTS_FULL.
|
||||
#endif
|
||||
|
||||
/* The first vector set in /usr/src/linux/crypto/testmgr.h
|
||||
* ecdsa_nist_p192_tv_template[], ecdsa_nist_p256_tv_template[], and
|
||||
* ecdsa_nist_p384_tv_template[] use SHA-1 (even if CONFIG_CRYPTO_SHA1 is
|
||||
* disabled), and kernel module signatures frequently use SHA-1 until quite
|
||||
* recently (dependent on CONFIG_CRYPTO_SHA1). If either is enabled, force
|
||||
* downgrade to 186-4.
|
||||
* recently.
|
||||
*/
|
||||
#if defined(WC_FIPS_186_5_PLUS) && \
|
||||
(defined(CONFIG_CRYPTO_SHA1) || (defined(CONFIG_CRYPTO_MANAGER) && !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS))) && \
|
||||
(defined(LINUXKM_LKCAPI_REGISTER_ALL) || defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) || defined(CONFIG_CRYPTO_ECDSA))
|
||||
#undef WC_FIPS_186_5_PLUS
|
||||
#ifdef WC_FIPS_186_5
|
||||
#undef WC_FIPS_186_5
|
||||
#else
|
||||
#error Unknown and incompatible FIPS 186 is enabled.
|
||||
#endif
|
||||
#define WC_FIPS_186_4
|
||||
#if (defined(WC_LINUXKM_HAVE_SELFTEST) || defined(CONFIG_MODULE_SIG_SHA1)) && \
|
||||
(((defined(WC_MIN_DIGEST_SIZE_FOR_VERIFY) && (WC_MIN_DIGEST_SIZE_FOR_VERIFY > 20)) || \
|
||||
(defined(NO_SHA) && !defined(WC_MIN_DIGEST_SIZE_FOR_VERIFY)))) && \
|
||||
defined(HAVE_ECC) && \
|
||||
(defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
|
||||
defined(LINUXKM_LKCAPI_REGISTER_ECDSA) || \
|
||||
(defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_ECDSA)))
|
||||
#error Target kernel requires SHA-1 signature verification support.
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@@ -427,24 +442,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0)
|
||||
#if defined(CONFIG_CRYPTO_MANAGER) && !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)
|
||||
#define WC_LINUXKM_HAVE_SELFTEST
|
||||
#endif
|
||||
#if defined(WC_LINUXKM_HAVE_SELFTEST) && defined(CONFIG_CRYPTO_MANAGER_EXTRA_TESTS)
|
||||
#define WC_LINUXKM_HAVE_SELFTEST_FULL
|
||||
#endif
|
||||
#else
|
||||
/* see Linux 698de822780f */
|
||||
#if defined(CONFIG_CRYPTO_MANAGER) && defined(CONFIG_CRYPTO_SELFTESTS)
|
||||
#define WC_LINUXKM_HAVE_SELFTEST
|
||||
#endif
|
||||
/* see Linux ac90aad0e9 */
|
||||
#if defined(WC_LINUXKM_HAVE_SELFTEST) && defined(CONFIG_CRYPTO_SELFTESTS_FULL)
|
||||
#define WC_LINUXKM_HAVE_SELFTEST_FULL
|
||||
#endif
|
||||
#endif
|
||||
#include <linux/fips.h>
|
||||
|
||||
/* Kernel non-FIPS self-test ("testmgr") has a KAT with all-zeros keys. */
|
||||
#if defined(WC_LINUXKM_HAVE_SELFTEST) && !defined(HAVE_FIPS)
|
||||
@@ -655,6 +653,12 @@
|
||||
#include <linux/uaccess.h>
|
||||
#endif
|
||||
#include <linux/slab.h>
|
||||
#ifndef WC_CONTAINERIZE_THIS
|
||||
/* for struct vm_struct and related -- used by
|
||||
* wc_linuxkm_malloc_usable_size().
|
||||
*/
|
||||
#include <linux/vmalloc.h>
|
||||
#endif
|
||||
#include <linux/sched.h>
|
||||
#if __has_include(<linux/sched/task_stack.h>)
|
||||
/* for task_stack_page() */
|
||||
@@ -823,6 +827,9 @@
|
||||
#error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unimplemented architecture.
|
||||
#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */
|
||||
|
||||
/* This pop must appear here, no later, so that conditional suppressions
|
||||
* below continue after inclusion.
|
||||
*/
|
||||
_Pragma("GCC diagnostic pop");
|
||||
|
||||
#define PTR_ERR(x) ((int)PTR_ERR(x))
|
||||
|
||||
@@ -96,8 +96,16 @@
|
||||
#define WOLFKM_AESOFB_NAME "ofb(aes)"
|
||||
#define WOLFKM_AESECB_NAME "ecb(aes)"
|
||||
|
||||
#if defined(USE_INTEL_SPEEDUP) || defined(USE_INTEL_SPEEDUP_FOR_AES)
|
||||
#define WOLFKM_AES_DRIVER_ISA_EXT "-aesni-avx"
|
||||
#if defined(WOLFSSL_X86_64_BUILD) && (defined(USE_INTEL_SPEEDUP) || defined(USE_INTEL_SPEEDUP_FOR_AES))
|
||||
#if !defined(NO_AVX512_SUPPORT)
|
||||
#define WOLFKM_AES_DRIVER_ISA_EXT "-vaes-avx512"
|
||||
#elif !defined(NO_VAES_SUPPORT)
|
||||
#define WOLFKM_AES_DRIVER_ISA_EXT "-vaes-avx2"
|
||||
#elif !defined(NO_AVX2_SUPPORT)
|
||||
#define WOLFKM_AES_DRIVER_ISA_EXT "-aesni-avx2"
|
||||
#else
|
||||
#define WOLFKM_AES_DRIVER_ISA_EXT "-aesni-avx"
|
||||
#endif
|
||||
#elif defined(WOLFSSL_AESNI)
|
||||
#define WOLFKM_AES_DRIVER_ISA_EXT "-aesni"
|
||||
#else
|
||||
|
||||
+485
-48
@@ -48,26 +48,17 @@
|
||||
|
||||
#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
|
||||
* without sign/verify after linux 6.13.
|
||||
*
|
||||
* In linux 6.13 the sign/verify callbacks were removed from
|
||||
* note: In linux 6.13 the sign/verify callbacks were removed from
|
||||
* akcipher_alg, and ecdsa changed from a struct akcipher_alg type to
|
||||
* struct sig_alg type.
|
||||
*
|
||||
* pkcs1pad rsa remained a struct akcipher_alg, but without sign/verify
|
||||
* functionality.
|
||||
* The 6.13+ base "ecdsa-nist-pN" sig_alg is verify-only, and takes the
|
||||
* signature in the kernel's raw format (struct ecdsa_raw_sig -- r and s
|
||||
* as little endian u64 digit arrays). The X9.62 (ASN.1 DER) and IEEE
|
||||
* P1363 signature encodings are handled by the kernel's "x962(...)" and
|
||||
* "p1363(...)" wrapping templates, instantiated around the base alg.
|
||||
*/
|
||||
#if defined (LINUXKM_LKCAPI_REGISTER_ECDSA)
|
||||
#undef LINUXKM_LKCAPI_REGISTER_ECDSA
|
||||
#endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */
|
||||
|
||||
#if defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_ECDSA) && \
|
||||
!defined(LINUXKM_LKCAPI_DONT_REGISTER_ECDSA)
|
||||
#error Config conflict: missing implementation forces off LINUXKM_LKCAPI_REGISTER_ECDSA.
|
||||
#endif
|
||||
#define LINUXKM_ECDSA_SIG_ALG
|
||||
#endif
|
||||
|
||||
#if defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && \
|
||||
@@ -82,6 +73,27 @@
|
||||
#include <wolfssl/wolfcrypt/asn.h>
|
||||
#include <wolfssl/wolfcrypt/ecc.h>
|
||||
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
#define ecdsa_tfm_type crypto_sig
|
||||
#define ecdsa_tfm_ctx_cb crypto_sig_ctx
|
||||
|
||||
/* Mirror of struct ecdsa_raw_sig from the kernel's
|
||||
* include/crypto/internal/ecc.h, which can't be included here because its
|
||||
* struct ecc_point collides with wolfCrypt's. The kernel dimensions the
|
||||
* digit arrays with ECC_MAX_DIGITS = DIV_ROUND_UP(521, 64) (NIST P521).
|
||||
* The u64 digits are ordered little endian, with native endianness within
|
||||
* each digit.
|
||||
*/
|
||||
#define KM_ECDSA_MAX_DIGITS ((521 + 63) / 64)
|
||||
struct km_ecdsa_raw_sig {
|
||||
u64 r[KM_ECDSA_MAX_DIGITS];
|
||||
u64 s[KM_ECDSA_MAX_DIGITS];
|
||||
};
|
||||
#else
|
||||
#define ecdsa_tfm_type crypto_akcipher
|
||||
#define ecdsa_tfm_ctx_cb akcipher_tfm_ctx
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
#if defined(WOLFSSL_SP_X86_64_ASM) && !defined(NO_AVX2_SUPPORT)
|
||||
#define WOLFKM_ECDSA_DRIVER_ISA_EXT "-avx2"
|
||||
#else
|
||||
@@ -123,26 +135,52 @@ struct km_ecdsa_ctx {
|
||||
ecc_key * key;
|
||||
int curve_id;
|
||||
word32 curve_len;
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
word32 curve_nbits;
|
||||
#endif /* LINUXKM_ECDSA_SIG_ALG */
|
||||
};
|
||||
|
||||
/* shared ecdsa callbacks */
|
||||
static void km_ecdsa_exit(struct crypto_akcipher *tfm);
|
||||
static int km_ecdsa_set_pub(struct crypto_akcipher *tfm,
|
||||
static void km_ecdsa_exit(struct ecdsa_tfm_type *tfm);
|
||||
static int km_ecdsa_set_pub(struct ecdsa_tfm_type *tfm,
|
||||
const void *key, unsigned int keylen);
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
static unsigned int km_ecdsa_key_size(struct crypto_sig *tfm);
|
||||
static unsigned int km_ecdsa_digest_size(struct crypto_sig *tfm);
|
||||
static int km_ecdsa_verify(struct crypto_sig *tfm,
|
||||
const void *src, unsigned int slen,
|
||||
const void *digest, unsigned int dlen);
|
||||
#else
|
||||
static unsigned int km_ecdsa_max_size(struct crypto_akcipher *tfm);
|
||||
static int km_ecdsa_verify(struct akcipher_request *req);
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
/* ecdsa_nist_pN callbacks */
|
||||
#if defined(LINUXKM_ECC192)
|
||||
static int km_ecdsa_nist_p192_init(struct crypto_akcipher *tfm);
|
||||
static int km_ecdsa_nist_p192_init(struct ecdsa_tfm_type *tfm);
|
||||
#endif /* LINUXKM_ECC192 */
|
||||
static int km_ecdsa_nist_p256_init(struct crypto_akcipher *tfm);
|
||||
static int km_ecdsa_nist_p384_init(struct crypto_akcipher *tfm);
|
||||
static int km_ecdsa_nist_p256_init(struct ecdsa_tfm_type *tfm);
|
||||
static int km_ecdsa_nist_p384_init(struct ecdsa_tfm_type *tfm);
|
||||
#if defined(HAVE_ECC521)
|
||||
static int km_ecdsa_nist_p521_init(struct crypto_akcipher *tfm);
|
||||
static int km_ecdsa_nist_p521_init(struct ecdsa_tfm_type *tfm);
|
||||
#endif /* HAVE_ECC521 */
|
||||
|
||||
#if defined(LINUXKM_ECC192)
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
static struct sig_alg ecdsa_nist_p192 = {
|
||||
.base.cra_name = WOLFKM_ECDSA_P192_NAME,
|
||||
.base.cra_driver_name = WOLFKM_ECDSA_P192_DRIVER,
|
||||
.base.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY,
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.base.cra_ctxsize = sizeof(struct km_ecdsa_ctx),
|
||||
.verify = km_ecdsa_verify,
|
||||
.set_pub_key = km_ecdsa_set_pub,
|
||||
.key_size = km_ecdsa_key_size,
|
||||
.digest_size = km_ecdsa_digest_size,
|
||||
.init = km_ecdsa_nist_p192_init,
|
||||
.exit = km_ecdsa_exit,
|
||||
};
|
||||
#else /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
static struct akcipher_alg ecdsa_nist_p192 = {
|
||||
.base.cra_name = WOLFKM_ECDSA_P192_NAME,
|
||||
.base.cra_driver_name = WOLFKM_ECDSA_P192_DRIVER,
|
||||
@@ -155,8 +193,24 @@ static struct akcipher_alg ecdsa_nist_p192 = {
|
||||
.init = km_ecdsa_nist_p192_init,
|
||||
.exit = km_ecdsa_exit,
|
||||
};
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
#endif /* LINUXKM_ECC192 */
|
||||
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
static struct sig_alg ecdsa_nist_p256 = {
|
||||
.base.cra_name = WOLFKM_ECDSA_P256_NAME,
|
||||
.base.cra_driver_name = WOLFKM_ECDSA_P256_DRIVER,
|
||||
.base.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY,
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.base.cra_ctxsize = sizeof(struct km_ecdsa_ctx),
|
||||
.verify = km_ecdsa_verify,
|
||||
.set_pub_key = km_ecdsa_set_pub,
|
||||
.key_size = km_ecdsa_key_size,
|
||||
.digest_size = km_ecdsa_digest_size,
|
||||
.init = km_ecdsa_nist_p256_init,
|
||||
.exit = km_ecdsa_exit,
|
||||
};
|
||||
#else /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
static struct akcipher_alg ecdsa_nist_p256 = {
|
||||
.base.cra_name = WOLFKM_ECDSA_P256_NAME,
|
||||
.base.cra_driver_name = WOLFKM_ECDSA_P256_DRIVER,
|
||||
@@ -169,7 +223,23 @@ static struct akcipher_alg ecdsa_nist_p256 = {
|
||||
.init = km_ecdsa_nist_p256_init,
|
||||
.exit = km_ecdsa_exit,
|
||||
};
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
static struct sig_alg ecdsa_nist_p384 = {
|
||||
.base.cra_name = WOLFKM_ECDSA_P384_NAME,
|
||||
.base.cra_driver_name = WOLFKM_ECDSA_P384_DRIVER,
|
||||
.base.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY,
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.base.cra_ctxsize = sizeof(struct km_ecdsa_ctx),
|
||||
.verify = km_ecdsa_verify,
|
||||
.set_pub_key = km_ecdsa_set_pub,
|
||||
.key_size = km_ecdsa_key_size,
|
||||
.digest_size = km_ecdsa_digest_size,
|
||||
.init = km_ecdsa_nist_p384_init,
|
||||
.exit = km_ecdsa_exit,
|
||||
};
|
||||
#else /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
static struct akcipher_alg ecdsa_nist_p384 = {
|
||||
.base.cra_name = WOLFKM_ECDSA_P384_NAME,
|
||||
.base.cra_driver_name = WOLFKM_ECDSA_P384_DRIVER,
|
||||
@@ -182,8 +252,24 @@ static struct akcipher_alg ecdsa_nist_p384 = {
|
||||
.init = km_ecdsa_nist_p384_init,
|
||||
.exit = km_ecdsa_exit,
|
||||
};
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
#if defined(HAVE_ECC521)
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
static struct sig_alg ecdsa_nist_p521 = {
|
||||
.base.cra_name = WOLFKM_ECDSA_P521_NAME,
|
||||
.base.cra_driver_name = WOLFKM_ECDSA_P521_DRIVER,
|
||||
.base.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY,
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.base.cra_ctxsize = sizeof(struct km_ecdsa_ctx),
|
||||
.verify = km_ecdsa_verify,
|
||||
.set_pub_key = km_ecdsa_set_pub,
|
||||
.key_size = km_ecdsa_key_size,
|
||||
.digest_size = km_ecdsa_digest_size,
|
||||
.init = km_ecdsa_nist_p521_init,
|
||||
.exit = km_ecdsa_exit,
|
||||
};
|
||||
#else /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
static struct akcipher_alg ecdsa_nist_p521 = {
|
||||
.base.cra_name = WOLFKM_ECDSA_P521_NAME,
|
||||
.base.cra_driver_name = WOLFKM_ECDSA_P521_DRIVER,
|
||||
@@ -196,6 +282,7 @@ static struct akcipher_alg ecdsa_nist_p521 = {
|
||||
.init = km_ecdsa_nist_p521_init,
|
||||
.exit = km_ecdsa_exit,
|
||||
};
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
#endif /* HAVE_ECC521 */
|
||||
|
||||
/**
|
||||
@@ -204,18 +291,18 @@ static struct akcipher_alg ecdsa_nist_p521 = {
|
||||
* Kernel crypto ECDSA api expects raw uncompressed format with concatenated
|
||||
* x and y points, with leading 0x04 on pub key.
|
||||
*
|
||||
* param tfm the crypto_akcipher transform
|
||||
* param tfm the crypto_akcipher (crypto_sig on linux 6.13+) transform
|
||||
* param key raw uncompressed x, y points, with leading 0x04
|
||||
* param keylen key length
|
||||
* */
|
||||
static int km_ecdsa_set_pub(struct crypto_akcipher *tfm, const void *key,
|
||||
static int km_ecdsa_set_pub(struct ecdsa_tfm_type *tfm, const void *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
int err = 0;
|
||||
struct km_ecdsa_ctx * ctx = NULL;
|
||||
const byte * pub = key;
|
||||
|
||||
ctx = akcipher_tfm_ctx(tfm);
|
||||
ctx = ecdsa_tfm_ctx_cb(tfm);
|
||||
|
||||
switch (ctx->curve_len) {
|
||||
#if defined(LINUXKM_ECC192)
|
||||
@@ -279,23 +366,45 @@ static int km_ecdsa_set_pub(struct crypto_akcipher *tfm, const void *key,
|
||||
return err;
|
||||
}
|
||||
|
||||
static unsigned int km_ecdsa_max_size(struct crypto_akcipher *tfm)
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
/* Returns the ECDSA key size (mirrors the kernel's ecdsa_key_size()):
|
||||
* linux kernel version < 6.15.3: key size in bytes.
|
||||
* linux kernel version >= 6.15.3: key size in bits.
|
||||
* */
|
||||
static unsigned int km_ecdsa_key_size(struct crypto_sig *tfm)
|
||||
{
|
||||
struct km_ecdsa_ctx * ctx = NULL;
|
||||
|
||||
ctx = akcipher_tfm_ctx(tfm);
|
||||
|
||||
#ifdef WOLFKM_DEBUG_ECDSA
|
||||
pr_info("info: exiting km_ecdsa_max_size\n");
|
||||
#endif /* WOLFKM_DEBUG_ECDSA */
|
||||
return (unsigned int) ctx->curve_len;
|
||||
struct km_ecdsa_ctx *ctx = crypto_sig_ctx(tfm);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 3)
|
||||
return ctx->curve_nbits;
|
||||
#else
|
||||
return ctx->curve_len;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void km_ecdsa_exit(struct crypto_akcipher *tfm)
|
||||
/* Mirrors the kernel's ecdsa_digest_size(): ECDSA keys are much smaller than
|
||||
* RSA keys, and can operate on (hashed) inputs that are larger than the key
|
||||
* size, e.g. a SHA-384 digest verified with a P-256 key, so advertise the
|
||||
* largest digest size km_ecdsa_verify() accepts rather than the key size
|
||||
* that crypto/sig.c would default to.
|
||||
* */
|
||||
static unsigned int km_ecdsa_digest_size(struct crypto_sig *tfm)
|
||||
{
|
||||
(void)tfm;
|
||||
return WC_MAX_DIGEST_SIZE;
|
||||
}
|
||||
#else /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
static unsigned int km_ecdsa_max_size(struct crypto_akcipher *tfm)
|
||||
{
|
||||
struct km_ecdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
|
||||
return ctx->curve_len;
|
||||
}
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
static void km_ecdsa_exit(struct ecdsa_tfm_type *tfm)
|
||||
{
|
||||
struct km_ecdsa_ctx * ctx = NULL;
|
||||
|
||||
ctx = akcipher_tfm_ctx(tfm);
|
||||
ctx = ecdsa_tfm_ctx_cb(tfm);
|
||||
|
||||
if (ctx->key) {
|
||||
wc_ecc_free(ctx->key);
|
||||
@@ -309,12 +418,11 @@ static void km_ecdsa_exit(struct crypto_akcipher *tfm)
|
||||
return;
|
||||
}
|
||||
|
||||
static int km_ecdsa_init(struct crypto_akcipher *tfm, int curve_id)
|
||||
static int km_ecdsa_init(struct ecdsa_tfm_type *tfm, int curve_id)
|
||||
{
|
||||
struct km_ecdsa_ctx * ctx = NULL;
|
||||
int ret = 0;
|
||||
struct km_ecdsa_ctx *ctx = ecdsa_tfm_ctx_cb(tfm);
|
||||
int ret = 0;
|
||||
|
||||
ctx = akcipher_tfm_ctx(tfm);
|
||||
XMEMSET(ctx, 0, sizeof(struct km_ecdsa_ctx));
|
||||
ctx->curve_id = curve_id;
|
||||
ctx->curve_len = 0;
|
||||
@@ -330,10 +438,17 @@ static int km_ecdsa_init(struct crypto_akcipher *tfm, int curve_id)
|
||||
|
||||
ctx->curve_len = (word32) ret;
|
||||
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
/* NIST P-521 is the only supported curve whose bit length isn't a
|
||||
* multiple of 8 (the kernel's ecdsa_key_size() returns
|
||||
* curve->nbits). */
|
||||
ctx->curve_nbits = (curve_id == ECC_SECP521R1) ? 521 :
|
||||
(ctx->curve_len * WOLFSSL_BIT_SIZE);
|
||||
#endif /* LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
ctx->key = (ecc_key *)malloc(sizeof(ecc_key));
|
||||
if (!ctx->key) {
|
||||
if (!ctx->key)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = wc_ecc_init(ctx->key);
|
||||
if (ret < 0) {
|
||||
@@ -350,29 +465,182 @@ static int km_ecdsa_init(struct crypto_akcipher *tfm, int curve_id)
|
||||
}
|
||||
|
||||
#if defined(LINUXKM_ECC192)
|
||||
static int km_ecdsa_nist_p192_init(struct crypto_akcipher *tfm)
|
||||
static int km_ecdsa_nist_p192_init(struct ecdsa_tfm_type *tfm)
|
||||
{
|
||||
return km_ecdsa_init(tfm, ECC_SECP192R1);
|
||||
}
|
||||
#endif /* LINUXKM_ECC192 */
|
||||
|
||||
static int km_ecdsa_nist_p256_init(struct crypto_akcipher *tfm)
|
||||
static int km_ecdsa_nist_p256_init(struct ecdsa_tfm_type *tfm)
|
||||
{
|
||||
return km_ecdsa_init(tfm, ECC_SECP256R1);
|
||||
}
|
||||
|
||||
static int km_ecdsa_nist_p384_init(struct crypto_akcipher *tfm)
|
||||
static int km_ecdsa_nist_p384_init(struct ecdsa_tfm_type *tfm)
|
||||
{
|
||||
return km_ecdsa_init(tfm, ECC_SECP384R1);
|
||||
}
|
||||
|
||||
#if defined(HAVE_ECC521)
|
||||
static int km_ecdsa_nist_p521_init(struct crypto_akcipher *tfm)
|
||||
static int km_ecdsa_nist_p521_init(struct ecdsa_tfm_type *tfm)
|
||||
{
|
||||
return km_ecdsa_init(tfm, ECC_SECP521R1);
|
||||
}
|
||||
#endif /* HAVE_ECC521 */
|
||||
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
|
||||
/* Convert a little endian u64 digit array (the kernel's raw r/s format) to a
|
||||
* big endian byte array of out_len bytes. Only the low 8*out_len bits of the
|
||||
* digit array are read -- digits past DIV_ROUND_UP(out_len, 8) may be
|
||||
* uninitialized in signatures decoded by the kernel's x962 template, and must
|
||||
* not be read.
|
||||
*/
|
||||
static void km_ecdsa_raw_digits_to_bytes(const u64 *digits, byte *out,
|
||||
word32 out_len)
|
||||
{
|
||||
word32 i;
|
||||
|
||||
for (i = 0; i < out_len; i++)
|
||||
out[out_len - 1U - i] = (byte)(digits[i >> 3] >> ((i & 7U) << 3));
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify an ecdsa_nist signature (linux 6.13+ struct sig_alg edition).
|
||||
*
|
||||
* src:
|
||||
* - the signature, formatted as the kernel's struct ecdsa_raw_sig: r then
|
||||
* s, each an array of ECC_MAX_DIGITS little endian u64 digits.
|
||||
* - slen must == sizeof(struct ecdsa_raw_sig) (curve-independent).
|
||||
*
|
||||
* The kernel's x962 and p1363 templates decode DER and IEEE P1363
|
||||
* signature encodings (respectively) to this raw format, zero-filling
|
||||
* the unused high bytes of the first DIV_ROUND_UP(curve_len, 8) digits
|
||||
* only.
|
||||
*
|
||||
* digest:
|
||||
* - the hash to be verified. wolfCrypt truncates oversized digests to
|
||||
* the group order bit length internally (FIPS 186-4 style), matching
|
||||
* the in-tree implementation.
|
||||
*
|
||||
* See kernel (6.13 or later):
|
||||
* - include/crypto/sig.h
|
||||
* - crypto/ecdsa.c
|
||||
*/
|
||||
static int km_ecdsa_verify(struct crypto_sig *tfm,
|
||||
const void *src, unsigned int slen,
|
||||
const void *digest, unsigned int dlen)
|
||||
{
|
||||
struct km_ecdsa_ctx *ctx = crypto_sig_ctx(tfm);
|
||||
const struct km_ecdsa_raw_sig
|
||||
*raw_sig = (const struct km_ecdsa_raw_sig *)src;
|
||||
byte *work_buffer = NULL;
|
||||
byte *r_buf = NULL;
|
||||
byte *s_buf = NULL;
|
||||
byte *der_sig = NULL;
|
||||
word32 der_sig_len = 0;
|
||||
int result = -1;
|
||||
int err = -1;
|
||||
|
||||
if (src == NULL || digest == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if ((ctx->key == NULL) || (ctx->key->type != ECC_PUBLICKEY))
|
||||
return -EINVAL;
|
||||
|
||||
if (slen != sizeof(struct km_ecdsa_raw_sig))
|
||||
return -EINVAL;
|
||||
|
||||
/* 6 ECDSA (struct sig_testvec) test vectors in crypto/testmgr.h use SHA-1
|
||||
* (m_size 20).
|
||||
*/
|
||||
#ifdef WC_LINUXKM_HAVE_SELFTEST
|
||||
wc_static_assert2(WC_MIN_DIGEST_SIZE_FOR_VERIFY <= 20,
|
||||
"WC_MIN_DIGEST_SIZE_FOR_VERIFY must allow SHA-1-sized digests when "
|
||||
"native kernel self-test is enabled.");
|
||||
#endif
|
||||
|
||||
if ((dlen > WC_MAX_DIGEST_SIZE) ||
|
||||
(dlen < WC_MIN_DIGEST_SIZE_FOR_VERIFY))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Reject set bits between the curve length and the top of the last
|
||||
* meaningful digit -- below, only the low 8*curve_len bits of each of r
|
||||
* and s are converted, and such bits would otherwise be silently masked
|
||||
* off. (the in-tree implementation rejects them via its r < n, s < n
|
||||
* checks.)
|
||||
*/
|
||||
if (ctx->curve_len & 7U) {
|
||||
word32 top_i = (ctx->curve_len - 1U) >> 3;
|
||||
word32 top_shift = (ctx->curve_len & 7U) << 3;
|
||||
if ((raw_sig->r[top_i] >> top_shift) ||
|
||||
(raw_sig->s[top_i] >> top_shift))
|
||||
{
|
||||
return -EBADMSG;
|
||||
}
|
||||
}
|
||||
|
||||
/* work_buffer holds the big endian r and s, followed by the
|
||||
* DER-encoded signature to be passed to wc_ecc_verify_hash(). */
|
||||
work_buffer = (byte *)malloc((2U * ctx->curve_len) + ECC_MAX_SIG_SIZE);
|
||||
if (unlikely(work_buffer == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
r_buf = work_buffer;
|
||||
s_buf = work_buffer + ctx->curve_len;
|
||||
der_sig = work_buffer + (2U * ctx->curve_len);
|
||||
|
||||
km_ecdsa_raw_digits_to_bytes(raw_sig->r, r_buf, ctx->curve_len);
|
||||
km_ecdsa_raw_digits_to_bytes(raw_sig->s, s_buf, ctx->curve_len);
|
||||
|
||||
der_sig_len = ECC_MAX_SIG_SIZE;
|
||||
err = wc_ecc_rs_raw_to_sig(r_buf, ctx->curve_len, s_buf, ctx->curve_len,
|
||||
der_sig, &der_sig_len);
|
||||
if (err) {
|
||||
#ifdef WOLFKM_DEBUG_ECDSA
|
||||
pr_err("error: %s: ecdsa verify: wc_ecc_rs_raw_to_sig returned: %d\n",
|
||||
WOLFKM_ECDSA_DRIVER, err);
|
||||
#endif /* WOLFKM_DEBUG_ECDSA */
|
||||
err = -EBADMSG;
|
||||
goto ecdsa_verify_end;
|
||||
}
|
||||
|
||||
err = wc_ecc_verify_hash(der_sig, der_sig_len, digest, dlen, &result,
|
||||
ctx->key);
|
||||
|
||||
if (err) {
|
||||
#ifdef WOLFKM_DEBUG_ECDSA
|
||||
pr_err("error: %s: ecdsa verify: verify_hash returned: %d\n",
|
||||
WOLFKM_ECDSA_DRIVER, err);
|
||||
#endif /* WOLFKM_DEBUG_ECDSA */
|
||||
err = -EBADMSG;
|
||||
goto ecdsa_verify_end;
|
||||
}
|
||||
|
||||
if (result != 1) {
|
||||
#ifdef WOLFKM_DEBUG_ECDSA
|
||||
pr_err("info: %s: ecdsa verify: verify fail: %d\n",
|
||||
WOLFKM_ECDSA_DRIVER, result);
|
||||
#endif /* WOLFKM_DEBUG_ECDSA */
|
||||
err = -EKEYREJECTED;
|
||||
goto ecdsa_verify_end;
|
||||
}
|
||||
|
||||
ecdsa_verify_end:
|
||||
|
||||
free(work_buffer);
|
||||
|
||||
#ifdef WOLFKM_DEBUG_ECDSA
|
||||
pr_info("info: exiting km_ecdsa_verify dlen %d, slen %d, "
|
||||
"err %d, result %d\n", dlen, slen, err, result);
|
||||
#endif /* WOLFKM_DEBUG_ECDSA */
|
||||
return err;
|
||||
}
|
||||
|
||||
#else /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
/*
|
||||
* Verify an ecdsa_nist signature.
|
||||
*
|
||||
@@ -405,8 +673,17 @@ static int km_ecdsa_verify(struct akcipher_request *req)
|
||||
sig_len = req->src_len;
|
||||
hash_len = req->dst_len;
|
||||
|
||||
/* 6 ECDSA (struct sig_testvec) test vectors in crypto/testmgr.h use SHA-1
|
||||
* (m_size 20).
|
||||
*/
|
||||
#ifdef WC_LINUXKM_HAVE_SELFTEST
|
||||
wc_static_assert2(WC_MIN_DIGEST_SIZE_FOR_VERIFY <= 20,
|
||||
"WC_MIN_DIGEST_SIZE_FOR_VERIFY must allow SHA-1-sized digests when "
|
||||
"native kernel self-test is enabled.");
|
||||
#endif
|
||||
|
||||
if ((hash_len > WC_MAX_DIGEST_SIZE) ||
|
||||
(hash_len < WC_MIN_DIGEST_SIZE))
|
||||
(hash_len < WC_MIN_DIGEST_SIZE_FOR_VERIFY))
|
||||
{
|
||||
err = -EINVAL;
|
||||
goto ecdsa_verify_end;
|
||||
@@ -456,7 +733,8 @@ static int km_ecdsa_verify(struct akcipher_request *req)
|
||||
}
|
||||
|
||||
ecdsa_verify_end:
|
||||
if (sig != NULL) { free(sig); sig = NULL; }
|
||||
|
||||
free(sig);
|
||||
|
||||
#ifdef WOLFKM_DEBUG_ECDSA
|
||||
pr_info("info: exiting km_ecdsa_verify hash_len %d, sig_len %d, "
|
||||
@@ -465,6 +743,8 @@ ecdsa_verify_end:
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
#if defined(LINUXKM_ECC192)
|
||||
static int linuxkm_test_ecdsa_nist_p192(void)
|
||||
{
|
||||
@@ -709,6 +989,161 @@ static int linuxkm_test_ecdsa_nist_p521(void)
|
||||
}
|
||||
#endif /* HAVE_ECC521 */
|
||||
|
||||
#ifdef LINUXKM_ECDSA_SIG_ALG
|
||||
|
||||
/* Convert a big endian byte array to the kernel's little endian u64 raw
|
||||
* digit array format, zero-filling the KM_ECDSA_MAX_DIGITS digits. Inverse
|
||||
* of km_ecdsa_raw_digits_to_bytes().
|
||||
*/
|
||||
static void km_ecdsa_bytes_to_raw_digits(const byte *in, word32 in_len,
|
||||
u64 *out)
|
||||
{
|
||||
word32 i;
|
||||
|
||||
XMEMSET(out, 0, KM_ECDSA_MAX_DIGITS * sizeof(u64));
|
||||
for (i = 0; i < in_len; i++)
|
||||
out[i >> 3] |= ((u64)in[in_len - 1U - i]) << ((i & 7U) << 3);
|
||||
}
|
||||
|
||||
static int linuxkm_test_ecdsa_nist_driver(const char * driver,
|
||||
const byte * pub, word32 pub_len,
|
||||
const byte * sig, word32 sig_len,
|
||||
const byte * hash, word32 hash_len)
|
||||
{
|
||||
int test_rc = WC_NO_ERR_TRACE(WC_FAILURE);
|
||||
int ret = 0;
|
||||
struct crypto_sig * tfm = NULL;
|
||||
struct km_ecdsa_raw_sig * raw_sig = NULL;
|
||||
byte * r_buf = NULL;
|
||||
byte * s_buf = NULL;
|
||||
word32 r_len = 0;
|
||||
word32 s_len = 0;
|
||||
word32 curve_len = 0;
|
||||
|
||||
/* infer the curve length from the raw uncompressed pub key:
|
||||
* 0x04 || x || y. */
|
||||
if ((pub_len < 1) || (((pub_len - 1) & 1) != 0)) {
|
||||
pr_err("error: %s: test pub key has invalid length %u\n",
|
||||
driver, pub_len);
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
curve_len = (pub_len - 1) >> 1;
|
||||
|
||||
/* allocate the kernel-raw-format signature, followed by buffers for the
|
||||
* big endian r and s decoded from the DER test signature. */
|
||||
raw_sig = (struct km_ecdsa_raw_sig *)malloc(
|
||||
sizeof(struct km_ecdsa_raw_sig) + (2 * curve_len));
|
||||
if (! raw_sig) {
|
||||
pr_err("error: allocating raw_sig buffer failed.\n");
|
||||
test_rc = MEMORY_E;
|
||||
goto test_ecdsa_nist_end;
|
||||
}
|
||||
r_buf = (byte *)raw_sig + sizeof(struct km_ecdsa_raw_sig);
|
||||
s_buf = r_buf + curve_len;
|
||||
|
||||
/*
|
||||
* Allocate the sig transform.
|
||||
*/
|
||||
tfm = crypto_alloc_sig(driver, 0, 0);
|
||||
if (IS_ERR(tfm)) {
|
||||
pr_err("error: allocating sig algorithm %s failed: %d\n",
|
||||
driver, (int)PTR_ERR(tfm));
|
||||
if (PTR_ERR(tfm) == -ENOMEM)
|
||||
test_rc = MEMORY_E;
|
||||
else
|
||||
test_rc = BAD_FUNC_ARG;
|
||||
tfm = NULL;
|
||||
goto test_ecdsa_nist_end;
|
||||
}
|
||||
|
||||
/* now set pub key for verify test. */
|
||||
ret = crypto_sig_set_pubkey(tfm, pub, pub_len);
|
||||
if (ret) {
|
||||
pr_err("error: crypto_sig_set_pubkey returned: %d\n", ret);
|
||||
test_rc = BAD_FUNC_ARG;
|
||||
goto test_ecdsa_nist_end;
|
||||
}
|
||||
|
||||
{
|
||||
/* The behavior of crypto_sig_Xsize (X= max, key, digest) changed
|
||||
* at linux kernel v6.15.3:
|
||||
* < 6.15.3: keysize is in bytes.
|
||||
* >= 6.15.3: keysize is in bits, maxsize and digestsize in
|
||||
* bytes. */
|
||||
unsigned int maxsize = crypto_sig_maxsize(tfm);
|
||||
unsigned int keysize = crypto_sig_keysize(tfm);
|
||||
unsigned int digestsize = crypto_sig_digestsize(tfm);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 3)
|
||||
keysize = ((keysize + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE);
|
||||
#endif /* linux >= 6.15.3 */
|
||||
|
||||
#ifdef WOLFKM_DEBUG_ECDSA
|
||||
pr_info("info: crypto_sig_{max, key, digest}size: "
|
||||
"{%d, %d, %d}\n",
|
||||
maxsize, keysize, digestsize);
|
||||
#endif /* WOLFKM_DEBUG_ECDSA */
|
||||
|
||||
if ((keysize != curve_len) ||
|
||||
(maxsize != curve_len) ||
|
||||
(digestsize != (unsigned int)WC_MAX_DIGEST_SIZE))
|
||||
{
|
||||
pr_err("error: crypto_sig_{max, key, digest}size "
|
||||
"returned {%u, %u, %u}, expected {%u, %u, %u}\n",
|
||||
maxsize, keysize, digestsize,
|
||||
curve_len, curve_len, (unsigned int)WC_MAX_DIGEST_SIZE);
|
||||
test_rc = BAD_FUNC_ARG;
|
||||
goto test_ecdsa_nist_end;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert the DER test signature to the kernel's raw format. */
|
||||
r_len = curve_len;
|
||||
s_len = curve_len;
|
||||
ret = wc_ecc_sig_to_rs(sig, sig_len, r_buf, &r_len, s_buf, &s_len);
|
||||
if (ret) {
|
||||
pr_err("error: wc_ecc_sig_to_rs returned: %d\n", ret);
|
||||
test_rc = ret;
|
||||
goto test_ecdsa_nist_end;
|
||||
}
|
||||
|
||||
km_ecdsa_bytes_to_raw_digits(r_buf, r_len, raw_sig->r);
|
||||
km_ecdsa_bytes_to_raw_digits(s_buf, s_len, raw_sig->s);
|
||||
|
||||
ret = crypto_sig_verify(tfm, raw_sig, (unsigned int)sizeof(*raw_sig),
|
||||
hash, hash_len);
|
||||
if (ret) {
|
||||
pr_err("error: crypto_sig_verify returned: %d\n", ret);
|
||||
test_rc = BAD_FUNC_ARG;
|
||||
goto test_ecdsa_nist_end;
|
||||
}
|
||||
|
||||
/* corrupt the signature -- verify should now fail. */
|
||||
raw_sig->r[0] ^= 1U;
|
||||
|
||||
ret = crypto_sig_verify(tfm, raw_sig, (unsigned int)sizeof(*raw_sig),
|
||||
hash, hash_len);
|
||||
if ((ret != -EBADMSG) && (ret != -EKEYREJECTED)) {
|
||||
pr_err("error: crypto_sig_verify returned %d, expected %d or %d\n",
|
||||
ret, -EBADMSG, -EKEYREJECTED);
|
||||
test_rc = BAD_FUNC_ARG;
|
||||
goto test_ecdsa_nist_end;
|
||||
}
|
||||
|
||||
test_rc = 0;
|
||||
test_ecdsa_nist_end:
|
||||
if (tfm)
|
||||
crypto_free_sig(tfm);
|
||||
free(raw_sig);
|
||||
|
||||
#ifdef WOLFKM_DEBUG_ECDSA
|
||||
pr_info("info: %s: self test returned: %d\n", driver, test_rc);
|
||||
#endif /* WOLFKM_DEBUG_ECDSA */
|
||||
return test_rc;
|
||||
}
|
||||
|
||||
#else /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
static int linuxkm_test_ecdsa_nist_driver(const char * driver,
|
||||
const byte * pub, word32 pub_len,
|
||||
const byte * sig, word32 sig_len,
|
||||
@@ -854,6 +1289,8 @@ test_ecdsa_nist_end:
|
||||
return test_rc;
|
||||
}
|
||||
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
|
||||
#endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */
|
||||
|
||||
#endif /* !WC_SKIP_INCLUDED_C_FILES */
|
||||
|
||||
+40
-12
@@ -40,7 +40,6 @@
|
||||
#if defined(CONFIG_CRYPTO_FIPS) != defined(HAVE_FIPS)
|
||||
#error CONFIG_CRYPTO_MANAGER requires that CONFIG_CRYPTO_FIPS match HAVE_FIPS.
|
||||
#endif
|
||||
#include <linux/fips.h>
|
||||
#endif
|
||||
|
||||
/* need misc.c for ForceZero(). */
|
||||
@@ -553,7 +552,24 @@ static int linuxkm_lkcapi_register(void)
|
||||
#endif
|
||||
|
||||
#ifdef LINUXKM_LKCAPI_REGISTER_ECDSA
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \
|
||||
#if defined(LINUXKM_ECDSA_SIG_ALG)
|
||||
/* linux 6.13+: the ecdsa-nist-pN algs are struct sig_alg. */
|
||||
#if defined(LINUXKM_ECC192)
|
||||
REGISTER_ALG(ecdsa_nist_p192, sig,
|
||||
linuxkm_test_ecdsa_nist_p192);
|
||||
#endif /* LINUXKM_ECC192 */
|
||||
|
||||
REGISTER_ALG(ecdsa_nist_p256, sig,
|
||||
linuxkm_test_ecdsa_nist_p256);
|
||||
|
||||
REGISTER_ALG(ecdsa_nist_p384, sig,
|
||||
linuxkm_test_ecdsa_nist_p384);
|
||||
|
||||
#if defined(HAVE_ECC521)
|
||||
REGISTER_ALG(ecdsa_nist_p521, sig,
|
||||
linuxkm_test_ecdsa_nist_p521);
|
||||
#endif /* HAVE_ECC521 */
|
||||
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \
|
||||
defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_FIPS) && \
|
||||
defined(WC_LINUXKM_HAVE_SELFTEST)
|
||||
/*
|
||||
@@ -575,7 +591,7 @@ static int linuxkm_lkcapi_register(void)
|
||||
REGISTER_ALG_OPTIONAL(ecdsa_nist_p521, akcipher,
|
||||
linuxkm_test_ecdsa_nist_p521);
|
||||
#endif /* HAVE_ECC521 */
|
||||
#else
|
||||
#else /* kernel 6.3-6.12 */
|
||||
#if defined(LINUXKM_ECC192)
|
||||
REGISTER_ALG(ecdsa_nist_p192, akcipher,
|
||||
linuxkm_test_ecdsa_nist_p192);
|
||||
@@ -591,7 +607,7 @@ static int linuxkm_lkcapi_register(void)
|
||||
REGISTER_ALG(ecdsa_nist_p521, akcipher,
|
||||
linuxkm_test_ecdsa_nist_p521);
|
||||
#endif /* HAVE_ECC521 */
|
||||
#endif /* if linux < 6.3 && HAVE_FIPS && etc.. */
|
||||
#endif /* kernel 6.3-6.12 */
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0)) && \
|
||||
defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_FIPS) && \
|
||||
@@ -917,14 +933,26 @@ static int linuxkm_lkcapi_unregister(void)
|
||||
#endif
|
||||
|
||||
#ifdef LINUXKM_LKCAPI_REGISTER_ECDSA
|
||||
#if defined(LINUXKM_ECC192)
|
||||
UNREGISTER_ALG(ecdsa_nist_p192, akcipher);
|
||||
#endif /* LINUXKM_ECC192 */
|
||||
UNREGISTER_ALG(ecdsa_nist_p256, akcipher);
|
||||
UNREGISTER_ALG(ecdsa_nist_p384, akcipher);
|
||||
#if defined(HAVE_ECC521)
|
||||
UNREGISTER_ALG(ecdsa_nist_p521, akcipher);
|
||||
#endif /* HAVE_ECC521 */
|
||||
#if defined(LINUXKM_ECDSA_SIG_ALG)
|
||||
/* linux 6.13+: the ecdsa-nist-pN algs are struct sig_alg. */
|
||||
#if defined(LINUXKM_ECC192)
|
||||
UNREGISTER_ALG(ecdsa_nist_p192, sig);
|
||||
#endif /* LINUXKM_ECC192 */
|
||||
UNREGISTER_ALG(ecdsa_nist_p256, sig);
|
||||
UNREGISTER_ALG(ecdsa_nist_p384, sig);
|
||||
#if defined(HAVE_ECC521)
|
||||
UNREGISTER_ALG(ecdsa_nist_p521, sig);
|
||||
#endif /* HAVE_ECC521 */
|
||||
#else /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
#if defined(LINUXKM_ECC192)
|
||||
UNREGISTER_ALG(ecdsa_nist_p192, akcipher);
|
||||
#endif /* LINUXKM_ECC192 */
|
||||
UNREGISTER_ALG(ecdsa_nist_p256, akcipher);
|
||||
UNREGISTER_ALG(ecdsa_nist_p384, akcipher);
|
||||
#if defined(HAVE_ECC521)
|
||||
UNREGISTER_ALG(ecdsa_nist_p521, akcipher);
|
||||
#endif /* HAVE_ECC521 */
|
||||
#endif /* !LINUXKM_ECDSA_SIG_ALG */
|
||||
#endif /* LINUXKM_LKCAPI_REGISTER_ECDSA */
|
||||
|
||||
#ifdef LINUXKM_LKCAPI_REGISTER_ECDH
|
||||
|
||||
@@ -1608,6 +1608,10 @@ static int wc_get_random_bytes_callbacks_installed = 0;
|
||||
|
||||
#elif defined(WOLFSSL_LINUXKM_USE_GET_RANDOM_KPROBES)
|
||||
|
||||
#ifndef WOLFSSL_EXPERIMENTAL_SETTINGS
|
||||
#error WOLFSSL_LINUXKM_USE_GET_RANDOM_KPROBES requires WOLFSSL_EXPERIMENTAL_SETTINGS.
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_KPROBES
|
||||
#error WOLFSSL_LINUXKM_USE_GET_RANDOM_KPROBES without CONFIG_KPROBES.
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#endif
|
||||
#ifndef NO_CRYPT_TEST
|
||||
#include <wolfcrypt/test/test.h>
|
||||
#include <linux/delay.h>
|
||||
#endif
|
||||
|
||||
#ifndef EXPORT_SYMBOL_NS
|
||||
|
||||
@@ -1316,10 +1316,6 @@ void *wc_linuxkm_realloc(void *ptr, size_t newsize)
|
||||
return kvrealloc(ptr, WC_LINUXKM_ROUND_UP_P_OF_2(newsize), (wc_linuxkm_can_block() ? GFP_KERNEL : GFP_ATOMIC));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_KPROBES
|
||||
#include <linux/vmalloc.h>
|
||||
#endif
|
||||
|
||||
size_t wc_linuxkm_malloc_usable_size(void *ptr)
|
||||
{
|
||||
if ((ptr == NULL) || is_vmalloc_addr(ptr)) {
|
||||
|
||||
+1
-1
@@ -5808,7 +5808,7 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
|
||||
|
||||
/* Check hash length */
|
||||
if ((outSz > WC_MAX_DIGEST_SIZE) ||
|
||||
(outSz < WC_MIN_DIGEST_SIZE)) {
|
||||
(outSz < WC_MIN_DIGEST_SIZE_FOR_VERIFY)) {
|
||||
return BAD_LENGTH_E;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -5306,7 +5306,7 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen,
|
||||
/* Check hash length */
|
||||
if ((ret == 1) &&
|
||||
((dLen > WC_MAX_DIGEST_SIZE) ||
|
||||
(dLen < WC_MIN_DIGEST_SIZE))) {
|
||||
(dLen < WC_MIN_DIGEST_SIZE_FOR_VERIFY))) {
|
||||
WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad digest size");
|
||||
ret = WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
@@ -5438,7 +5438,7 @@ int wolfSSL_ECDSA_verify(int type, const unsigned char *digest, int digestSz,
|
||||
/* Check hash length */
|
||||
if ((ret == 1) &&
|
||||
((digestSz > WC_MAX_DIGEST_SIZE) ||
|
||||
(digestSz < WC_MIN_DIGEST_SIZE))) {
|
||||
(digestSz < WC_MIN_DIGEST_SIZE_FOR_VERIFY))) {
|
||||
WOLFSSL_MSG("wolfSSL_ECDSA_verify Bad digest size");
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
+20
-4
@@ -4282,8 +4282,16 @@ static int test_wolfSSL_CTX_SetTmpDH_file(void)
|
||||
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParamFile,
|
||||
CERT_FILETYPE));
|
||||
#if defined(WOLFSSL_WPAS) && !defined(NO_DSA)
|
||||
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dsaParamFile,
|
||||
CERT_FILETYPE));
|
||||
if (EXPECT_SUCCESS()) {
|
||||
if (ctx->minDhKeySz <= 128 /* bytes */) {
|
||||
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dsaParamFile,
|
||||
CERT_FILETYPE));
|
||||
}
|
||||
else {
|
||||
ExpectIntEQ(DH_KEY_SIZE_E, wolfSSL_CTX_SetTmpDH_file(ctx, dsaParamFile,
|
||||
CERT_FILETYPE));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wolfSSL_CTX_free(ctx);
|
||||
@@ -4791,8 +4799,16 @@ static int test_wolfSSL_SetTmpDH_file(void)
|
||||
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhX942ParamFile,
|
||||
CERT_FILETYPE));
|
||||
#if defined(WOLFSSL_WPAS) && !defined(NO_DSA)
|
||||
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dsaParamFile,
|
||||
CERT_FILETYPE));
|
||||
if (EXPECT_SUCCESS()) {
|
||||
if (ctx->minDhKeySz <= 128 /* bytes */) {
|
||||
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dsaParamFile,
|
||||
CERT_FILETYPE));
|
||||
}
|
||||
else {
|
||||
ExpectIntEQ(DH_KEY_SIZE_E, wolfSSL_CTX_SetTmpDH_file(ctx, dsaParamFile,
|
||||
CERT_FILETYPE));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wolfSSL_free(ssl);
|
||||
|
||||
+14
-8
@@ -39,29 +39,35 @@
|
||||
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
|
||||
#if defined(WC_FIPS_186_5_PLUS)
|
||||
/* Old FIPS headers don't allow comparisons with WC_MIN_DIGEST_SIZE_FOR_SIGN by
|
||||
* the preprocessor, so we catch those builds with one of the first two
|
||||
* clauses.
|
||||
*/
|
||||
#if defined(WC_FIPS_186_5_PLUS) && \
|
||||
defined(HAVE_FIPS) && FIPS_VERSION3_LT(7, 0, 0)
|
||||
#define TEST_STRING "WC_FIPS_186_5_PLUS test test"
|
||||
#define TEST_STRING_SZ 28
|
||||
#elif defined(WC_FIPS_186_4_PLUS) || defined(HAVE_SELFTEST)
|
||||
#elif defined(HAVE_SELFTEST) || (defined(WC_FIPS_186_4_PLUS) && \
|
||||
defined(HAVE_FIPS) && FIPS_VERSION3_LT(7, 0, 0))
|
||||
#define TEST_STRING "WC_FIPS_186_4_PLUS test.."
|
||||
#define TEST_STRING_SZ 25
|
||||
#elif WC_MIN_DIGEST_SIZE <= 25
|
||||
#elif WC_MIN_DIGEST_SIZE_FOR_SIGN <= 25
|
||||
#define TEST_STRING "Everyone gets Friday off."
|
||||
#define TEST_STRING_SZ 25
|
||||
#elif WC_MIN_DIGEST_SIZE <= 28
|
||||
#elif WC_MIN_DIGEST_SIZE_FOR_SIGN <= 28
|
||||
#define TEST_STRING "Everyone works the weekends."
|
||||
#define TEST_STRING_SZ 28
|
||||
#elif WC_MIN_DIGEST_SIZE <= 32
|
||||
#elif WC_MIN_DIGEST_SIZE_FOR_SIGN <= 32
|
||||
#define TEST_STRING "Everyone works through the night"
|
||||
#define TEST_STRING_SZ 32
|
||||
#elif WC_MIN_DIGEST_SIZE <= 48
|
||||
#elif WC_MIN_DIGEST_SIZE_FOR_SIGN <= 48
|
||||
#define TEST_STRING "Everyone gets to summer in Tuscany with Chianti."
|
||||
#define TEST_STRING_SZ 48
|
||||
#elif WC_MIN_DIGEST_SIZE <= 64
|
||||
#elif WC_MIN_DIGEST_SIZE_FOR_SIGN <= 64
|
||||
#define TEST_STRING "Everyone works from Christmas Eve, clear through New Year's Day."
|
||||
#define TEST_STRING_SZ 64
|
||||
#else
|
||||
#error WC_MIN_DIGEST_SIZE value not supported by unit test.
|
||||
#error WC_MIN_DIGEST_SIZE_FOR_SIGN value not supported by unit test.
|
||||
#endif
|
||||
|
||||
#ifndef ONEK_BUF
|
||||
|
||||
@@ -1526,7 +1526,11 @@ static int test_wolfSSL_EVP_PKEY_sign_verify(int keyType)
|
||||
!defined(HAVE_SELFTEST)
|
||||
#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))
|
||||
{
|
||||
#ifdef HAVE_FIPS
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, WC_RSA_EXPONENT, NULL, NULL));
|
||||
#else
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL));
|
||||
#endif
|
||||
ExpectIntEQ(EVP_PKEY_assign_RSA(pkey, rsa), WOLFSSL_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
@@ -2159,7 +2163,11 @@ int test_wolfSSL_EVP_PKEY_encrypt(void)
|
||||
XMEMSET(outDec, 0, rsaKeySz);
|
||||
}
|
||||
|
||||
#ifdef HAVE_FIPS
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, WC_RSA_EXPONENT, NULL, NULL));
|
||||
#else
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL));
|
||||
#endif
|
||||
ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new());
|
||||
ExpectIntEQ(EVP_PKEY_assign_RSA(pkey, rsa), WOLFSSL_SUCCESS);
|
||||
if (EXPECT_FAIL()) {
|
||||
|
||||
@@ -65,7 +65,11 @@ int test_wolfSSL_RSA(void)
|
||||
|
||||
RSA_free(rsa);
|
||||
rsa = NULL;
|
||||
#ifdef HAVE_FIPS
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, WC_RSA_EXPONENT, NULL, NULL));
|
||||
#else
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL));
|
||||
#endif
|
||||
ExpectIntEQ(RSA_size(rsa), 256);
|
||||
|
||||
#if (!defined(HAVE_FIPS) || FIPS_VERSION3_GT(6,0,0)) && !defined(HAVE_SELFTEST)
|
||||
@@ -306,7 +310,11 @@ int test_wolfSSL_RSA(void)
|
||||
rsa = NULL;
|
||||
|
||||
#if !defined(USE_FAST_MATH) || (FP_MAX_BITS >= (3072*2))
|
||||
#ifdef HAVE_FIPS
|
||||
ExpectNotNull(rsa = RSA_generate_key(3072, WC_RSA_EXPONENT, NULL, NULL));
|
||||
#else
|
||||
ExpectNotNull(rsa = RSA_generate_key(3072, 17, NULL, NULL));
|
||||
#endif
|
||||
ExpectIntEQ(RSA_size(rsa), 384);
|
||||
ExpectIntEQ(RSA_bits(rsa), 3072);
|
||||
RSA_free(rsa);
|
||||
@@ -461,7 +469,11 @@ int test_wolfSSL_RSA_print(void)
|
||||
|
||||
RSA_free(rsa);
|
||||
rsa = NULL;
|
||||
#ifdef HAVE_FIPS
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, WC_RSA_EXPONENT, NULL, NULL));
|
||||
#else
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL));
|
||||
#endif
|
||||
|
||||
ExpectIntEQ(RSA_print(bio, rsa, 0), 1);
|
||||
ExpectIntEQ(RSA_print(bio, rsa, 4), 1);
|
||||
@@ -644,7 +656,11 @@ int test_wolfSSL_RSA_meth(void)
|
||||
RSA_METHOD *rsa_meth = NULL;
|
||||
|
||||
#ifdef WOLFSSL_KEY_GEN
|
||||
#ifdef HAVE_FIPS
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, WC_RSA_EXPONENT, NULL, NULL));
|
||||
#else
|
||||
ExpectNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL));
|
||||
#endif
|
||||
RSA_free(rsa);
|
||||
rsa = NULL;
|
||||
#else
|
||||
|
||||
@@ -82,6 +82,9 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
|
||||
* WOLFSSL_AESNI_BY4: AES-NI 4-block parallel processing default: off
|
||||
* WOLFSSL_AESNI_BY6: AES-NI 6-block parallel processing default: off
|
||||
* USE_INTEL_SPEEDUP: Intel AVX/AVX2 for AES acceleration default: off
|
||||
* USE_INTEL_SPEEDUP_FOR_AES:
|
||||
Same as USE_INTEL_SPEEDUP, but scoped
|
||||
to AES. default: off
|
||||
* WOLFSSL_AES_SMALL_TABLES: Use smaller AES S-box tables default: off
|
||||
* WOLFSSL_AES_NO_UNROLL: Disable AES round loop unrolling default: off
|
||||
* WOLFSSL_AES_TOUCH_LINES: Touch all cache lines for default: off
|
||||
@@ -812,6 +815,10 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
|
||||
XASM_LINK("AES_256_Key_Expansion_AESNI");
|
||||
|
||||
#ifdef WOLFSSL_X86_64_BUILD
|
||||
#if defined(USE_INTEL_SPEEDUP_FOR_AES) && !defined(USE_INTEL_SPEEDUP)
|
||||
#define USE_INTEL_SPEEDUP
|
||||
#endif
|
||||
|
||||
/* Wide ECB / CBC / CTR variants for x86_64. They share the AES-NI key
|
||||
* schedule declared above and are selected at runtime from intel_flags.
|
||||
* AES_CBC_decrypt_AESNI is the single max-width path (the by4/by6/by8
|
||||
|
||||
+6
-7
@@ -755,7 +755,10 @@ int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, word32* ySz)
|
||||
|
||||
int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng)
|
||||
{
|
||||
/* use sha1 by default for backwards compatibility */
|
||||
/* Use sha1 by default for backwards compatibility. This API will always
|
||||
* fail in FIPS 186-5 builds, due to the forbidden SHA-1 sign operation, as
|
||||
* required.
|
||||
*/
|
||||
return wc_DsaSign_ex(digest, WC_SHA_DIGEST_SIZE, out, key, rng);
|
||||
}
|
||||
|
||||
@@ -787,7 +790,7 @@ int wc_DsaSign_ex(const byte* digest, word32 digestSz, byte* out, DsaKey* key,
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if ((digestSz > WC_MAX_DIGEST_SIZE) ||
|
||||
(digestSz < WC_MIN_DIGEST_SIZE))
|
||||
(digestSz < WC_MIN_DIGEST_SIZE_FOR_SIGN))
|
||||
{
|
||||
return BAD_LENGTH_E;
|
||||
}
|
||||
@@ -1121,12 +1124,8 @@ int wc_DsaVerify_ex(const byte* digest, word32 digestSz, const byte* sig,
|
||||
if (digest == NULL || sig == NULL || key == NULL || answer == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* Note the min allowed digestSz here is WC_SHA_DIGEST_SIZE, not
|
||||
* WC_MIN_DIGEST_SIZE, to allow verify-only legacy DSA operations, as
|
||||
* expressly allowed under FIPS 186-5, FIPS 140-3, and SP 800-131A.
|
||||
*/
|
||||
if ((digestSz > WC_MAX_DIGEST_SIZE) ||
|
||||
(digestSz < WC_SHA_DIGEST_SIZE))
|
||||
(digestSz < WC_MIN_DIGEST_SIZE_FOR_VERIFY))
|
||||
{
|
||||
return BAD_LENGTH_E;
|
||||
}
|
||||
|
||||
+4
-4
@@ -6907,7 +6907,7 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
|
||||
return ECC_BAD_ARG_E;
|
||||
}
|
||||
if ((inlen > WC_MAX_DIGEST_SIZE) ||
|
||||
(inlen < WC_MIN_DIGEST_SIZE))
|
||||
(inlen < WC_MIN_DIGEST_SIZE_FOR_SIGN))
|
||||
{
|
||||
return BAD_LENGTH_E;
|
||||
}
|
||||
@@ -7441,7 +7441,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
|
||||
return ECC_BAD_ARG_E;
|
||||
}
|
||||
if ((inlen > WC_MAX_DIGEST_SIZE) ||
|
||||
(inlen < WC_MIN_DIGEST_SIZE))
|
||||
(inlen < WC_MIN_DIGEST_SIZE_FOR_SIGN))
|
||||
{
|
||||
return BAD_LENGTH_E;
|
||||
}
|
||||
@@ -8755,7 +8755,7 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
|
||||
|
||||
/* Check hash length */
|
||||
if ((hashlen > WC_MAX_DIGEST_SIZE) ||
|
||||
(hashlen < WC_MIN_DIGEST_SIZE)) {
|
||||
(hashlen < WC_MIN_DIGEST_SIZE_FOR_VERIFY)) {
|
||||
return BAD_LENGTH_E;
|
||||
}
|
||||
|
||||
@@ -9474,7 +9474,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
|
||||
|
||||
/* Check hash length */
|
||||
if ((hashlen > WC_MAX_DIGEST_SIZE) ||
|
||||
(hashlen < WC_MIN_DIGEST_SIZE)) {
|
||||
(hashlen < WC_MIN_DIGEST_SIZE_FOR_VERIFY)) {
|
||||
return BAD_LENGTH_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -4786,7 +4786,7 @@ static int wc_PKCS7_EcdsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
|
||||
|
||||
/* Check hash length */
|
||||
if ((hashSz > WC_MAX_DIGEST_SIZE) ||
|
||||
(hashSz < WC_MIN_DIGEST_SIZE)) {
|
||||
(hashSz < WC_MIN_DIGEST_SIZE_FOR_VERIFY)) {
|
||||
return BAD_LENGTH_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -4915,10 +4915,6 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
|
||||
#elif defined(WOLFSSL_LINUXKM)
|
||||
|
||||
#ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
|
||||
#include <linux/random.h>
|
||||
#endif
|
||||
|
||||
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
{
|
||||
(void)os;
|
||||
|
||||
+219
-99
@@ -71,6 +71,10 @@
|
||||
((rng_ptr)->drbg == NULL)
|
||||
#endif
|
||||
|
||||
/* To disable retry looping in wc_rng_bank_init(), pass timeout_secs=0, and to
|
||||
* retry indefinitely, pass negative timeout_secs -- the flags arg here is only
|
||||
* used to initialize the flags in the new bank.
|
||||
*/
|
||||
WOLFSSL_API int wc_rng_bank_init(
|
||||
struct wc_rng_bank *ctx,
|
||||
int n_rngs,
|
||||
@@ -133,6 +137,22 @@ WOLFSSL_API int wc_rng_bank_init(
|
||||
WC_RELAX_LONG_LOOP();
|
||||
if (ret == 0)
|
||||
break;
|
||||
|
||||
/* Several plausible error codes are non-retryable -- fail early
|
||||
* for these.
|
||||
*/
|
||||
switch (ret) {
|
||||
case WC_NO_ERR_TRACE(BAD_MUTEX_E):
|
||||
case WC_NO_ERR_TRACE(BAD_FUNC_ARG):
|
||||
case WC_NO_ERR_TRACE(MEMORY_E):
|
||||
case WC_NO_ERR_TRACE(NOT_COMPILED_IN):
|
||||
case WC_NO_ERR_TRACE(MISSING_RNG_E):
|
||||
case WC_NO_ERR_TRACE(BUFFER_E):
|
||||
case WC_NO_ERR_TRACE(OPEN_RAN_E):
|
||||
case WC_NO_ERR_TRACE(FIPS_NOT_ALLOWED_E):
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Allow interrupt only if we're stuck spinning retries -- i.e.,
|
||||
* don't allow an untimely user signal to derail an
|
||||
* initialization that is proceeding expeditiously.
|
||||
@@ -141,7 +161,7 @@ WOLFSSL_API int wc_rng_bank_init(
|
||||
if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
break;
|
||||
ts2 = XTIME(0);
|
||||
if (ts2 - ts1 > timeout_secs) {
|
||||
if ((timeout_secs >= 0) && (ts2 - ts1 > timeout_secs)) {
|
||||
ret = WC_TIMEOUT_E;
|
||||
break;
|
||||
}
|
||||
@@ -160,6 +180,8 @@ WOLFSSL_API int wc_rng_bank_init(
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
if (ret != 0)
|
||||
(void)wc_rng_bank_fini(ctx);
|
||||
|
||||
@@ -220,6 +242,8 @@ WOLFSSL_API int wc_rng_bank_set_affinity_handlers(
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx) {
|
||||
int i;
|
||||
int ret;
|
||||
WC_ATOMIC_INT_ARG new_refcount;
|
||||
|
||||
if (ctx == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
@@ -235,6 +259,18 @@ WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx) {
|
||||
else if (wolfSSL_RefCur(ctx->refcount) < 1)
|
||||
return BAD_STATE_E;
|
||||
|
||||
wolfSSL_RefDec_IfEquals(&ctx->refcount, 1, &new_refcount, &ret);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_fini() called with refcount %d.", new_refcount);
|
||||
#endif
|
||||
if (new_refcount > 1)
|
||||
return BUSY_E;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef WC_RNG_BANK_STATIC
|
||||
if (ctx->rngs)
|
||||
#endif
|
||||
@@ -247,7 +283,13 @@ WOLFSSL_API int wc_rng_bank_fini(struct wc_rng_bank *ctx) {
|
||||
"BUG: wc_rng_bank_fini() called with RNG #%d still "
|
||||
"locked.\n", i);
|
||||
#endif
|
||||
return BUSY_E;
|
||||
wolfSSL_RefInc2(&ctx->refcount, &new_refcount, &ret);
|
||||
/* Always return BAD_STATE_E here -- a locked rng with a zero
|
||||
* refcount on the bank is always a corruption.
|
||||
*/
|
||||
(void)new_refcount;
|
||||
(void)ret;
|
||||
return BAD_STATE_E;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,22 +355,19 @@ WOLFSSL_API int wc_rng_bank_default_set(struct wc_rng_bank *bank) {
|
||||
if (bank == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if ((! (bank->flags & WC_RNG_BANK_FLAG_INITED)) ||
|
||||
(wolfSSL_RefCur(bank->refcount) < 1))
|
||||
{
|
||||
if (! (bank->flags & WC_RNG_BANK_FLAG_INITED))
|
||||
return BAD_STATE_E;
|
||||
}
|
||||
|
||||
wolfSSL_RefInc2(&bank->refcount, &new_refcount, &ret);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
wolfSSL_RefInc_IfAtLeast(&bank->refcount, 1, &new_refcount, &ret);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (new_refcount < 2)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: wc_rng_bank_default_set() new_refcount %d.\n", new_refcount);
|
||||
"BUG: wc_rng_bank_default_set() with refcount %d.\n", new_refcount);
|
||||
#else
|
||||
(void)new_refcount;
|
||||
(void)new_refcount;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
if (wolfSSL_Atomic_Ptr_CompareExchange((void * volatile *)&default_rng_bank, (void **)&cur_default_rng_bank, bank))
|
||||
return 0;
|
||||
else {
|
||||
@@ -351,13 +390,19 @@ WOLFSSL_API int wc_rng_bank_default_set(struct wc_rng_bank *bank) {
|
||||
WOLFSSL_API int wc_rng_bank_default_checkout(struct wc_rng_bank **bank) {
|
||||
int ret;
|
||||
struct wc_rng_bank *cur_default_rng_bank = default_rng_bank;
|
||||
WC_ATOMIC_INT_ARG new_refcount;
|
||||
|
||||
if (bank == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (cur_default_rng_bank == NULL)
|
||||
return BAD_STATE_E;
|
||||
wolfSSL_RefInc(&cur_default_rng_bank->refcount, &ret);
|
||||
if (ret == 0)
|
||||
*bank = cur_default_rng_bank;
|
||||
|
||||
wolfSSL_RefInc_IfAtLeast(&cur_default_rng_bank->refcount, 2, &new_refcount, &ret);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
*bank = cur_default_rng_bank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -431,6 +476,7 @@ WOLFSSL_API int wc_rng_bank_checkout(
|
||||
int ret = 0;
|
||||
time_t ts1, ts2;
|
||||
int n_rngs_tried = 0;
|
||||
WC_ATOMIC_INT_ARG new_refcount;
|
||||
|
||||
#ifdef WC_RNG_BANK_DEFAULT_SUPPORT
|
||||
if (bank == NULL)
|
||||
@@ -460,45 +506,16 @@ WOLFSSL_API int wc_rng_bank_checkout(
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK) {
|
||||
if ((bank->affinity_lock_cb == NULL) ||
|
||||
(bank->affinity_unlock_cb == NULL))
|
||||
{
|
||||
/* Increment bank->refcount here speculatively, and assert on the resulting
|
||||
* refcount, to mitigate races with bank deallocation.
|
||||
*/
|
||||
wolfSSL_RefInc_IfAtLeast(&bank->refcount, 1, &new_refcount, &ret);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: wc_rng_bank_checkout() called with _AFFINITY_LOCK but "
|
||||
"missing _lock_cb.\n");
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"wc_rng_bank_checkout() called with refcount %d.\n", new_refcount);
|
||||
#endif
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
ret = bank->affinity_lock_cb(bank->cb_arg);
|
||||
if (ret == 0)
|
||||
new_lock_value |= WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED;
|
||||
else if (ret != WC_NO_ERR_TRACE(ALREADY_E))
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST) {
|
||||
preferred_inst_offset = -1;
|
||||
ret = bank->affinity_get_id_cb(bank->cb_arg, &preferred_inst_offset);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: bank->affinity_get_id_cb() returned err %d.\n", ret);
|
||||
#endif
|
||||
}
|
||||
else if (((preferred_inst_offset < 0) ||
|
||||
(preferred_inst_offset >= bank->n_rngs)))
|
||||
{
|
||||
ret = BAD_INDEX_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((preferred_inst_offset < 0) ||
|
||||
(preferred_inst_offset >= bank->n_rngs))
|
||||
{
|
||||
ret = BAD_INDEX_E;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((timeout_secs > 0) && (flags & WC_RNG_BANK_FLAG_CAN_WAIT))
|
||||
@@ -509,6 +526,46 @@ WOLFSSL_API int wc_rng_bank_checkout(
|
||||
for (; ret == 0;) {
|
||||
int expected = 0;
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK) {
|
||||
if ((bank->affinity_lock_cb == NULL) ||
|
||||
(bank->affinity_unlock_cb == NULL))
|
||||
{
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: wc_rng_bank_checkout() called with _AFFINITY_LOCK but "
|
||||
"missing _lock_cb.\n");
|
||||
#endif
|
||||
ret = BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
ret = bank->affinity_lock_cb(bank->cb_arg);
|
||||
if (ret == 0)
|
||||
new_lock_value |= WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED;
|
||||
else if (ret == WC_NO_ERR_TRACE(ALREADY_E))
|
||||
ret = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST) {
|
||||
preferred_inst_offset = -1;
|
||||
ret = bank->affinity_get_id_cb(bank->cb_arg, &preferred_inst_offset);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"BUG: bank->affinity_get_id_cb() returned err %d.\n", ret);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((preferred_inst_offset < 0) ||
|
||||
(preferred_inst_offset >= bank->n_rngs))
|
||||
{
|
||||
ret = BAD_INDEX_E;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wolfSSL_Atomic_Int_CompareExchange(
|
||||
&bank->rngs[preferred_inst_offset].lock,
|
||||
&expected,
|
||||
@@ -523,6 +580,7 @@ WOLFSSL_API int wc_rng_bank_checkout(
|
||||
(n_rngs_tried < bank->n_rngs))
|
||||
{
|
||||
WOLFSSL_ATOMIC_STORE((*rng_inst)->lock, WC_RNG_BANK_INST_LOCK_FREE);
|
||||
*rng_inst = NULL;
|
||||
}
|
||||
else {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
@@ -544,65 +602,102 @@ WOLFSSL_API int wc_rng_bank_checkout(
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_USE_SAVE_VECTOR_REGISTERS
|
||||
if ((flags | bank->flags) & WC_RNG_BANK_FLAG_NO_VECTOR_OPS) {
|
||||
if (DISABLE_VECTOR_REGISTERS() == 0)
|
||||
ret = DISABLE_VECTOR_REGISTERS();
|
||||
if (ret == 0)
|
||||
WOLFSSL_ATOMIC_STORE((*rng_inst)->lock, new_lock_value |
|
||||
WC_RNG_BANK_INST_LOCK_VEC_OPS_INH);
|
||||
else if (ret == WC_NO_ERR_TRACE(WC_ACCEL_INHIBIT_E))
|
||||
ret = 0;
|
||||
else {
|
||||
WOLFSSL_ATOMIC_STORE((*rng_inst)->lock, WC_RNG_BANK_INST_LOCK_FREE);
|
||||
*rng_inst = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */
|
||||
|
||||
return 0; /* Short-circuit return, holding onto RNG and affinity
|
||||
* locks and vector register inhibition.
|
||||
return 0; /* Short-circuit return, holding onto bank refcount,
|
||||
* RNG lock, affinity locks, and (if applicable)
|
||||
* vector register inhibition.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST) {
|
||||
if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) &&
|
||||
(n_rngs_tried >= bank->n_rngs))
|
||||
if ((n_rngs_tried >= bank->n_rngs) &&
|
||||
((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) ||
|
||||
(timeout_secs == 0)))
|
||||
{
|
||||
ret = BUSY_E;
|
||||
break; /* jump to cleanup. */
|
||||
}
|
||||
/* There's no longer any consistent connection between the CPU ID
|
||||
* and the instance -- no point getting an affinity lock.
|
||||
*/
|
||||
flags &= ~(word32)WC_RNG_BANK_FLAG_AFFINITY_LOCK;
|
||||
flags &= ~(word32)WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST;
|
||||
|
||||
++preferred_inst_offset;
|
||||
if (preferred_inst_offset >= bank->n_rngs)
|
||||
preferred_inst_offset = 0;
|
||||
++n_rngs_tried;
|
||||
}
|
||||
else {
|
||||
if (! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) {
|
||||
if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) ||
|
||||
(timeout_secs == 0))
|
||||
{
|
||||
ret = BUSY_E;
|
||||
break; /* jump to cleanup. */
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK)
|
||||
if (new_lock_value & WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED) {
|
||||
(void)bank->affinity_unlock_cb(bank->cb_arg);
|
||||
|
||||
ret = WC_CHECK_FOR_INTR_SIGNALS();
|
||||
if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
return ret; /* immediate return -- no locks held */
|
||||
|
||||
if (timeout_secs > 0) {
|
||||
ts2 = XTIME(0);
|
||||
if (ts2 - ts1 >= timeout_secs)
|
||||
return WC_TIMEOUT_E; /* immediate return -- no locks held */
|
||||
}
|
||||
WC_RELAX_LONG_LOOP();
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK) {
|
||||
ret = bank->affinity_lock_cb(bank->cb_arg);
|
||||
if (ret)
|
||||
return ret; /* immediate return -- no locks held */
|
||||
new_lock_value &= ~WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED;
|
||||
}
|
||||
|
||||
/* Note that we may have been migrated at this point, but it doesn't
|
||||
* matter -- we only reach this point if we have to retry/iterate.
|
||||
*/
|
||||
if ((flags & WC_RNG_BANK_FLAG_CAN_WAIT) && (timeout_secs != 0)) {
|
||||
ret = WC_CHECK_FOR_INTR_SIGNALS();
|
||||
if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
break;
|
||||
|
||||
if (timeout_secs > 0) {
|
||||
ts2 = XTIME(0);
|
||||
if (ts2 - ts1 >= timeout_secs) {
|
||||
ret = WC_TIMEOUT_E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WC_RELAX_LONG_LOOP();
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & WC_RNG_BANK_FLAG_AFFINITY_LOCK)
|
||||
if (ret == 0)
|
||||
ret = RNG_FAILURE_E;
|
||||
|
||||
if (new_lock_value & WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED)
|
||||
(void)bank->affinity_unlock_cb(bank->cb_arg);
|
||||
|
||||
/* Decrement the speculative refcount increment. */
|
||||
{
|
||||
int refdec_err;
|
||||
wolfSSL_RefDec2(&bank->refcount, &new_refcount, &refdec_err);
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (refdec_err != 0)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_checkout() cleanup wolfSSL_RefDec2 returned %d.", refdec_err);
|
||||
else if (new_refcount <= 0)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_checkout() bank refcount after wolfSSL_RefDec2() is %d.", new_refcount);
|
||||
#else
|
||||
(void)new_refcount;
|
||||
(void)refdec_err;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -670,9 +765,28 @@ WOLFSSL_API int wc_rng_bank_checkin(
|
||||
REENABLE_VECTOR_REGISTERS();
|
||||
|
||||
if (lockval & WC_RNG_BANK_INST_LOCK_AFFINITY_LOCKED)
|
||||
return bank->affinity_unlock_cb(bank->cb_arg);
|
||||
ret = bank->affinity_unlock_cb(bank->cb_arg);
|
||||
else
|
||||
return 0;
|
||||
ret = 0;
|
||||
|
||||
{
|
||||
WC_ATOMIC_INT_ARG new_refcount;
|
||||
int refdec_err;
|
||||
wolfSSL_RefDec2(&bank->refcount, &new_refcount, &refdec_err);
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (refdec_err != 0)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_checkin() wolfSSL_RefDec2 returned %d.", refdec_err);
|
||||
else if (new_refcount <= 0)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_checkin() bank refcount after wolfSSL_RefDec2() is %d.", new_refcount);
|
||||
#else
|
||||
(void)new_refcount;
|
||||
(void)refdec_err;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* note the rng_inst passed to wc_rng_bank_inst_reinit() must have been obtained
|
||||
@@ -720,7 +834,7 @@ WOLFSSL_API int wc_rng_bank_inst_reinit(
|
||||
bank->heap, devId);
|
||||
if (ret == 0)
|
||||
break;
|
||||
if (! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) {
|
||||
if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) || (timeout_secs == 0)) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"WARNING: wc_rng_bank_inst_reinit() returning err %d.\n", ret);
|
||||
@@ -849,21 +963,27 @@ WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank,
|
||||
(word32)sizeof(scratch));
|
||||
if (ret == 0)
|
||||
break;
|
||||
if ((timeout_secs <= 0) ||
|
||||
if ((timeout_secs == 0) ||
|
||||
(! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
ts2 = XTIME(0);
|
||||
if (ts2 - ts1 > timeout_secs) {
|
||||
if (timeout_secs > 0) {
|
||||
ts2 = XTIME(0);
|
||||
if (ts2 - ts1 > timeout_secs) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: timeout after attempted reseed by "
|
||||
"wc_RNG_GenerateBlock() for DRBG #%d, err %d.", n, ret);
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: timeout after attempted reseed by "
|
||||
"wc_RNG_GenerateBlock() for DRBG #%d, err %d.", n, ret);
|
||||
#endif
|
||||
ret = WC_TIMEOUT_E;
|
||||
break;
|
||||
ret = WC_TIMEOUT_E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = WC_CHECK_FOR_INTR_SIGNALS();
|
||||
if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
break;
|
||||
WC_RELAX_LONG_LOOP();
|
||||
}
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if ((ret != 0) && (ret != WC_NO_ERR_TRACE(WC_TIMEOUT_E)))
|
||||
@@ -872,8 +992,11 @@ WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank,
|
||||
"for DRBG #%d returned %d.", n, ret);
|
||||
#endif
|
||||
(void)wc_rng_bank_checkin(bank, &drbg);
|
||||
if (ret == WC_NO_ERR_TRACE(WC_TIMEOUT_E))
|
||||
if ((ret == WC_NO_ERR_TRACE(WC_TIMEOUT_E)) ||
|
||||
(ret == WC_NO_ERR_TRACE(INTERRUPTED_E)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
ret = WC_CHECK_FOR_INTR_SIGNALS();
|
||||
if (ret == WC_NO_ERR_TRACE(INTERRUPTED_E))
|
||||
return ret;
|
||||
@@ -892,6 +1015,7 @@ WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank,
|
||||
WOLFSSL_API int wc_InitRng_BankRef(struct wc_rng_bank *bank, WC_RNG *rng)
|
||||
{
|
||||
int ret;
|
||||
WC_ATOMIC_INT_ARG new_refcount;
|
||||
|
||||
#ifdef WC_RNG_BANK_DEFAULT_SUPPORT
|
||||
if (bank == NULL)
|
||||
@@ -904,19 +1028,15 @@ WOLFSSL_API int wc_InitRng_BankRef(struct wc_rng_bank *bank, WC_RNG *rng)
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if ((! (bank->flags & WC_RNG_BANK_FLAG_INITED)) ||
|
||||
(wolfSSL_RefCur(bank->refcount) < 1))
|
||||
{
|
||||
if (! (bank->flags & WC_RNG_BANK_FLAG_INITED))
|
||||
return BAD_STATE_E;
|
||||
}
|
||||
|
||||
XMEMSET(rng, 0, sizeof(*rng));
|
||||
|
||||
wolfSSL_RefInc(&bank->refcount, &ret);
|
||||
|
||||
wolfSSL_RefInc_IfAtLeast(&bank->refcount, 1, &new_refcount, &ret);
|
||||
(void)new_refcount;
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
XMEMSET(rng, 0, sizeof(*rng));
|
||||
rng->heap = bank->heap;
|
||||
rng->status = WC_DRBG_BANKREF;
|
||||
rng->bankref = bank;
|
||||
|
||||
@@ -2153,6 +2153,28 @@ void wolfSSL_RefWithMutexInc2(wolfSSL_RefWithMutex* ref, int *new_count,
|
||||
*err = ret;
|
||||
}
|
||||
|
||||
void wolfSSL_RefWithMutexInc_IfAtLeast(wolfSSL_RefWithMutex* ref,
|
||||
int cur_at_least, int *new_count,
|
||||
int* err)
|
||||
{
|
||||
*err = wc_LockMutex(&ref->mutex);
|
||||
if (*err != 0) {
|
||||
WOLFSSL_MSG("Failed to lock mutex for reference increment!");
|
||||
*new_count = -1;
|
||||
}
|
||||
else {
|
||||
if (ref->count < cur_at_least) {
|
||||
*new_count = ref->count;
|
||||
*err = BAD_STATE_E;
|
||||
}
|
||||
else {
|
||||
*new_count = ++ref->count;
|
||||
*err = 0;
|
||||
}
|
||||
wc_UnLockMutex(&ref->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
int wolfSSL_RefWithMutexLock(wolfSSL_RefWithMutex* ref)
|
||||
{
|
||||
return wc_LockMutex(&ref->mutex);
|
||||
@@ -2198,6 +2220,29 @@ void wolfSSL_RefWithMutexDec2(wolfSSL_RefWithMutex* ref, int* new_count,
|
||||
}
|
||||
*err = ret;
|
||||
}
|
||||
|
||||
void wolfSSL_RefWithMutexDec_IfEquals(wolfSSL_RefWithMutex* ref,
|
||||
int current_count, int* new_count,
|
||||
int* err)
|
||||
{
|
||||
*err = wc_LockMutex(&ref->mutex);
|
||||
if (*err != 0) {
|
||||
WOLFSSL_MSG("Failed to lock mutex for reference decrement!");
|
||||
*new_count = -1;
|
||||
}
|
||||
else {
|
||||
if (ref->count != current_count) {
|
||||
*new_count = ref->count;
|
||||
*err = BAD_STATE_E;
|
||||
}
|
||||
else {
|
||||
*new_count = --ref->count;
|
||||
*err = 0;
|
||||
}
|
||||
wc_UnLockMutex(&ref->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ! SINGLE_THREADED */
|
||||
|
||||
#if WOLFSSL_CRYPT_HW_MUTEX
|
||||
|
||||
+22
-9
@@ -38112,7 +38112,7 @@ static wc_test_ret_t ecc_test_vector_item(const eccVector* vector)
|
||||
#endif /* !NO_ASN */
|
||||
|
||||
#ifdef HAVE_ECC_VERIFY
|
||||
if (vector->msgLen >= WC_MIN_DIGEST_SIZE) {
|
||||
if (vector->msgLen >= WC_MIN_DIGEST_SIZE_FOR_VERIFY) {
|
||||
do {
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
ret = wc_AsyncWait(ret, &userA->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
|
||||
@@ -43936,10 +43936,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test_buffers(void)
|
||||
wc_test_ret_t ret;
|
||||
word32 idx = 0;
|
||||
#ifndef WC_NO_RNG
|
||||
/* 32 bytes: evenly divisible by AES_BLOCK_SZ and meets WC_MIN_DIGEST_SIZE */
|
||||
/* 32 bytes: evenly divisible by AES_BLOCK_SZ and meets WC_MIN_DIGEST_SIZE_FOR_SIGN */
|
||||
byte in[] = "Everyone gets Friday off. ecc p";
|
||||
const word32 inLen = sizeof(in); /* includes null terminator */
|
||||
wc_static_assert(sizeof(in) >= WC_MIN_DIGEST_SIZE_FOR_SIGN);
|
||||
wc_static_assert2(sizeof(in) == 32, "in[] must be exactly 32 bytes");
|
||||
const word32 inLen = sizeof(in); /* includes null terminator */
|
||||
byte out[256];
|
||||
byte plain[256];
|
||||
WOLFSSL_ENTER("ecc_test_buffers");
|
||||
@@ -75449,16 +75450,26 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
|
||||
* ecc_test calls to it are not skipped (WC_TEST_SKIP_ECC_CHECK_KEY); the
|
||||
* counter legitimately stays 0 otherwise. CAAM is excluded because the
|
||||
* check-pubkey dispatch in _ecc_validate_public_key is compiled out there
|
||||
* (CAAM uses software validation failure to detect black keys). */
|
||||
* (CAAM uses software validation failure to detect black keys).
|
||||
*
|
||||
* The FIPS wrappers force the devId to FIPS_INVALID_DEVID, so we skip
|
||||
* the check for FIPS.
|
||||
*/
|
||||
#if !defined(WOLF_CRYPTO_CB_ONLY_ECC) && defined(HAVE_ECC_CHECK_KEY) && \
|
||||
!defined(WC_TEST_SKIP_ECC_CHECK_KEY) && !defined(WOLFSSL_CAAM)
|
||||
!defined(WC_TEST_SKIP_ECC_CHECK_KEY) && !defined(WOLFSSL_CAAM) && \
|
||||
!defined(HAVE_FIPS)
|
||||
if (ret == 0 && myCtx.eccCheckPubCount == 0)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
#endif
|
||||
/* Regression: an explicit public point with zero coordinates must cross
|
||||
* the callback boundary as X9.63 0x04||0||0, not as pubKey = NULL. */
|
||||
* the callback boundary as X9.63 0x04||0||0, not as pubKey = NULL.
|
||||
*
|
||||
* The FIPS wrappers force the devId to FIPS_INVALID_DEVID, so we skip
|
||||
* the check for FIPS.
|
||||
*/
|
||||
#if !defined(WOLFSSL_SWDEV) && defined(HAVE_ECC_CHECK_KEY) && \
|
||||
!defined(WOLFSSL_CAAM) && !defined(NO_ECC256)
|
||||
!defined(WOLFSSL_CAAM) && !defined(NO_ECC256) && \
|
||||
!defined(HAVE_FIPS)
|
||||
if (ret == 0) {
|
||||
WC_DECLARE_VAR(zeroKey, ecc_key, 1, HEAP_HINT);
|
||||
int haveZeroKey = 0;
|
||||
@@ -75502,7 +75513,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
|
||||
!defined(WOLFSSL_SILABS_SE_ACCEL) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) && \
|
||||
!defined(NO_ECC_SECP) && !defined(WOLFSSL_NO_MALLOC) && \
|
||||
!defined(WOLFSSL_CRYPTOCELL) && !defined(NO_ECC256) && \
|
||||
defined(HAVE_ECC_KEY_EXPORT)
|
||||
defined(HAVE_ECC_KEY_EXPORT) && \
|
||||
!defined(HAVE_FIPS)
|
||||
if (ret == 0 && myCtx.eccMakePubCount == 0)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
#endif
|
||||
@@ -75519,7 +75531,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
|
||||
!defined(WOLFSSL_SWDEV) && !defined(NO_ECC_SECP) && \
|
||||
!defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_CRYPTOCELL) && \
|
||||
!defined(WOLFSSL_SE050) && \
|
||||
!defined(NO_ECC256) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG)
|
||||
!defined(NO_ECC256) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) && \
|
||||
!defined(HAVE_FIPS)
|
||||
if (ret == 0) {
|
||||
/* generated keypair: private scalar for the negative tests, public
|
||||
* point for the resident-key test */
|
||||
|
||||
@@ -176,25 +176,31 @@ typedef struct {
|
||||
#define WC_MAX_BLOCK_SIZE WC_HASH_CUSTOM_MAX_BLOCK_SIZE
|
||||
#endif
|
||||
|
||||
/* Set up WC_MIN_DIGEST_SIZE. This is the shortest digest supported by any
|
||||
* fixed-output-size hash algorithm enabled in the library. It is not
|
||||
* necessarily the shortest digest permitted for signature generation -- that is
|
||||
* designated by WC_MIN_DIGEST_SIZE_FOR_SIGN, defined below, with additional
|
||||
* restrictions under FIPS 186-5.
|
||||
*/
|
||||
#if defined(WC_HASH_CUSTOM_MIN_DIGEST_SIZE)
|
||||
#if defined(WC_FIPS_186_5_PLUS) && \
|
||||
(WC_HASH_CUSTOM_MIN_DIGEST_SIZE < 224 / 8)
|
||||
#error FIPS 186-5 requires a minimum hash size >= SHA-224.
|
||||
#elif defined(WC_FIPS_186_4) && \
|
||||
/* Note, FIPS 186-5 allows (and we need) SHA-1 in verify-only mode, but
|
||||
* restricts signing to SHA-224 and larger, enforced below.
|
||||
*/
|
||||
#if defined(WC_FIPS_186_4_PLUS) && \
|
||||
(WC_HASH_CUSTOM_MIN_DIGEST_SIZE < 160 / 8)
|
||||
#error FIPS 186-4 requires a minimum hash size >= SHA-1.
|
||||
#error FIPS 186 requires a minimum hash size >= SHA-1.
|
||||
#elif (WC_HASH_CUSTOM_MIN_DIGEST_SIZE < 128 / 8)
|
||||
#error WC_HASH_CUSTOM_MIN_DIGEST_SIZE is too small.
|
||||
#endif
|
||||
/* Let the user override the minimum digest size */
|
||||
#define WC_MIN_DIGEST_SIZE WC_HASH_CUSTOM_MIN_DIGEST_SIZE
|
||||
#elif defined(WOLFSSL_MD2) && !defined(WC_FIPS_186_4_PLUS)
|
||||
#elif defined(WOLFSSL_MD2)
|
||||
#define WC_MIN_DIGEST_SIZE WC_MD2_DIGEST_SIZE /* 16 */
|
||||
#elif !defined(NO_MD4) && !defined(WC_FIPS_186_4_PLUS)
|
||||
#elif !defined(NO_MD4)
|
||||
#define WC_MIN_DIGEST_SIZE WC_MD4_DIGEST_SIZE /* 16 */
|
||||
#elif !defined(NO_MD5) && !defined(WC_FIPS_186_4_PLUS)
|
||||
#elif !defined(NO_MD5)
|
||||
#define WC_MIN_DIGEST_SIZE WC_MD5_DIGEST_SIZE /* 16 */
|
||||
#elif !defined(NO_SHA) && !defined(WC_FIPS_186_5_PLUS)
|
||||
#elif !defined(NO_SHA)
|
||||
#define WC_MIN_DIGEST_SIZE WC_SHA_DIGEST_SIZE /* 20 */
|
||||
#elif defined(WOLFSSL_SHA224)
|
||||
#define WC_MIN_DIGEST_SIZE WC_SHA224_DIGEST_SIZE
|
||||
@@ -232,6 +238,55 @@ typedef struct {
|
||||
#define WC_MIN_DIGEST_SIZE 64
|
||||
#endif
|
||||
|
||||
/* We can't use preprocessor comparisons for asserts and conditional definitions
|
||||
* here, because old FIPS uses enums for most of the digest sizes. Moreover we
|
||||
* can't use WC_SHA_DIGEST_SIZE at all here, because we support SHA-1-sized
|
||||
* digests even in NO_SHA builds.
|
||||
*/
|
||||
#ifdef WC_MIN_DIGEST_SIZE_FOR_SIGN
|
||||
wc_static_assert2((WC_MIN_DIGEST_SIZE_FOR_SIGN <= WC_MAX_DIGEST_SIZE) &&
|
||||
(WC_MIN_DIGEST_SIZE_FOR_SIGN >= WC_MIN_DIGEST_SIZE),
|
||||
"Supplied WC_MIN_DIGEST_SIZE_FOR_SIGN is out of range.");
|
||||
#if defined(WC_FIPS_186_5_PLUS)
|
||||
wc_static_assert2(WC_MIN_DIGEST_SIZE_FOR_SIGN >= 224 / 8,
|
||||
"FIPS 186-5 requires a minimum sign-mode hash size >= SHA-224.");
|
||||
#elif defined(WC_FIPS_186_4)
|
||||
wc_static_assert2(WC_MIN_DIGEST_SIZE_FOR_SIGN >= 160 / 8,
|
||||
"FIPS 186-4 requires a minimum sign-mode hash size >= SHA-1.");
|
||||
#endif
|
||||
#else
|
||||
#if defined(WC_FIPS_186_5_PLUS)
|
||||
#define WC_MIN_DIGEST_SIZE_FOR_SIGN \
|
||||
((WC_MIN_DIGEST_SIZE < 224 / 8) ? (224 / 8) : WC_MIN_DIGEST_SIZE)
|
||||
#elif defined(WC_FIPS_186_4)
|
||||
#define WC_MIN_DIGEST_SIZE_FOR_SIGN \
|
||||
((WC_MIN_DIGEST_SIZE < 224 / 8) ? (160 / 8) : WC_MIN_DIGEST_SIZE)
|
||||
#else
|
||||
#define WC_MIN_DIGEST_SIZE_FOR_SIGN WC_MIN_DIGEST_SIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The minimum digest _FOR_VERIFY_under FIPS 186-5, FIPS 140-3, and SP 800-131A,
|
||||
* is permitted to be shorter, to allow verify-only legacy DSA and ECDSA
|
||||
* operations.
|
||||
*/
|
||||
#ifdef WC_MIN_DIGEST_SIZE_FOR_VERIFY
|
||||
wc_static_assert2((WC_MIN_DIGEST_SIZE_FOR_VERIFY <= WC_MAX_DIGEST_SIZE) &&
|
||||
(WC_MIN_DIGEST_SIZE_FOR_VERIFY >= 128 / 8),
|
||||
"Supplied WC_MIN_DIGEST_SIZE_FOR_VERIFY is out of range.");
|
||||
#if defined(WC_FIPS_186_4_PLUS)
|
||||
wc_static_assert2(WC_MIN_DIGEST_SIZE_FOR_VERIFY >= 160 / 8,
|
||||
"FIPS 186 requires a minimum verify-mode hash size >= SHA-1.");
|
||||
#endif
|
||||
#else
|
||||
#if defined(WC_FIPS_186_4_PLUS)
|
||||
#define WC_MIN_DIGEST_SIZE_FOR_VERIFY \
|
||||
((WC_MIN_DIGEST_SIZE < 160 / 8) ? (160 / 8) : WC_MIN_DIGEST_SIZE)
|
||||
#else
|
||||
#define WC_MIN_DIGEST_SIZE_FOR_VERIFY WC_MIN_DIGEST_SIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC)
|
||||
WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type);
|
||||
WOLFSSL_API enum wc_HashType wc_OidGetHash(int oid);
|
||||
|
||||
@@ -517,15 +517,14 @@
|
||||
#define FIPS_VERSION3_NE(major,minor,patch) \
|
||||
(WOLFSSL_FIPS_VERSION_CODE != WOLFSSL_MAKE_FIPS_VERSION3(major,minor,patch))
|
||||
|
||||
#if defined(HAVE_FIPS) && !defined(WC_FIPS_186_5) && !defined(WC_FIPS_186_4)
|
||||
#if FIPS_VERSION3_GE(7,0,0) && !defined(WOLFSSL_FIPS_READY)
|
||||
#ifndef WC_FIPS_186_5
|
||||
#define WC_FIPS_186_5
|
||||
#endif
|
||||
#if (defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
|
||||
!defined(WC_FIPS_186_5) && !defined(WC_FIPS_186_4)
|
||||
#if defined(HAVE_SELFTEST)
|
||||
#define WC_FIPS_186_4
|
||||
#elif FIPS_VERSION3_GE(7,0,0) && !defined(WOLFSSL_FIPS_READY)
|
||||
#define WC_FIPS_186_5
|
||||
#else
|
||||
#ifndef WC_FIPS_186_4
|
||||
#define WC_FIPS_186_4
|
||||
#endif
|
||||
#define WC_FIPS_186_4
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WC_FIPS_186_4) && defined(WC_FIPS_186_5)
|
||||
@@ -4282,6 +4281,23 @@
|
||||
/* siphash asm produces wrong results in kernel mode. */
|
||||
#define WC_SIPHASH_NO_ASM
|
||||
#endif
|
||||
|
||||
/* The first vector set in /usr/src/linux/crypto/testmgr.h
|
||||
* ecdsa_nist_p192_tv_template[], ecdsa_nist_p256_tv_template[], and
|
||||
* ecdsa_nist_p384_tv_template[] use SHA-1 (even if CONFIG_CRYPTO_SHA1 is
|
||||
* disabled), and kernel module signatures frequently use SHA-1 until quite
|
||||
* recently. Force the minimum downward in NO_SHA builds to assure the
|
||||
* required support is present.
|
||||
*/
|
||||
#if defined(NO_SHA) && !defined(WC_MIN_DIGEST_SIZE_FOR_VERIFY) && \
|
||||
defined(HAVE_ECC) && \
|
||||
(defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
|
||||
defined(LINUXKM_LKCAPI_REGISTER_ECDSA) || \
|
||||
(defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && \
|
||||
defined(CONFIG_CRYPTO_ECDSA)))
|
||||
#define WC_MIN_DIGEST_SIZE_FOR_VERIFY 20
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_LINUXKM */
|
||||
|
||||
/* FreeBSD Kernel Module */
|
||||
|
||||
@@ -2332,14 +2332,14 @@ WOLFSSL_API word32 CheckRunTimeSettings(void);
|
||||
|
||||
/* DISABLE_VECTOR_REGISTERS() and REENABLE_VECTOR_REGISTERS() are currently only
|
||||
* used by Linux kernel code. If WC_HAVE_VECTOR_SPEEDUPS, we default
|
||||
* DISABLE_VECTOR_REGISTERS() to -1, to assure calling code is forced to handle
|
||||
* the failure. But if the build disables vec regs globally, we can return 0
|
||||
* harmlessly. The kernel build defines real calls for these in vectorized
|
||||
* builds, otherwise it uses these fallbacks.
|
||||
* DISABLE_VECTOR_REGISTERS() to NOT_COMPILED_IN, to assure calling code is
|
||||
* forced to handle the failure. But if the build disables vec regs globally,
|
||||
* we can return 0 harmlessly. The kernel build defines real calls for these in
|
||||
* vectorized builds, otherwise it uses these fallbacks.
|
||||
*/
|
||||
#ifndef DISABLE_VECTOR_REGISTERS
|
||||
#ifdef WC_HAVE_VECTOR_SPEEDUPS
|
||||
#define DISABLE_VECTOR_REGISTERS() (-1)
|
||||
#define DISABLE_VECTOR_REGISTERS() NOT_COMPILED_IN
|
||||
#else
|
||||
#define DISABLE_VECTOR_REGISTERS() 0
|
||||
#endif
|
||||
|
||||
@@ -146,8 +146,11 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FIPS) || defined(HAVE_SELFTEST)
|
||||
#if (defined(HAVE_FIPS) && FIPS_VERSION3_LT(7,0,0)) || defined(HAVE_SELFTEST)
|
||||
#define INLINE WC_INLINE
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define __FUNCTION__ __func__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WC_NO_INLINE
|
||||
@@ -811,6 +814,25 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref;
|
||||
*(new_count) = wolfSSL_Atomic_Int_AddFetch(&(ref)->count, 1); \
|
||||
*(err) = 0; \
|
||||
} while(0)
|
||||
#define wolfSSL_RefInc_IfAtLeast(ref, cur_at_least, new_count, err) \
|
||||
do { \
|
||||
WC_ATOMIC_INT_ARG _expected_count = \
|
||||
WOLFSSL_ATOMIC_LOAD((ref)->count); \
|
||||
while (_expected_count >= (cur_at_least)) { \
|
||||
*(new_count) = _expected_count + 1; \
|
||||
if (wolfSSL_Atomic_Int_CompareExchange( \
|
||||
&(ref)->count, \
|
||||
&_expected_count, \
|
||||
*(new_count))) \
|
||||
break; \
|
||||
} \
|
||||
if (_expected_count < (cur_at_least)) { \
|
||||
*(new_count) = _expected_count; \
|
||||
*(err) = BAD_STATE_E; \
|
||||
} \
|
||||
else \
|
||||
*(err) = 0; \
|
||||
} while(0)
|
||||
#define wolfSSL_RefDec(ref, isZero, err) \
|
||||
do { \
|
||||
int __prev = wolfSSL_Atomic_Int_FetchSub(&(ref)->count, 1); \
|
||||
@@ -823,6 +845,25 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref;
|
||||
*(new_count) = wolfSSL_Atomic_Int_SubFetch(&(ref)->count, 1); \
|
||||
*(err) = 0; \
|
||||
} while(0)
|
||||
#define wolfSSL_RefDec_IfEquals(ref, current_count, new_count, err) \
|
||||
do { \
|
||||
WC_ATOMIC_INT_ARG _expected_count = \
|
||||
WOLFSSL_ATOMIC_LOAD((ref)->count); \
|
||||
while (_expected_count == (current_count)) {\
|
||||
*(new_count) = _expected_count - 1; \
|
||||
if (wolfSSL_Atomic_Int_CompareExchange( \
|
||||
&(ref)->count, \
|
||||
&_expected_count, \
|
||||
*(new_count))) \
|
||||
break; \
|
||||
} \
|
||||
if (_expected_count != (current_count)) { \
|
||||
*(new_count) = _expected_count; \
|
||||
*(err) = BAD_STATE_E; \
|
||||
} \
|
||||
else \
|
||||
*(err) = 0; \
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
|
||||
@@ -832,8 +873,10 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref;
|
||||
#define wolfSSL_RefFree wolfSSL_RefWithMutexFree
|
||||
#define wolfSSL_RefInc wolfSSL_RefWithMutexInc
|
||||
#define wolfSSL_RefInc2 wolfSSL_RefWithMutexInc2
|
||||
#define wolfSSL_RefInc_IfAtLeast wolfSSL_RefWithMutexInc_IfAtLeast
|
||||
#define wolfSSL_RefDec wolfSSL_RefWithMutexDec
|
||||
#define wolfSSL_RefDec2 wolfSSL_RefWithMutexDec2
|
||||
#define wolfSSL_RefDec_IfEquals wolfSSL_RefWithMutexDec_IfEquals
|
||||
|
||||
#endif
|
||||
|
||||
@@ -843,10 +886,12 @@ typedef struct wolfSSL_RefWithMutex wolfSSL_Ref;
|
||||
#define wolfSSL_RefWithMutexFree wolfSSL_RefFree
|
||||
#define wolfSSL_RefWithMutexInc wolfSSL_RefInc
|
||||
#define wolfSSL_RefWithMutexInc2 wolfSSL_RefInc2
|
||||
#define wolfSSL_RefWithMutexInc_IfAtLeast wolfSSL_RefInc_IfAtLeast
|
||||
#define wolfSSL_RefWithMutexLock(ref) 0
|
||||
#define wolfSSL_RefWithMutexUnlock(ref) 0
|
||||
#define wolfSSL_RefWithMutexDec wolfSSL_RefDec
|
||||
#define wolfSSL_RefWithMutexDec2 wolfSSL_RefDec2
|
||||
#define wolfSSL_RefWithMutexDec_IfEquals wolfSSL_RefDec_IfEquals
|
||||
|
||||
#else
|
||||
|
||||
@@ -858,12 +903,19 @@ WOLFSSL_LOCAL void wolfSSL_RefWithMutexInc(wolfSSL_RefWithMutex* ref,
|
||||
WOLFSSL_LOCAL void wolfSSL_RefWithMutexInc2(wolfSSL_RefWithMutex* ref,
|
||||
int *new_count,
|
||||
int* err);
|
||||
WOLFSSL_LOCAL void wolfSSL_RefWithMutexInc_IfAtLeast(wolfSSL_RefWithMutex* ref,
|
||||
int cur_at_least,
|
||||
int *new_count,
|
||||
int* err);
|
||||
WOLFSSL_LOCAL int wolfSSL_RefWithMutexLock(wolfSSL_RefWithMutex* ref);
|
||||
WOLFSSL_LOCAL int wolfSSL_RefWithMutexUnlock(wolfSSL_RefWithMutex* ref);
|
||||
WOLFSSL_LOCAL void wolfSSL_RefWithMutexDec(wolfSSL_RefWithMutex* ref,
|
||||
int* isZero, int* err);
|
||||
WOLFSSL_LOCAL void wolfSSL_RefWithMutexDec2(wolfSSL_RefWithMutex* ref,
|
||||
int* new_count, int* err);
|
||||
WOLFSSL_LOCAL void wolfSSL_RefWithMutexDec_IfEquals(wolfSSL_RefWithMutex* ref,
|
||||
int current_count,
|
||||
int* new_count, int* err);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user