Merge tag 'v7.3-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

Pull crypto update from Herbert Xu:
 "API:
   - Add af_alg_restrict sysctl and white list
   - Fix potential suspend/resume races in hwrng

  Algorithms:
   - Optimize vli additive operations using compiler builtins in ecc

  Drivers:
   - Remove unsafe/deprecated algorithms from qce
   - Mark qce as BROKEN
   - Add runtime PM and interconnect bandwidth scaling support to qce
   - Remove crypto_rng from qcom, sun8i and caam
   - Fix SG list issues in iaa
   - Fix SEV init path bugs in ccp"

* tag 'v7.3-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (122 commits)
  crypto: lskcipher - propagate errors from unaligned crypt
  crypto: keembay - use crypto_memneq() to compare CCM AEAD tags
  crypto: keembay - use crypto_memneq() to compare GCM AEAD tags
  crypto: sa2ul - use crypto_memneq() to compare AEAD tag
  hwrng: drivers - use named initializers for acpi_device_id
  crypto: qce - fix CCM AAD buffer underallocation
  crypto: iaa - unmap dst before software fallback on decompress
  crypto: iaa - use bounce buffer for multi-sg decompress input
  crypto: iaa - avoid counting fallback decompression bytes
  crypto: iaa - fall back to software for multi-entry scatterlists
  hwrng: core - Stop/start hwrng_fillfn() kthread before/after suspend-resume
  crypto: hisilicon/sec2 - fix CCM algorithm long packet failure
  crypto: eip93 - use struct_size() and flexible array for ring allocation
  crypto: krb5 - use kfree_sensitive() for derived key buffers
  crypto: af_alg - Stop after finding name in allowlist
  crypto: af_alg - Replace 'bool privileged' with flags
  crypto: af_alg - Make cbc(paes) privileged-only
  hwrng: imx-rngc - Disable clock on registration failure
  crypto: qat - remove dead ADF_HEX code
  crypto: qce - simplify qce_handle_request
  ...
This commit is contained in:
Linus Torvalds
2026-08-19 17:25:42 -07:00
135 changed files with 1405 additions and 2019 deletions

View File

@@ -0,0 +1,19 @@
What: /sys/firmware/sev/vulnerabilities/supported_mitigations
Date: June 2026
Contact: linux-crypto@vger.kernel.org
Description:
Read-only interface that reports the vector of SEV-SNP
firmware vulnerability mitigations supported by the firmware.
What: /sys/firmware/sev/vulnerabilities/verified_mitigations
Date: June 2026
Contact: linux-crypto@vger.kernel.org
Description:
Read/write interface that reports the vector of SEV-SNP
firmware vulnerability mitigations already verified by the
firmware. Writing a vector value requests the firmware to
VERIFY the corresponding mitigation bit(s).
The list of supported mitigations and the meaning of each
vector bit are both platform- and bug-specific and are
published as part of the AMD Security Bulletin.

View File

@@ -7,6 +7,42 @@ kernel configuration:
.. contents:: :local:
.. _af_alg_restrict:
af_alg_restrict
===============
Controls the level of restriction of AF_ALG.
AF_ALG is a deprecated and rarely-used userspace interface that is a
frequent source of vulnerabilities. It also unnecessarily exposes a
large number of kernel implementation details. For more information
about AF_ALG, see :ref:`Documentation/crypto/userspace-if.rst
<crypto_userspace_interface>`.
Starting in Linux v7.3, AF_ALG supports only a limited set of
algorithms by default. This sysctl allows the system administrator to
remove this restriction when needed for compatibility reasons, or to
go further and disable AF_ALG entirely. The default value is 1.
=== ==================================================================
0 AF_ALG is unrestricted.
1 AF_ALG is supported with a limited list of algorithms. The list
is designed for compatibility with known users such as iwd and
bluez that haven't yet been fixed to use userspace crypto code.
Specifically, there is an allowlist for unprivileged processes
and a somewhat longer allowlist for processes that hold
CAP_SYS_ADMIN or CAP_NET_ADMIN in the initial user namespace.
Attempts to bind() an AF_ALG socket with a disallowed algorithm
fail with ENOENT.
2 AF_ALG is completely disabled. Attempts to create an AF_ALG
socket fail with EAFNOSUPPORT.
=== ==================================================================
fips_enabled
============

View File

@@ -95,7 +95,7 @@ additional templates may enclose other templates, such as
::
template1(template2(single block cipher)))
template1(template2(single block cipher))
The kernel crypto API may provide multiple implementations of a template

View File

@@ -1,3 +1,5 @@
.. _crypto_userspace_interface:
User Space Interface
====================
@@ -12,9 +14,14 @@ AF_ALG is insecure and is deprecated. Originally added to the kernel in 2010,
most kernel developers now consider it to be a mistake. Support for hardware
accelerators, which was the original purpose of AF_ALG, has been removed.
AF_ALG continues to be supported only for backwards compatibility. On systems
where no programs using AF_ALG remain, the support for it should be disabled by
disabling ``CONFIG_CRYPTO_USER_API_*``.
AF_ALG continues to be supported only for backwards compatibility.
Starting in Linux v7.3, the set of algorithms supported by AF_ALG is limited by
default. See :ref:`/proc/sys/crypto/af_alg_restrict <af_alg_restrict>`.
On systems where no programs using AF_ALG remain, the support for it should be
disabled entirely by setting ``/proc/sys/crypto/af_alg_restrict`` to 2 or by
disabling ``CONFIG_CRYPTO_USER_API_*`` in the kernel configuration.
Deprecation
-----------

View File

@@ -16,15 +16,19 @@ properties:
- qcom,eliza-inline-crypto-engine
- qcom,hawi-inline-crypto-engine
- qcom,kaanapali-inline-crypto-engine
- qcom,maili-inline-crypto-engine
- qcom,milos-inline-crypto-engine
- qcom,nord-inline-crypto-engine
- qcom,qcs8300-inline-crypto-engine
- qcom,sa8775p-inline-crypto-engine
- qcom,sc7180-inline-crypto-engine
- qcom,sc7280-inline-crypto-engine
- qcom,shikra-inline-crypto-engine
- qcom,sm8450-inline-crypto-engine
- qcom,sm8550-inline-crypto-engine
- qcom,sm8650-inline-crypto-engine
- qcom,sm8750-inline-crypto-engine
- qcom,x1e80100-inline-crypto-engine
- const: qcom,inline-crypto-engine
reg:
@@ -55,14 +59,25 @@ required:
additionalProperties: false
# Do not extend the list.
# Legacy SoCs are allowed for single clock.
# New SoCs must provide both clocks and power domains.
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,eliza-inline-crypto-engine
- qcom,milos-inline-crypto-engine
not:
properties:
compatible:
contains:
enum:
- qcom,kaanapali-inline-crypto-engine
- qcom,qcs8300-inline-crypto-engine
- qcom,sa8775p-inline-crypto-engine
- qcom,sc7180-inline-crypto-engine
- qcom,sc7280-inline-crypto-engine
- qcom,sm8450-inline-crypto-engine
- qcom,sm8550-inline-crypto-engine
- qcom,sm8650-inline-crypto-engine
- qcom,sm8750-inline-crypto-engine
then:
required:

View File

@@ -23,6 +23,7 @@ properties:
- qcom,ipq5424-trng
- qcom,ipq9574-trng
- qcom,kaanapali-trng
- qcom,maili-trng
- qcom,milos-trng
- qcom,nord-trng
- qcom,qcs615-trng
@@ -30,6 +31,7 @@ properties:
- qcom,sa8255p-trng
- qcom,sa8775p-trng
- qcom,sc7280-trng
- qcom,shikra-trng
- qcom,sm8450-trng
- qcom,sm8550-trng
- qcom,sm8650-trng

View File

@@ -54,6 +54,7 @@ properties:
- qcom,qcs8300-qce
- qcom,sa8775p-qce
- qcom,sc7280-qce
- qcom,shikra-qce
- qcom,sm6350-qce
- qcom,sm8250-qce
- qcom,sm8350-qce

View File

@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/rng/inside-secure,safexcel-eip76.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Inside-Secure HWRNG Module
title: Inside-Secure SafeXcel EIP-76 HWRNG Module
maintainers:
- Jayesh Choudhary <j-choudhary@ti.com>

View File

@@ -11848,7 +11848,7 @@ W: http://www.hisilicon.com
F: drivers/spi/spi-hisi-sfc-v3xx.c
HISILICON ZIP Controller DRIVER
M: Yang Shen <shenyang39@huawei.com>
M: Chenghai Huang<huangchenghai2@huawei.com>
M: Zhou Wang <wangzhou1@hisilicon.com>
L: linux-crypto@vger.kernel.org
S: Maintained

View File

@@ -407,6 +407,7 @@ CONFIG_ASPEED_KCS_IPMI_BMC=m
CONFIG_ASPEED_BT_IPMI_BMC=m
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_ST=y
CONFIG_HW_RANDOM_QCOM=m
CONFIG_TCG_TPM=m
CONFIG_TCG_TIS_I2C_INFINEON=m
CONFIG_I2C_CHARDEV=y
@@ -1322,8 +1323,6 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=m
CONFIG_CRYPTO_DEV_ATMEL_TDES=m
CONFIG_CRYPTO_DEV_ATMEL_SHA=m
CONFIG_CRYPTO_DEV_MARVELL_CESA=m
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCOM_RNG=m
CONFIG_CRYPTO_DEV_ROCKCHIP=m
CONFIG_CRYPTO_DEV_STM32_HASH=m
CONFIG_CRYPTO_DEV_STM32_CRYP=m

View File

@@ -117,6 +117,7 @@ CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_QCOM=m
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
@@ -296,7 +297,6 @@ CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_DEV_QCOM_RNG=m
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=64
CONFIG_PRINTK_TIME=y

View File

@@ -603,6 +603,7 @@ CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_HW_RANDOM_HISI_TRNG=m
CONFIG_HW_RANDOM_XILINX=m
CONFIG_HW_RANDOM_QCOM=m
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS=m
CONFIG_TCG_TIS_SPI=m
@@ -1948,8 +1949,6 @@ CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_DEV_SUN8I_CE=m
CONFIG_CRYPTO_DEV_FSL_CAAM=m
CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCOM_RNG=m
CONFIG_CRYPTO_DEV_TEGRA=m
CONFIG_CRYPTO_DEV_ZYNQMP_AES=m
CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=m

View File

