ima: calculate the hash of a buffer using aynchronous hash(ahash)
authorMimi Zohar <zohar@linux.vnet.ibm.com>
Mon, 28 Dec 2015 16:56:09 +0000 (11:56 -0500)
committerMimi Zohar <zohar@linux.vnet.ibm.com>
Thu, 18 Feb 2016 22:14:44 +0000 (17:14 -0500)
Setting up ahash has some overhead.  Only use ahash to calculate the
hash of a buffer, if the buffer is larger than ima_ahash_minsize.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Acked-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
security/integrity/ima/ima_crypto.c

index fccb6ceb388bc69ef42e99f6ef73bec32a9bf12d..38f2ed830dd6fb23c216b014e39405318705d8ee 100644 (file)
@@ -519,6 +519,63 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
        return rc;
 }
 
+static int calc_buffer_ahash_atfm(const void *buf, loff_t len,
+                                 struct ima_digest_data *hash,
+                                 struct crypto_ahash *tfm)
+{
+       struct ahash_request *req;
+       struct scatterlist sg;
+       struct ahash_completion res;
+       int rc, ahash_rc = 0;
+
+       hash->length = crypto_ahash_digestsize(tfm);
+
+       req = ahash_request_alloc(tfm, GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       init_completion(&res.completion);
+       ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+                                  CRYPTO_TFM_REQ_MAY_SLEEP,
+                                  ahash_complete, &res);
+
+       rc = ahash_wait(crypto_ahash_init(req), &res);
+       if (rc)
+               goto out;
+
+       sg_init_one(&sg, buf, len);
+       ahash_request_set_crypt(req, &sg, NULL, len);
+
+       ahash_rc = crypto_ahash_update(req);
+
+       /* wait for the update request to complete */
+       rc = ahash_wait(ahash_rc, &res);
+       if (!rc) {
+               ahash_request_set_crypt(req, NULL, hash->digest, 0);
+               rc = ahash_wait(crypto_ahash_final(req), &res);
+       }
+out:
+       ahash_request_free(req);
+       return rc;
+}
+
+static int calc_buffer_ahash(const void *buf, loff_t len,
+                            struct ima_digest_data *hash)
+{
+       struct crypto_ahash *tfm;
+       int rc;
+
+       tfm = ima_alloc_atfm(hash->algo);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+
+       rc = calc_buffer_ahash_atfm(buf, len, hash, tfm);
+
+       ima_free_atfm(tfm);
+
+       return rc;
+}
+
 static int calc_buffer_shash_tfm(const void *buf, loff_t size,
                                struct ima_digest_data *hash,
                                struct crypto_shash *tfm)
@@ -550,8 +607,8 @@ static int calc_buffer_shash_tfm(const void *buf, loff_t size,
        return rc;
 }
 
-int ima_calc_buffer_hash(const void *buf, loff_t len,
-                        struct ima_digest_data *hash)
+static int calc_buffer_shash(const void *buf, loff_t len,
+                            struct ima_digest_data *hash)
 {
        struct crypto_shash *tfm;
        int rc;
@@ -566,6 +623,20 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,
        return rc;
 }
 
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+                        struct ima_digest_data *hash)
+{
+       int rc;
+
+       if (ima_ahash_minsize && len >= ima_ahash_minsize) {
+               rc = calc_buffer_ahash(buf, len, hash);
+               if (!rc)
+                       return 0;
+       }
+
+       return calc_buffer_shash(buf, len, hash);
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
        if (!ima_used_chip)
This page took 0.027763 seconds and 5 git commands to generate.