]> Pileus Git - ~andy/linux/blobdiff - fs/cifs/cifsencrypt.c
Limit allocation of crypto mechanisms to dialect which requires
[~andy/linux] / fs / cifs / cifsencrypt.c
index 3d8bf941d1269ff3afa45baf1ed9f5aee8491431..45e57cc38200448da67b1ce2c896efff555f0e73 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsencrypt.c
  *
- *   Copyright (C) International Business Machines  Corp., 2005,2006
+ *   Copyright (C) International Business Machines  Corp., 2005,2013
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
 #include <linux/random.h>
 #include <linux/highmem.h>
 
+static int
+cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
+{
+       int rc;
+       unsigned int size;
+
+       if (server->secmech.sdescmd5 != NULL)
+               return 0; /* already allocated */
+
+       server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
+       if (IS_ERR(server->secmech.md5)) {
+               cifs_dbg(VFS, "could not allocate crypto md5\n");
+               return PTR_ERR(server->secmech.md5);
+       }
+
+       size = sizeof(struct shash_desc) +
+                       crypto_shash_descsize(server->secmech.md5);
+       server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
+       if (!server->secmech.sdescmd5) {
+               rc = -ENOMEM;
+               crypto_free_shash(server->secmech.md5);
+               server->secmech.md5 = NULL;
+               return rc;
+       }
+       server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
+       server->secmech.sdescmd5->shash.flags = 0x0;
+
+       return 0;
+}
+
 /*
  * Calculate and return the CIFS signature based on the mac key and SMB PDU.
  * The 16 byte signature must be allocated by the caller. Note we only use the
@@ -50,8 +80,11 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
                return -EINVAL;
 
        if (!server->secmech.sdescmd5) {
-               cifs_dbg(VFS, "%s: Can't generate signature\n", __func__);
-               return -1;
+               rc = cifs_crypto_shash_md5_allocate(server);
+               if (rc) {
+                       cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
+                       return -1;
+               }
        }
 
        rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
@@ -556,6 +589,33 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
        return rc;
 }
 
+static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
+{
+       unsigned int size;
+
+       /* check if already allocated */
+       if (server->secmech.sdeschmacmd5)
+               return 0;
+
+       server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
+       if (IS_ERR(server->secmech.hmacmd5)) {
+               cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
+               return PTR_ERR(server->secmech.hmacmd5);
+       }
+
+       size = sizeof(struct shash_desc) +
+                       crypto_shash_descsize(server->secmech.hmacmd5);
+       server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
+       if (!server->secmech.sdeschmacmd5) {
+               crypto_free_shash(server->secmech.hmacmd5);
+               server->secmech.hmacmd5 = NULL;
+               return -ENOMEM;
+       }
+       server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
+       server->secmech.sdeschmacmd5->shash.flags = 0x0;
+
+       return 0;
+}
 
 int
 setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
@@ -606,6 +666,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 
        memcpy(ses->auth_key.response + baselen, tiblob, tilen);
 