@@ -72,7 +72,7 @@ static int p8_aes_cbc_setkey(struct crypto_skcipher *tfm, const u8 *key,
return ret ? -EINVAL : 0;
}
static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc)
static int p8_aes_cbc_crypt(struct skcipher_request *req, bool enc)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
const struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
@@ -110,12 +110,12 @@ static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc)
static int p8_aes_cbc_encrypt(struct skcipher_request *req)
{
return p8_aes_cbc_crypt(req, 1);
return p8_aes_cbc_crypt(req, true);
}
static int p8_aes_cbc_decrypt(struct skcipher_request *req)
{
return p8_aes_cbc_crypt(req, 0);
return p8_aes_cbc_crypt(req, false);
}
struct skcipher_alg p8_aes_cbc_alg = {

View File

@@ -8,6 +8,7 @@
*/
#include <linux/atomic.h>
#include <linux/capability.h>
#include <crypto/if_alg.h>
#include <linux/crypto.h>
#include <linux/init.h>
@@ -22,10 +23,28 @@
#include <linux/sched/signal.h>
#include <linux/security.h>
#include <linux/string.h>
#include <linux/sysctl.h>
#include <linux/user_namespace.h>
#include <keys/user-type.h>
#include <keys/trusted-type.h>
#include <keys/encrypted-type.h>
static int af_alg_restrict = 1;
static const struct ctl_table af_alg_table[] = {
{
.procname = "af_alg_restrict",
.data = &af_alg_restrict,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_TWO,
},
};
static struct ctl_table_header *af_alg_header;
struct alg_type_list {
const struct af_alg_type *type;
struct list_head list;
@@ -110,6 +129,43 @@ int af_alg_unregister_type(const struct af_alg_type *type)
}
EXPORT_SYMBOL_GPL(af_alg_unregister_type);
static bool af_alg_capable(void)
{
return ns_capable_noaudit(&init_user_ns, CAP_NET_ADMIN) ||
capable(CAP_SYS_ADMIN);
}
int af_alg_check_restriction(const char *name,
const struct af_alg_allowlist_entry allowlist[])
{
int level = READ_ONCE(af_alg_restrict);
if (level == 0)
return 0;
if (level == 1) {
for (const struct af_alg_allowlist_entry *ent = allowlist;
ent->name; ent++) {
if (strcmp(name, ent->name) == 0) {
if ((ent->flags & AF_ALG_UNPRIVILEGED) ||
af_alg_capable())
return 0;
/* List contains at most one entry per name. */
break;
}
}
}
/*
* Use -ENOENT (the error code for "algorithm not found") instead of
* -EACCES or -EPERM, for the highest chance of correctly triggering
* fallback code paths in userspace programs.
*
* Don't log a warning, since it would be noisy. iwd tries to bind a
* bunch of algorithms that it never uses.
*/
return -ENOENT;
}
EXPORT_SYMBOL_GPL(af_alg_check_restriction);
static void alg_do_release(const struct af_alg_type *type, void *private)
{
if (!type)
@@ -506,6 +562,9 @@ static int alg_create(struct net *net, struct socket *sock, int protocol,
struct sock *sk;
int err;
if (READ_ONCE(af_alg_restrict) == 2)
return -EAFNOSUPPORT;
if (sock->type != SOCK_SEQPACKET)
return -ESOCKTNOSUPPORT;
if (protocol != 0)
@@ -1222,27 +1281,32 @@ EXPORT_SYMBOL_GPL(af_alg_get_rsgl);
static int __init af_alg_init(void)
{
int err = proto_register(&alg_proto, 0);
int err;
af_alg_header = register_sysctl("crypto", af_alg_table);
err = proto_register(&alg_proto, 0);
if (err)
goto out;
goto out_unregister_sysctl;
err = sock_register(&alg_family);
if (err != 0)
if (err)
goto out_unregister_proto;
out:
return err;
return 0;
out_unregister_proto:
proto_unregister(&alg_proto);
goto out;
out_unregister_sysctl:
unregister_sysctl_table(af_alg_header);
return err;
}
static void __exit af_alg_exit(void)
{
sock_unregister(PF_ALG);
proto_unregister(&alg_proto);
unregister_sysctl_table(af_alg_header);
}
module_init(af_alg_init);

View File

@@ -34,6 +34,11 @@
#include <linux/net.h>
#include <net/sock.h>
static const struct af_alg_allowlist_entry aead_allowlist[] = {
{ "ccm(aes)" }, /* bluez */
{},
};
static inline bool aead_sufficient_data(struct sock *sk)
{
struct alg_sock *ask = alg_sk(sk);
@@ -344,6 +349,12 @@ static struct proto_ops algif_aead_ops_nokey = {
static void *aead_bind(const char *name)
{
int err;
err = af_alg_check_restriction(name, aead_allowlist);
if (err)
return ERR_PTR(err);
return crypto_alloc_aead(name, 0, AF_ALG_CRYPTOAPI_MASK);
}

View File

@@ -16,6 +16,24 @@
#include <linux/net.h>
#include <net/sock.h>
static const struct af_alg_allowlist_entry hash_allowlist[] = {
{ "cmac(aes)" }, /* iwd, bluez */
{ "hmac(md5)" }, /* iwd */
{ "hmac(sha1)" }, /* iwd */
{ "hmac(sha224)" }, /* iwd */
{ "hmac(sha256)" }, /* iwd */
{ "hmac(sha384)" }, /* iwd */
{ "hmac(sha512)" }, /* iwd, sha512hmac */
{ "md4" }, /* iwd */
{ "md5" }, /* iwd */
{ "sha1", AF_ALG_UNPRIVILEGED }, /* iwd, iproute2 < 7.0 */
{ "sha224" }, /* iwd */
{ "sha256" }, /* iwd */
{ "sha384" }, /* iwd */
{ "sha512" }, /* iwd */
{},
};
struct hash_ctx {
struct af_alg_sgl sgl;
@@ -382,6 +400,12 @@ static struct proto_ops algif_hash_ops_nokey = {
static void *hash_bind(const char *name)
{
int err;
err = af_alg_check_restriction(name, hash_allowlist);
if (err)
return ERR_PTR(err);
return crypto_alloc_ahash(name, 0, AF_ALG_CRYPTOAPI_MASK);
}

View File

@@ -50,6 +50,10 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
MODULE_DESCRIPTION("User-space interface for random number generators");
static const struct af_alg_allowlist_entry rng_allowlist[] = {
{},
};
struct rng_ctx {
#define MAXSIZE 128
unsigned int len;
@@ -201,6 +205,11 @@ static void *rng_bind(const char *name)
{
struct rng_parent_ctx *pctx;
struct crypto_rng *rng;
int err;
err = af_alg_check_restriction(name, rng_allowlist);
if (err)
return ERR_PTR(err);
pctx = kzalloc_obj(*pctx);
if (!pctx)

View File

@@ -35,6 +35,24 @@
#include <linux/string.h>
#include <net/sock.h>
static const struct af_alg_allowlist_entry skcipher_allowlist[] = {
{ "adiantum(xchacha12,aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "adiantum(xchacha20,aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "cbc(aes)" }, /* iwd */
{ "cbc(des)" }, /* iwd */
{ "cbc(des3_ede)" }, /* iwd */
{ "cbc(paes)" }, /* caam and others */
{ "ctr(aes)" }, /* iwd */
{ "ecb(aes)" }, /* iwd, bluez */
{ "ecb(des)" }, /* iwd */
{ "hctr2(aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "xts(aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup benchmark */
{ "xts(camellia)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "xts(serpent)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "xts(twofish)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{},
};
static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
size_t size)
{
@@ -311,6 +329,11 @@ static struct proto_ops algif_skcipher_ops_nokey = {
static void *skcipher_bind(const char *name)
{
u32 mask = AF_ALG_CRYPTOAPI_MASK;
int err;
err = af_alg_check_restriction(name, skcipher_allowlist);
if (err)
return ERR_PTR(err);
if (strcmp(name, "cbc(paes)") == 0)
mask = 0;

View File

@@ -116,7 +116,7 @@ struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
larval->alg.cra_priority = -1;
larval->alg.cra_destroy = crypto_larval_destroy;
strscpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME);
strscpy(larval->alg.cra_name, name);
init_completion(&larval->completion);
return larval;

View File

@@ -11,6 +11,7 @@
#include <linux/cryptouser.h>
#include <linux/sched.h>
#include <linux/security.h>
#include <linux/string.h>
#include <net/netlink.h>
#include <net/net_namespace.h>
#include <net/sock.h>
@@ -87,11 +88,9 @@ static int crypto_report_one(struct crypto_alg *alg,
{
memset(ualg, 0, sizeof(*ualg));
strscpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
strscpy(ualg->cru_driver_name, alg->cra_driver_name,
sizeof(ualg->cru_driver_name));
strscpy(ualg->cru_module_name, module_name(alg->cra_module),
sizeof(ualg->cru_module_name));
strscpy(ualg->cru_name, alg->cra_name);
strscpy(ualg->cru_driver_name, alg->cra_driver_name);
strscpy(ualg->cru_module_name, module_name(alg->cra_module));
ualg->cru_type = 0;
ualg->cru_mask = 0;

View File

@@ -279,6 +279,48 @@ static void vli_rshift1(u64 *vli, unsigned int ndigits)
}
}
#ifdef __has_builtin
#if __has_builtin(__builtin_addcll)
#define USE_BUILTIN_ADDC
#endif
#endif
/* Computes result = left + right + carry_in and updates carry_out */
static inline void add_carry(u64 left, u64 right, u64 *result, u64 carry_in,
u64 *carry_out)
{
#ifdef USE_BUILTIN_ADDC
*result = __builtin_addcll(left, right, carry_in, carry_out);
#else
u64 sum1, sum2;
u64 c1 = __builtin_uaddll_overflow(left, right, &sum1);
u64 c2 = __builtin_uaddll_overflow(sum1, carry_in, &sum2);
*result = sum2;
*carry_out = c1 | c2;
#endif
}
#ifdef __has_builtin
#if __has_builtin(__builtin_subcll)
#define USE_BUILTIN_SUBC
#endif
#endif
/* Computes result = left - right - borrow_in and updates borrow_out */
static inline void sub_borrow(u64 left, u64 right, u64 *result, u64 borrow_in,
u64 *borrow_out)
{
#ifdef USE_BUILTIN_SUBC
*result = __builtin_subcll(left, right, borrow_in, borrow_out);
#else
u64 diff1, diff2;
u64 b1 = __builtin_usubll_overflow(left, right, &diff1);
u64 b2 = __builtin_usubll_overflow(diff1, borrow_in, &diff2);
*result = diff2;
*borrow_out = b1 | b2;
#endif
}
/* Computes result = left + right, returning carry. Can modify in place. */
static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
unsigned int ndigits)
@@ -286,15 +328,8 @@ static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
u64 carry = 0;
int i;
for (i = 0; i < ndigits; i++) {
u64 sum;
sum = left[i] + right[i] + carry;
if (sum != left[i])
carry = (sum < left[i]);
result[i] = sum;
}
for (i = 0; i < ndigits; i++)
add_carry(left[i], right[i], &result[i], carry, &carry);
return carry;
}
@@ -303,40 +338,29 @@ static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
static u64 vli_uadd(u64 *result, const u64 *left, u64 right,
unsigned int ndigits)
{
u64 carry = right;
u64 carry;
int i;
for (i = 0; i < ndigits; i++) {
u64 sum;
if (ndigits == 0)
return right;
sum = left[i] + carry;
if (sum != left[i])
carry = (sum < left[i]);
else
carry = !!carry;
carry = __builtin_uaddll_overflow(left[0], right, &result[0]);
result[i] = sum;
}
for (i = 1; i < ndigits; i++)
carry = __builtin_uaddll_overflow(left[i], carry, &result[i]);
return carry;
}
/* Computes result = left - right, returning borrow. Can modify in place. */
u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
unsigned int ndigits)
unsigned int ndigits)
{
u64 borrow = 0;
int i;
for (i = 0; i < ndigits; i++) {
u64 diff;
diff = left[i] - right[i] - borrow;
if (diff != left[i])
borrow = (diff > left[i]);
result[i] = diff;
}
for (i = 0; i < ndigits; i++)
sub_borrow(left[i], right[i], &result[i], borrow, &borrow);
return borrow;
}
@@ -344,20 +368,18 @@ EXPORT_SYMBOL(vli_sub);
/* Computes result = left - right, returning borrow. Can modify in place. */
static u64 vli_usub(u64 *result, const u64 *left, u64 right,
unsigned int ndigits)
unsigned int ndigits)
{
u64 borrow = right;
u64 borrow;
int i;
for (i = 0; i < ndigits; i++) {
u64 diff;
if (ndigits == 0)
return right;
diff = left[i] - borrow;
if (diff != left[i])
borrow = (diff > left[i]);
borrow = __builtin_usubll_overflow(left[0], right, &result[0]);
result[i] = diff;
}
for (i = 1; i < ndigits; i++)
borrow = __builtin_usubll_overflow(left[i], borrow, &result[i]);
return borrow;
}

View File

@@ -354,8 +354,7 @@ static int hctr2_create_common(struct crypto_template *tmpl, struct rtattr **tb,
err = -EINVAL;
if (strncmp(xctr_alg->base.cra_name, "xctr(", 5))
goto err_free_inst;
len = strscpy(blockcipher_name, xctr_alg->base.cra_name + 5,
sizeof(blockcipher_name));
len = strscpy(blockcipher_name, xctr_alg->base.cra_name + 5);
if (len < 1)
goto err_free_inst;
if (blockcipher_name[len - 1] != ')')

View File

@@ -263,10 +263,10 @@ struct crypto_aead *crypto_krb5_prepare_encryption(const struct krb5_enctype *kr
goto err;
}
kfree(keys.data);
kfree_sensitive(keys.data);
return ci;
err:
kfree(keys.data);
kfree_sensitive(keys.data);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(crypto_krb5_prepare_encryption);
@@ -333,10 +333,10 @@ struct crypto_shash *crypto_krb5_prepare_checksum(const struct krb5_enctype *krb
goto err;
}
kfree(keys.data);
kfree_sensitive(keys.data);
return ci;
err:
kfree(keys.data);
kfree_sensitive(keys.data);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(crypto_krb5_prepare_checksum);

View File

@@ -359,7 +359,7 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
if (!memcmp(cipher_name, "ecb(", 4)) {
int len;
len = strscpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
len = strscpy(ecb_name, cipher_name + 4);
if (len < 2)
goto err_free_inst;

View File

@@ -95,7 +95,6 @@ static int crypto_lskcipher_crypt_unaligned(
while (len >= bs) {
unsigned chunk = min((unsigned)PAGE_SIZE, len);
int err;
if (chunk > cs)
chunk &= ~(cs - 1);
@@ -528,8 +527,7 @@ struct lskcipher_instance *lskcipher_alloc_instance_simple(
int len;
err = -EINVAL;
len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4],
sizeof(ecb_name));
len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4]);
if (len < 2)
goto err_free_inst;

View File

@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <crypto/xts.h>
#include <crypto/b128ops.h>
@@ -400,7 +401,7 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
if (!memcmp(cipher_name, "ecb(", 4)) {
int len;
len = strscpy(name, cipher_name + 4, sizeof(name));
len = strscpy(name, cipher_name + 4);
if (len < 2)
goto err_free_inst;

View File

@@ -193,7 +193,7 @@ config HW_RANDOM_IXP4XX
config HW_RANDOM_OMAP
tristate "OMAP Random Number Generator support"
depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU || ARCH_K3 || COMPILE_TEST
depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU || ARCH_K3 || ARCH_RZN1 || COMPILE_TEST
default HW_RANDOM
help
This driver provides kernel-side support for the Random Number
@@ -636,6 +636,17 @@ config HW_RANDOM_XILINX
To compile this driver as a module, choose M here: the module
will be called xilinx-trng.
config HW_RANDOM_QCOM
tristate "Qualcomm True Random Number Generator Driver"
depends on ARCH_QCOM || COMPILE_TEST
depends on HW_RANDOM
help
This driver provides support for the True Random Number
Generator hardware found on some Qualcomm SoCs.
To compile this driver as a module, choose M here. The
module will be called qcom-rng. If unsure, say N.
endif # HW_RANDOM
config UML_RANDOM

View File

@@ -54,3 +54,4 @@ obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o
obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o
obj-$(CONFIG_HW_RANDOM_JH7110) += jh7110-trng.o
obj-$(CONFIG_HW_RANDOM_XILINX) += xilinx-trng.o
obj-$(CONFIG_HW_RANDOM_QCOM) += qcom-rng.o

View File

@@ -186,10 +186,8 @@ static int airoha_trng_probe(struct platform_device *pdev)
airoha_trng_irq_mask(trng);
ret = devm_request_irq(&pdev->dev, irq, airoha_trng_irq, 0,
pdev->name, (void *)trng);
if (ret) {
dev_err(dev, "Can't get interrupt working.\n");
if (ret)
return ret;
}
init_completion(&trng->rng_op_done);

View File

@@ -185,7 +185,7 @@ static int __maybe_unused atmel_trng_runtime_resume(struct device *dev)
return atmel_trng_init(trng);
}
static const struct dev_pm_ops __maybe_unused atmel_trng_pm_ops = {
static const struct dev_pm_ops atmel_trng_pm_ops = {
SET_RUNTIME_PM_OPS(atmel_trng_runtime_suspend,
atmel_trng_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,

View File

@@ -509,7 +509,7 @@ static int cctrng_probe(struct platform_device *pdev)
/* register the driver isr function */
rc = devm_request_irq(dev, irq, cc_isr, IRQF_SHARED, "cctrng", drvdata);
if (rc)
return dev_err_probe(dev, rc, "Could not register to interrupt %d\n", irq);
return rc;
dev_dbg(dev, "Registered to IRQ: %d\n", irq);
/* Clear all pending interrupts */

View File

@@ -17,14 +17,17 @@
#include <linux/hw_random.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/lockdep.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/random.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/suspend.h>
#include <linux/sysfs.h>
#include <linux/uaccess.h>
#include <linux/workqueue.h>
@@ -45,6 +48,8 @@ static DEFINE_MUTEX(rng_mutex);
static DEFINE_MUTEX(reading_mutex);
static int data_avail;
static u8 *rng_buffer, *rng_fillbuf;
/* Set to true during suspend-resume by PM notifier, protected by rng_mutex */
static bool hwrng_fillfn_stopped;
static unsigned short current_quality;
static unsigned short default_quality = 1024; /* default to maximum */
@@ -57,6 +62,8 @@ MODULE_PARM_DESC(default_quality,
static int hwrng_init(struct hwrng *rng);
static int hwrng_fillfn(void *unused);
static void hwrng_start_hwrng_fillfn(void);
static void hwrng_stop_hwrng_fillfn(void);
static size_t rng_buffer_size(void)
{
@@ -114,13 +121,7 @@ static int set_current_rng(struct hwrng *rng)
}
/* if necessary, start hwrng thread */
if (!hwrng_fill) {
hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
if (IS_ERR(hwrng_fill)) {
pr_err("hwrng_fill thread creation failed\n");
hwrng_fill = NULL;
}
}
hwrng_start_hwrng_fillfn();
return 0;
}
@@ -137,10 +138,7 @@ static void drop_current_rng(void)
RCU_INIT_POINTER(current_rng, NULL);
synchronize_rcu();
if (hwrng_fill) {
kthread_stop(hwrng_fill);
hwrng_fill = NULL;
}
hwrng_stop_hwrng_fillfn();
/* decrease last reference for triggering the cleanup */
kref_put(&rng->ref, cleanup_rng);
@@ -506,6 +504,36 @@ static struct attribute *rng_dev_attrs[] = {
ATTRIBUTE_GROUPS(rng_dev);
static void hwrng_start_hwrng_fillfn(void)
{
lockdep_assert_held(&rng_mutex);
/*
* PM notifier stopped the hwrng_fillfn kthread, prevent userspace to
* restart it until kernel freezes threads.
*/
if (hwrng_fillfn_stopped)
return;
if (!hwrng_fill) {
hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
if (IS_ERR(hwrng_fill)) {
pr_err("hwrng_fill thread creation failed\n");
hwrng_fill = NULL;
}
}
}
static void hwrng_stop_hwrng_fillfn(void)
{
lockdep_assert_held(&rng_mutex);
if (hwrng_fill) {
kthread_stop(hwrng_fill);
hwrng_fill = NULL;
}
}
static int hwrng_fillfn(void *unused)
{
size_t entropy, entropy_credit = 0; /* in 1/1024 of a bit */
@@ -559,6 +587,37 @@ static int hwrng_fillfn(void *unused)
return 0;
}
static int hwrng_pm_notifier(struct notifier_block *nb, unsigned long action,
void *data)
{
switch (action) {
case PM_SUSPEND_PREPARE:
case PM_HIBERNATION_PREPARE:
case PM_RESTORE_PREPARE:
mutex_lock(&rng_mutex);
hwrng_stop_hwrng_fillfn();
hwrng_fillfn_stopped = true;
mutex_unlock(&rng_mutex);
break;
case PM_POST_SUSPEND:
case PM_POST_HIBERNATION:
case PM_POST_RESTORE:
mutex_lock(&rng_mutex);
hwrng_fillfn_stopped = false;
if (rcu_access_pointer(current_rng))
hwrng_start_hwrng_fillfn();
mutex_unlock(&rng_mutex);
break;
}
return NOTIFY_DONE;
}
static struct notifier_block hwrng_pm_nb = {
.notifier_call = hwrng_pm_notifier,
};
int hwrng_register(struct hwrng *rng)
{
int err = -EINVAL;
@@ -596,11 +655,13 @@ int hwrng_register(struct hwrng *rng)
*/
err = set_current_rng(rng);
if (err)
goto out_unlock;
goto out_list_del;
}
}
mutex_unlock(&rng_mutex);
return 0;
out_list_del:
list_del_init(&rng->list);
out_unlock:
mutex_unlock(&rng_mutex);
out:
@@ -705,10 +766,20 @@ static int __init hwrng_modinit(void)
}
ret = misc_register(&rng_miscdev);
if (ret) {
kfree(rng_fillbuf);
kfree(rng_buffer);
}
if (ret)
goto misc_err;
ret = register_pm_notifier(&hwrng_pm_nb);
if (ret)
goto pm_err;
return 0;
pm_err:
misc_deregister(&rng_miscdev);
misc_err:
kfree(rng_fillbuf);
kfree(rng_buffer);
return ret;
}
@@ -721,6 +792,8 @@ static void __exit hwrng_modexit(void)
kfree(rng_fillbuf);
mutex_unlock(&rng_mutex);
unregister_pm_notifier(&hwrng_pm_nb);
misc_deregister(&rng_miscdev);
}

View File

@@ -77,7 +77,7 @@ static int hisi_trng_probe(struct platform_device *pdev)
}
static const struct acpi_device_id hisi_trng_acpi_match[] = {
{ "HISI02B3", 0 },
{ .id = "HISI02B3" },
{ }
};
MODULE_DEVICE_TABLE(acpi, hisi_trng_acpi_match);

View File

@@ -296,7 +296,7 @@ static int __init imx_rngc_probe(struct platform_device *pdev)
irq, imx_rngc_irq, 0, pdev->name, (void *)rngc);
if (ret) {
clk_disable_unprepare(rngc->clk);
return dev_err_probe(&pdev->dev, ret, "Can't get interrupt working.\n");
return ret;
}
if (self_test) {
@@ -313,8 +313,10 @@ static int __init imx_rngc_probe(struct platform_device *pdev)
devm_pm_runtime_enable(&pdev->dev);
ret = devm_hwrng_register(&pdev->dev, &rngc->rng);
if (ret)
if (ret) {
clk_disable_unprepare(rngc->clk);
return dev_err_probe(&pdev->dev, ret, "hwrng registration failed\n");
}
dev_info(&pdev->dev,
"Freescale RNG%c registered (HW revision %d.%02d)\n",

View File

@@ -303,8 +303,7 @@ static int starfive_trng_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, irq, starfive_trng_irq, 0, pdev->name,
(void *)trng);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"Failed to register interrupt handler\n");
return ret;
trng->hclk = devm_clk_get(&pdev->dev, "hclk");
if (IS_ERR(trng->hclk))

View File

@@ -242,7 +242,14 @@ static int ks_sa_rng_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, "Failed to enable SA power-domain\n");
}
return devm_hwrng_register(&pdev->dev, &ks_sa_rng->rng);
ret = devm_hwrng_register(dev, &ks_sa_rng->rng);
if (ret) {
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
return ret;
}
return 0;
}
static void ks_sa_rng_remove(struct platform_device *pdev)

View File

@@ -391,11 +391,8 @@ static int of_get_omap_rng_device_details(struct omap_rng_dev *priv,
err = devm_request_irq(dev, irq, omap4_rng_irq,
IRQF_TRIGGER_NONE, dev_name(dev), priv);
if (err) {
dev_err(dev, "unable to request irq %d, err = %d\n",
irq, err);
if (err)
return err;
}
/*
* On OMAP4, enabling the shutdown_oflo interrupt is
@@ -455,32 +452,40 @@ static int omap_rng_probe(struct platform_device *pdev)
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to runtime_get device: %d\n", ret);
goto err_ioremap;
goto err_pm_disable;
}
priv->clk = devm_clk_get(&pdev->dev, NULL);
if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (PTR_ERR(priv->clk) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto err_pm_put;
}
if (!IS_ERR(priv->clk)) {
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(&pdev->dev,
"Unable to enable the clk: %d\n", ret);
goto err_register;
goto err_pm_put;
}
} else {
priv->clk = NULL;
}
priv->clk_reg = devm_clk_get(&pdev->dev, "reg");
if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto err_clk;
}
if (!IS_ERR(priv->clk_reg)) {
ret = clk_prepare_enable(priv->clk_reg);
if (ret) {
dev_err(&pdev->dev,
"Unable to enable the register clk: %d\n",
ret);
goto err_register;
goto err_clk;
}
} else {
priv->clk_reg = NULL;
}
ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) :
@@ -498,12 +503,14 @@ static int omap_rng_probe(struct platform_device *pdev)
return 0;
err_register:
clk_disable_unprepare(priv->clk_reg);
err_clk:
clk_disable_unprepare(priv->clk);
err_pm_put:
priv->base = NULL;
pm_runtime_put_sync(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(priv->clk_reg);
clk_disable_unprepare(priv->clk);
err_ioremap:
dev_err(dev, "initialization failed.\n");
return ret;

View File

@@ -3,10 +3,8 @@
//
// Based on msm-rng.c and downstream driver
#include <crypto/internal/rng.h>
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/crypto.h>
#include <linux/hw_random.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@@ -32,24 +30,15 @@
#define QCOM_TRNG_QUALITY 1024
struct qcom_rng {
struct mutex lock;
void __iomem *base;
struct clk *clk;
struct hwrng hwrng;
struct qcom_rng_match_data *match_data;
};
struct qcom_rng_ctx {
struct qcom_rng *rng;
};
struct qcom_rng_match_data {
bool skip_init;
bool hwrng_support;
};
static struct qcom_rng *qcom_rng_dev;
static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
{
unsigned int currsize = 0;
@@ -65,8 +54,6 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
return ret;
val = readl_relaxed(rng->base + PRNG_DATA_OUT);
if (!val)
return -EINVAL;
if ((max - currsize) >= WORD_SZ) {
memcpy(data, &val, WORD_SZ);
@@ -82,35 +69,11 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
return currsize;
}
static int qcom_rng_generate(struct crypto_rng *tfm,
const u8 *src, unsigned int slen,
u8 *dstn, unsigned int dlen)
static int qcom_hwrng_init(struct hwrng *hwrng)
{
struct qcom_rng_ctx *ctx = crypto_rng_ctx(tfm);
struct qcom_rng *rng = ctx->rng;
int ret;
struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
ret = clk_prepare_enable(rng->clk);
if (ret)
return ret;
mutex_lock(&rng->lock);
ret = qcom_rng_read(rng, dstn, dlen);
mutex_unlock(&rng->lock);
clk_disable_unprepare(rng->clk);
if (ret >= 0)
ret = 0;
return ret;
}
static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
unsigned int slen)
{
return 0;
return clk_prepare_enable(qrng->clk);
}
static int qcom_hwrng_read(struct hwrng *hwrng, void *data, size_t max, bool wait)
@@ -120,74 +83,33 @@ static int qcom_hwrng_read(struct hwrng *hwrng, void *data, size_t max, bool wai
return qcom_rng_read(qrng, data, max);
}
static int qcom_rng_enable(struct qcom_rng *rng)
static void qcom_hwrng_cleanup(struct hwrng *hwrng)
{
u32 val;
int ret;
struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
ret = clk_prepare_enable(rng->clk);
if (ret)
return ret;
/* Enable PRNG only if it is not already enabled */
val = readl_relaxed(rng->base + PRNG_CONFIG);
if (val & PRNG_CONFIG_HW_ENABLE)
goto already_enabled;
val = readl_relaxed(rng->base + PRNG_LFSR_CFG);
val &= ~PRNG_LFSR_CFG_MASK;
val |= PRNG_LFSR_CFG_CLOCKS;
writel(val, rng->base + PRNG_LFSR_CFG);
val = readl_relaxed(rng->base + PRNG_CONFIG);
val |= PRNG_CONFIG_HW_ENABLE;
writel(val, rng->base + PRNG_CONFIG);
already_enabled:
clk_disable_unprepare(rng->clk);
return 0;
clk_disable_unprepare(qrng->clk);
}
static int qcom_rng_init(struct crypto_tfm *tfm)
{
struct qcom_rng_ctx *ctx = crypto_tfm_ctx(tfm);
ctx->rng = qcom_rng_dev;
if (!ctx->rng->match_data->skip_init)
return qcom_rng_enable(ctx->rng);
return 0;
}
static struct rng_alg qcom_rng_alg = {
.generate = qcom_rng_generate,
.seed = qcom_rng_seed,
.seedsize = 0,
.base = {
.cra_name = "stdrng",
.cra_driver_name = "qcom-rng",
.cra_flags = CRYPTO_ALG_TYPE_RNG,
.cra_priority = 300,
.cra_ctxsize = sizeof(struct qcom_rng_ctx),
.cra_module = THIS_MODULE,
.cra_init = qcom_rng_init,
}
};
static int qcom_rng_probe(struct platform_device *pdev)
{
const struct qcom_rng_match_data *match_data;
struct qcom_rng *rng;
int ret;
match_data = device_get_match_data(&pdev->dev);
if (match_data == NULL || !match_data->hwrng_support) {
dev_info(&pdev->dev, "TRNG support not detected\n");
/*
* In this case the driver does nothing except the dev_info(),
* but bind the device anyway to avoid effects on GCC state.
*/
return 0;
}
rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
if (!rng)
return -ENOMEM;
platform_set_drvdata(pdev, rng);
mutex_init(&rng->lock);
rng->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rng->base))
return PTR_ERR(rng->base);
@@ -196,53 +118,26 @@ static int qcom_rng_probe(struct platform_device *pdev)
if (IS_ERR(rng->clk))
return PTR_ERR(rng->clk);
rng->match_data = (struct qcom_rng_match_data *)device_get_match_data(&pdev->dev);
qcom_rng_dev = rng;
ret = crypto_register_rng(&qcom_rng_alg);
if (ret) {
dev_err(&pdev->dev, "Register crypto rng failed: %d\n", ret);
qcom_rng_dev = NULL;
return ret;
}
if (rng->match_data->hwrng_support) {
rng->hwrng.name = "qcom_hwrng";
rng->hwrng.read = qcom_hwrng_read;
rng->hwrng.quality = QCOM_TRNG_QUALITY;
ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
if (ret) {
dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
qcom_rng_dev = NULL;
goto fail;
}
}
rng->hwrng.name = "qcom_hwrng";
rng->hwrng.init = qcom_hwrng_init;
rng->hwrng.read = qcom_hwrng_read;
rng->hwrng.cleanup = qcom_hwrng_cleanup;
rng->hwrng.quality = QCOM_TRNG_QUALITY;
ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
if (ret)
dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
return ret;
fail:
crypto_unregister_rng(&qcom_rng_alg);
return ret;
}
static void qcom_rng_remove(struct platform_device *pdev)
{
crypto_unregister_rng(&qcom_rng_alg);
qcom_rng_dev = NULL;
}
static struct qcom_rng_match_data qcom_prng_match_data = {
.skip_init = false,
.hwrng_support = false,
};
static struct qcom_rng_match_data qcom_prng_ee_match_data = {
.skip_init = true,
.hwrng_support = false,
};
static struct qcom_rng_match_data qcom_trng_match_data = {
.skip_init = true,
.hwrng_support = true,
};
@@ -262,7 +157,6 @@ MODULE_DEVICE_TABLE(of, qcom_rng_of_match);
static struct platform_driver qcom_rng_driver = {
.probe = qcom_rng_probe,
.remove = qcom_rng_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = qcom_rng_of_match,

View File

@@ -368,11 +368,6 @@ static int stm32_rng_init(struct hwrng *rng)
return 0;
}
static void stm32_rng_remove(struct platform_device *ofdev)
{
pm_runtime_disable(&ofdev->dev);
}
static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev)
{
struct stm32_rng_private *priv = dev_get_drvdata(dev);
@@ -590,7 +585,9 @@ static int stm32_rng_probe(struct platform_device *ofdev)
pm_runtime_set_autosuspend_delay(dev, 100);
pm_runtime_use_autosuspend(dev);
pm_runtime_enable(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
return ret;
return devm_hwrng_register(dev, &priv->rng);
}
@@ -602,7 +599,6 @@ static struct platform_driver stm32_rng_driver = {
.of_match_table = stm32_rng_match,
},
.probe = stm32_rng_probe,
.remove = stm32_rng_remove,
};
module_platform_driver(stm32_rng_driver);

View File

@@ -296,7 +296,7 @@ static int xgene_rng_init(struct hwrng *rng)
#ifdef CONFIG_ACPI
static const struct acpi_device_id xgene_rng_acpi_match[] = {
{ "APMC0D18", },
{ .id = "APMC0D18" },
{ }
};
MODULE_DEVICE_TABLE(acpi, xgene_rng_acpi_match);
@@ -336,7 +336,7 @@ static int xgene_rng_probe(struct platform_device *pdev)
rc = devm_request_irq(&pdev->dev, ctx->irq, xgene_rng_irq_handler, 0,
dev_name(&pdev->dev), ctx);
if (rc)
return dev_err_probe(&pdev->dev, rc, "Could not request RNG alarm IRQ\n");
return rc;
/* Enable IP clock */
clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);

View File

@@ -86,8 +86,8 @@ static void xtrng_softreset(struct xilinx_rng *rng)
xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 0);
}
/* Return no. of bytes read */
static size_t xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32, bool wait)
/* Return no. of bytes read or a negative error before any data is read. */
static int xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32, bool wait)
{
int read = 0, ret;
int timeout = 1;
@@ -102,8 +102,11 @@ static size_t xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks3
ret = readl_poll_timeout(rng_base + TRNG_STATUS_OFFSET, val,
(val & TRNG_STATUS_QCNT_MASK) ==
TRNG_STATUS_QCNT_16_BYTES, !!wait, timeout);
if (ret)
if (ret) {
if (!read)
return ret;
break;
}
for (idx = 0; idx < TRNG_READ_4_WORD; idx++) {
*(buf + read) = cpu_to_be32(ioread32(rng_base + TRNG_CORE_OUTPUT_OFFSET));
@@ -118,27 +121,40 @@ static int xtrng_collect_random_data(struct xilinx_rng *rng, u8 *rand_gen_buf,
{
u8 randbuf[TRNG_SEC_STRENGTH_BYTES];
int byteleft, blocks, count = 0;
int full_blocks_bytes;
int ret;
byteleft = no_of_random_bytes & (TRNG_SEC_STRENGTH_BYTES - 1);
blocks = no_of_random_bytes >> TRNG_SEC_STRENGTH_SHIFT;
full_blocks_bytes = blocks * TRNG_SEC_STRENGTH_BYTES;
xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK,
TRNG_CTRL_PRNGSTART_MASK);
if (blocks) {
ret = xtrng_readblock32(rng->rng_base, (__be32 *)rand_gen_buf, blocks, wait);
if (!ret)
return 0;
if (ret <= 0) {
count = ret;
goto out_stop;
}
count += ret;
if (ret < full_blocks_bytes)
goto out_stop;
}
if (byteleft) {
ret = xtrng_readblock32(rng->rng_base, (__be32 *)randbuf, 1, wait);
if (ret < 0) {
if (!count)
count = ret;
goto out_stop;
}
if (!ret)
return count;
memcpy(rand_gen_buf + (blocks * TRNG_SEC_STRENGTH_BYTES), randbuf, byteleft);
count += byteleft;
goto out_stop;
ret = min(ret, no_of_random_bytes - count);
memcpy(rand_gen_buf + count, randbuf, ret);
count += ret;
}
out_stop:
xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET,
TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGSTART_MASK, 0U);

View File

@@ -528,13 +528,17 @@ source "drivers/crypto/intel/Kconfig"
config CRYPTO_DEV_QCE
tristate "Qualcomm crypto engine accelerator"
depends on ARCH_QCOM || COMPILE_TEST
depends on (BROKEN && ARCH_QCOM) || COMPILE_TEST
depends on HAS_IOMEM
help
This driver supports Qualcomm crypto engine accelerator
hardware. To compile this driver as a module, choose M here. The
module will be called qcrypto.
This driver does not have exclusive access to the
hardware, causing races with the secure world. It
is also slower than the CPU.
config CRYPTO_DEV_QCE_SKCIPHER
bool
depends on CRYPTO_DEV_QCE
@@ -637,18 +641,6 @@ config CRYPTO_DEV_QCE_SW_MAX_LEN
always processed by the software fallback, and all DES requests
are done by the hardware.
config CRYPTO_DEV_QCOM_RNG
tristate "Qualcomm Random Number Generator Driver"
depends on ARCH_QCOM || COMPILE_TEST
depends on HW_RANDOM
select CRYPTO_RNG
help
This driver provides support for the Random Number
Generator hardware found on Qualcomm SoCs.
To compile this driver as a module, choose M here. The
module will be called qcom-rng. If unsure, say N.
config CRYPTO_DEV_IMGTEC_HASH
tristate "Imagination Technologies hardware hash accelerator"
depends on MIPS || COMPILE_TEST

View File

@@ -27,7 +27,6 @@ obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/
obj-$(CONFIG_CRYPTO_DEV_QCOM_RNG) += qcom-rng.o
obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/
obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
obj-$(CONFIG_CRYPTO_DEV_SA2UL) += sa2ul.o

View File

@@ -70,14 +70,6 @@ config CRYPTO_DEV_SUN8I_CE_HASH
help
Say y to enable support for hash algorithms.
config CRYPTO_DEV_SUN8I_CE_PRNG
bool "Support for Allwinner Crypto Engine PRNG"
depends on CRYPTO_DEV_SUN8I_CE
select CRYPTO_RNG
help
Select this option if you want to provide kernel-side support for
the Pseudo-Random Number Generator found in the Crypto Engine.
config CRYPTO_DEV_SUN8I_CE_TRNG
bool "Support for Allwinner Crypto Engine TRNG"
depends on CRYPTO_DEV_SUN8I_CE
@@ -113,14 +105,6 @@ config CRYPTO_DEV_SUN8I_SS_DEBUG
This will create /sys/kernel/debug/sun8i-ss/stats for displaying
the number of requests per flow and per algorithm.
config CRYPTO_DEV_SUN8I_SS_PRNG
bool "Support for Allwinner Security System PRNG"
depends on CRYPTO_DEV_SUN8I_SS
select CRYPTO_RNG
help
Select this option if you want to provide kernel-side support for
the Pseudo-Random Number Generator found in the Security System.
config CRYPTO_DEV_SUN8I_SS_HASH
bool "Enable support for hash on sun8i-ss"
depends on CRYPTO_DEV_SUN8I_SS

View File

@@ -1,5 +1,4 @@
obj-$(CONFIG_CRYPTO_DEV_SUN8I_CE) += sun8i-ce.o
sun8i-ce-y += sun8i-ce-core.o sun8i-ce-cipher.o
sun8i-ce-$(CONFIG_CRYPTO_DEV_SUN8I_CE_HASH) += sun8i-ce-hash.o
sun8i-ce-$(CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG) += sun8i-ce-prng.o
sun8i-ce-$(CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG) += sun8i-ce-trng.o

View File

@@ -12,7 +12,6 @@
#include <crypto/engine.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/rng.h>
#include <crypto/internal/skcipher.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -49,7 +48,6 @@ static const struct ce_variant ce_h3_variant = {
{ "mod", 50000000, 0 },
},
.esr = ESR_H3,
.prng = CE_ALG_PRNG,
.trng = CE_ID_NOTSUPP,
};
@@ -66,7 +64,6 @@ static const struct ce_variant ce_h5_variant = {
{ "mod", 300000000, 0 },
},
.esr = ESR_H5,
.prng = CE_ALG_PRNG,
.trng = CE_ID_NOTSUPP,
};
@@ -80,7 +77,6 @@ static const struct ce_variant ce_h6_variant = {
},
.cipher_t_dlen_in_bytes = true,
.hash_t_dlen_in_bits = true,
.prng_t_dlen_in_bytes = true,
.trng_t_dlen_in_bytes = true,
.ce_clks = {
{ "bus", 0, 200000000 },
@@ -88,7 +84,6 @@ static const struct ce_variant ce_h6_variant = {
{ "ram", 0, 400000000 },
},
.esr = ESR_H6,
.prng = CE_ALG_PRNG_V2,
.trng = CE_ALG_TRNG_V2,
};
@@ -102,7 +97,6 @@ static const struct ce_variant ce_h616_variant = {
},
.cipher_t_dlen_in_bytes = true,
.hash_t_dlen_in_bits = true,
.prng_t_dlen_in_bytes = true,
.trng_t_dlen_in_bytes = true,
.needs_word_addresses = true,
.ce_clks = {
@@ -112,7 +106,6 @@ static const struct ce_variant ce_h616_variant = {
{ "trng", 0, 0 },
},
.esr = ESR_H6,
.prng = CE_ALG_PRNG_V2,
.trng = CE_ALG_TRNG_V2,
};
@@ -129,7 +122,6 @@ static const struct ce_variant ce_a64_variant = {
{ "mod", 300000000, 0 },
},
.esr = ESR_A64,
.prng = CE_ALG_PRNG,
.trng = CE_ID_NOTSUPP,
};
@@ -148,7 +140,6 @@ static const struct ce_variant ce_d1_variant = {
{ "trng", 0, 0 },
},
.esr = ESR_D1,
.prng = CE_ALG_PRNG,
.trng = CE_ALG_TRNG,
};
@@ -165,7 +156,6 @@ static const struct ce_variant ce_r40_variant = {
{ "mod", 300000000, 0 },
},
.esr = ESR_R40,
.prng = CE_ALG_PRNG,
.trng = CE_ID_NOTSUPP,
};
@@ -614,25 +604,6 @@ static struct sun8i_ce_alg_template ce_algs[] = {
},
},
#endif
#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG
{
.type = CRYPTO_ALG_TYPE_RNG,
.alg.rng = {
.base = {
.cra_name = "stdrng",
.cra_driver_name = "sun8i-ce-prng",
.cra_priority = 300,
.cra_ctxsize = sizeof(struct sun8i_ce_rng_tfm_ctx),
.cra_module = THIS_MODULE,
.cra_init = sun8i_ce_prng_init,
.cra_exit = sun8i_ce_prng_exit,
},
.generate = sun8i_ce_prng_generate,
.seed = sun8i_ce_prng_seed,
.seedsize = PRNG_SEED_SIZE,
}
},
#endif
};
static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v)
@@ -693,14 +664,6 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v)
seq_printf(seq, "\tFallback due to SG numbers: %lu\n",
ce_algs[i].stat_fb_maxsg);
break;
#endif
#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG
case CRYPTO_ALG_TYPE_RNG:
seq_printf(seq, "%s %s reqs=%lu bytes=%lu\n",
ce_algs[i].alg.rng.base.cra_driver_name,
ce_algs[i].alg.rng.base.cra_name,
ce_algs[i].stat_req, ce_algs[i].stat_bytes);
break;
#endif
}
}
@@ -930,25 +893,6 @@ static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce)
return err;
}
break;
#endif
#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG
case CRYPTO_ALG_TYPE_RNG:
if (ce->variant->prng == CE_ID_NOTSUPP) {
dev_info(ce->dev,
"DEBUG: Algo of %s not supported\n",
ce_algs[i].alg.rng.base.cra_name);
ce_algs[i].ce = NULL;
break;
}
dev_info(ce->dev, "Register %s\n",
ce_algs[i].alg.rng.base.cra_name);
err = crypto_register_rng(&ce_algs[i].alg.rng);
if (err) {
dev_err(ce->dev, "Fail to register %s\n",
ce_algs[i].alg.rng.base.cra_name);
ce_algs[i].ce = NULL;
}
break;
#endif
default:
ce_algs[i].ce = NULL;
@@ -977,13 +921,6 @@ static void sun8i_ce_unregister_algs(struct sun8i_ce_dev *ce)
ce_algs[i].alg.hash.base.halg.base.cra_name);
crypto_engine_unregister_ahash(&ce_algs[i].alg.hash);
break;
#endif
#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG
case CRYPTO_ALG_TYPE_RNG:
dev_info(ce->dev, "Unregister %d %s\n", i,
ce_algs[i].alg.rng.base.cra_name);
crypto_unregister_rng(&ce_algs[i].alg.rng);
break;
#endif
}
}
@@ -1039,10 +976,8 @@ static int sun8i_ce_probe(struct platform_device *pdev)
err = devm_request_irq(&pdev->dev, irq, ce_irq_handler, 0,
"sun8i-ce-ns", ce);
if (err) {
dev_err(ce->dev, "Cannot request CryptoEngine Non-secure IRQ (err=%d)\n", err);
if (err)
goto error_pm;
}
err = sun8i_ce_register_algs(ce);
if (err)

