mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 08:15:07 -04:00
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:
19
Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
Normal file
19
Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
Normal 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.
|
||||
@@ -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
|
||||
============
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
-----------
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
98
crypto/ecc.c
98
crypto/ecc.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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] != ')')
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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, ¶ms) < 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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -28,7 +28,6 @@ enum adf_cfg_service_type {
|
||||
|
||||
enum adf_cfg_val_type {
|
||||
ADF_DEC,
|
||||
ADF_HEX,
|
||||
ADF_STR
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user