summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/smb/client/Kconfig1
-rw-r--r--fs/smb/client/cifsencrypt.c60
-rw-r--r--fs/smb/client/cifsglob.h2
-rw-r--r--fs/smb/client/smb2transport.c41
4 files changed, 30 insertions, 74 deletions
diff --git a/fs/smb/client/Kconfig b/fs/smb/client/Kconfig
index 63831242fddf..029bbe595d5f 100644
--- a/fs/smb/client/Kconfig
+++ b/fs/smb/client/Kconfig
@@ -10,6 +10,7 @@ config CIFS
select CRYPTO_CCM
select CRYPTO_GCM
select CRYPTO_AES
+ select CRYPTO_LIB_AES_CBC_MACS
select CRYPTO_LIB_ARC4
select CRYPTO_LIB_MD5
select CRYPTO_LIB_SHA256
diff --git a/fs/smb/client/cifsencrypt.c b/fs/smb/client/cifsencrypt.c
index 3d731f3af235..d092bca2df62 100644
--- a/fs/smb/client/cifsencrypt.c
+++ b/fs/smb/client/cifsencrypt.c
@@ -22,49 +22,33 @@
#include <linux/fips.h>
#include <linux/iov_iter.h>
#include <crypto/aead.h>
+#include <crypto/aes-cbc-macs.h>
#include <crypto/arc4.h>
#include <crypto/md5.h>
#include <crypto/sha2.h>
-static int cifs_sig_update(struct cifs_calc_sig_ctx *ctx,
- const u8 *data, size_t len)
+static size_t cifs_sig_step(void *iter_base, size_t progress, size_t len,
+ void *priv, void *priv2)
{
- if (ctx->md5) {
- md5_update(ctx->md5, data, len);
- return 0;
- }
- if (ctx->hmac) {
- hmac_sha256_update(ctx->hmac, data, len);
- return 0;
- }
- return crypto_shash_update(ctx->shash, data, len);
+ struct cifs_calc_sig_ctx *ctx = priv;
+
+ if (ctx->md5)
+ md5_update(ctx->md5, iter_base, len);
+ else if (ctx->hmac)
+ hmac_sha256_update(ctx->hmac, iter_base, len);
+ else
+ aes_cmac_update(ctx->cmac, iter_base, len);
+ return 0; /* Return value is length *not* processed, i.e. 0. */
}
-static int cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out)
+static void cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out)
{
- if (ctx->md5) {
+ if (ctx->md5)
md5_final(ctx->md5, out);
- return 0;
- }
- if (ctx->hmac) {
+ else if (ctx->hmac)
hmac_sha256_final(ctx->hmac, out);
- return 0;
- }
- return crypto_shash_final(ctx->shash, out);
-}
-
-static size_t cifs_sig_step(void *iter_base, size_t progress, size_t len,
- void *priv, void *priv2)
-{
- struct cifs_calc_sig_ctx *ctx = priv;
- int ret, *pret = priv2;
-
- ret = cifs_sig_update(ctx, iter_base, len);
- if (ret < 0) {
- *pret = ret;
- return len;
- }
- return 0;
+ else
+ aes_cmac_final(ctx->cmac, out);
}
/*
@@ -75,9 +59,8 @@ static int cifs_sig_iter(const struct iov_iter *iter, size_t maxsize,
{
struct iov_iter tmp_iter = *iter;
size_t did;
- int err;
- did = iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, &err,
+ did = iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, NULL,
cifs_sig_step);
if (did != maxsize)
return smb_EIO2(smb_eio_trace_sig_iter, did, maxsize);
@@ -108,11 +91,8 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
if (rc < 0)
return rc;
- rc = cifs_sig_final(ctx, signature);
- if (rc)
- cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
-
- return rc;
+ cifs_sig_final(ctx, signature);
+ return 0;
}
/* Build a proper attribute value/target info pairs blob.
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index ccfde157d3be..74265d055c26 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -2324,7 +2324,7 @@ static inline void mid_execute_callback(struct TCP_Server_Info *server,
struct cifs_calc_sig_ctx {
struct md5_ctx *md5;
struct hmac_sha256_ctx *hmac;
- struct shash_desc *shash;
+ struct aes_cmac_ctx *cmac;
};
#define CIFS_RECONN_DELAY_SECS 30
diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
index 81be2b226e26..b233e0cd9152 100644
--- a/fs/smb/client/smb2transport.c
+++ b/fs/smb/client/smb2transport.c
@@ -19,6 +19,7 @@
#include <linux/mempool.h>
#include <linux/highmem.h>
#include <crypto/aead.h>
+#include <crypto/aes-cbc-macs.h>
#include <crypto/sha2.h>
#include <crypto/utils.h>
#include "cifsglob.h"
@@ -474,7 +475,8 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
unsigned char smb3_signature[SMB2_CMACAES_SIZE];
struct kvec *iov = rqst->rq_iov;
struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
- struct shash_desc *shash = NULL;
+ struct aes_cmac_key cmac_key;
+ struct aes_cmac_ctx cmac_ctx;
struct smb_rqst drqst;
u8 key[SMB3_SIGN_KEY_SIZE];
@@ -487,33 +489,16 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
return rc;
}
- if (allocate_crypto) {
- rc = cifs_alloc_hash("cmac(aes)", &shash);
- if (rc)
- return rc;
- } else {
- shash = server->secmech.aes_cmac;
- }
-
memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
- rc = crypto_shash_setkey(shash->tfm, key, SMB2_CMACAES_SIZE);
+ rc = aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
- goto out;
+ return rc;
}
- /*
- * we already allocate aes_cmac when we init smb3 signing key,
- * so unlike smb2 case we do not have to check here if secmech are
- * initialized
- */
- rc = crypto_shash_init(shash);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
- goto out;
- }
+ aes_cmac_init(&cmac_ctx, &cmac_key);
/*
* For SMB2+, __cifs_calc_signature() expects to sign only the actual
@@ -524,26 +509,16 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
*/
drqst = *rqst;
if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
- rc = crypto_shash_update(shash, iov[0].iov_base,
- iov[0].iov_len);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not update with payload\n",
- __func__);
- goto out;
- }
+ aes_cmac_update(&cmac_ctx, iov[0].iov_base, iov[0].iov_len);
drqst.rq_iov++;
drqst.rq_nvec--;
}
rc = __cifs_calc_signature(
&drqst, server, smb3_signature,
- &(struct cifs_calc_sig_ctx){ .shash = shash });
+ &(struct cifs_calc_sig_ctx){ .cmac = &cmac_ctx });
if (!rc)
memcpy(shdr->Signature, smb3_signature, SMB2_SIGNATURE_SIZE);
-
-out:
- if (allocate_crypto)
- cifs_free_hash(&shash);
return rc;
}