fs: cifs: switch to RC4 library interface
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 12 Jun 2019 16:19:59 +0000 (18:19 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 20 Jun 2019 06:19:55 +0000 (14:19 +0800)
The CIFS code uses the sync skcipher API to invoke the ecb(arc4) skcipher,
of which only a single generic C code implementation exists. This means
that going through all the trouble of using scatterlists etc buys us
very little, and we're better off just invoking the arc4 library directly.

This also reverts commit 5f4b55699aaf ("CIFS: Fix BUG() in calc_seckey()"),
since it is no longer necessary to allocate sec_key on the heap.

Cc: linux-cifs@vger.kernel.org
Cc: Steve French <sfrench@samba.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
fs/cifs/Kconfig
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c

index 76724efc831cf2f6c1707d0ab23c5aa7dc2cc07c..3da294231dccdd636b6536aced351b37b3d0927d 100644 (file)
@@ -9,7 +9,7 @@ config CIFS
        select CRYPTO_SHA512
        select CRYPTO_CMAC
        select CRYPTO_HMAC
-       select CRYPTO_ARC4
+       select CRYPTO_LIB_ARC4
        select CRYPTO_AEAD2
        select CRYPTO_CCM
        select CRYPTO_ECB
index d2a05e46d6f52cee5026ea42227291a7cb124597..97b7497c13ef52217f7c7de71dd6d298a6538393 100644 (file)
@@ -33,7 +33,8 @@
 #include <linux/ctype.h>
 #include <linux/random.h>
 #include <linux/highmem.h>
-#include <crypto/skcipher.h>
+#include <linux/fips.h>
+#include <crypto/arc4.h>
 #include <crypto/aead.h>
 
 int __cifs_calc_signature(struct smb_rqst *rqst,
@@ -772,63 +773,32 @@ setup_ntlmv2_rsp_ret:
 int
 calc_seckey(struct cifs_ses *ses)
 {
-       int rc;
-       struct crypto_skcipher *tfm_arc4;
-       struct scatterlist sgin, sgout;
-       struct skcipher_request *req;
-       unsigned char *sec_key;
+       unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
+       struct arc4_ctx *ctx_arc4;
 
-       sec_key = kmalloc(CIFS_SESS_KEY_SIZE, GFP_KERNEL);
-       if (sec_key == NULL)
-               return -ENOMEM;
+       if (fips_enabled)
+               return -ENODEV;
 
        get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
 
-       tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(tfm_arc4)) {
-               rc = PTR_ERR(tfm_arc4);
-               cifs_dbg(VFS, "could not allocate crypto API arc4\n");
-               goto out;
-       }
-
-       rc = crypto_skcipher_setkey(tfm_arc4, ses->auth_key.response,
-                                       CIFS_SESS_KEY_SIZE);
-       if (rc) {
-               cifs_dbg(VFS, "%s: Could not set response as a key\n",
-                        __func__);
-               goto out_free_cipher;
-       }
-
-       req = skcipher_request_alloc(tfm_arc4, GFP_KERNEL);
-       if (!req) {
-               rc = -ENOMEM;
-               cifs_dbg(VFS, "could not allocate crypto API arc4 request\n");
-               goto out_free_cipher;
+       ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
+       if (!ctx_arc4) {
+               cifs_dbg(VFS, "could not allocate arc4 context\n");
+               return -ENOMEM;
        }
 
-       sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
-       sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
-
-       skcipher_request_set_callback(req, 0, NULL, NULL);
-       skcipher_request_set_crypt(req, &sgin, &sgout, CIFS_CPHTXT_SIZE, NULL);
-
-       rc = crypto_skcipher_encrypt(req);
-       skcipher_request_free(req);
-       if (rc) {
-               cifs_dbg(VFS, "could not encrypt session key rc: %d\n", rc);
-               goto out_free_cipher;
-       }
+       arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
+       arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
+                  CIFS_CPHTXT_SIZE);
 
        /* make secondary_key/nonce as session key */
        memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
        /* and make len as that of session key only */
        ses->auth_key.len = CIFS_SESS_KEY_SIZE;
 
-out_free_cipher:
-       crypto_free_skcipher(tfm_arc4);
-out:
-       kfree(sec_key);
-       return rc;
+       memzero_explicit(sec_key, CIFS_SESS_KEY_SIZE);
+       kzfree(ctx_arc4);
+       return 0;
 }
 
 void
index f5fcd6360056500772b1249cf462c834991df268..e55afaf9e5a3f9f0e3f43c6dca73920f6152041f 100644 (file)
@@ -1590,7 +1590,6 @@ MODULE_DESCRIPTION
        ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and "
        "also older servers complying with the SNIA CIFS Specification)");
 MODULE_VERSION(CIFS_VERSION);
-MODULE_SOFTDEP("pre: arc4");
 MODULE_SOFTDEP("pre: des");
 MODULE_SOFTDEP("pre: ecb");
 MODULE_SOFTDEP("pre: hmac");