View File

@@ -1,159 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* sun8i-ce-prng.c - hardware cryptographic offloader for
* Allwinner H3/A64/H5/H2+/H6/R40 SoC
*
* Copyright (C) 2015-2020 Corentin Labbe <clabbe@baylibre.com>
*
* This file handle the PRNG
*
* You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include "sun8i-ce.h"
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <crypto/internal/rng.h>
int sun8i_ce_prng_init(struct crypto_tfm *tfm)
{
struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
memset(ctx, 0, sizeof(struct sun8i_ce_rng_tfm_ctx));
return 0;
}
void sun8i_ce_prng_exit(struct crypto_tfm *tfm)
{
struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
kfree_sensitive(ctx->seed);
ctx->seed = NULL;
ctx->slen = 0;
}
int sun8i_ce_prng_seed(struct crypto_rng *tfm, const u8 *seed,
unsigned int slen)
{
struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
if (ctx->seed && ctx->slen != slen) {
kfree_sensitive(ctx->seed);
ctx->slen = 0;
ctx->seed = NULL;
}
if (!ctx->seed)
ctx->seed = kmalloc(slen, GFP_KERNEL | GFP_DMA);
if (!ctx->seed)
return -ENOMEM;
memcpy(ctx->seed, seed, slen);
ctx->slen = slen;
return 0;
}
int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src,
unsigned int slen, u8 *dst, unsigned int dlen)
{
struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
struct rng_alg *alg = crypto_rng_alg(tfm);
struct sun8i_ce_alg_template *algt;
struct sun8i_ce_dev *ce;
dma_addr_t dma_iv, dma_dst;
int err = 0;
int flow = 3;
unsigned int todo;
struct sun8i_ce_flow *chan;
struct ce_task *cet;
u32 common, sym;
void *d;
algt = container_of(alg, struct sun8i_ce_alg_template, alg.rng);
ce = algt->ce;
if (ctx->slen == 0) {
dev_err(ce->dev, "not seeded\n");
return -EINVAL;
}
/* we want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE */
todo = dlen + ctx->slen + PRNG_DATA_SIZE * 2;
todo -= todo % PRNG_DATA_SIZE;
d = kzalloc(todo, GFP_KERNEL | GFP_DMA);
if (!d) {
err = -ENOMEM;
goto err_mem;
}
dev_dbg(ce->dev, "%s PRNG slen=%u dlen=%u todo=%u multi=%u\n", __func__,
slen, dlen, todo, todo / PRNG_DATA_SIZE);
#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG
algt->stat_req++;
algt->stat_bytes += todo;
#endif
dma_iv = dma_map_single(ce->dev, ctx->seed, ctx->slen, DMA_TO_DEVICE);
if (dma_mapping_error(ce->dev, dma_iv)) {
dev_err(ce->dev, "Cannot DMA MAP IV\n");
err = -EFAULT;
goto err_iv;
}
dma_dst = dma_map_single(ce->dev, d, todo, DMA_FROM_DEVICE);
if (dma_mapping_error(ce->dev, dma_dst)) {
dev_err(ce->dev, "Cannot DMA MAP DST\n");
err = -EFAULT;
goto err_dst;
}
err = pm_runtime_resume_and_get(ce->dev);
if (err < 0)
goto err_pm;
mutex_lock(&ce->rnglock);
chan = &ce->chanlist[flow];
cet = &chan->tl[0];
memset(cet, 0, sizeof(struct ce_task));
cet->t_id = cpu_to_le32(flow);
common = ce->variant->prng | CE_COMM_INT;
cet->t_common_ctl = cpu_to_le32(common);
/* recent CE (H6) need length in bytes, in word otherwise */
if (ce->variant->prng_t_dlen_in_bytes)
cet->t_dlen = cpu_to_le32(todo);
else
cet->t_dlen = cpu_to_le32(todo / 4);
sym = PRNG_LD;
cet->t_sym_ctl = cpu_to_le32(sym);
cet->t_asym_ctl = 0;
cet->t_key = desc_addr_val_le32(ce, dma_iv);
cet->t_iv = desc_addr_val_le32(ce, dma_iv);
cet->t_dst[0].addr = desc_addr_val_le32(ce, dma_dst);
cet->t_dst[0].len = cpu_to_le32(todo / 4);
err = sun8i_ce_run_task(ce, 3, "PRNG");
mutex_unlock(&ce->rnglock);
pm_runtime_put(ce->dev);
err_pm:
dma_unmap_single(ce->dev, dma_dst, todo, DMA_FROM_DEVICE);
err_dst:
dma_unmap_single(ce->dev, dma_iv, ctx->slen, DMA_TO_DEVICE);
if (!err) {
memcpy(dst, d, dlen);
memcpy(ctx->seed, d + dlen, ctx->slen);
}
err_iv:
kfree_sensitive(d);
err_mem:
return err;
}