+       rc = crypto_hmacmd5_alloc(ses->server);
+       if (rc) {
+               cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
+               goto setup_ntlmv2_rsp_ret;
+       }
+
        /* calculate ntlmv2_hash */
        rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
        if (rc) {
@@ -705,123 +771,32 @@ calc_seckey(struct cifs_ses *ses)
 void
 cifs_crypto_shash_release(struct TCP_Server_Info *server)
 {
-       if (server->secmech.cmacaes)
+       if (server->secmech.cmacaes) {
                crypto_free_shash(server->secmech.cmacaes);
+               server->secmech.cmacaes = NULL;
+       }
 
-       if (server->secmech.hmacsha256)
+       if (server->secmech.hmacsha256) {
                crypto_free_shash(server->secmech.hmacsha256);
+               server->secmech.hmacsha256 = NULL;
+       }
 
-       if (server->secmech.md5)
+       if (server->secmech.md5) {
                crypto_free_shash(server->secmech.md5);
+               server->secmech.md5 = NULL;
+       }
 
-       if (server->secmech.hmacmd5)
+       if (server->secmech.hmacmd5) {
                crypto_free_shash(server->secmech.hmacmd5);
+               server->secmech.hmacmd5 = NULL;
+       }
 
        kfree(server->secmech.sdesccmacaes);
-
+       server->secmech.sdesccmacaes = NULL;
        kfree(server->secmech.sdeschmacsha256);
-
+       server->secmech.sdeschmacsha256 = NULL;
        kfree(server->secmech.sdeschmacmd5);
-
+       server->secmech.sdeschmacmd5 = NULL;
        kfree(server->secmech.sdescmd5);
-}
-
-int
-cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
-{
-       int rc;
-       unsigned int size;
-
-       server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
-       if (IS_ERR(server->secmech.hmacmd5)) {
-               cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
-               return PTR_ERR(server->secmech.hmacmd5);
-       }
-
-       server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
-       if (IS_ERR(server->secmech.md5)) {
-               cifs_dbg(VFS, "could not allocate crypto md5\n");
-               rc = PTR_ERR(server->secmech.md5);
-               goto crypto_allocate_md5_fail;
-       }
-
-       server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
-       if (IS_ERR(server->secmech.hmacsha256)) {
-               cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
-               rc = PTR_ERR(server->secmech.hmacsha256);
-               goto crypto_allocate_hmacsha256_fail;
-       }
-
-       server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
-       if (IS_ERR(server->secmech.cmacaes)) {
-               cifs_dbg(VFS, "could not allocate crypto cmac-aes");
-               rc = PTR_ERR(server->secmech.cmacaes);
-               goto crypto_allocate_cmacaes_fail;
-       }
-
-       size = sizeof(struct shash_desc) +
-                       crypto_shash_descsize(server->secmech.hmacmd5);
-       server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
-       if (!server->secmech.sdeschmacmd5) {
-               rc = -ENOMEM;
-               goto crypto_allocate_hmacmd5_sdesc_fail;
-       }
-       server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
-       server->secmech.sdeschmacmd5->shash.flags = 0x0;
-
-       size = sizeof(struct shash_desc) +
-                       crypto_shash_descsize(server->secmech.md5);
-       server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
-       if (!server->secmech.sdescmd5) {
-               rc = -ENOMEM;
-               goto crypto_allocate_md5_sdesc_fail;
-       }
-       server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
-       server->secmech.sdescmd5->shash.flags = 0x0;
-
-       size = sizeof(struct shash_desc) +
-                       crypto_shash_descsize(server->secmech.hmacsha256);
-       server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
-       if (!server->secmech.sdeschmacsha256) {
-               rc = -ENOMEM;
-               goto crypto_allocate_hmacsha256_sdesc_fail;
-       }
-       server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
-       server->secmech.sdeschmacsha256->shash.flags = 0x0;
-
-       size = sizeof(struct shash_desc) +
-                       crypto_shash_descsize(server->secmech.cmacaes);
-       server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
-       if (!server->secmech.sdesccmacaes) {
-               cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
-               rc = -ENOMEM;
-               goto crypto_allocate_cmacaes_sdesc_fail;
-       }
-       server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
-       server->secmech.sdesccmacaes->shash.flags = 0x0;
-
-       return 0;
-
-crypto_allocate_cmacaes_sdesc_fail:
-       kfree(server->secmech.sdeschmacsha256);
-
-crypto_allocate_hmacsha256_sdesc_fail:
-       kfree(server->secmech.sdescmd5);
-
-crypto_allocate_md5_sdesc_fail:
-       kfree(server->secmech.sdeschmacmd5);
-
-crypto_allocate_hmacmd5_sdesc_fail:
-       crypto_free_shash(server->secmech.cmacaes);
-
-crypto_allocate_cmacaes_fail:
-       crypto_free_shash(server->secmech.hmacsha256);
-
-crypto_allocate_hmacsha256_fail:
-       crypto_free_shash(server->secmech.md5);
-
-crypto_allocate_md5_fail:
-       crypto_free_shash(server->secmech.hmacmd5);
-
-       return rc;
+       server->secmech.sdescmd5 = NULL;
 }