mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 23:52:08 +02:00
smb: client: Use AES-CMAC library for SMB3 signature calculation
Convert smb3_calc_signature() to use the AES-CMAC library instead of a "cmac(aes)" crypto_shash. The result is simpler and faster code. With the library there's no need to allocate memory, no need to handle errors except for key preparation, and the AES-CMAC code is accessed directly without inefficient indirect calls and other unnecessary API overhead. For now a "cmac(aes)" crypto_shash is still being allocated in 'struct cifs_secmech'. Later commits will remove that, simplifying the code even further. Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Eric Biggers <ebiggers@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
44ccf4162a
commit
3a4580e713
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static int cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out)
|
||||
{
|
||||
if (ctx->md5) {
|
||||
md5_final(ctx->md5, out);
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
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 void cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out)
|
||||
{
|
||||
if (ctx->md5)
|
||||
md5_final(ctx->md5, out);
|
||||
else if (ctx->hmac)
|
||||
hmac_sha256_final(ctx->hmac, out);
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user