View File

@@ -15,7 +15,6 @@
#include <linux/hw_random.h>
#include <crypto/internal/hash.h>
#include <crypto/md5.h>
#include <crypto/rng.h>
#include <crypto/sha1.h>
#include <crypto/sha2.h>
@@ -58,9 +57,7 @@
#define CE_ALG_SHA384 20
#define CE_ALG_SHA512 21
#define CE_ALG_TRNG 48
#define CE_ALG_PRNG 49
#define CE_ALG_TRNG_V2 0x1c
#define CE_ALG_PRNG_V2 0x1d
/* Used in ce_variant */
#define CE_ID_NOTSUPP 0xFF
@@ -96,10 +93,6 @@
#define ESR_H6 4
#define ESR_D1 5
#define PRNG_DATA_SIZE (160 / 8)
#define PRNG_SEED_SIZE DIV_ROUND_UP(175, 8)
#define PRNG_LD BIT(17)
#define CE_DIE_ID_SHIFT 16
#define CE_DIE_ID_MASK 0x07
@@ -136,13 +129,10 @@ struct ce_clock {
* bytes or words
* @hash_t_dlen_in_bytes: Does the request size for hash is in
* bits or words
* @prng_t_dlen_in_bytes: Does the request size for PRNG is in
* bytes or words
* @trng_t_dlen_in_bytes: Does the request size for TRNG is in
* bytes or words
* @ce_clks: list of clocks needed by this variant
* @esr: The type of error register
* @prng: The CE_ALG_XXX value for the PRNG
* @trng: The CE_ALG_XXX value for the TRNG
*/
struct ce_variant {
@@ -151,12 +141,10 @@ struct ce_variant {
u32 op_mode[CE_ID_OP_MAX];
bool cipher_t_dlen_in_bytes;
bool hash_t_dlen_in_bits;
bool prng_t_dlen_in_bytes;
bool trng_t_dlen_in_bytes;
bool needs_word_addresses;
struct ce_clock ce_clks[CE_MAX_CLOCKS];
int esr;
unsigned char prng;
unsigned char trng;
};
@@ -327,16 +315,6 @@ struct sun8i_ce_hash_reqctx {
struct ahash_request fallback_req; // keep at the end
};
/*
* struct sun8i_ce_prng_ctx - context for PRNG TFM
* @seed: The seed to use
* @slen: The size of the seed
*/
struct sun8i_ce_rng_tfm_ctx {
void *seed;
unsigned int slen;
};
/*
* struct sun8i_ce_alg_template - crypto_alg template
* @type: the CRYPTO_ALG_TYPE for this template
@@ -357,7 +335,6 @@ struct sun8i_ce_alg_template {
union {
struct skcipher_engine_alg skcipher;
struct ahash_engine_alg hash;
struct rng_alg rng;
} alg;
unsigned long stat_req;
unsigned long stat_fb;
@@ -398,11 +375,5 @@ int sun8i_ce_hash_finup(struct ahash_request *areq);
int sun8i_ce_hash_digest(struct ahash_request *areq);
int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq);
int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src,
unsigned int slen, u8 *dst, unsigned int dlen);
int sun8i_ce_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);
void sun8i_ce_prng_exit(struct crypto_tfm *tfm);
int sun8i_ce_prng_init(struct crypto_tfm *tfm);
int sun8i_ce_hwrng_register(struct sun8i_ce_dev *ce);
void sun8i_ce_hwrng_unregister(struct sun8i_ce_dev *ce);

View File

@@ -1,4 +1,3 @@
obj-$(CONFIG_CRYPTO_DEV_SUN8I_SS) += sun8i-ss.o
sun8i-ss-y += sun8i-ss-core.o sun8i-ss-cipher.o
sun8i-ss-$(CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG) += sun8i-ss-prng.o
sun8i-ss-$(CONFIG_CRYPTO_DEV_SUN8I_SS_HASH) += sun8i-ss-hash.o

View File

@@ -11,7 +11,6 @@
*/
#include <crypto/engine.h>
#include <crypto/internal/rng.h>
#include <crypto/internal/skcipher.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -283,25 +282,6 @@ static struct sun8i_ss_alg_template ss_algs[] = {
.do_one_request = sun8i_ss_handle_cipher_request,
},
},
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG
{
.type = CRYPTO_ALG_TYPE_RNG,
.alg.rng = {
.base = {
.cra_name = "stdrng",
.cra_driver_name = "sun8i-ss-prng",
.cra_priority = 300,
.cra_ctxsize = sizeof(struct sun8i_ss_rng_tfm_ctx),
.cra_module = THIS_MODULE,
.cra_init = sun8i_ss_prng_init,
.cra_exit = sun8i_ss_prng_exit,
},
.generate = sun8i_ss_prng_generate,
.seed = sun8i_ss_prng_seed,
.seedsize = PRNG_SEED_SIZE,
}
},
#endif
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH
{ .type = CRYPTO_ALG_TYPE_AHASH,
.ss_algo_id = SS_ID_HASH_MD5,
@@ -501,14 +481,6 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v)
seq_printf(seq, "\tFallback due to SG numbers: %lu\n",
ss_algs[i].stat_fb_sgnum);
break;
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG
case CRYPTO_ALG_TYPE_RNG:
seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n",
ss_algs[i].alg.rng.base.cra_driver_name,
ss_algs[i].alg.rng.base.cra_name,
ss_algs[i].stat_req, ss_algs[i].stat_bytes);
break;
#endif
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH
case CRYPTO_ALG_TYPE_AHASH:
seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n",
@@ -711,16 +683,6 @@ static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss)
return err;
}
break;
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG
case CRYPTO_ALG_TYPE_RNG:
err = crypto_register_rng(&ss_algs[i].alg.rng);
if (err) {
dev_err(ss->dev, "Fail to register %s\n",
ss_algs[i].alg.rng.base.cra_name);
ss_algs[i].ss = NULL;
}
break;
#endif
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH
case CRYPTO_ALG_TYPE_AHASH:
id = ss_algs[i].ss_algo_id;
@@ -764,13 +726,6 @@ static void sun8i_ss_unregister_algs(struct sun8i_ss_dev *ss)
ss_algs[i].alg.skcipher.base.base.cra_name);
crypto_engine_unregister_skcipher(&ss_algs[i].alg.skcipher);
break;
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG
case CRYPTO_ALG_TYPE_RNG:
dev_info(ss->dev, "Unregister %d %s\n", i,
ss_algs[i].alg.rng.base.cra_name);
crypto_unregister_rng(&ss_algs[i].alg.rng);
break;
#endif
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH
case CRYPTO_ALG_TYPE_AHASH:
dev_info(ss->dev, "Unregister %d %s\n", i,
@@ -869,10 +824,8 @@ static int sun8i_ss_probe(struct platform_device *pdev)
goto error_pm;
err = devm_request_irq(&pdev->dev, irq, ss_irq_handler, 0, "sun8i-ss", ss);
if (err) {
dev_err(ss->dev, "Cannot request SecuritySystem IRQ (err=%d)\n", err);
if (err)
goto error_irq;
}
err = sun8i_ss_register_algs(ss);
if (err)

View File

@@ -1,177 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* sun8i-ss-prng.c - hardware cryptographic offloader for
* Allwinner A80/A83T SoC
*
* Copyright (C) 2015-2020 Corentin Labbe <clabbe@baylibre.com>
*
* This file handle the PRNG found in the SS
*
* You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
*/
#include "sun8i-ss.h"
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/pm_runtime.h>
#include <crypto/internal/rng.h>
int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed,
unsigned int slen)
{
struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
if (ctx->seed && ctx->slen != slen) {
kfree_sensitive(ctx->seed);
ctx->slen = 0;
ctx->seed = NULL;
}
if (!ctx->seed)
ctx->seed = kmalloc(slen, GFP_KERNEL);
if (!ctx->seed)
return -ENOMEM;
memcpy(ctx->seed, seed, slen);
ctx->slen = slen;
return 0;
}
int sun8i_ss_prng_init(struct crypto_tfm *tfm)
{
struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
memset(ctx, 0, sizeof(struct sun8i_ss_rng_tfm_ctx));
return 0;
}
void sun8i_ss_prng_exit(struct crypto_tfm *tfm)
{
struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
kfree_sensitive(ctx->seed);
ctx->seed = NULL;
ctx->slen = 0;
}
int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
unsigned int slen, u8 *dst, unsigned int dlen)
{
struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
struct rng_alg *alg = crypto_rng_alg(tfm);
struct sun8i_ss_alg_template *algt;
unsigned int todo_with_padding;
struct sun8i_ss_dev *ss;
dma_addr_t dma_iv, dma_dst;
unsigned int todo;
int err = 0;
int flow;
void *d;
u32 v;
algt = container_of(alg, struct sun8i_ss_alg_template, alg.rng);
ss = algt->ss;
if (ctx->slen == 0) {
dev_err(ss->dev, "The PRNG is not seeded\n");
return -EINVAL;
}
/* The SS does not give an updated seed, so we need to get a new one.
* So we will ask for an extra PRNG_SEED_SIZE data.
* We want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE
*/
todo = dlen + PRNG_SEED_SIZE + PRNG_DATA_SIZE;
todo -= todo % PRNG_DATA_SIZE;
todo_with_padding = ALIGN(todo, dma_get_cache_alignment());
if (todo_with_padding < todo || todo < dlen)
return -EOVERFLOW;
d = kzalloc(todo_with_padding, GFP_KERNEL);
if (!d)
return -ENOMEM;
flow = sun8i_ss_get_engine_number(ss);
#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG
algt->stat_req++;
algt->stat_bytes += todo;
#endif
v = SS_ALG_PRNG | SS_PRNG_CONTINUE | SS_START;
if (flow)
v |= SS_FLOW1;
else
v |= SS_FLOW0;
dma_iv = dma_map_single(ss->dev, ctx->seed, ctx->slen, DMA_TO_DEVICE);
if (dma_mapping_error(ss->dev, dma_iv)) {
dev_err(ss->dev, "Cannot DMA MAP IV\n");
err = -EFAULT;
goto err_free;
}
dma_dst = dma_map_single(ss->dev, d, todo, DMA_FROM_DEVICE);
if (dma_mapping_error(ss->dev, dma_dst)) {
dev_err(ss->dev, "Cannot DMA MAP DST\n");
err = -EFAULT;
goto err_iv;
}
err = pm_runtime_resume_and_get(ss->dev);
if (err < 0)
goto err_pm;
err = 0;
mutex_lock(&ss->mlock);
writel(dma_iv, ss->base + SS_IV_ADR_REG);
/* the PRNG act badly (failing rngtest) without SS_KEY_ADR_REG set */
writel(dma_iv, ss->base + SS_KEY_ADR_REG);
writel(dma_dst, ss->base + SS_DST_ADR_REG);
writel(todo / 4, ss->base + SS_LEN_ADR_REG);
reinit_completion(&ss->flows[flow].complete);
ss->flows[flow].status = 0;
/* Be sure all data is written before enabling the task */
wmb();
writel(v, ss->base + SS_CTL_REG);
wait_for_completion_interruptible_timeout(&ss->flows[flow].complete,
msecs_to_jiffies(todo));
if (ss->flows[flow].status == 0) {
dev_err(ss->dev, "DMA timeout for PRNG (size=%u)\n", todo);
err = -EFAULT;
}
/* Since cipher and hash use the linux/cryptoengine and that we have
* a cryptoengine per flow, we are sure that they will issue only one
* request per flow.
* Since the cryptoengine wait for completion before submitting a new
* one, the mlock could be left just after the final writel.
* But cryptoengine cannot handle crypto_rng, so we need to be sure
* nothing will use our flow.
* The easiest way is to grab mlock until the hardware end our requests.
* We could have used a per flow lock, but this would increase
* complexity.
* The drawback is that no request could be handled for the other flow.
*/
mutex_unlock(&ss->mlock);
pm_runtime_put(ss->dev);
err_pm:
dma_unmap_single(ss->dev, dma_dst, todo, DMA_FROM_DEVICE);
err_iv:
dma_unmap_single(ss->dev, dma_iv, ctx->slen, DMA_TO_DEVICE);
if (!err) {
memcpy(dst, d, dlen);
/* Update seed */
memcpy(ctx->seed, d + dlen, ctx->slen);
}
err_free:
kfree_sensitive(d);
return err;
}

View File

