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

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

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

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

* tag 'v7.3-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (122 commits)
  crypto: lskcipher - propagate errors from unaligned crypt
  crypto: keembay - use crypto_memneq() to compare CCM AEAD tags
  crypto: keembay - use crypto_memneq() to compare GCM AEAD tags
  crypto: sa2ul - use crypto_memneq() to compare AEAD tag
  hwrng: drivers - use named initializers for acpi_device_id
  crypto: qce - fix CCM AAD buffer underallocation
  crypto: iaa - unmap dst before software fallback on decompress
  crypto: iaa - use bounce buffer for multi-sg decompress input
  crypto: iaa - avoid counting fallback decompression bytes
  crypto: iaa - fall back to software for multi-entry scatterlists
  hwrng: core - Stop/start hwrng_fillfn() kthread before/after suspend-resume
  crypto: hisilicon/sec2 - fix CCM algorithm long packet failure
  crypto: eip93 - use struct_size() and flexible array for ring allocation
  crypto: krb5 - use kfree_sensitive() for derived key buffers
  crypto: af_alg - Stop after finding name in allowlist
  crypto: af_alg - Replace 'bool privileged' with flags
  crypto: af_alg - Make cbc(paes) privileged-only
  hwrng: imx-rngc - Disable clock on registration failure
  crypto: qat - remove dead ADF_HEX code
  crypto: qce - simplify qce_handle_request
  ...
