From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Eric Biggers <ebiggers@kernel.org>
Subject: [PATCH 32/33] ksmbd: Use AES-GCM and AES-CCM libraries
Date: Mon, 6 Jul 2026 22:35:02 -0700 [thread overview]
Message-ID: <20260707053503.209874-33-ebiggers@kernel.org> (raw)
In-Reply-To: <20260707053503.209874-1-ebiggers@kernel.org>
Now that there are library APIs for AES-GCM and AES-CCM, use them
instead of "gcm(aes)" and "ccm(aes)" crypto_aeads. This significantly
simplifies the code, especially since the pool of crypto_aead objects
and all the scatterlist building code go away.
Move the encryption and decryption code directly into smb3_decrypt_req()
and smb3_encrypt_resp() to take advantage of their respective data
layouts.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
fs/smb/server/Kconfig | 6 +-
fs/smb/server/Makefile | 2 +-
fs/smb/server/auth.c | 227 -------------------------------------
fs/smb/server/auth.h | 2 -
fs/smb/server/crypto_ctx.c | 176 ----------------------------
fs/smb/server/crypto_ctx.h | 32 ------
fs/smb/server/server.c | 14 +--
fs/smb/server/smb2pdu.c | 133 +++++++++++++++++++---
8 files changed, 124 insertions(+), 468 deletions(-)
delete mode 100644 fs/smb/server/crypto_ctx.c
delete mode 100644 fs/smb/server/crypto_ctx.h
diff --git a/fs/smb/server/Kconfig b/fs/smb/server/Kconfig
index 08d8b7a965a6..6b1a23d01acd 100644
--- a/fs/smb/server/Kconfig
+++ b/fs/smb/server/Kconfig
@@ -6,17 +6,15 @@ config SMB_SERVER
select NLS
select NLS_UTF8
select NLS_UCS2_UTILS
- select CRYPTO
select CRYPTO_LIB_AES_CBC_MACS
+ select CRYPTO_LIB_AES_CCM
+ select CRYPTO_LIB_AES_GCM
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_AEAD2
- select CRYPTO_CCM
- select CRYPTO_GCM
select ASN1
select OID_REGISTRY
select CRC32
diff --git a/fs/smb/server/Makefile b/fs/smb/server/Makefile
index a3e9306055e8..da1c972b9042 100644
--- a/fs/smb/server/Makefile
+++ b/fs/smb/server/Makefile
@@ -5,7 +5,7 @@
obj-$(CONFIG_SMB_SERVER) += ksmbd.o
ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o ndr.o \
- misc.o oplock.o connection.o ksmbd_work.o crypto_ctx.o \
+ misc.o oplock.o connection.o ksmbd_work.o \
mgmt/ksmbd_ida.o mgmt/user_config.o mgmt/share_config.o \
mgmt/tree_connect.o mgmt/user_session.o smb_common.o \
transport_tcp.o transport_ipc.o smbacl.o smb2pdu.o \
diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c
index 86f521e849d5..07aaeb2fcd34 100644
--- a/fs/smb/server/auth.c
+++ b/fs/smb/server/auth.c
@@ -11,27 +11,23 @@
#include <linux/writeback.h>
#include <linux/uio.h>
#include <linux/xattr.h>
-#include <crypto/aead.h>
#include <crypto/aes-cbc-macs.h>
#include <crypto/md5.h>
#include <crypto/sha2.h>
#include <crypto/utils.h>
#include <linux/random.h>
-#include <linux/scatterlist.h>
#include "auth.h"
#include "glob.h"
#include <linux/fips.h>
#include <crypto/arc4.h>
-#include <crypto/des.h>
#include "server.h"
#include "smb_common.h"
#include "connection.h"
#include "mgmt/user_session.h"
#include "mgmt/user_config.h"
-#include "crypto_ctx.h"
#include "transport_ipc.h"
/*
@@ -700,226 +696,3 @@ int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
sha512_final(&sha_ctx, pi_hash);
return 0;
}
-
-static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
- int enc, u8 *key)
-{
- struct ksmbd_session *sess;
- u8 *ses_enc_key;
-
- if (enc)
- sess = work->sess;
- else
- sess = ksmbd_session_lookup_all(work->conn, ses_id);
- if (!sess)
- return -EINVAL;
-
- ses_enc_key = enc ? sess->smb3encryptionkey :
- sess->smb3decryptionkey;
- memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
- if (!enc)
- ksmbd_user_session_put(sess);
-
- return 0;
-}
-
-static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
- unsigned int buflen)
-{
- void *addr;
-
- if (is_vmalloc_addr(buf))
- addr = vmalloc_to_page(buf);
- else
- addr = virt_to_page(buf);
- sg_set_page(sg, addr, buflen, offset_in_page(buf));
-}
-
-static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
- u8 *sign)
-{
- struct scatterlist *sg;
- unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
- int i, *nr_entries, total_entries = 0, sg_idx = 0;
-
- if (!nvec)
- return NULL;
-
- nr_entries = kzalloc_objs(int, nvec, KSMBD_DEFAULT_GFP);
- if (!nr_entries)
- return NULL;
-
- for (i = 0; i < nvec - 1; i++) {
- unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
-
- if (is_vmalloc_addr(iov[i + 1].iov_base)) {
- nr_entries[i] = ((kaddr + iov[i + 1].iov_len +
- PAGE_SIZE - 1) >> PAGE_SHIFT) -
- (kaddr >> PAGE_SHIFT);
- } else {
- nr_entries[i]++;
- }
- total_entries += nr_entries[i];
- }
-
- /* Add two entries for transform header and signature */
- total_entries += 2;
-
- sg = kmalloc_objs(struct scatterlist, total_entries, KSMBD_DEFAULT_GFP);
- if (!sg) {
- kfree(nr_entries);
- return NULL;
- }
-
- sg_init_table(sg, total_entries);
- smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
- for (i = 0; i < nvec - 1; i++) {
- void *data = iov[i + 1].iov_base;
- int len = iov[i + 1].iov_len;
-
- if (is_vmalloc_addr(data)) {
- int j, offset = offset_in_page(data);
-
- for (j = 0; j < nr_entries[i]; j++) {
- unsigned int bytes = PAGE_SIZE - offset;
-
- if (!len)
- break;
-
- if (bytes > len)
- bytes = len;
-
- sg_set_page(&sg[sg_idx++],
- vmalloc_to_page(data), bytes,
- offset_in_page(data));
-
- data += bytes;
- len -= bytes;
- offset = 0;
- }
- } else {
- sg_set_page(&sg[sg_idx++], virt_to_page(data), len,
- offset_in_page(data));
- }
- }
- smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
- kfree(nr_entries);
- return sg;
-}
-
-int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
- unsigned int nvec, int enc)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_transform_hdr *tr_hdr = smb_get_msg(iov[0].iov_base);
- unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
- int rc;
- DECLARE_CRYPTO_WAIT(wait);
- struct scatterlist *sg;
- u8 sign[SMB2_SIGNATURE_SIZE] = {};
- u8 key[SMB3_ENC_DEC_KEY_SIZE];
- struct aead_request *req;
- char *iv;
- unsigned int iv_len;
- struct crypto_aead *tfm;
- unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
- struct ksmbd_crypto_ctx *ctx;
-
- rc = ksmbd_get_encryption_key(work,
- le64_to_cpu(tr_hdr->SessionId),
- enc,
- key);
- if (rc) {
- pr_err("Could not get %scryption key\n", enc ? "en" : "de");
- return rc;
- }
-
- if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
- ctx = ksmbd_crypto_ctx_find_gcm();
- else
- ctx = ksmbd_crypto_ctx_find_ccm();
- if (!ctx) {
- pr_err("crypto alloc failed\n");
- return -ENOMEM;
- }
-
- if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
- tfm = CRYPTO_GCM(ctx);
- else
- tfm = CRYPTO_CCM(ctx);
-
- if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
- rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
- else
- rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
- if (rc) {
- pr_err("Failed to set aead key %d\n", rc);
- goto free_ctx;
- }
-
- rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
- if (rc) {
- pr_err("Failed to set authsize %d\n", rc);
- goto free_ctx;
- }
-
- req = aead_request_alloc(tfm, KSMBD_DEFAULT_GFP);
- if (!req) {
- rc = -ENOMEM;
- goto free_ctx;
- }
-
- if (!enc) {
- memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
- crypt_len += SMB2_SIGNATURE_SIZE;
- }
-
- sg = ksmbd_init_sg(iov, nvec, sign);
- if (!sg) {
- pr_err("Failed to init sg\n");
- rc = -ENOMEM;
- goto free_req;
- }
-
- iv_len = crypto_aead_ivsize(tfm);
- iv = kzalloc(iv_len, KSMBD_DEFAULT_GFP);
- if (!iv) {
- rc = -ENOMEM;
- goto free_sg;
- }
-
- if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
- memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
- } else {
- iv[0] = 3;
- memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
- }
-
- aead_request_set_crypt(req, sg, sg, crypt_len, iv);
- aead_request_set_ad(req, assoc_data_len);
- aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
- CRYPTO_TFM_REQ_MAY_SLEEP,
- crypto_req_done, &wait);
-
- rc = crypto_wait_req(enc ? crypto_aead_encrypt(req) :
- crypto_aead_decrypt(req), &wait);
- if (rc)
- goto free_iv;
-
- if (enc)
- memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
-
-free_iv:
- kfree(iv);
-free_sg:
- kfree(sg);
-free_req:
- aead_request_free(req);
-free_ctx:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
-}
diff --git a/fs/smb/server/auth.h b/fs/smb/server/auth.h
index 5767aabc63c9..f438167e9cc2 100644
--- a/fs/smb/server/auth.h
+++ b/fs/smb/server/auth.h
@@ -36,8 +36,6 @@ struct ksmbd_conn;
struct ksmbd_work;
struct kvec;
-int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
- unsigned int nvec, int enc);
void ksmbd_copy_gss_neg_header(void *buf);
int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
diff --git a/fs/smb/server/crypto_ctx.c b/fs/smb/server/crypto_ctx.c
deleted file mode 100644
index 2fe7d3300480..000000000000
--- a/fs/smb/server/crypto_ctx.c
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2019 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-
-#include "glob.h"
-#include "crypto_ctx.h"
-
-struct crypto_ctx_list {
- spinlock_t ctx_lock;
- int avail_ctx;
- struct list_head idle_ctx;
- wait_queue_head_t ctx_wait;
-};
-
-static struct crypto_ctx_list ctx_list;
-
-static inline void free_aead(struct crypto_aead *aead)
-{
- if (aead)
- crypto_free_aead(aead);
-}
-
-static struct crypto_aead *alloc_aead(int id)
-{
- struct crypto_aead *tfm = NULL;
-
- switch (id) {
- case CRYPTO_AEAD_AES_GCM:
- tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
- break;
- case CRYPTO_AEAD_AES_CCM:
- tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
- break;
- default:
- pr_err("Does not support encrypt ahead(id : %d)\n", id);
- return NULL;
- }
-
- if (IS_ERR(tfm)) {
- pr_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
- return NULL;
- }
-
- return tfm;
-}
-
-static void ctx_free(struct ksmbd_crypto_ctx *ctx)
-{
- int i;
-
- for (i = 0; i < CRYPTO_AEAD_MAX; i++)
- free_aead(ctx->ccmaes[i]);
- kfree(ctx);
-}
-
-static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- while (1) {
- spin_lock(&ctx_list.ctx_lock);
- if (!list_empty(&ctx_list.idle_ctx)) {
- ctx = list_entry(ctx_list.idle_ctx.next,
- struct ksmbd_crypto_ctx,
- list);
- list_del(&ctx->list);
- spin_unlock(&ctx_list.ctx_lock);
- return ctx;
- }
-
- if (ctx_list.avail_ctx > num_online_cpus()) {
- spin_unlock(&ctx_list.ctx_lock);
- wait_event(ctx_list.ctx_wait,
- !list_empty(&ctx_list.idle_ctx));
- continue;
- }
-
- ctx_list.avail_ctx++;
- spin_unlock(&ctx_list.ctx_lock);
-
- ctx = kzalloc_obj(struct ksmbd_crypto_ctx, KSMBD_DEFAULT_GFP);
- if (!ctx) {
- spin_lock(&ctx_list.ctx_lock);
- ctx_list.avail_ctx--;
- spin_unlock(&ctx_list.ctx_lock);
- wait_event(ctx_list.ctx_wait,
- !list_empty(&ctx_list.idle_ctx));
- continue;
- }
- break;
- }
- return ctx;
-}
-
-void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx)
-{
- if (!ctx)
- return;
-
- spin_lock(&ctx_list.ctx_lock);
- if (ctx_list.avail_ctx <= num_online_cpus()) {
- list_add(&ctx->list, &ctx_list.idle_ctx);
- spin_unlock(&ctx_list.ctx_lock);
- wake_up(&ctx_list.ctx_wait);
- return;
- }
-
- ctx_list.avail_ctx--;
- spin_unlock(&ctx_list.ctx_lock);
- ctx_free(ctx);
-}
-
-static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- if (id >= CRYPTO_AEAD_MAX)
- return NULL;
-
- ctx = ksmbd_find_crypto_ctx();
- if (ctx->ccmaes[id])
- return ctx;
-
- ctx->ccmaes[id] = alloc_aead(id);
- if (ctx->ccmaes[id])
- return ctx;
- ksmbd_release_crypto_ctx(ctx);
- return NULL;
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void)
-{
- return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_GCM);
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void)
-{
- return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_CCM);
-}
-
-void ksmbd_crypto_destroy(void)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- while (!list_empty(&ctx_list.idle_ctx)) {
- ctx = list_entry(ctx_list.idle_ctx.next,
- struct ksmbd_crypto_ctx,
- list);
- list_del(&ctx->list);
- ctx_free(ctx);
- }
-}
-
-int ksmbd_crypto_create(void)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- spin_lock_init(&ctx_list.ctx_lock);
- INIT_LIST_HEAD(&ctx_list.idle_ctx);
- init_waitqueue_head(&ctx_list.ctx_wait);
- ctx_list.avail_ctx = 1;
-
- ctx = kzalloc_obj(struct ksmbd_crypto_ctx, KSMBD_DEFAULT_GFP);
- if (!ctx)
- return -ENOMEM;
- list_add(&ctx->list, &ctx_list.idle_ctx);
- return 0;
-}
diff --git a/fs/smb/server/crypto_ctx.h b/fs/smb/server/crypto_ctx.h
deleted file mode 100644
index b22c6e086f03..000000000000
--- a/fs/smb/server/crypto_ctx.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2019 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __CRYPTO_CTX_H__
-#define __CRYPTO_CTX_H__
-
-#include <crypto/aead.h>
-
-enum {
- CRYPTO_AEAD_AES_GCM = 16,
- CRYPTO_AEAD_AES_CCM,
- CRYPTO_AEAD_MAX,
-};
-
-struct ksmbd_crypto_ctx {
- struct list_head list;
-
- struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX];
-};
-
-#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_gcm(void);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
-void ksmbd_crypto_destroy(void);
-int ksmbd_crypto_create(void);
-
-#endif /* __CRYPTO_CTX_H__ */
diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
index 36a5ea4828ad..dece42e58d66 100644
--- a/fs/smb/server/server.c
+++ b/fs/smb/server/server.c
@@ -19,7 +19,6 @@
#include "connection.h"
#include "transport_ipc.h"
#include "mgmt/user_session.h"
-#include "crypto_ctx.h"
#include "auth.h"
#include "stats.h"
#include "compress.h"
@@ -564,7 +563,6 @@ static int ksmbd_server_shutdown(void)
ksmbd_workqueue_destroy();
ksmbd_ipc_release();
ksmbd_conn_transport_destroy();
- ksmbd_crypto_destroy();
ksmbd_free_global_file_table();
destroy_lease_table(NULL);
ksmbd_work_pool_destroy();
@@ -612,13 +610,9 @@ static int __init ksmbd_server_init(void)
if (ret)
goto err_destroy_file_table;
- ret = ksmbd_crypto_create();
- if (ret)
- goto err_release_inode_hash;
-
ret = ksmbd_workqueue_init();
if (ret)
- goto err_crypto_destroy;
+ goto err_release_inode_hash;
ret = ksmbd_conn_wq_init();
if (ret)
@@ -628,8 +622,6 @@ static int __init ksmbd_server_init(void)
err_workqueue_destroy:
ksmbd_workqueue_destroy();
-err_crypto_destroy:
- ksmbd_crypto_destroy();
err_release_inode_hash:
ksmbd_release_inode_hash();
err_destroy_file_table:
@@ -666,9 +658,5 @@ MODULE_AUTHOR("Namjae Jeon <linkinjeon@kernel.org>");
MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
MODULE_LICENSE("GPL");
MODULE_SOFTDEP("pre: nls");
-MODULE_SOFTDEP("pre: aes");
-MODULE_SOFTDEP("pre: aead2");
-MODULE_SOFTDEP("pre: ccm");
-MODULE_SOFTDEP("pre: gcm");
module_init(ksmbd_server_init)
module_exit(ksmbd_server_exit)
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 097f51fc7ed6..6668d63157c7 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -4,6 +4,8 @@
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
*/
+#include <crypto/aes-ccm.h>
+#include <crypto/aes-gcm.h>
#include <crypto/utils.h>
#include <linux/inetdevice.h>
#include <net/addrconf.h>
@@ -9731,9 +9733,28 @@ static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
int smb3_encrypt_resp(struct ksmbd_work *work)
{
+ struct ksmbd_session *sess = work->sess;
+ __le16 cipher_type = work->conn->cipher_type;
struct kvec *iov = work->iov;
+ unsigned int nvec = work->iov_idx + 1;
int rc = -ENOMEM;
void *tr_buf;
+ struct smb2_transform_hdr *tr_hdr;
+ union {
+ struct {
+ struct aes_gcm_key key;
+ struct aes_gcm_ctx ctx;
+ } gcm;
+ struct {
+ struct aes_ccm_key key;
+ struct aes_ccm_ctx ctx;
+ } ccm;
+ } u;
+ u8 *assoc_data;
+ size_t orig_size, assoc_data_size;
+
+ if (!sess)
+ return -EINVAL;
tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, KSMBD_DEFAULT_GFP);
if (!tr_buf)
@@ -9742,11 +9763,60 @@ int smb3_encrypt_resp(struct ksmbd_work *work)
/* fill transform header */
fill_transform_hdr(tr_buf, work->response_buf, work->conn->cipher_type);
+ work->tr_buf = tr_buf;
+
+ tr_hdr = smb_get_msg(tr_buf);
+ orig_size = le32_to_cpu(tr_hdr->OriginalMessageSize);
+ assoc_data = tr_buf + 24;
+ assoc_data_size = sizeof(struct smb2_transform_hdr) - 20;
+
iov[0].iov_base = tr_buf;
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
- work->tr_buf = tr_buf;
- return ksmbd_crypt_message(work, iov, work->iov_idx + 1, 1);
+ if (cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
+ cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
+ size_t key_size = (cipher_type == SMB2_ENCRYPTION_AES128_GCM) ?
+ AES_KEYSIZE_128 :
+ AES_KEYSIZE_256;
+
+ rc = aes_gcm_preparekey(&u.gcm.key, sess->smb3encryptionkey,
+ key_size, SMB2_SIGNATURE_SIZE);
+ if (rc)
+ goto out;
+ aes_gcm_init(&u.gcm.ctx, tr_hdr->Nonce, &u.gcm.key);
+ aes_gcm_auth_update(&u.gcm.ctx, assoc_data, assoc_data_size);
+ for (unsigned int i = 1; i < nvec; i++)
+ aes_gcm_encrypt_update(&u.gcm.ctx, iov[i].iov_base,
+ iov[i].iov_base, iov[i].iov_len);
+ aes_gcm_encrypt_final(&u.gcm.ctx, tr_hdr->Signature);
+ rc = 0;
+ } else if (cipher_type == SMB2_ENCRYPTION_AES128_CCM ||
+ cipher_type == SMB2_ENCRYPTION_AES256_CCM) {
+ size_t key_size = (cipher_type == SMB2_ENCRYPTION_AES128_CCM) ?
+ AES_KEYSIZE_128 :
+ AES_KEYSIZE_256;
+
+ rc = aes_ccm_preparekey(&u.ccm.key, sess->smb3encryptionkey,
+ key_size, SMB2_SIGNATURE_SIZE);
+ if (rc)
+ goto out;
+ rc = aes_ccm_init(&u.ccm.ctx, tr_hdr->Nonce, SMB3_AES_CCM_NONCE,
+ assoc_data_size, orig_size, &u.ccm.key);
+ if (rc)
+ goto out;
+ aes_ccm_auth_update(&u.ccm.ctx, assoc_data, assoc_data_size);
+ for (unsigned int i = 1; i < nvec; i++)
+ aes_ccm_encrypt_update(&u.ccm.ctx, iov[i].iov_base,
+ iov[i].iov_base, iov[i].iov_len);
+ aes_ccm_encrypt_final(&u.ccm.ctx, tr_hdr->Signature);
+ rc = 0;
+ } else {
+ WARN_ON_ONCE(1);
+ rc = -EOPNOTSUPP;
+ }
+out:
+ memzero_explicit(&u, sizeof(u));
+ return rc;
}
bool smb3_is_transform_hdr(void *buf)
@@ -9759,11 +9829,17 @@ bool smb3_is_transform_hdr(void *buf)
int smb3_decrypt_req(struct ksmbd_work *work)
{
struct ksmbd_session *sess;
+ __le16 cipher_type = work->conn->cipher_type;
char *buf = work->request_buf;
unsigned int pdu_length = get_rfc1002_len(buf);
- struct kvec iov[2];
int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr);
struct smb2_transform_hdr *tr_hdr = smb_get_msg(buf);
+ union {
+ struct aes_gcm_key gcm;
+ struct aes_ccm_key ccm;
+ } key;
+ u8 *data, *assoc_data;
+ size_t orig_size, assoc_data_size;
int rc = 0;
if (pdu_length < sizeof(struct smb2_transform_hdr) ||
@@ -9773,10 +9849,14 @@ int smb3_decrypt_req(struct ksmbd_work *work)
return -ECONNABORTED;
}
- if (buf_data_size < le32_to_cpu(tr_hdr->OriginalMessageSize)) {
+ orig_size = le32_to_cpu(tr_hdr->OriginalMessageSize);
+ if (buf_data_size < orig_size) {
pr_err("Transform message is broken\n");
return -ECONNABORTED;
}
+ data = buf + sizeof(struct smb2_transform_hdr) + 4;
+ assoc_data = buf + 24;
+ assoc_data_size = sizeof(struct smb2_transform_hdr) - 20;
sess = ksmbd_session_lookup_all(work->conn, le64_to_cpu(tr_hdr->SessionId));
if (!sess) {
@@ -9784,19 +9864,46 @@ int smb3_decrypt_req(struct ksmbd_work *work)
le64_to_cpu(tr_hdr->SessionId));
return -ECONNABORTED;
}
- ksmbd_user_session_put(sess);
- iov[0].iov_base = buf;
- iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
- iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr) + 4;
- iov[1].iov_len = buf_data_size;
- rc = ksmbd_crypt_message(work, iov, 2, 0);
+ if (cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
+ cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
+ size_t key_size = (cipher_type == SMB2_ENCRYPTION_AES128_GCM) ?
+ AES_KEYSIZE_128 :
+ AES_KEYSIZE_256;
+
+ rc = aes_gcm_preparekey(&key.gcm, sess->smb3decryptionkey,
+ key_size, SMB2_SIGNATURE_SIZE);
+ if (rc)
+ goto put_session;
+ rc = aes_gcm_decrypt(data, data, tr_hdr->Signature, orig_size,
+ assoc_data, assoc_data_size, tr_hdr->Nonce,
+ &key.gcm);
+ } else if (cipher_type == SMB2_ENCRYPTION_AES128_CCM ||
+ cipher_type == SMB2_ENCRYPTION_AES256_CCM) {
+ size_t key_size = (cipher_type == SMB2_ENCRYPTION_AES128_CCM) ?
+ AES_KEYSIZE_128 :
+ AES_KEYSIZE_256;
+
+ rc = aes_ccm_preparekey(&key.ccm, sess->smb3decryptionkey,
+ key_size, SMB2_SIGNATURE_SIZE);
+ if (rc)
+ goto put_session;
+ rc = aes_ccm_decrypt(data, data, tr_hdr->Signature, orig_size,
+ assoc_data, assoc_data_size, tr_hdr->Nonce,
+ SMB3_AES_CCM_NONCE, &key.ccm);
+ } else {
+ WARN_ON_ONCE(1);
+ rc = -EOPNOTSUPP;
+ }
+put_session:
+ ksmbd_user_session_put(sess);
if (rc)
- return rc;
+ goto out;
- memmove(buf + 4, iov[1].iov_base, buf_data_size);
+ memmove(buf + 4, data, buf_data_size);
*(__be32 *)buf = cpu_to_be32(buf_data_size);
-
+out:
+ memzero_explicit(&key, sizeof(key));
return rc;
}
--
2.54.0
next prev parent reply other threads:[~2026-07-07 5:37 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 5:34 [PATCH 00/33] Library APIs for AES encryption modes Eric Biggers
2026-07-07 5:34 ` [PATCH 01/33] crypto: xts - Split out __xts_verify_key() helper Eric Biggers
2026-07-07 13:20 ` Thomas Huth
2026-07-07 5:34 ` [PATCH 02/33] lib/crypto: aes: Add ECB support Eric Biggers
2026-07-07 13:59 ` Thomas Huth
2026-07-07 19:22 ` Eric Biggers
2026-07-08 5:29 ` Thomas Huth
2026-07-07 5:34 ` [PATCH 03/33] lib/crypto: aes: Add CBC and CBC-CTS support Eric Biggers
2026-07-09 13:06 ` Thomas Huth
2026-07-13 23:37 ` Eric Biggers
2026-07-07 5:34 ` [PATCH 04/33] lib/crypto: aes: Add CTR and XCTR support Eric Biggers
2026-07-13 8:39 ` Thomas Huth
2026-07-13 23:54 ` Eric Biggers
2026-07-14 4:53 ` Thomas Huth
2026-07-07 5:34 ` [PATCH 05/33] lib/crypto: aes: Add XTS support Eric Biggers
2026-07-13 12:15 ` Thomas Huth
2026-07-14 0:23 ` Eric Biggers
2026-07-07 5:34 ` [PATCH 06/33] lib/crypto: aes: Add GCM support Eric Biggers
2026-07-07 5:34 ` [PATCH 07/33] lib/crypto: aes: Add CCM support Eric Biggers
2026-07-07 5:34 ` [PATCH 08/33] crypto: aes - Add ECB support using library Eric Biggers
2026-07-07 5:34 ` [PATCH 09/33] crypto: aes - Add CBC and CBC-CTS " Eric Biggers
2026-07-07 5:34 ` [PATCH 10/33] crypto: aes - Add CTR and XCTR " Eric Biggers
2026-07-07 5:34 ` [PATCH 11/33] crypto: aes - Add XTS " Eric Biggers
2026-07-07 5:34 ` [PATCH 12/33] crypto: aes - Add GCM " Eric Biggers
2026-07-07 5:34 ` [PATCH 13/33] crypto: aes - Add CCM " Eric Biggers
2026-07-07 5:34 ` [PATCH 14/33] x86/sev: Use new AES-GCM library Eric Biggers
2026-07-07 5:34 ` [PATCH 15/33] lib/crypto: aesgcm: Remove old " Eric Biggers
2026-07-07 5:34 ` [PATCH 16/33] crypto: aes - Remove AES-CBC-MAC support Eric Biggers
2026-07-07 5:34 ` [PATCH 17/33] lib/crypto: aes: Remove aes_cbcmac_* functions Eric Biggers
2026-07-07 5:34 ` [PATCH 18/33] fscrypt: Use aes_ecb_encrypt() for v1 key derivation Eric Biggers
2026-07-07 5:34 ` [PATCH 19/33] KEYS: encrypted: Use AES-CBC library instead of crypto_skcipher Eric Biggers
2026-07-07 5:34 ` [PATCH 20/33] KEYS: trusted: dcp: Use AES-GCM library instead of crypto_aead Eric Biggers
2026-07-07 5:34 ` [PATCH 21/33] libceph: Use AES-CBC library in ceph_aes_crypt() Eric Biggers
2026-07-07 5:34 ` [PATCH 22/33] libceph: Reimplement messenger v2 encryption using AES-GCM library Eric Biggers
2026-07-07 5:34 ` [PATCH 23/33] wifi: mac80211: Use AES-CTR library in fils_aead.c Eric Biggers
2026-07-07 5:34 ` [PATCH 24/33] wifi: mac80211: Use AES-GCM library for GMAC suite Eric Biggers
2026-07-07 5:34 ` [PATCH 25/33] wifi: mac80211: Use crypto libraries for GCMP and CCMP suites Eric Biggers
2026-07-07 5:34 ` [PATCH 26/33] macsec: Use AES-GCM library instead of crypto_aead Eric Biggers
2026-07-07 5:34 ` [PATCH 27/33] wifi: ipw2x00: Use AES-CCM library Eric Biggers
2026-07-07 5:34 ` [PATCH 28/33] mac802154: Use AES-CCM and AES-CTR libraries Eric Biggers
2026-07-07 5:34 ` [PATCH 29/33] bpf: crypto: Use AES-CBC and AES-ECB libraries Eric Biggers
2026-07-07 15:01 ` Vadim Fedorenko
2026-07-07 18:20 ` Eric Biggers
2026-07-07 22:50 ` Vadim Fedorenko
2026-07-07 23:16 ` Eric Biggers
2026-07-08 11:47 ` Vadim Fedorenko
2026-07-09 15:47 ` Eric Biggers
2026-07-09 16:46 ` Vadim Fedorenko
2026-07-07 5:35 ` [PATCH 30/33] bpf: crypto: Add AES-GCM support Eric Biggers
2026-07-07 15:02 ` Vadim Fedorenko
2026-07-07 5:35 ` [PATCH 31/33] smb: client: Use AES-GCM and AES-CCM libraries Eric Biggers
2026-07-07 5:35 ` Eric Biggers [this message]
2026-07-07 10:51 ` [PATCH 32/33] ksmbd: " Namjae Jeon
2026-07-07 5:35 ` [PATCH 33/33] net: tipc: Use AES-GCM library instead of crypto_aead Eric Biggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260707053503.209874-33-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.