@@ -8,7 +8,6 @@
#include <crypto/aes.h>
#include <crypto/des.h>
#include <crypto/engine.h>
#include <crypto/rng.h>
#include <crypto/skcipher.h>
#include <linux/atomic.h>
#include <linux/debugfs.h>
@@ -27,7 +26,6 @@
#define SS_ALG_DES (1 << 2)
#define SS_ALG_3DES (2 << 2)
#define SS_ALG_MD5 (3 << 2)
#define SS_ALG_PRNG (4 << 2)
#define SS_ALG_SHA1 (6 << 2)
#define SS_ALG_SHA224 (7 << 2)
#define SS_ALG_SHA256 (8 << 2)
@@ -68,8 +66,6 @@
#define SS_FLOW0 BIT(30)
#define SS_FLOW1 BIT(31)
#define SS_PRNG_CONTINUE BIT(18)
#define MAX_SG 8
#define MAXFLOW 2
@@ -79,9 +75,6 @@
#define SS_DIE_ID_SHIFT 20
#define SS_DIE_ID_MASK 0x07
#define PRNG_DATA_SIZE (160 / 8)
#define PRNG_SEED_SIZE DIV_ROUND_UP(175, 8)
#define MAX_PAD_SIZE 4096
/*
@@ -213,16 +206,6 @@ struct sun8i_cipher_tfm_ctx {
struct crypto_skcipher *fallback_tfm;
};
/*
* struct sun8i_ss_prng_ctx - context for PRNG TFM
* @seed: The seed to use
* @slen: The size of the seed
*/
struct sun8i_ss_rng_tfm_ctx {
void *seed;
unsigned int slen;
};
/*
* struct sun8i_ss_hash_tfm_ctx - context for an ahash TFM
* @fallback_tfm: pointer to the fallback TFM
@@ -274,7 +257,6 @@ struct sun8i_ss_alg_template {
struct sun8i_ss_dev *ss;
union {
struct skcipher_engine_alg skcipher;
struct rng_alg rng;
struct ahash_engine_alg hash;
} alg;
unsigned long stat_req;
@@ -300,11 +282,6 @@ int sun8i_ss_skencrypt(struct skcipher_request *areq);
int sun8i_ss_get_engine_number(struct sun8i_ss_dev *ss);
int sun8i_ss_run_task(struct sun8i_ss_dev *ss, struct sun8i_cipher_req_ctx *rctx, const char *name);
int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
unsigned int slen, u8 *dst, unsigned int dlen);
int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);
int sun8i_ss_prng_init(struct crypto_tfm *tfm);
void sun8i_ss_prng_exit(struct crypto_tfm *tfm);
int sun8i_ss_hash_init_tfm(struct crypto_ahash *tfm);
void sun8i_ss_hash_exit_tfm(struct crypto_ahash *tfm);

View File

@@ -1251,6 +1251,10 @@ static int crypto4xx_probe(struct platform_device *ofdev)
if (!core_dev->dev)
return -ENOMEM;
core_dev->dev->ce_base = devm_platform_ioremap_resource(ofdev, 0);
if (IS_ERR(core_dev->dev->ce_base))
return PTR_ERR(core_dev->dev->ce_base);
/*
* Older version of 460EX/GT have a hardware bug.
* Hence they do not support H/W based security intr coalescing
@@ -1286,25 +1290,18 @@ static int crypto4xx_probe(struct platform_device *ofdev)
tasklet_init(&core_dev->tasklet, crypto4xx_bh_tasklet_cb,
(unsigned long) dev);
core_dev->dev->ce_base = devm_platform_ioremap_resource(ofdev, 0);
if (IS_ERR(core_dev->dev->ce_base)) {
dev_err(&ofdev->dev, "failed to ioremap resource");
rc = PTR_ERR(core_dev->dev->ce_base);
goto err_build_sdr;
}
/* Register for Crypto isr, Crypto Engine IRQ */
core_dev->irq = platform_get_irq(ofdev, 0);
if (core_dev->irq < 0) {
rc = core_dev->irq;
goto err_iomap;
goto err_tasklet;
}
rc = devm_request_irq(&ofdev->dev, core_dev->irq,
is_revb ? crypto4xx_ce_interrupt_handler_revb :
crypto4xx_ce_interrupt_handler,
0, KBUILD_MODNAME, dev);
rc = request_irq(core_dev->irq,
is_revb ? crypto4xx_ce_interrupt_handler_revb :
crypto4xx_ce_interrupt_handler,
0, KBUILD_MODNAME, dev);
if (rc)
goto err_iomap;
goto err_tasklet;
/* need to setup pdr, rdr, gdr and sdr before this */
crypto4xx_hw_init(core_dev->dev);
@@ -1313,12 +1310,14 @@ static int crypto4xx_probe(struct platform_device *ofdev)
rc = crypto4xx_register_alg(core_dev->dev, crypto4xx_alg,
ARRAY_SIZE(crypto4xx_alg));
if (rc)
goto err_iomap;
goto err_irq;
ppc4xx_trng_probe(core_dev);
return 0;
err_iomap:
err_irq:
free_irq(core_dev->irq, dev);
err_tasklet:
tasklet_kill(&core_dev->tasklet);
err_build_sdr:
crypto4xx_destroy_sdr(core_dev->dev);
@@ -1334,6 +1333,11 @@ static void crypto4xx_remove(struct platform_device *ofdev)
ppc4xx_trng_remove(core_dev);
/*
* Free IRQ before killing the tasklet to prevent the interrupt
* handler from rescheduling the tasklet after it has been killed.
*/
free_irq(core_dev->irq, dev);
tasklet_kill(&core_dev->tasklet);
/* Un-register with Linux CryptoAPI */
crypto4xx_unregister_alg(core_dev->dev);

View File

@@ -257,10 +257,8 @@ static int meson_crypto_probe(struct platform_device *pdev)
err = devm_request_irq(&pdev->dev, mc->irqs[i], meson_irq_handler, 0,
"gxl-crypto", mc);
if (err < 0) {
dev_err(mc->dev, "Cannot request IRQ for flow %d\n", i);
if (err < 0)
return err;
}
}
err = clk_prepare_enable(mc->busclk);

View File

@@ -728,14 +728,12 @@ static int aspeed_acry_probe(struct platform_device *pdev)
/* Get irq number and register it */
acry_dev->irq = platform_get_irq(pdev, 0);
if (acry_dev->irq < 0)
return -ENXIO;
return acry_dev->irq;
rc = devm_request_irq(dev, acry_dev->irq, aspeed_acry_irq, 0,
dev_name(dev), acry_dev);
if (rc) {
dev_err(dev, "Failed to request irq.\n");
if (rc)
return rc;
}
acry_dev->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(acry_dev->clk)) {

View File

@@ -127,14 +127,12 @@ static int aspeed_hace_probe(struct platform_device *pdev)
/* Get irq number and register it */
hace_dev->irq = platform_get_irq(pdev, 0);
if (hace_dev->irq < 0)
return -ENXIO;
return hace_dev->irq;
rc = devm_request_irq(&pdev->dev, hace_dev->irq, aspeed_hace_irq, 0,
dev_name(&pdev->dev), hace_dev);
if (rc) {
dev_err(&pdev->dev, "Failed to request interrupt\n");
if (rc)
return rc;
}
/* Get clk and enable it */
hace_dev->clk = devm_clk_get(&pdev->dev, NULL);

View File

@@ -2368,10 +2368,8 @@ static int atmel_aes_probe(struct platform_device *pdev)
err = devm_request_irq(&pdev->dev, aes_dd->irq, atmel_aes_irq,
IRQF_SHARED, "atmel-aes", aes_dd);
if (err) {
dev_err(dev, "unable to request aes irq.\n");
if (err)
goto err_tasklet_kill;
}
/* Initializing the clock */
aes_dd->iclk = devm_clk_get_prepared(&pdev->dev, "aes_clk");

View File

@@ -27,21 +27,18 @@ static struct atmel_ecc_driver_data driver_data;
/**
* struct atmel_ecdh_ctx - transformation context
* @client : pointer to i2c client device
* @fallback : used for unsupported curves or when user wants to use its own
* private key.
* @public_key : generated when calling set_secret(). It's the responsibility
* of the user to not call set_secret() while
* generate_public_key() or compute_shared_secret() are in flight.
* @curve_id : elliptic curve id
* @do_fallback: true when the device doesn't support the curve or when the user
* wants to use its own private key.
* @client: I2C client device
* @fallback: ECDH fallback used for caller-provided private keys
* @public_key: cached public key for the device-generated private key
* @do_fallback: true when ECDH operations should use @fallback
*
* The caller must not invoke set_secret() while generate_public_key()
* or compute_shared_secret() are in flight.
*/
struct atmel_ecdh_ctx {
struct i2c_client *client;
struct crypto_kpp *fallback;
const u8 *public_key;
unsigned int curve_id;
bool do_fallback;
};
@@ -55,7 +52,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,
if (status)
goto free_work_data;
/* might want less than we've got */
/* copy only as much as requested, capped at 32 bytes */
n_sz = min(ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len);
/* copy the shared secret */
@@ -64,15 +61,15 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,
if (copied != n_sz)
status = -EINVAL;
/* fall through */
free_work_data:
kfree_sensitive(work_data);
kpp_request_complete(req, status);
}
/*
* A random private key is generated and stored in the device. The device
* returns the pair public key.
* If no private key is provided, generate one in the device and cache
* the corresponding public key. The generated private key never leaves
* the device.
*/
static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
unsigned int len)
@@ -83,10 +80,9 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
struct ecdh params;
int ret = -ENOMEM;
/* free the old public key, if any */
kfree(ctx->public_key);
/* make sure you don't free the old public key twice */
ctx->public_key = NULL;
ctx->do_fallback = false;
if (crypto_ecdh_decode_key(buf, len, &params) < 0) {
dev_err(&ctx->client->dev, "crypto_ecdh_decode_key failed\n");
@@ -94,41 +90,30 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
}
if (params.key_size) {
/* fallback to ecdh software implementation */
ctx->do_fallback = true;
return crypto_kpp_set_secret(ctx->fallback, buf, len);
ret = crypto_kpp_set_secret(ctx->fallback, buf, len);
ctx->do_fallback = !ret;
return ret;
}
cmd = kmalloc_obj(*cmd);
if (!cmd)
return -ENOMEM;
/*
* The device only supports NIST P256 ECC keys. The public key size will
* always be the same. Use a macro for the key size to avoid unnecessary
* computations.
*/
public_key = kmalloc(ATMEL_ECC_PUBKEY_SIZE, GFP_KERNEL);
if (!public_key)
goto free_cmd;
ctx->do_fallback = false;
atmel_i2c_init_genkey_cmd(cmd, DATA_SLOT_2);
ret = atmel_i2c_send_receive(ctx->client, cmd);
if (ret)
goto free_public_key;
if (ret) {
kfree(public_key);
goto free_cmd;
}
/* save the public key */
memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE);
ctx->public_key = public_key;
kfree(cmd);
return 0;
free_public_key:
kfree(public_key);
free_cmd:
kfree(cmd);
return ret;
@@ -139,7 +124,6 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req)
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm);
size_t copied, nbytes;
int ret = 0;
if (ctx->do_fallback) {
kpp_request_set_tfm(req, ctx->fallback);
@@ -149,7 +133,7 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req)
if (!ctx->public_key)
return -EINVAL;
/* might want less than we've got */
/* copy only as much as requested, capped at 64 bytes */
nbytes = min(ATMEL_ECC_PUBKEY_SIZE, req->dst_len);
/* public key was saved at private key generation */
@@ -157,9 +141,9 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req)
sg_nents_for_len(req->dst, nbytes),
ctx->public_key, nbytes);
if (copied != nbytes)
ret = -EINVAL;
return -EINVAL;
return ret;
return 0;
}
static int atmel_ecdh_compute_shared_secret(struct kpp_request *req)
@@ -175,7 +159,10 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req)
return crypto_kpp_compute_shared_secret(req);
}
/* must have exactly two points to be on the curve */
if (!ctx->public_key)
return -EINVAL;
/* A P-256 public key must contain two 32-byte coordinates */
if (req->src_len != ATMEL_ECC_PUBKEY_SIZE)
return -EINVAL;
@@ -250,7 +237,6 @@ static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm)
struct crypto_kpp *fallback;
struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm);
ctx->curve_id = ECC_CURVE_NIST_P256;
ctx->client = atmel_ecc_i2c_client_alloc();
if (IS_ERR(ctx->client)) {
pr_err("tfm - i2c_client binding failed\n");

View File

@@ -138,9 +138,8 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
cmd->param2 = cpu_to_le16(DATA_SLOT_2);
/*
* The device only supports NIST P256 ECC keys. The public key size will
* always be the same. Use a macro for the key size to avoid unnecessary
* computations.
* The device only supports P-256. Its public key is encoded as
* two 32-byte coordinates.
*/
copied = sg_copy_to_buffer(pubkey,
sg_nents_for_len(pubkey,

View File

@@ -2604,10 +2604,8 @@ static int atmel_sha_probe(struct platform_device *pdev)
err = devm_request_irq(&pdev->dev, sha_dd->irq, atmel_sha_irq,
IRQF_SHARED, "atmel-sha", sha_dd);
if (err) {
dev_err(dev, "unable to request sha irq.\n");
if (err)
goto err_tasklet_kill;
}
/* Initializing the clock */
sha_dd->iclk = devm_clk_get_prepared(&pdev->dev, "sha_clk");

View File

@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/workqueue.h>
#include "atmel-i2c.h"
@@ -31,10 +32,14 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data,
struct atmel_i2c_client_priv *i2c_priv = work_data->ctx;
struct hwrng *rng = areq;
if (status)
if (status) {
dev_warn_ratelimited(&i2c_priv->client->dev,
"i2c transaction failed (%d)\n",
status);
kfree_sensitive(work_data);
atomic_dec(&i2c_priv->tfm_count);
return;
}
rng->priv = (unsigned long)work_data;
atomic_dec(&i2c_priv->tfm_count);
@@ -91,12 +96,15 @@ static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max,
ret = atmel_i2c_send_receive(i2c_priv->client, &cmd);
if (ret)
return ret;
goto out;
max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
memcpy(data, &cmd.data[RSP_DATA_IDX], max);
ret = max;
return max;
out:
memzero_explicit(&cmd, sizeof(cmd));
return ret;
}
static int atmel_sha204a_otp_read(struct i2c_client *client, u16 addr, u8 *otp)
@@ -205,7 +213,7 @@ static void atmel_sha204a_remove(struct i2c_client *client)
devm_hwrng_unregister(&client->dev, &i2c_priv->hwrng);
atmel_i2c_flush_queue();
kfree((void *)i2c_priv->hwrng.priv);
kfree_sensitive((void *)i2c_priv->hwrng.priv);
}
static const struct of_device_id atmel_sha204a_dt_ids[] = {

View File

@@ -284,7 +284,6 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd)
{
int err = 0;
size_t count;
atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
@@ -296,24 +295,23 @@ static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd)
dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out,
dd->dma_size, DMA_FROM_DEVICE);
/* copy data */
count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset,
dd->buf_out, dd->buflen, dd->dma_size, 1);
if (count != dd->dma_size) {
err = -EINVAL;
dev_dbg(dd->dev, "not all data converted: %zu\n", count);
return -EINVAL;
}
}
return err;
return 0;
}
static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd)
{
int err = -ENOMEM;
dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0);
dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0);
dd->buf_in = (void *)__get_free_page(GFP_KERNEL);
dd->buf_out = (void *)__get_free_page(GFP_KERNEL);
dd->buflen = PAGE_SIZE;
dd->buflen &= ~(DES_BLOCK_SIZE - 1);
@@ -450,26 +448,19 @@ static int atmel_tdes_crypt_dma(struct atmel_tdes_dev *dd,
static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd)
{
int err, fast = 0, in, out;
bool fast;
int err;
size_t count;
dma_addr_t addr_in, addr_out;
if ((!dd->in_offset) && (!dd->out_offset)) {
/* check for alignment */
in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)) &&
IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size);
out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)) &&
IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size);
fast = in && out;
fast = !dd->in_offset && !dd->out_offset &&
dd->in_sg->length == dd->out_sg->length &&
IS_ALIGNED(dd->in_sg->offset, sizeof(u32)) &&
IS_ALIGNED(dd->out_sg->offset, sizeof(u32)) &&
IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size);
if (sg_dma_len(dd->in_sg) != sg_dma_len(dd->out_sg))
fast = 0;
}
if (fast) {
count = min_t(size_t, dd->total, sg_dma_len(dd->in_sg));
count = min_t(size_t, count, sg_dma_len(dd->out_sg));
if (fast) {
count = min(dd->total, dd->in_sg->length);
err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
if (!err) {
@@ -609,28 +600,25 @@ static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
{
int err = -EINVAL;
size_t count;
if (dd->flags & TDES_FLAGS_DMA) {
err = 0;
if (dd->flags & TDES_FLAGS_FAST) {
dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
} else {
dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out,
dd->dma_size, DMA_FROM_DEVICE);
if (dd->flags & TDES_FLAGS_FAST) {
dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
} else {
dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out, dd->dma_size,
DMA_FROM_DEVICE);
/* copy data */
count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset,
dd->buf_out, dd->buflen, dd->dma_size, 1);
if (count != dd->dma_size) {
err = -EINVAL;
dev_dbg(dd->dev, "not all data converted: %zu\n", count);
}
count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset,
dd->buf_out, dd->buflen,
dd->dma_size, 1);
if (count != dd->dma_size) {
dev_dbg(dd->dev, "not all data converted: %zu\n", count);
return -EINVAL;
}
}
return err;
return 0;
}
static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode)
@@ -979,10 +967,8 @@ static int atmel_tdes_probe(struct platform_device *pdev)
err = devm_request_irq(&pdev->dev, tdes_dd->irq, atmel_tdes_irq,
IRQF_SHARED, "atmel-tdes", tdes_dd);
if (err) {
dev_err(dev, "unable to request tdes irq.\n");
if (err)
goto err_tasklet_kill;
}
/* Initializing the clock */
tdes_dd->iclk = devm_clk_get(&pdev->dev, "tdes_clk");

View File

@@ -2387,9 +2387,7 @@ static int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key,
* outer hashing in software.
*/
if (iproc_priv.spu.spu_type == SPU_TYPE_SPUM) {
memcpy(ctx->ipad, ctx->authkey, ctx->authkeylen);
memset(ctx->ipad + ctx->authkeylen, 0,
blocksize - ctx->authkeylen);
memcpy_and_pad(ctx->ipad, blocksize, ctx->authkey, ctx->authkeylen, 0);
ctx->authkeylen = 0;
unsafe_memcpy(ctx->opad, ctx->ipad, blocksize,
"fortified memcpy causes -Wrestrict warning");

View File

@@ -145,20 +145,11 @@ config CRYPTO_DEV_FSL_CAAM_PKC_API
config CRYPTO_DEV_FSL_CAAM_RNG_API
bool "Register caam device for hwrng API"
default y
select CRYPTO_RNG
select HW_RANDOM
help
Selecting this will register the SEC4 hardware rng to
the hw_random API for supplying the kernel entropy pool.
config CRYPTO_DEV_FSL_CAAM_PRNG_API
bool "Register Pseudo random number generation implementation with Crypto API"
default y
select CRYPTO_RNG
help
Selecting this will register the SEC hardware prng to
the Crypto API.
config CRYPTO_DEV_FSL_CAAM_BLOB_GEN
bool

View File

@@ -20,7 +20,6 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API) += caamprng.o
caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o
caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_BLOB_GEN) += blob_gen.o

View File