This commit is contained in:
Linus Torvalds
2026-08-19 17:25:42 -07:00
135 changed files with 1405 additions and 2019 deletions
+70 -6
View File
@@ -8,6 +8,7 @@
*/
#include <linux/atomic.h>
#include <linux/capability.h>
#include <crypto/if_alg.h>
#include <linux/crypto.h>
#include <linux/init.h>
@@ -22,10 +23,28 @@
#include <linux/sched/signal.h>
#include <linux/security.h>
#include <linux/string.h>
#include <linux/sysctl.h>
#include <linux/user_namespace.h>
#include <keys/user-type.h>
#include <keys/trusted-type.h>
#include <keys/encrypted-type.h>
static int af_alg_restrict = 1;
static const struct ctl_table af_alg_table[] = {
{
.procname = "af_alg_restrict",
.data = &af_alg_restrict,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_TWO,
},
};
static struct ctl_table_header *af_alg_header;
struct alg_type_list {
const struct af_alg_type *type;
struct list_head list;
@@ -110,6 +129,43 @@ int af_alg_unregister_type(const struct af_alg_type *type)
}
EXPORT_SYMBOL_GPL(af_alg_unregister_type);
static bool af_alg_capable(void)
{
return ns_capable_noaudit(&init_user_ns, CAP_NET_ADMIN) ||
capable(CAP_SYS_ADMIN);
}
int af_alg_check_restriction(const char *name,
const struct af_alg_allowlist_entry allowlist[])
{
int level = READ_ONCE(af_alg_restrict);
if (level == 0)
return 0;
if (level == 1) {
for (const struct af_alg_allowlist_entry *ent = allowlist;
ent->name; ent++) {
if (strcmp(name, ent->name) == 0) {
if ((ent->flags & AF_ALG_UNPRIVILEGED) ||
af_alg_capable())
return 0;
/* List contains at most one entry per name. */
break;
}
}
}
/*
* Use -ENOENT (the error code for "algorithm not found") instead of
* -EACCES or -EPERM, for the highest chance of correctly triggering
* fallback code paths in userspace programs.
*
* Don't log a warning, since it would be noisy. iwd tries to bind a
* bunch of algorithms that it never uses.
*/
return -ENOENT;
}
EXPORT_SYMBOL_GPL(af_alg_check_restriction);
static void alg_do_release(const struct af_alg_type *type, void *private)
{
if (!type)
@@ -506,6 +562,9 @@ static int alg_create(struct net *net, struct socket *sock, int protocol,
struct sock *sk;
int err;
if (READ_ONCE(af_alg_restrict) == 2)
return -EAFNOSUPPORT;
if (sock->type != SOCK_SEQPACKET)
return -ESOCKTNOSUPPORT;
if (protocol != 0)
@@ -1222,27 +1281,32 @@ EXPORT_SYMBOL_GPL(af_alg_get_rsgl);
static int __init af_alg_init(void)
{
int err = proto_register(&alg_proto, 0);
int err;
af_alg_header = register_sysctl("crypto", af_alg_table);
err = proto_register(&alg_proto, 0);
if (err)
goto out;
goto out_unregister_sysctl;
err = sock_register(&alg_family);
if (err != 0)
if (err)
goto out_unregister_proto;
out:
return err;
return 0;
out_unregister_proto:
proto_unregister(&alg_proto);
goto out;
out_unregister_sysctl:
unregister_sysctl_table(af_alg_header);
return err;
}
static void __exit af_alg_exit(void)
{
sock_unregister(PF_ALG);
proto_unregister(&alg_proto);
unregister_sysctl_table(af_alg_header);
}
module_init(af_alg_init);
+11
View File
@@ -34,6 +34,11 @@
#include <linux/net.h>
#include <net/sock.h>
static const struct af_alg_allowlist_entry aead_allowlist[] = {
{ "ccm(aes)" }, /* bluez */
{},
};
static inline bool aead_sufficient_data(struct sock *sk)
{
struct alg_sock *ask = alg_sk(sk);
@@ -344,6 +349,12 @@ static struct proto_ops algif_aead_ops_nokey = {
static void *aead_bind(const char *name)
{
int err;
err = af_alg_check_restriction(name, aead_allowlist);
if (err)
return ERR_PTR(err);
return crypto_alloc_aead(name, 0, AF_ALG_CRYPTOAPI_MASK);
}
+24
View File
@@ -16,6 +16,24 @@
#include <linux/net.h>
#include <net/sock.h>
static const struct af_alg_allowlist_entry hash_allowlist[] = {
{ "cmac(aes)" }, /* iwd, bluez */
{ "hmac(md5)" }, /* iwd */
{ "hmac(sha1)" }, /* iwd */
{ "hmac(sha224)" }, /* iwd */
{ "hmac(sha256)" }, /* iwd */
{ "hmac(sha384)" }, /* iwd */
{ "hmac(sha512)" }, /* iwd, sha512hmac */
{ "md4" }, /* iwd */
{ "md5" }, /* iwd */
{ "sha1", AF_ALG_UNPRIVILEGED }, /* iwd, iproute2 < 7.0 */
{ "sha224" }, /* iwd */
{ "sha256" }, /* iwd */
{ "sha384" }, /* iwd */
{ "sha512" }, /* iwd */
{},
};
struct hash_ctx {
struct af_alg_sgl sgl;
@@ -382,6 +400,12 @@ static struct proto_ops algif_hash_ops_nokey = {
static void *hash_bind(const char *name)
{
int err;
err = af_alg_check_restriction(name, hash_allowlist);
if (err)
return ERR_PTR(err);
return crypto_alloc_ahash(name, 0, AF_ALG_CRYPTOAPI_MASK);
}
+9
View File
@@ -50,6 +50,10 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
MODULE_DESCRIPTION("User-space interface for random number generators");
static const struct af_alg_allowlist_entry rng_allowlist[] = {
{},
};
struct rng_ctx {
#define MAXSIZE 128
unsigned int len;
@@ -201,6 +205,11 @@ static void *rng_bind(const char *name)
{
struct rng_parent_ctx *pctx;
struct crypto_rng *rng;
int err;
err = af_alg_check_restriction(name, rng_allowlist);
if (err)
return ERR_PTR(err);
pctx = kzalloc_obj(*pctx);
if (!pctx)
+23
View File
@@ -35,6 +35,24 @@
#include <linux/string.h>
#include <net/sock.h>
static const struct af_alg_allowlist_entry skcipher_allowlist[] = {
{ "adiantum(xchacha12,aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "adiantum(xchacha20,aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "cbc(aes)" }, /* iwd */
{ "cbc(des)" }, /* iwd */
{ "cbc(des3_ede)" }, /* iwd */
{ "cbc(paes)" }, /* caam and others */
{ "ctr(aes)" }, /* iwd */
{ "ecb(aes)" }, /* iwd, bluez */
{ "ecb(des)" }, /* iwd */
{ "hctr2(aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "xts(aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup benchmark */
{ "xts(camellia)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "xts(serpent)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{ "xts(twofish)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */
{},
};
static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
size_t size)
{
@@ -311,6 +329,11 @@ static struct proto_ops algif_skcipher_ops_nokey = {
static void *skcipher_bind(const char *name)
{
u32 mask = AF_ALG_CRYPTOAPI_MASK;
int err;
err = af_alg_check_restriction(name, skcipher_allowlist);
if (err)
return ERR_PTR(err);
if (strcmp(name, "cbc(paes)") == 0)
mask = 0;
+1 -1
View File
@@ -116,7 +116,7 @@ struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
larval->alg.cra_priority = -1;
larval->alg.cra_destroy = crypto_larval_destroy;
strscpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME);
strscpy(larval->alg.cra_name, name);
init_completion(&larval->completion);
return larval;
+4 -5
View File
@@ -11,6 +11,7 @@
#include <linux/cryptouser.h>
#include <linux/sched.h>
#include <linux/security.h>
#include <linux/string.h>
#include <net/netlink.h>
#include <net/net_namespace.h>
#include <net/sock.h>
@@ -87,11 +88,9 @@ static int crypto_report_one(struct crypto_alg *alg,
{
memset(ualg, 0, sizeof(*ualg));
strscpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
strscpy(ualg->cru_driver_name, alg->cra_driver_name,
sizeof(ualg->cru_driver_name));
strscpy(ualg->cru_module_name, module_name(alg->cra_module),
sizeof(ualg->cru_module_name));
strscpy(ualg->cru_name, alg->cra_name);
strscpy(ualg->cru_driver_name, alg->cra_driver_name);
strscpy(ualg->cru_module_name, module_name(alg->cra_module));
ualg->cru_type = 0;
ualg->cru_mask = 0;
+60 -38
View File
@@ -279,6 +279,48 @@ static void vli_rshift1(u64 *vli, unsigned int ndigits)
}
}
#ifdef __has_builtin
#if __has_builtin(__builtin_addcll)
#define USE_BUILTIN_ADDC
#endif
#endif
/* Computes result = left + right + carry_in and updates carry_out */
static inline void add_carry(u64 left, u64 right, u64 *result, u64 carry_in,
u64 *carry_out)
{
#ifdef USE_BUILTIN_ADDC
*result = __builtin_addcll(left, right, carry_in, carry_out);
#else
u64 sum1, sum2;
u64 c1 = __builtin_uaddll_overflow(left, right, &sum1);
u64 c2 = __builtin_uaddll_overflow(sum1, carry_in, &sum2);
*result = sum2;
*carry_out = c1 | c2;
#endif
}
#ifdef __has_builtin
#if __has_builtin(__builtin_subcll)
#define USE_BUILTIN_SUBC
#endif
#endif
/* Computes result = left - right - borrow_in and updates borrow_out */
static inline void sub_borrow(u64 left, u64 right, u64 *result, u64 borrow_in,
u64 *borrow_out)
{
#ifdef USE_BUILTIN_SUBC
*result = __builtin_subcll(left, right, borrow_in, borrow_out);
#else
u64 diff1, diff2;
u64 b1 = __builtin_usubll_overflow(left, right, &diff1);
u64 b2 = __builtin_usubll_overflow(diff1, borrow_in, &diff2);
*result = diff2;
*borrow_out = b1 | b2;
#endif
}
/* Computes result = left + right, returning carry. Can modify in place. */
static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
unsigned int ndigits)
@@ -286,15 +328,8 @@ static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
u64 carry = 0;
int i;
for (i = 0; i < ndigits; i++) {
u64 sum;
sum = left[i] + right[i] + carry;
if (sum != left[i])
carry = (sum < left[i]);
result[i] = sum;
}
for (i = 0; i < ndigits; i++)
add_carry(left[i], right[i], &result[i], carry, &carry);
return carry;
}
@@ -303,40 +338,29 @@ static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
static u64 vli_uadd(u64 *result, const u64 *left, u64 right,
unsigned int ndigits)
{
u64 carry = right;
u64 carry;
int i;
for (i = 0; i < ndigits; i++) {
u64 sum;
if (ndigits == 0)
return right;
sum = left[i] + carry;
if (sum != left[i])
carry = (sum < left[i]);
else
carry = !!carry;
carry = __builtin_uaddll_overflow(left[0], right, &result[0]);
result[i] = sum;
}
for (i = 1; i < ndigits; i++)
carry = __builtin_uaddll_overflow(left[i], carry, &result[i]);
return carry;
}
/* Computes result = left - right, returning borrow. Can modify in place. */
u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
unsigned int ndigits)
unsigned int ndigits)
{
u64 borrow = 0;
int i;
for (i = 0; i < ndigits; i++) {
u64 diff;
diff = left[i] - right[i] - borrow;
if (diff != left[i])
borrow = (diff > left[i]);
result[i] = diff;
}
for (i = 0; i < ndigits; i++)
sub_borrow(left[i], right[i], &result[i], borrow, &borrow);
return borrow;
}
@@ -344,20 +368,18 @@ EXPORT_SYMBOL(vli_sub);
/* Computes result = left - right, returning borrow. Can modify in place. */
static u64 vli_usub(u64 *result, const u64 *left, u64 right,
unsigned int ndigits)
unsigned int ndigits)
{
u64 borrow = right;
u64 borrow;
int i;
for (i = 0; i < ndigits; i++) {
u64 diff;
if (ndigits == 0)
return right;
diff = left[i] - borrow;
if (diff != left[i])
borrow = (diff > left[i]);
borrow = __builtin_usubll_overflow(left[0], right, &result[0]);
result[i] = diff;
}
for (i = 1; i < ndigits; i++)
borrow = __builtin_usubll_overflow(left[i], borrow, &result[i]);
return borrow;
}
+1 -2
View File
@@ -354,8 +354,7 @@ static int hctr2_create_common(struct crypto_template *tmpl, struct rtattr **tb,
err = -EINVAL;
if (strncmp(xctr_alg->base.cra_name, "xctr(", 5))
goto err_free_inst;
len = strscpy(blockcipher_name, xctr_alg->base.cra_name + 5,
sizeof(blockcipher_name));
len = strscpy(blockcipher_name, xctr_alg->base.cra_name + 5);
if (len < 1)
goto err_free_inst;
if (blockcipher_name[len - 1] != ')')
+4 -4
View File
@@ -263,10 +263,10 @@ struct crypto_aead *crypto_krb5_prepare_encryption(const struct krb5_enctype *kr
goto err;
}
kfree(keys.data);
kfree_sensitive(keys.data);
return ci;
err:
kfree(keys.data);
kfree_sensitive(keys.data);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(crypto_krb5_prepare_encryption);
@@ -333,10 +333,10 @@ struct crypto_shash *crypto_krb5_prepare_checksum(const struct krb5_enctype *krb
goto err;
}
kfree(keys.data);
kfree_sensitive(keys.data);
return ci;
err:
kfree(keys.data);
kfree_sensitive(keys.data);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(crypto_krb5_prepare_checksum);
+1 -1
View File
@@ -359,7 +359,7 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
if (!memcmp(cipher_name, "ecb(", 4)) {
int len;
len = strscpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
len = strscpy(ecb_name, cipher_name + 4);
if (len < 2)
goto err_free_inst;
+1 -3
View File
@@ -95,7 +95,6 @@ static int crypto_lskcipher_crypt_unaligned(
while (len >= bs) {
unsigned chunk = min((unsigned)PAGE_SIZE, len);
int err;
if (chunk > cs)
chunk &= ~(cs - 1);
@@ -528,8 +527,7 @@ struct lskcipher_instance *lskcipher_alloc_instance_simple(
int len;
err = -EINVAL;
len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4],
sizeof(ecb_name));
len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4]);
if (len < 2)
goto err_free_inst;
+2 -1
View File
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <crypto/xts.h>
#include <crypto/b128ops.h>
@@ -400,7 +401,7 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
if (!memcmp(cipher_name, "ecb(", 4)) {
int len;
len = strscpy(name, cipher_name + 4, sizeof(name));
len = strscpy(name, cipher_name + 4);
if (len < 2)
goto err_free_inst;