summaryrefslogtreecommitdiff
path: root/fs/smb/server
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@kernel.org>2026-04-18 15:17:07 -0700
committerSteve French <stfrench@microsoft.com>2026-04-22 08:11:23 -0500
commitcc92b479b6ed1d7d1a6eb13aba472badb836a832 (patch)
tree2c54611f884294783b2d1edfb913047b3704c3aa /fs/smb/server
parentdef036ef87f8641c1c525d5ae17438d7a1006491 (diff)
downloadlwn-cc92b479b6ed1d7d1a6eb13aba472badb836a832.tar.gz
lwn-cc92b479b6ed1d7d1a6eb13aba472badb836a832.zip
ksmbd: Use AES-CMAC library for SMB3 signature calculation
Now that AES-CMAC has a library API, convert ksmbd_sign_smb3_pdu() to use it instead of a "cmac(aes)" crypto_shash. The result is simpler and faster code. With the library there's no need to dynamically allocate memory, no need to handle errors, and the AES-CMAC code is accessed directly without inefficient indirect calls and other unnecessary API overhead. Acked-by: Namjae Jeon <linkinjeon@kernel.org> Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Eric Biggers <ebiggers@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/smb/server')
-rw-r--r--fs/smb/server/Kconfig2
-rw-r--r--fs/smb/server/auth.c51
-rw-r--r--fs/smb/server/auth.h4
-rw-r--r--fs/smb/server/crypto_ctx.c58
-rw-r--r--fs/smb/server/crypto_ctx.h12
-rw-r--r--fs/smb/server/server.c1
-rw-r--r--fs/smb/server/smb2pdu.c8
7 files changed, 19 insertions, 117 deletions
diff --git a/fs/smb/server/Kconfig b/fs/smb/server/Kconfig
index 37387410e5bb..8827b3653786 100644
--- a/fs/smb/server/Kconfig
+++ b/fs/smb/server/Kconfig
@@ -7,13 +7,13 @@ config SMB_SERVER
select NLS_UTF8
select NLS_UCS2_UTILS
select CRYPTO
+ select CRYPTO_LIB_AES_CBC_MACS
select CRYPTO_LIB_ARC4
select CRYPTO_LIB_DES
select CRYPTO_LIB_MD5
select CRYPTO_LIB_SHA256
select CRYPTO_LIB_SHA512
select CRYPTO_LIB_UTILS
- select CRYPTO_CMAC
select CRYPTO_AEAD2
select CRYPTO_CCM
select CRYPTO_GCM
diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c
index 7d0691f7263f..e99409fa721c 100644
--- a/fs/smb/server/auth.c
+++ b/fs/smb/server/auth.c
@@ -11,8 +11,8 @@
#include <linux/writeback.h>
#include <linux/uio.h>
#include <linux/xattr.h>
-#include <crypto/hash.h>
#include <crypto/aead.h>
+#include <crypto/aes-cbc-macs.h>
#include <crypto/md5.h>
#include <crypto/sha2.h>
#include <crypto/utils.h>
@@ -490,46 +490,21 @@ void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
* @sig: signature value generated for client request packet
*
*/
-int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
- int n_vec, char *sig)
+void ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
+ int n_vec, char *sig)
{
- struct ksmbd_crypto_ctx *ctx;
- int rc, i;
-
- ctx = ksmbd_crypto_ctx_find_cmacaes();
- if (!ctx) {
- ksmbd_debug(AUTH, "could not crypto alloc cmac\n");
- return -ENOMEM;
- }
-
- rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx),
- key,
- SMB2_CMACAES_SIZE);
- if (rc)
- goto out;
-
- rc = crypto_shash_init(CRYPTO_CMACAES(ctx));
- if (rc) {
- ksmbd_debug(AUTH, "cmaces init error %d\n", rc);
- goto out;
- }
+ struct aes_cmac_key cmac_key;
+ struct aes_cmac_ctx cmac_ctx;
+ int i;
- for (i = 0; i < n_vec; i++) {
- rc = crypto_shash_update(CRYPTO_CMACAES(ctx),
- iov[i].iov_base,
- iov[i].iov_len);
- if (rc) {
- ksmbd_debug(AUTH, "cmaces update error %d\n", rc);
- goto out;
- }
- }
+ /* This cannot fail, since we always pass a valid key length. */
+ static_assert(SMB2_CMACAES_SIZE == AES_KEYSIZE_128);
+ aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE);
- rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig);
- if (rc)
- ksmbd_debug(AUTH, "cmaces generation error %d\n", rc);
-out:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
+ aes_cmac_init(&cmac_ctx, &cmac_key);
+ for (i = 0; i < n_vec; i++)
+ aes_cmac_update(&cmac_ctx, iov[i].iov_base, iov[i].iov_len);
+ aes_cmac_final(&cmac_ctx, sig);
}
struct derivation {
diff --git a/fs/smb/server/auth.h b/fs/smb/server/auth.h
index 6d351d61b0e5..5767aabc63c9 100644
--- a/fs/smb/server/auth.h
+++ b/fs/smb/server/auth.h
@@ -54,8 +54,8 @@ int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
int in_len, char *out_blob, int *out_len);
void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
int n_vec, char *sig);
-int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
- int n_vec, char *sig);
+void ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
+ int n_vec, char *sig);
int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
struct ksmbd_conn *conn);
int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
diff --git a/fs/smb/server/crypto_ctx.c b/fs/smb/server/crypto_ctx.c
index 8fd9713b00b7..2fe7d3300480 100644
--- a/fs/smb/server/crypto_ctx.c
+++ b/fs/smb/server/crypto_ctx.c
@@ -28,14 +28,6 @@ static inline void free_aead(struct crypto_aead *aead)
crypto_free_aead(aead);
}
-static void free_shash(struct shash_desc *shash)
-{
- if (shash) {
- crypto_free_shash(shash->tfm);
- kfree(shash);
- }
-}
-
static struct crypto_aead *alloc_aead(int id)
{
struct crypto_aead *tfm = NULL;
@@ -60,37 +52,10 @@ static struct crypto_aead *alloc_aead(int id)
return tfm;
}
-static struct shash_desc *alloc_shash_desc(int id)
-{
- struct crypto_shash *tfm = NULL;
- struct shash_desc *shash;
-
- switch (id) {
- case CRYPTO_SHASH_CMACAES:
- tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
- break;
- default:
- return NULL;
- }
-
- if (IS_ERR(tfm))
- return NULL;
-
- shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
- KSMBD_DEFAULT_GFP);
- if (!shash)
- crypto_free_shash(tfm);
- else
- shash->tfm = tfm;
- return shash;
-}
-
static void ctx_free(struct ksmbd_crypto_ctx *ctx)
{
int i;
- for (i = 0; i < CRYPTO_SHASH_MAX; i++)
- free_shash(ctx->desc[i]);
for (i = 0; i < CRYPTO_AEAD_MAX; i++)
free_aead(ctx->ccmaes[i]);
kfree(ctx);
@@ -153,29 +118,6 @@ void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx)
ctx_free(ctx);
}
-static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- if (id >= CRYPTO_SHASH_MAX)
- return NULL;
-
- ctx = ksmbd_find_crypto_ctx();
- if (ctx->desc[id])
- return ctx;
-
- ctx->desc[id] = alloc_shash_desc(id);
- if (ctx->desc[id])
- return ctx;
- ksmbd_release_crypto_ctx(ctx);
- return NULL;
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
-{
- return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
-}
-
static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
{
struct ksmbd_crypto_ctx *ctx;
diff --git a/fs/smb/server/crypto_ctx.h b/fs/smb/server/crypto_ctx.h
index 27fd553d10aa..b22c6e086f03 100644
--- a/fs/smb/server/crypto_ctx.h
+++ b/fs/smb/server/crypto_ctx.h
@@ -6,15 +6,9 @@
#ifndef __CRYPTO_CTX_H__
#define __CRYPTO_CTX_H__
-#include <crypto/hash.h>
#include <crypto/aead.h>
enum {
- CRYPTO_SHASH_CMACAES = 0,
- CRYPTO_SHASH_MAX,
-};
-
-enum {
CRYPTO_AEAD_AES_GCM = 16,
CRYPTO_AEAD_AES_CCM,
CRYPTO_AEAD_MAX,
@@ -23,19 +17,13 @@ enum {
struct ksmbd_crypto_ctx {
struct list_head list;
- struct shash_desc *desc[CRYPTO_SHASH_MAX];
struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX];
};
-#define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES])
-
-#define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm)
-
#define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])
#define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM])
void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
void ksmbd_crypto_destroy(void);
diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
index d8893079abdb..58ef02c423fc 100644
--- a/fs/smb/server/server.c
+++ b/fs/smb/server/server.c
@@ -631,7 +631,6 @@ MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
MODULE_LICENSE("GPL");
MODULE_SOFTDEP("pre: nls");
MODULE_SOFTDEP("pre: aes");
-MODULE_SOFTDEP("pre: cmac");
MODULE_SOFTDEP("pre: aead2");
MODULE_SOFTDEP("pre: ccm");
MODULE_SOFTDEP("pre: gcm");
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 652b6771ccaf..a5d9a56cdee8 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -9066,8 +9066,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
iov[0].iov_base = (char *)&hdr->ProtocolId;
iov[0].iov_len = len;
- if (ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature))
- return 0;
+ ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature);
if (crypto_memneq(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
pr_err("bad smb2 signature\n");
@@ -9118,9 +9117,8 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
iov = &work->iov[work->iov_idx];
}
- if (!ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec,
- signature))
- memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
+ ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec, signature);
+ memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
}
/**