@@ -1,241 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Driver to expose SEC4 PRNG via crypto RNG API
*
* Copyright 2022 NXP
*
*/
#include <linux/completion.h>
#include <crypto/internal/rng.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include "compat.h"
#include "regs.h"
#include "intern.h"
#include "desc_constr.h"
#include "jr.h"
#include "error.h"
/*
* Length of used descriptors, see caam_init_desc()
*/
#define CAAM_PRNG_MAX_DESC_LEN (CAAM_CMD_SZ + \
CAAM_CMD_SZ + \
CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
/* prng per-device context */
struct caam_prng_ctx {
int err;
struct completion done;
};
struct caam_prng_alg {
struct rng_alg rng;
bool registered;
};
static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
void *context)
{
struct caam_prng_ctx *jctx = context;
jctx->err = err ? caam_jr_strstatus(jrdev, err) : 0;
complete(&jctx->done);
}
static u32 *caam_init_reseed_desc(u32 *desc)
{
init_job_desc(desc, 0); /* + 1 cmd_sz */
/* Generate random bytes: + 1 cmd_sz */
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
OP_ALG_AS_FINALIZE);
print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
16, 4, desc, desc_bytes(desc), 1);
return desc;
}
static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
{
init_job_desc(desc, 0); /* + 1 cmd_sz */
/* Generate random bytes: + 1 cmd_sz */
append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
/* Store bytes: + 1 cmd_sz + caam_ptr_sz */
append_fifo_store(desc, dst_dma,
len, FIFOST_TYPE_RNGSTORE);
print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
16, 4, desc, desc_bytes(desc), 1);
return desc;
}
static int caam_prng_generate(struct crypto_rng *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int dlen)
{
unsigned int aligned_dlen = ALIGN(dlen, dma_get_cache_alignment());
struct caam_prng_ctx ctx;
struct device *jrdev;
dma_addr_t dst_dma;
u32 *desc;
u8 *buf;
int ret;
if (aligned_dlen < dlen)
return -EOVERFLOW;
buf = kzalloc(aligned_dlen, GFP_KERNEL);
if (!buf)
return -ENOMEM;
jrdev = caam_jr_alloc();
ret = PTR_ERR_OR_ZERO(jrdev);
if (ret) {
pr_err("Job Ring Device allocation failed\n");
kfree(buf);
return ret;
}
desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL);
if (!desc) {
ret = -ENOMEM;
goto out1;
}
dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE);
if (dma_mapping_error(jrdev, dst_dma)) {
dev_err(jrdev, "Failed to map destination buffer memory\n");
ret = -ENOMEM;
goto out;
}
init_completion(&ctx.done);
ret = caam_jr_enqueue(jrdev,
caam_init_prng_desc(desc, dst_dma, dlen),
caam_prng_done, &ctx);
if (ret == -EINPROGRESS) {
wait_for_completion(&ctx.done);
ret = ctx.err;
}
dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
if (!ret)
memcpy(dst, buf, dlen);
out:
kfree(desc);
out1:
caam_jr_free(jrdev);
kfree(buf);
return ret;
}
static void caam_prng_exit(struct crypto_tfm *tfm) {}
static int caam_prng_init(struct crypto_tfm *tfm)
{
return 0;
}
static int caam_prng_seed(struct crypto_rng *tfm,
const u8 *seed, unsigned int slen)
{
struct caam_prng_ctx ctx;
struct device *jrdev;
u32 *desc;
int ret;
if (slen) {
pr_err("Seed length should be zero\n");
return -EINVAL;
}
jrdev = caam_jr_alloc();
ret = PTR_ERR_OR_ZERO(jrdev);
if (ret) {
pr_err("Job Ring Device allocation failed\n");
return ret;
}
desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL);
if (!desc) {
caam_jr_free(jrdev);
return -ENOMEM;
}
init_completion(&ctx.done);
ret = caam_jr_enqueue(jrdev,
caam_init_reseed_desc(desc),
caam_prng_done, &ctx);
if (ret == -EINPROGRESS) {
wait_for_completion(&ctx.done);
ret = ctx.err;
}
kfree(desc);
caam_jr_free(jrdev);
return ret;
}
static struct caam_prng_alg caam_prng_alg = {
.rng = {
.generate = caam_prng_generate,
.seed = caam_prng_seed,
.seedsize = 0,
.base = {
.cra_name = "stdrng",
.cra_driver_name = "prng-caam",
.cra_priority = 500,
.cra_ctxsize = sizeof(struct caam_prng_ctx),
.cra_module = THIS_MODULE,
.cra_init = caam_prng_init,
.cra_exit = caam_prng_exit,
},
}
};
void caam_prng_unregister(void *data)
{
if (caam_prng_alg.registered)
crypto_unregister_rng(&caam_prng_alg.rng);
}
int caam_prng_register(struct device *ctrldev)
{
struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
u32 rng_inst;
int ret = 0;
/* Check for available RNG blocks before registration */
if (priv->era < 10)
rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
else
rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
if (!rng_inst) {
dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n");
return ret;
}
ret = crypto_register_rng(&caam_prng_alg.rng);
if (ret) {
dev_err(ctrldev,
"couldn't register rng crypto alg: %d\n",
ret);
return ret;
}
caam_prng_alg.registered = true;
dev_info(ctrldev,
"rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name);
return 0;
}

View File

@@ -212,21 +212,6 @@ static inline void caam_rng_exit(struct device *dev) {}
#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */
#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API
int caam_prng_register(struct device *dev);
void caam_prng_unregister(void *data);
#else
static inline int caam_prng_register(struct device *dev)
{
return 0;
}
static inline void caam_prng_unregister(void *data) {}
#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API */
#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI
int caam_qi_algapi_init(struct device *dev);

View File

@@ -40,7 +40,6 @@ static void register_algs(struct caam_drv_private_jr *jrpriv,
caam_algapi_hash_init(dev);
caam_pkc_init(dev);
jrpriv->hwrng = !caam_rng_init(dev);
caam_prng_register(dev);
caam_qi_algapi_init(dev);
algs_unlock:
@@ -55,7 +54,6 @@ static void unregister_algs(void)
goto algs_unlock;
caam_qi_algapi_exit();
caam_prng_unregister(NULL);
caam_pkc_exit();
caam_algapi_hash_exit();
caam_algapi_exit();
@@ -576,23 +574,25 @@ static int caam_jr_init(struct device *dev)
return error;
}
static void caam_jr_irq_dispose_mapping(void *data)
{
irq_dispose_mapping((unsigned long)data);
}
/*
* Probe routine for each detected JobR subsystem.
*/
static int caam_jr_probe(struct platform_device *pdev)
{
struct device *jrdev;
struct device_node *nprop;
struct caam_job_ring __iomem *ctrl;
struct caam_drv_private_jr *jrpriv;
static int total_jobrs;
struct resource *r;
void __iomem *ctrl;
int error;
int irq;
ctrl = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ctrl))
return PTR_ERR(ctrl);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
jrdev = &pdev->dev;
jrpriv = devm_kzalloc(jrdev, sizeof(*jrpriv), GFP_KERNEL);
@@ -604,22 +604,7 @@ static int caam_jr_probe(struct platform_device *pdev)
/* save ring identity relative to detection */
jrpriv->ridx = total_jobrs++;
nprop = pdev->dev.of_node;
/* Get configuration properties from device tree */
/* First, get register page */
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(jrdev, "platform_get_resource() failed\n");
return -ENOMEM;
}
ctrl = devm_ioremap(jrdev, r->start, resource_size(r));
if (!ctrl) {
dev_err(jrdev, "devm_ioremap() failed\n");
return -ENOMEM;
}
jrpriv->rregs = (struct caam_job_ring __iomem __force *)ctrl;
jrpriv->rregs = ctrl;
error = dma_set_mask_and_coherent(jrdev, caam_get_dma_mask(jrdev));
if (error) {
@@ -649,16 +634,7 @@ static int caam_jr_probe(struct platform_device *pdev)
}
/* Identify the interrupt */
jrpriv->irq = irq_of_parse_and_map(nprop, 0);
if (!jrpriv->irq) {
dev_err(jrdev, "irq_of_parse_and_map failed\n");
return -EINVAL;
}
error = devm_add_action_or_reset(jrdev, caam_jr_irq_dispose_mapping,
(void *)(unsigned long)jrpriv->irq);
if (error)
return error;
jrpriv->irq = irq;
/* Now do the platform independent part */
error = caam_jr_init(jrdev); /* now turn on hardware */

View File

@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/delay.h>
#include <linux/string.h>
#include "nitrox_dev.h"
#include "nitrox_csr.h"
@@ -647,7 +648,7 @@ void nitrox_get_hwinfo(struct nitrox_device *ndev)
ndev->hw.revision_id);
/* copy partname */
strscpy(ndev->hw.partname, name, sizeof(ndev->hw.partname));
strscpy(ndev->hw.partname, name);
}
void enable_pf2vf_mbox_interrupts(struct nitrox_device *ndev)

View File

@@ -426,7 +426,7 @@ static int ccp_register_hmac_alg(struct list_head *head,
*ccp_alg = *base_alg;
INIT_LIST_HEAD(&ccp_alg->entry);
strscpy(ccp_alg->child_alg, def->name, CRYPTO_MAX_ALG_NAME);
strscpy(ccp_alg->child_alg, def->name);
alg = &ccp_alg->alg;
alg->setkey = ccp_sha_setkey;

View File

@@ -245,6 +245,7 @@ static int sev_cmd_buffer_len(int cmd)
case SEV_CMD_SNP_LAUNCH_FINISH: return sizeof(struct sev_data_snp_launch_finish);
case SEV_CMD_SNP_DBG_DECRYPT: return sizeof(struct sev_data_snp_dbg);
case SEV_CMD_SNP_DBG_ENCRYPT: return sizeof(struct sev_data_snp_dbg);
case SEV_CMD_SNP_VERIFY_MITIGATION: return sizeof(struct sev_data_snp_verify_mitigation);
case SEV_CMD_SNP_PAGE_UNSMASH: return sizeof(struct sev_data_snp_page_unsmash);
case SEV_CMD_SNP_PLATFORM_STATUS: return sizeof(struct sev_data_snp_addr);
case SEV_CMD_SNP_GUEST_REQUEST: return sizeof(struct sev_data_snp_guest_request);
@@ -1348,6 +1349,162 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg)
return 0;
}
#ifdef CONFIG_SYSFS
static int snp_verify_mitigation(u16 command, u64 vector,
struct sev_data_snp_verify_mitigation_dst *dst)
{
struct sev_data_snp_verify_mitigation_dst *mit_dst = NULL;
struct sev_data_snp_verify_mitigation data = {0};
struct sev_device *sev = psp_master->sev_data;
int ret, error = 0;
mit_dst = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO);
if (!mit_dst)
return -ENOMEM;
data.length = sizeof(data);
data.subcommand = command;
data.vector = vector;
data.dst_paddr = __psp_pa(mit_dst);
data.dst_paddr_en = true;
ret = sev_do_cmd(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &error);
if (!ret)
memcpy(dst, mit_dst, sizeof(*mit_dst));
else
dev_err(sev->dev, "SNP_VERIFY_MITIGATION command failed, ret = %d, error = %#x\n",
ret, error);
snp_free_firmware_page(mit_dst);
return ret;
}
static ssize_t supported_mitigations_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct sev_data_snp_verify_mitigation_dst dst;
int ret;
ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
if (ret)
return ret;
return sysfs_emit(buf, "0x%llx\n", dst.mit_supported_vector);
}
static struct kobj_attribute supported_attr =
__ATTR_RO_MODE(supported_mitigations, 0400);
static ssize_t verified_mitigations_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct sev_data_snp_verify_mitigation_dst dst;
int ret;
ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
if (ret)
return ret;
return sysfs_emit(buf, "0x%llx\n", dst.mit_verified_vector);
}
static ssize_t verified_mitigations_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct sev_data_snp_verify_mitigation_dst dst;
struct sev_device *sev = psp_master->sev_data;
u64 vector;
int ret;
ret = kstrtoull(buf, 0, &vector);
if (ret)
return ret;
/*
* The firmware verifies a single mitigation per call. Reject vectors
* with more than one bit set early to avoid a guaranteed-to-fail call
*/
if (hweight64(vector) != 1)
return -EINVAL;
ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_VERIFY, vector, &dst);
if (ret)
return ret;
if (dst.mit_failure_status) {
dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n",
dst.mit_failure_status);
return -EINVAL;
}
return count;
}
static struct kobj_attribute verified_attr =
__ATTR_RW_MODE(verified_mitigations, 0600);
static struct attribute *mitigation_attrs[] = {
&supported_attr.attr,
&verified_attr.attr,
NULL
};
static const struct attribute_group mit_attr_group = {
.attrs = mitigation_attrs,
};
static void sev_snp_register_verify_mitigation(struct sev_device *sev)
{
int rc;
if (!(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED) ||
sev->verify_mit)
return;
if (!sev->sev_kobj) {
sev->sev_kobj = kobject_create_and_add("sev", firmware_kobj);
if (!sev->sev_kobj)
return;
}
sev->verify_mit = kobject_create_and_add("vulnerabilities", sev->sev_kobj);
if (!sev->verify_mit)
goto err_sev_kobj;
rc = sysfs_create_group(sev->verify_mit, &mit_attr_group);
if (rc)
goto err_verify_mit;
return;
err_verify_mit:
kobject_put(sev->verify_mit);
sev->verify_mit = NULL;
err_sev_kobj:
kobject_put(sev->sev_kobj);
sev->sev_kobj = NULL;
}
static void sev_snp_unregister_verify_mitigation(struct sev_device *sev)
{
if (sev->verify_mit) {
sysfs_remove_group(sev->verify_mit, &mit_attr_group);
kobject_put(sev->verify_mit);
sev->verify_mit = NULL;
}
if (sev->sev_kobj) {
kobject_put(sev->sev_kobj);
sev->sev_kobj = NULL;
}
}
#else // CONFIG_SYSFS
static void sev_snp_register_verify_mitigation(struct sev_device *sev) { }
static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { }
#endif // CONFIG_SYSFS
static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
{
struct sev_data_range_list *snp_range_list __free(kfree) = NULL;
@@ -1541,7 +1698,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
if (sev_init_ex_buffer)
return 0;
page = alloc_pages(GFP_KERNEL, get_order(NV_LENGTH));
page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(NV_LENGTH));
if (!page) {
dev_err(sev->dev, "SEV: INIT_EX NV memory allocation failed\n");
return -ENOMEM;
@@ -1551,20 +1708,31 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
rc = sev_read_init_ex_file();
if (rc)
return rc;
goto err_free;
/* If SEV-SNP is initialized, transition to firmware page. */
if (sev->snp_initialized) {
unsigned long npages;
npages = 1UL << get_order(NV_LENGTH);
if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, false)) {
if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, true)) {
dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n");
return -ENOMEM;
rc = -ENOMEM;
/*
* Pages can be in an inconsistent state, don't release them back to the
* system.
*/
goto err_reset;
}
}
return 0;
err_free:
__free_pages(page, get_order(NV_LENGTH));
err_reset:
sev_init_ex_buffer = NULL;
return rc;
}
static int __sev_platform_init_locked(int *error)
@@ -1671,6 +1839,17 @@ int sev_platform_init(struct sev_platform_init_args *args)
rc = _sev_platform_init_locked(args);
mutex_unlock(&sev_cmd_mutex);
/*
* Register the sysfs interface outside the sev_cmd_mutex. The
* _show()/_store() handlers issue SEV commands that acquire the
* sev_cmd_mutex, so creating (and on the shutdown path, removing) the
* sysfs group must stay outside that lock. sysfs provides its own
* synchronization between group creation/removal and concurrent
* attribute access.
*/
if (!rc)
sev_snp_register_verify_mitigation(psp_master->sev_data);
return rc;
}
EXPORT_SYMBOL_GPL(sev_platform_init);
@@ -2765,6 +2944,15 @@ static void sev_firmware_shutdown(struct sev_device *sev)
if (sev->tio_status)
sev_tsm_uninit(sev);
/*
* Remove the sysfs interface before taking the sev_cmd_mutex.
* sysfs_remove_group() waits for in-flight _show()/_store() handlers
* to drain, and those handlers issue SNP_VERIFY_MITIGATION via
* sev_do_cmd() which acquires the sev_cmd_mutex. Removing the group
* while holding the mutex could therefore deadlock.
*/
sev_snp_unregister_verify_mitigation(sev);
mutex_lock(&sev_cmd_mutex);
__sev_firmware_shutdown(sev, false);

View File

@@ -59,6 +59,9 @@ struct sev_device {
bool snp_initialized;
struct kobject *sev_kobj;
struct kobject *verify_mit;
struct sev_user_data_status sev_plat_status;
struct sev_user_data_snp_status snp_plat_status;

View File

@@ -471,10 +471,8 @@ static int init_cc_resources(struct platform_device *plat_dev)
/* register the driver isr function */
rc = devm_request_irq(dev, irq, cc_isr, IRQF_SHARED, "ccree",
new_drvdata);
if (rc) {
dev_err(dev, "Could not register to interrupt %d\n", irq);
if (rc)
goto post_pm_err;
}
dev_dbg(dev, "Registered to IRQ: %d\n", irq);
init_cc_cache_params(new_drvdata);

View File

@@ -56,10 +56,6 @@ static bool sl3516_ce_need_fallback(struct skcipher_request *areq)
ce->fallback_mod16++;
return true;
}
if ((sg_dma_len(sg) % 16) != 0) {
ce->fallback_mod16++;
return true;
}
if (!IS_ALIGNED(sg->offset, 16)) {
ce->fallback_align16++;
return true;
@@ -72,10 +68,6 @@ static bool sl3516_ce_need_fallback(struct skcipher_request *areq)
ce->fallback_mod16++;
return true;
}
if ((sg_dma_len(sg) % 16) != 0) {
ce->fallback_mod16++;
return true;
}
if (!IS_ALIGNED(sg->offset, 16)) {
ce->fallback_align16++;
return true;

View File

@@ -414,10 +414,8 @@ static int sl3516_ce_probe(struct platform_device *pdev)
return irq;
err = devm_request_irq(&pdev->dev, irq, ce_irq_handler, 0, "crypto", ce);
if (err) {
dev_err(ce->dev, "Cannot request Crypto Engine IRQ (err=%d)\n", err);
if (err)
return err;
}
ce->reset = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(ce->reset))

View File

@@ -2944,11 +2944,8 @@ static int qm_alloc_uacce(struct hisi_qm *qm)
.flags = UACCE_DEV_SVA,
.ops = &uacce_qm_ops,
};
int ret;
ret = strscpy(interface.name, dev_driver_string(&pdev->dev),
sizeof(interface.name));
if (ret < 0)
if (strscpy(interface.name, dev_driver_string(&pdev->dev)) < 0)
return -ENAMETOOLONG;
uacce = uacce_alloc(&pdev->dev, &interface);

View File

