]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: Use AES-CMAC library for SMB3 signature calculation
authorEric Biggers <ebiggers@kernel.org>
Sat, 18 Apr 2026 22:17:07 +0000 (15:17 -0700)
committerSteve French <stfrench@microsoft.com>
Wed, 22 Apr 2026 13:11:23 +0000 (08:11 -0500)
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>
fs/smb/server/Kconfig
fs/smb/server/auth.c
fs/smb/server/auth.h
fs/smb/server/crypto_ctx.c
fs/smb/server/crypto_ctx.h
fs/smb/server/server.c
fs/smb/server/smb2pdu.c

index 37387410e5bb31936448bdbc91cae6951bf49840..8827b3653786445cd3a55d4489c1ab74a384cbb6 100644 (file)
@@ -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
index 7d0691f7263fe2d0080563df3c75ccce618e6317..e99409fa721cd0587d92a4339c520eba1214260a 100644 (file)
@@ -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 {
index 6d351d61b0e575e2902784b2b0a2d5f106df7418..5767aabc63c9be030139e7d4007ad243d45dafde 100644 (file)
@@ -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,
index 8fd9713b00b7f8ac441956fd4cd01c5d6a47e579..2fe7d330048074453285e4733e55696f0b343591 100644 (file)
@@ -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;
index 27fd553d10aab893b310aee5b002c9456d60207f..b22c6e086f032b7084d6b54856e161073e4e9760 100644 (file)
@@ -6,14 +6,8 @@
 #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,
@@ -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);
index d8893079abdb5de143a6c44c711dde8db5b83eda..58ef02c423fcef78d1b8813a6b852b9864aa317a 100644 (file)
@@ -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");
index 652b6771ccaf2c9ee9458657ac7ab740588b0a2f..a5d9a56cdee85dcc9288614f01e9f815fe1d074d 100644 (file)
@@ -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);
 }
 
 /**