Merge pull request #10856 from douzzer/20260702-linuxkm-various

20260702-linuxkm-various
This commit is contained in:
philljj
2026-07-07 17:44:50 -05:00
committed by GitHub
26 changed files with 1090 additions and 261 deletions
+1
View File
@@ -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
View File
@@ -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))
+10 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
+4
View File
@@ -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
-1
View File
@@ -32,7 +32,6 @@
#endif
#ifndef NO_CRYPT_TEST
#include <wolfcrypt/test/test.h>
#include <linux/delay.h>
#endif
#ifndef EXPORT_SYMBOL_NS
-4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+8
View File
@@ -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()) {
+16
View File
@@ -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
+7
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}
-4
View File
@@ -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
View File
@@ -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;
+45
View File
@@ -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
View File
@@ -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 */
+64 -9
View File
@@ -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);
+24 -8
View File
@@ -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 */
+5 -5
View File
@@ -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
+53 -1
View File
@@ -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