@@ -1010,25 +1010,12 @@ static void sec_queue_base_init(struct sec_dev_info *info,
static int sec_map_io(struct sec_dev_info *info, struct platform_device *pdev)
{
struct resource *res;
int i;
for (i = 0; i < SEC_NUM_ADDR_REGIONS; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res) {
dev_err(info->dev, "Memory resource %d not found\n", i);
return -EINVAL;
}
info->regs[i] = devm_ioremap(info->dev, res->start,
resource_size(res));
if (!info->regs[i]) {
dev_err(info->dev,
"Memory resource %d could not be remapped\n",
i);
return -EINVAL;
}
info->regs[i] = devm_platform_ioremap_resource(pdev, i);
if (IS_ERR(info->regs[i]))
return PTR_ERR(info->regs[i]);
}
return 0;

View File

@@ -181,9 +181,6 @@ struct sec_ctx {
const struct sec_req_op *req_op;
struct hisi_qp **qps;
/* Half queues for encipher, and half for decipher */
u32 hlf_q_num;
/* Current cyclic index to select a queue for encipher */
atomic_t enc_qcyclic;

View File

@@ -96,7 +96,6 @@
#define IV_FLAGS_OFFSET 0x6
#define IV_CM_OFFSET 0x3
#define IV_LAST_BYTE1 1
#define IV_LAST_BYTE2 2
#define IV_LAST_BYTE_MASK 0xFF
#define IV_CTR_INIT 0x1
#define IV_BYTE_OFFSET 0x8
@@ -669,9 +668,13 @@ static int sec_ctx_base_init(struct sec_ctx *ctx)
sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm);
ctx->sec = sec;
ctx->dev = &sec->qm.pdev->dev;
ctx->hlf_q_num = sec->ctx_q_num >> 1;
ctx->pbuf_supported = ctx->sec->iommu_used;
if (sec->qm.ver < QM_HW_V3)
ctx->type_supported = SEC_BD_TYPE2;
else
ctx->type_supported = SEC_BD_TYPE3;
ctx->qp_ctx = kzalloc_objs(struct sec_qp_ctx, sec->ctx_q_num);
if (!ctx->qp_ctx) {
ret = -ENOMEM;
@@ -1696,7 +1699,7 @@ static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req)
struct sec_cipher_req *c_req = &req->c_req;
u32 data_size = aead_req->cryptlen;
u8 flage = 0;
u8 cm, cl;
u8 cm, cl, i;
/* the specification has been checked in aead_iv_demension_check() */
cl = c_req->c_ivin[0] + 1;
@@ -1720,15 +1723,16 @@ static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req)
* the last 32bit is counter's initial number,
* but the nonce uses the first 16bit
* the tail 16bit fill with the cipher length
* When CL is 3, the tail 24bit fill with the cipher length.
*/
if (!c_req->encrypt)
data_size = aead_req->cryptlen - authsize;
a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE1] =
data_size & IV_LAST_BYTE_MASK;
data_size >>= IV_BYTE_OFFSET;
a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE2] =
for (i = 1; i <= cl; i++) {
a_req->a_ivin[ctx->c_ctx.ivsize - i] =
data_size & IV_LAST_BYTE_MASK;
data_size >>= IV_BYTE_OFFSET;
}
}
static void sec_aead_set_iv(struct sec_ctx *ctx, struct sec_req *req)
@@ -2067,13 +2071,10 @@ static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
if (!ctx->qps)
return 0;
if (ctx->sec->qm.ver < QM_HW_V3) {
ctx->type_supported = SEC_BD_TYPE2;
ctx->req_op = &sec_skcipher_req_ops;
} else {
ctx->type_supported = SEC_BD_TYPE3;
if (ctx->type_supported == SEC_BD_TYPE3)
ctx->req_op = &sec_skcipher_req_ops_v3;
}
else
ctx->req_op = &sec_skcipher_req_ops;
return 0;
}
@@ -2100,13 +2101,11 @@ static int sec_aead_init(struct crypto_aead *tfm)
ret = sec_ctx_base_init(ctx);
if (ret)
return ret;
if (ctx->sec->qm.ver < QM_HW_V3) {
ctx->type_supported = SEC_BD_TYPE2;
ctx->req_op = &sec_aead_req_ops;
} else {
ctx->type_supported = SEC_BD_TYPE3;
if (ctx->type_supported == SEC_BD_TYPE3)
ctx->req_op = &sec_aead_req_ops_v3;
}
else
ctx->req_op = &sec_aead_req_ops;
ret = sec_auth_init(ctx);
if (ret)

View File

@@ -966,10 +966,8 @@ static int img_hash_probe(struct platform_device *pdev)
err = devm_request_irq(dev, irq, img_irq_handler, 0,
dev_name(dev), hdev);
if (err) {
dev_err(dev, "unable to request irq\n");
if (err)
goto res_err;
}
dev_dbg(dev, "using IRQ channel %d\n", irq);
hdev->hash_clk = devm_clk_get_enabled(&pdev->dev, "hash");

View File

@@ -415,7 +415,7 @@ static int eip93_crypto_probe(struct platform_device *pdev)
u32 ver, algo_flags;
int ret;
eip93 = devm_kzalloc(dev, sizeof(*eip93), GFP_KERNEL);
eip93 = devm_kzalloc(dev, struct_size(eip93, ring, 1), GFP_KERNEL);
if (!eip93)
return -ENOMEM;
@@ -436,10 +436,6 @@ static int eip93_crypto_probe(struct platform_device *pdev)
if (ret)
return ret;
eip93->ring = devm_kcalloc(eip93->dev, 1, sizeof(*eip93->ring), GFP_KERNEL);
if (!eip93->ring)
return -ENOMEM;
ret = eip93_desc_init(eip93);
if (ret)
return ret;

View File

@@ -92,17 +92,6 @@
EIP93_HASH_SHA224 | \
EIP93_HASH_SHA256))
/**
* struct eip93_device - crypto engine device structure
*/
struct eip93_device {
void __iomem *base;
struct device *dev;
struct clk *clk;
int irq;
struct eip93_ring *ring;
};
struct eip93_desc_ring {
void *base;
void *base_end;
@@ -131,6 +120,17 @@ struct eip93_ring {
struct idr crypto_async_idr;
};
/**
* struct eip93_device - crypto engine device structure
*/
struct eip93_device {
void __iomem *base;
struct device *dev;
struct clk *clk;
int irq;
struct eip93_ring ring[];
};
enum eip93_alg_type {
EIP93_ALG_TYPE_AEAD,
EIP93_ALG_TYPE_SKCIPHER,

View File

@@ -1172,10 +1172,8 @@ static int safexcel_request_ring_irq(void *pdev, int irqid,
ret = devm_request_threaded_irq(dev, irq, handler,
threaded_handler, IRQF_ONESHOT,
dev_name(dev), ring_irq_priv);
if (ret) {
dev_err(dev, "unable to request IRQ %d\n", irq);
if (ret)
return ret;
}
/* Set affinity */
cpu = cpumask_local_spread(ring_id, NUMA_NO_NODE);

View File

@@ -2,12 +2,14 @@
/* Copyright(c) 2021 Intel Corporation. All rights rsvd. */
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/iommu.h>
#include <linux/mempool.h>
#include <uapi/linux/idxd.h>
#include <linux/highmem.h>
#include <linux/sched/smt.h>
@@ -156,6 +158,16 @@ static bool async_mode;
/* Use interrupts */
static bool use_irq;
struct iaa_req_ctx {
u32 compression_crc;
struct page *bounce_src;
dma_addr_t bounce_src_dma;
unsigned int bounce_src_len;
};
static mempool_t *iaa_bounce_pool;
#define IAA_BOUNCE_POOL_SIZE 128
/**
* set_iaa_sync_mode - Set IAA sync mode
* @name: The name of the sync mode
@@ -983,6 +995,28 @@ static inline int check_completion(struct device *dev,
return ret;
}
static bool iaa_error_should_retry(struct idxd_desc *idxd_desc)
{
return idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR;
}
static void iaa_unmap_src(struct device *dev, struct acomp_req *req)
{
struct iaa_req_ctx *req_ctx = acomp_request_ctx(req);
if (req_ctx->bounce_src) {
dma_unmap_page(dev, req_ctx->bounce_src_dma,
req_ctx->bounce_src_len, DMA_TO_DEVICE);
mempool_free(req_ctx->bounce_src, iaa_bounce_pool);
req_ctx->bounce_src = NULL;
req_ctx->bounce_src_dma = 0;
req_ctx->bounce_src_len = 0;
return;
}
dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE);
}
static int deflate_generic_decompress(struct acomp_req *req)
{
ACOMP_FBREQ_ON_STACK(fbreq, req);
@@ -996,6 +1030,19 @@ static int deflate_generic_decompress(struct acomp_req *req)
return ret;
}
static int deflate_generic_compress(struct acomp_req *req)
{
ACOMP_FBREQ_ON_STACK(fbreq, req);
int ret;
ret = crypto_acomp_compress(fbreq);
req->dlen = fbreq->dlen;
update_total_sw_comp_calls();
return ret;
}
static int iaa_remap_for_verify(struct device *dev, struct iaa_wq *iaa_wq,
struct acomp_req *req,
dma_addr_t *src_addr, dma_addr_t *dst_addr);
@@ -1013,6 +1060,7 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc,
struct iaa_device_compression_mode *active_compression_mode;
struct iaa_compression_ctx *compression_ctx;
struct crypto_ctx *ctx = __ctx;
struct iaa_req_ctx *req_ctx = acomp_request_ctx(ctx->req);
struct iaa_device *iaa_device;
struct idxd_device *idxd;
struct iaa_wq *iaa_wq;
@@ -1039,40 +1087,44 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc,
ctx->compress, false);
if (ret) {
dev_dbg(dev, "%s: check_completion failed ret=%d\n", __func__, ret);
if (!ctx->compress &&
idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR) {
if (!ctx->compress && iaa_error_should_retry(idxd_desc)) {
pr_warn("%s: falling back to deflate-generic decompress, "
"analytics error code %x\n", __func__,
idxd_desc->iax_completion->error_code);
dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst),
DMA_FROM_DEVICE);
iaa_unmap_src(dev, ctx->req);
ret = deflate_generic_decompress(ctx->req);
if (ret) {
dev_dbg(dev, "%s: deflate-generic failed ret=%d\n",
__func__, ret);
err = -EIO;
goto err;
}
goto out;
} else {
err = -EIO;
goto err;
}
} else {
ctx->req->dlen = idxd_desc->iax_completion->output_size;
if (!ctx->compress) {
update_total_decomp_bytes_in(ctx->req->slen);
update_wq_decomp_bytes(iaa_wq->wq, ctx->req->slen);
}
}
/* Update stats */
if (ctx->compress) {
update_total_comp_bytes_out(ctx->req->dlen);
update_wq_comp_bytes(iaa_wq->wq, ctx->req->dlen);
} else {
update_total_decomp_bytes_in(ctx->req->slen);
update_wq_decomp_bytes(iaa_wq->wq, ctx->req->slen);
}
if (ctx->compress && compression_ctx->verify_compress) {
u32 *compression_crc = acomp_request_ctx(ctx->req);
dma_addr_t src_addr, dst_addr;
*compression_crc = idxd_desc->iax_completion->crc;
req_ctx->compression_crc = idxd_desc->iax_completion->crc;
ret = iaa_remap_for_verify(dev, iaa_wq, ctx->req, &src_addr, &dst_addr);
if (ret) {
@@ -1095,7 +1147,7 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc,
}
err:
dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst), DMA_FROM_DEVICE);
dma_unmap_sg(dev, ctx->req->src, sg_nents(ctx->req->src), DMA_TO_DEVICE);
iaa_unmap_src(dev, ctx->req);
out:
if (ret != 0)
dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret);
@@ -1115,7 +1167,7 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,
{
struct iaa_device_compression_mode *active_compression_mode;
struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);
u32 *compression_crc = acomp_request_ctx(req);
struct iaa_req_ctx *req_ctx = acomp_request_ctx(req);
struct iaa_device *iaa_device;
struct idxd_desc *idxd_desc;
struct iax_hw_desc *desc;
@@ -1206,7 +1258,7 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,
update_total_comp_bytes_out(*dlen);
update_wq_comp_bytes(wq, *dlen);
*compression_crc = idxd_desc->iax_completion->crc;
req_ctx->compression_crc = idxd_desc->iax_completion->crc;
if (!ctx->async_mode)
idxd_free_desc(wq, idxd_desc);
@@ -1266,7 +1318,7 @@ static int iaa_compress_verify(struct crypto_tfm *tfm, struct acomp_req *req,
{
struct iaa_device_compression_mode *active_compression_mode;
struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm);
u32 *compression_crc = acomp_request_ctx(req);
struct iaa_req_ctx *req_ctx = acomp_request_ctx(req);
struct iaa_device *iaa_device;
struct idxd_desc *idxd_desc;
struct iax_hw_desc *desc;
@@ -1326,10 +1378,10 @@ static int iaa_compress_verify(struct crypto_tfm *tfm, struct acomp_req *req,
goto err;
}
if (*compression_crc != idxd_desc->iax_completion->crc) {
if (req_ctx->compression_crc != idxd_desc->iax_completion->crc) {
ret = -EINVAL;
dev_dbg(dev, "(verify) iaa comp/decomp crc mismatch:"
" comp=0x%x, decomp=0x%x\n", *compression_crc,
dev_dbg(dev, "(verify) iaa comp/decomp crc mismatch: comp=0x%x, decomp=0x%x\n",
req_ctx->compression_crc,
idxd_desc->iax_completion->crc);
print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET,
8, 1, idxd_desc->iax_completion, 64, 0);
@@ -1433,31 +1485,21 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,
ret = check_completion(dev, idxd_desc->iax_completion, false, false);
if (ret) {
dev_dbg(dev, "%s: check_completion failed ret=%d\n", __func__, ret);
if (idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR) {
pr_warn("%s: falling back to deflate-generic decompress, "
"analytics error code %x\n", __func__,
idxd_desc->iax_completion->error_code);
ret = deflate_generic_decompress(req);
if (ret) {
dev_dbg(dev, "%s: deflate-generic failed ret=%d\n",
__func__, ret);
goto err;
}
} else {
goto err;
}
if (iaa_error_should_retry(idxd_desc))
ret = -EAGAIN;
goto err;
} else {
req->dlen = idxd_desc->iax_completion->output_size;
/* Update stats */
update_total_decomp_bytes_in(slen);
update_wq_decomp_bytes(wq, slen);
}
*dlen = req->dlen;
if (!ctx->async_mode)
idxd_free_desc(wq, idxd_desc);
/* Update stats */
update_total_decomp_bytes_in(slen);
update_wq_decomp_bytes(wq, slen);
out:
return ret;
err:
@@ -1469,14 +1511,19 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,
static int iaa_comp_acompress(struct acomp_req *req)
{
struct iaa_req_ctx *req_ctx = acomp_request_ctx(req);
struct iaa_compression_ctx *compression_ctx;
struct crypto_tfm *tfm = req->base.tfm;
dma_addr_t src_addr, dst_addr;
int nr_sgs, cpu, ret = 0;
int cpu, ret = 0;
struct iaa_wq *iaa_wq;
struct idxd_wq *wq;
struct device *dev;
req_ctx->bounce_src = NULL;
req_ctx->bounce_src_dma = 0;
req_ctx->bounce_src_len = 0;
compression_ctx = crypto_tfm_ctx(tfm);
if (!iaa_crypto_enabled) {
@@ -1484,11 +1531,15 @@ static int iaa_comp_acompress(struct acomp_req *req)
return -ENODEV;
}
if (!req->src || !req->slen) {
pr_debug("invalid src, not compressing\n");
if (!req->src || !req->slen || !req->dst) {
pr_debug("invalid req, not compressing\n");
return -EINVAL;
}
/* Fall back to software if src or dst has multiple sg entries */
if (sg_nents(req->src) > 1 || sg_nents(req->dst) > 1)
return deflate_generic_compress(req);
cpu = get_cpu();
wq = wq_table_next_wq(cpu);
put_cpu();
@@ -1507,30 +1558,25 @@ static int iaa_comp_acompress(struct acomp_req *req)
dev = &wq->idxd->pdev->dev;
nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);
if (nr_sgs <= 0 || nr_sgs > 1) {
dev_dbg(dev, "couldn't map src sg for iaa device %d,"
" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,
iaa_wq->wq->id, ret);
ret = -EIO;
goto out;
if (!dma_map_sg(dev, req->src, 1, DMA_TO_DEVICE)) {
dev_dbg(dev, "couldn't map src sg for iaa device %d, wq %d\n",
iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id);
iaa_wq_put(wq);
return deflate_generic_compress(req);
}
src_addr = sg_dma_address(req->src);
dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"
" req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs,
dev_dbg(dev, "map src %llx req->src %p slen %d sg_len %d\n", src_addr,
req->src, req->slen, sg_dma_len(req->src));
nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);
if (nr_sgs <= 0 || nr_sgs > 1) {
dev_dbg(dev, "couldn't map dst sg for iaa device %d,"
" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,
iaa_wq->wq->id, ret);
ret = -EIO;
goto err_map_dst;
if (!dma_map_sg(dev, req->dst, 1, DMA_FROM_DEVICE)) {
dev_dbg(dev, "couldn't map dst sg for iaa device %d, wq %d\n",
iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id);
dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE);
iaa_wq_put(wq);
return deflate_generic_compress(req);
}
dst_addr = sg_dma_address(req->dst);
dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"
" req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs,
dev_dbg(dev, "map dst %llx req->dst %p dlen %d sg_len %d\n", dst_addr,
req->dst, req->dlen, sg_dma_len(req->dst));
ret = iaa_compress(tfm, req, wq, src_addr, req->slen, dst_addr,
@@ -1550,8 +1596,8 @@ static int iaa_comp_acompress(struct acomp_req *req)
if (ret)
dev_dbg(dev, "asynchronous compress verification failed ret=%d\n", ret);
dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_TO_DEVICE);
dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE);
dma_unmap_sg(dev, req->dst, 1, DMA_TO_DEVICE);
dma_unmap_sg(dev, req->src, 1, DMA_FROM_DEVICE);
goto out;
}
@@ -1559,9 +1605,8 @@ static int iaa_comp_acompress(struct acomp_req *req)
if (ret)
dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret);
dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);
err_map_dst:
dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);
dma_unmap_sg(dev, req->dst, 1, DMA_FROM_DEVICE);
dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE);
out:
iaa_wq_put(wq);
@@ -1570,23 +1615,40 @@ static int iaa_comp_acompress(struct acomp_req *req)
static int iaa_comp_adecompress(struct acomp_req *req)
{
struct iaa_req_ctx *req_ctx = acomp_request_ctx(req);
struct crypto_tfm *tfm = req->base.tfm;
dma_addr_t src_addr, dst_addr;
int nr_sgs, cpu, ret = 0;
bool use_bounce_src = false;
int cpu, ret = 0;
struct iaa_wq *iaa_wq;
struct device *dev;
struct idxd_wq *wq;
struct page *page;
req_ctx->bounce_src = NULL;
req_ctx->bounce_src_dma = 0;
req_ctx->bounce_src_len = 0;
if (!iaa_crypto_enabled) {
pr_debug("iaa_crypto disabled, not decompressing\n");
return -ENODEV;
}
if (!req->src || !req->slen) {
pr_debug("invalid src, not decompressing\n");
if (!req->src || !req->slen || !req->dst) {
pr_debug("invalid req, not decompressing\n");
return -EINVAL;
}
/* Fall back to software if dst has multiple sg entries */
if (sg_nents(req->dst) > 1)
return deflate_generic_decompress(req);
if (sg_nents(req->src) > 1) {
if (req->slen > PAGE_SIZE)
return deflate_generic_decompress(req);
use_bounce_src = true;
}
cpu = get_cpu();
wq = wq_table_next_wq(cpu);
put_cpu();
@@ -1605,30 +1667,52 @@ static int iaa_comp_adecompress(struct acomp_req *req)
dev = &wq->idxd->pdev->dev;
nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);
if (nr_sgs <= 0 || nr_sgs > 1) {
dev_dbg(dev, "couldn't map src sg for iaa device %d,"
" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,
iaa_wq->wq->id, ret);
ret = -EIO;
goto out;
}
src_addr = sg_dma_address(req->src);
dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"
" req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs,
req->src, req->slen, sg_dma_len(req->src));
if (unlikely(use_bounce_src)) {
page = mempool_alloc(iaa_bounce_pool, GFP_ATOMIC);
if (!page) {
iaa_wq_put(wq);
return deflate_generic_decompress(req);
}
nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);
if (nr_sgs <= 0 || nr_sgs > 1) {
dev_dbg(dev, "couldn't map dst sg for iaa device %d,"
" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,
iaa_wq->wq->id, ret);
ret = -EIO;
goto err_map_dst;
if (sg_copy_to_buffer(req->src, sg_nents(req->src),
page_address(page), req->slen) != req->slen) {
mempool_free(page, iaa_bounce_pool);
iaa_wq_put(wq);
return deflate_generic_decompress(req);
}
src_addr = dma_map_page(dev, page, 0, req->slen, DMA_TO_DEVICE);
if (dma_mapping_error(dev, src_addr)) {
mempool_free(page, iaa_bounce_pool);
iaa_wq_put(wq);
return deflate_generic_decompress(req);
}
req_ctx->bounce_src = page;
req_ctx->bounce_src_dma = src_addr;
req_ctx->bounce_src_len = req->slen;
} else {
if (!dma_map_sg(dev, req->src, 1, DMA_TO_DEVICE)) {
dev_dbg(dev, "couldn't map src sg for iaa device %d, wq %d\n",
iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id);
iaa_wq_put(wq);
return deflate_generic_decompress(req);
}
src_addr = sg_dma_address(req->src);
dev_dbg(dev, "map src %llx req->src %p slen %d sg_len %d\n", src_addr,
req->src, req->slen, sg_dma_len(req->src));
}
if (!dma_map_sg(dev, req->dst, 1, DMA_FROM_DEVICE)) {
dev_dbg(dev, "couldn't map dst sg for iaa device %d, wq %d\n",
iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id);
iaa_unmap_src(dev, req);
iaa_wq_put(wq);
return deflate_generic_decompress(req);
}
dst_addr = sg_dma_address(req->dst);
dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"
" req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs,
dev_dbg(dev, "map dst %llx req->dst %p dlen %d sg_len %d\n", dst_addr,
req->dst, req->dlen, sg_dma_len(req->dst));
ret = iaa_decompress(tfm, req, wq, src_addr, req->slen,
@@ -1636,15 +1720,16 @@ static int iaa_comp_adecompress(struct acomp_req *req)
if (ret == -EINPROGRESS)
return ret;
if (ret != 0)
if (ret != 0 && ret != -EAGAIN)
dev_dbg(dev, "asynchronous decompress failed ret=%d\n", ret);
dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);
err_map_dst:
dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);
out:
dma_unmap_sg(dev, req->dst, 1, DMA_FROM_DEVICE);
iaa_unmap_src(dev, req);
iaa_wq_put(wq);
if (ret == -EAGAIN)
ret = deflate_generic_decompress(req);
return ret;
}
@@ -1676,7 +1761,7 @@ static struct acomp_alg iaa_acomp_fixed_deflate = {
.cra_driver_name = "deflate-iaa",
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_ctxsize = sizeof(struct iaa_compression_ctx),
.cra_reqsize = sizeof(u32),
.cra_reqsize = sizeof(struct iaa_req_ctx),
.cra_module = THIS_MODULE,
.cra_priority = IAA_ALG_PRIORITY,
}
@@ -1875,6 +1960,12 @@ static int __init iaa_crypto_init_module(void)
goto err_aecs_init;
}
iaa_bounce_pool = mempool_create_page_pool(IAA_BOUNCE_POOL_SIZE, 0);
if (!iaa_bounce_pool) {
ret = -ENOMEM;
goto err_bounce_pool;
}
ret = idxd_driver_register(&iaa_crypto_driver);
if (ret) {
pr_debug("IAA wq sub-driver registration failed\n");
@@ -1908,6 +1999,9 @@ static int __init iaa_crypto_init_module(void)
err_verify_attr_create:
idxd_driver_unregister(&iaa_crypto_driver);
err_driver_reg:
mempool_destroy(iaa_bounce_pool);
iaa_bounce_pool = NULL;
err_bounce_pool:
iaa_aecs_cleanup_fixed();
err_aecs_init:
@@ -1924,6 +2018,8 @@ static void __exit iaa_crypto_cleanup_module(void)
driver_remove_file(&iaa_crypto_driver.drv,
&driver_attr_verify_compress);
idxd_driver_unregister(&iaa_crypto_driver);
mempool_destroy(iaa_bounce_pool);
iaa_bounce_pool = NULL;
iaa_aecs_cleanup_fixed();
pr_debug("cleaned up\n");

View File

@@ -19,6 +19,7 @@
static atomic64_t total_comp_calls;
static atomic64_t total_decomp_calls;
static atomic64_t total_sw_comp_calls;
static atomic64_t total_sw_decomp_calls;
static atomic64_t total_comp_bytes_out;
static atomic64_t total_decomp_bytes_in;
@@ -43,6 +44,11 @@ void update_total_decomp_calls(void)
atomic64_inc(&total_decomp_calls);
}
void update_total_sw_comp_calls(void)
{
atomic64_inc(&total_sw_comp_calls);
}
void update_total_sw_decomp_calls(void)
{
atomic64_inc(&total_sw_decomp_calls);
@@ -104,6 +110,7 @@ static void reset_iaa_crypto_stats(void)
{
atomic64_set(&total_comp_calls, 0);
atomic64_set(&total_decomp_calls, 0);
atomic64_set(&total_sw_comp_calls, 0);
atomic64_set(&total_sw_decomp_calls, 0);
atomic64_set(&total_comp_bytes_out, 0);
atomic64_set(&total_decomp_bytes_in, 0);
@@ -174,6 +181,8 @@ static int global_stats_show(struct seq_file *m, void *v)
atomic64_read(&total_comp_calls));
seq_printf(m, " total_decomp_calls: %llu\n",
atomic64_read(&total_decomp_calls));
seq_printf(m, " total_sw_comp_calls: %llu\n",
atomic64_read(&total_sw_comp_calls));
seq_printf(m, " total_sw_decomp_calls: %llu\n",
atomic64_read(&total_sw_decomp_calls));
seq_printf(m, " total_comp_bytes_out: %llu\n",

View File

@@ -11,6 +11,7 @@ void iaa_crypto_debugfs_cleanup(void);
void update_total_comp_calls(void);
void update_total_comp_bytes_out(int n);
void update_total_decomp_calls(void);
void update_total_sw_comp_calls(void);
void update_total_sw_decomp_calls(void);
void update_total_decomp_bytes_in(int n);
void update_completion_einval_errs(void);
@@ -29,6 +30,7 @@ static inline void iaa_crypto_debugfs_cleanup(void) {}
static inline void update_total_comp_calls(void) {}
static inline void update_total_comp_bytes_out(int n) {}
static inline void update_total_decomp_calls(void) {}
static inline void update_total_sw_comp_calls(void) {}
static inline void update_total_sw_decomp_calls(void) {}
static inline void update_total_decomp_bytes_in(int n) {}
static inline void update_completion_einval_errs(void) {}

View File

@@ -1591,6 +1591,7 @@ static const struct of_device_id ixp4xx_crypto_of_match[] = {
},
{},
};
MODULE_DEVICE_TABLE(of, ixp4xx_crypto_of_match);
static struct platform_driver ixp_crypto_driver = {
.probe = ixp_crypto_probe,

View File

@@ -11,6 +11,7 @@
#include <crypto/internal/aead.h>
#include <crypto/internal/skcipher.h>
#include <crypto/scatterwalk.h>
#include <crypto/utils.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/dma-mapping.h>
@@ -919,7 +920,7 @@ static int kmb_ocs_aead_run(struct aead_request *req)
/* For GCM decrypt, we have to compare in_tag with out_tag. */
if (rctx->instruction == OCS_DECRYPT) {
rc = memcmp(rctx->in_tag, rctx->out_tag, tag_size) ?
rc = crypto_memneq(rctx->in_tag, rctx->out_tag, tag_size) ?
-EBADMSG : 0;
goto exit;
}
@@ -1541,7 +1542,7 @@ static int register_aes_algs(struct ocs_aes_dev *aes_dev)
/*
* If any algorithm fails to register, all preceding algorithms that
* were successfully registered will be automatically unregistered.
* were registered in the same call are automatically unregistered.
*/
ret = crypto_engine_register_aeads(algs_aead, ARRAY_SIZE(algs_aead));
if (ret)
@@ -1549,7 +1550,7 @@ static int register_aes_algs(struct ocs_aes_dev *aes_dev)
ret = crypto_engine_register_skciphers(algs, ARRAY_SIZE(algs));
if (ret)
crypto_engine_unregister_aeads(algs_aead, ARRAY_SIZE(algs));
crypto_engine_unregister_aeads(algs_aead, ARRAY_SIZE(algs_aead));
return ret;
}
@@ -1561,6 +1562,7 @@ static const struct of_device_id kmb_ocs_aes_of_match[] = {
},
{}
};
MODULE_DEVICE_TABLE(of, kmb_ocs_aes_of_match);
static void kmb_ocs_aes_remove(struct platform_device *pdev)
{
@@ -1602,6 +1604,8 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev)
if (IS_ERR(aes_dev->base_reg))
return PTR_ERR(aes_dev->base_reg);
init_completion(&aes_dev->irq_completion);
/* Get and request IRQ */
aes_dev->irq = platform_get_irq(pdev, 0);
if (aes_dev->irq < 0)
@@ -1609,18 +1613,14 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev)
rc = devm_request_threaded_irq(dev, aes_dev->irq, ocs_aes_irq_handler,
NULL, 0, "keembay-ocs-aes", aes_dev);
if (rc < 0) {
dev_err(dev, "Could not request IRQ\n");
if (rc < 0)
return rc;
}
INIT_LIST_HEAD(&aes_dev->list);
spin_lock(&ocs_aes.lock);
list_add_tail(&aes_dev->list, &ocs_aes.dev_list);
spin_unlock(&ocs_aes.lock);
init_completion(&aes_dev->irq_completion);
/* Initialize crypto engine */
aes_dev->engine = crypto_engine_alloc_init(dev, true);
if (!aes_dev->engine) {

View File

@@ -900,10 +900,8 @@ static int kmb_ocs_ecc_probe(struct platform_device *pdev)
rc = devm_request_threaded_irq(dev, ecc_dev->irq, ocs_ecc_irq_handler,
NULL, 0, "keembay-ocs-ecc", ecc_dev);
if (rc < 0) {
dev_err(dev, "Could not request IRQ\n");
if (rc < 0)
goto list_del;
}
/* Add device to the list of OCS ECC devices. */
spin_lock(&ocs_ecc.lock);
@@ -978,6 +976,7 @@ static const struct of_device_id kmb_ocs_ecc_of_match[] = {
},
{}
};
MODULE_DEVICE_TABLE(of, kmb_ocs_ecc_of_match);
/* The OCS driver is a platform device. */
static struct platform_driver kmb_ocs_ecc_driver = {

View File

@@ -1204,10 +1204,8 @@ static int kmb_ocs_hcu_probe(struct platform_device *pdev)
rc = devm_request_threaded_irq(&pdev->dev, hcu_dev->irq,
ocs_hcu_irq_handler, NULL, 0,
"keembay-ocs-hcu", hcu_dev);
if (rc < 0) {
dev_err(dev, "Could not request IRQ.\n");
if (rc < 0)
return rc;
}
INIT_LIST_HEAD(&hcu_dev->list);

View File

@@ -17,6 +17,7 @@
#include <crypto/aes.h>
#include <crypto/gcm.h>
#include <crypto/utils.h>
#include "ocs-aes.h"
@@ -1283,7 +1284,7 @@ static inline int ccm_compare_tag_to_yr(struct ocs_aes_dev *aes_dev,
(i * sizeof(u32)));
}
return memcmp(tag, yr, tag_size_bytes) ? -EBADMSG : 0;
return crypto_memneq(tag, yr, tag_size_bytes) ? -EBADMSG : 0;
}
/**

View File

@@ -189,6 +189,8 @@ static void adf_device_reset_worker(struct work_struct *work)
queue_work(device_sriov_wq, &sriov_data.sriov_work);
if (wait_for_completion_timeout(&sriov_data.compl, wait_jiffies))
adf_pf2vf_notify_restarted(accel_dev);
else
cancel_work_sync(&sriov_data.sriov_work);
adf_dev_restarted_notify(accel_dev);
clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);

View File

@@ -2,6 +2,7 @@
/* Copyright(c) 2014 - 2020 Intel Corporation */
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/seq_file.h>
#include "adf_accel_devices.h"
@@ -284,16 +285,13 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
return -ENOMEM;
INIT_LIST_HEAD(&key_val->list);
strscpy(key_val->key, key, sizeof(key_val->key));
strscpy(key_val->key, key);
if (type == ADF_DEC) {
snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
"%ld", (*((long *)val)));
} else if (type == ADF_STR) {
strscpy(key_val->val, (char *)val, sizeof(key_val->val));
} else if (type == ADF_HEX) {
snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
"0x%lx", (unsigned long)val);
strscpy(key_val->val, (char *)val);
} else {
dev_err(&GET_DEV(accel_dev), "Unknown type given.\n");
kfree(key_val);
@@ -350,7 +348,7 @@ int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
if (!sec)
return -ENOMEM;
strscpy(sec->name, name, sizeof(sec->name));
strscpy(sec->name, name);
INIT_LIST_HEAD(&sec->param_head);
down_write(&cfg->lock);
list_add_tail(&sec->list, &cfg->sec_list);

View File

@@ -28,7 +28,6 @@ enum adf_cfg_service_type {
enum adf_cfg_val_type {
ADF_DEC,
ADF_HEX,
ADF_STR
};

View File

@@ -49,18 +49,17 @@ static_assert(sizeof(ADF_CFG_SYM ADF_SERVICES_DELIMITER
ADF_CFG_DCC) < ADF_CFG_MAX_VAL_LEN_IN_BYTES);
static int adf_service_string_to_mask(struct adf_accel_dev *accel_dev, const char *buf,
size_t len, unsigned long *out_mask)
unsigned long *out_mask)
{
struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { };
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
unsigned long mask = 0;
char *substr, *token;
int id, num_svc = 0;
if (len > ADF_CFG_MAX_VAL_LEN_IN_BYTES - 1)
if (strscpy_pad(services, buf) < 0)
return -EINVAL;
strscpy(services, buf, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
substr = services;
while ((token = strsep(&substr, ADF_SERVICES_DELIMITER))) {
@@ -103,12 +102,12 @@ static int adf_service_mask_to_string(unsigned long mask, char *buf, size_t len)
}
int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in,
size_t in_len, char *out, size_t out_len)
char *out, size_t out_len)
{
unsigned long mask;
int ret;
ret = adf_service_string_to_mask(accel_dev, in, in_len, &mask);
ret = adf_service_string_to_mask(accel_dev, in, &mask);
if (ret)
return ret;
@@ -121,7 +120,6 @@ int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in,
int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask)
{
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { };
size_t len;
int ret;
ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
@@ -132,8 +130,7 @@ int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask)
return ret;
}
len = strnlen(services, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
ret = adf_service_string_to_mask(accel_dev, services, len, mask);
ret = adf_service_string_to_mask(accel_dev, services, mask);
if (ret)
dev_err(&GET_DEV(accel_dev), "Invalid value of %s param: %s\n",
ADF_SERVICES_ENABLED, services);

View File

@@ -35,7 +35,7 @@ enum {
#define MAX_NUM_CONCURR_SVC ADF_THREE_SERVICES
int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in,
size_t in_len, char *out, size_t out_len);
char *out, size_t out_len);
int adf_get_service_enabled(struct adf_accel_dev *accel_dev);
int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask);
enum adf_cfg_service_type adf_srv_to_cfg_svc_type(enum adf_base_services svc);

View File

@@ -155,12 +155,8 @@ static int adf_gen2_comp_dev_config(struct adf_accel_dev *accel_dev)
}
val = i;
ret = adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_DC,
&val, ADF_DEC);
if (ret)
return ret;
return ret;
return adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
ADF_NUM_DC, &val, ADF_DEC);
err:
dev_err(&GET_DEV(accel_dev), "Failed to add configuration for compression\n");

View File

@@ -2,6 +2,7 @@
/* Copyright(c) 2024 Intel Corporation */
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
#include "adf_mstate_mgr.h"
@@ -158,7 +159,7 @@ static struct adf_mstate_sect_h *adf_mstate_sect_add_header(struct adf_mstate_mg
return NULL;
}
strscpy(sect->id, id, sizeof(sect->id));
strscpy(sect->id, id);
sect->size = 0;
sect->sub_sects = 0;
mgr->state += sizeof(*sect);

View File

@@ -125,7 +125,7 @@ static ssize_t cfg_services_store(struct device *dev, struct device_attribute *a
if (!accel_dev)
return -EINVAL;
ret = adf_parse_service_string(accel_dev, buf, count, services,
ret = adf_parse_service_string(accel_dev, buf, services,
ADF_CFG_MAX_VAL_LEN_IN_BYTES);
if (ret)
return ret;

View File

@@ -2,6 +2,7 @@
/* Copyright(c) 2014 - 2020 Intel Corporation */
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/seq_file.h>
#include "adf_accel_devices.h"
#include "adf_transport_internal.h"
@@ -103,7 +104,7 @@ int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name)
if (!ring_debug)
return -ENOMEM;
strscpy(ring_debug->ring_name, name, sizeof(ring_debug->ring_name));
strscpy(ring_debug->ring_name, name);
snprintf(entry_name, sizeof(entry_name), "ring_%02d",
ring->ring_number);

Some files were not shown because too many files have changed in this diff Show More