From patchwork Mon Jan 27 17:04:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 11352939 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D0E581395 for ; Mon, 27 Jan 2020 17:06:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AE70F214D8 for ; Mon, 27 Jan 2020 17:06:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726296AbgA0RGP (ORCPT ); Mon, 27 Jan 2020 12:06:15 -0500 Received: from lhrrgout.huawei.com ([185.176.76.210]:2301 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725845AbgA0RGP (ORCPT ); Mon, 27 Jan 2020 12:06:15 -0500 Received: from LHREML710-CAH.china.huawei.com (unknown [172.18.7.106]) by Forcepoint Email with ESMTP id B982F9C7A7F77069A018; Mon, 27 Jan 2020 17:06:13 +0000 (GMT) Received: from roberto-HP-EliteDesk-800-G2-DM-65W.huawei.com (10.204.65.160) by smtpsuk.huawei.com (10.201.108.33) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 27 Jan 2020 17:06:03 +0000 From: Roberto Sassu To: , , , CC: , , , Roberto Sassu Subject: [PATCH 1/8] tpm: initialize crypto_id of allocated_banks to HASH_ALGO__LAST Date: Mon, 27 Jan 2020 18:04:36 +0100 Message-ID: <20200127170443.21538-2-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200127170443.21538-1-roberto.sassu@huawei.com> References: <20200127170443.21538-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.65.160] X-CFilter-Loop: Reflected Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org chip->allocated_banks contains the list of TPM algorithm IDs of allocated PCR banks. It also contains the corresponding ID of the crypto subsystem, so that users of the TPM driver can calculate a digest for a PCR extend operation. However, if there is no mapping between TPM algorithm ID and crypto ID, the crypto_id field in chip->allocated_banks remains set to zero (the array is allocated and initialized with kcalloc() in tpm2_get_pcr_allocation()). Zero should not be used as value for unknown mappings, as it is a valid crypto ID (HASH_ALGO_MD4). This patch initializes crypto_id to HASH_ALGO__LAST. Signed-off-by: Roberto Sassu Reviewed-by: Petr Vorel --- drivers/char/tpm/tpm2-cmd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 13696deceae8..760329598b99 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -525,6 +525,8 @@ static int tpm2_init_bank_info(struct tpm_chip *chip, u32 bank_index) return 0; } + bank->crypto_id = HASH_ALGO__LAST; + return tpm2_pcr_read(chip, 0, &digest, &bank->digest_size); } From patchwork Mon Jan 27 17:04:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 11352943 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0B646924 for ; Mon, 27 Jan 2020 17:06:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E7F6A22464 for ; Mon, 27 Jan 2020 17:06:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726438AbgA0RGZ (ORCPT ); Mon, 27 Jan 2020 12:06:25 -0500 Received: from lhrrgout.huawei.com ([185.176.76.210]:2302 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726181AbgA0RGZ (ORCPT ); Mon, 27 Jan 2020 12:06:25 -0500 Received: from LHREML710-CAH.china.huawei.com (unknown [172.18.7.107]) by Forcepoint Email with ESMTP id 5258FA187E27F3DCACAC; Mon, 27 Jan 2020 17:06:24 +0000 (GMT) Received: from roberto-HP-EliteDesk-800-G2-DM-65W.huawei.com (10.204.65.160) by smtpsuk.huawei.com (10.201.108.33) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 27 Jan 2020 17:06:14 +0000 From: Roberto Sassu To: , , , CC: , , , Roberto Sassu Subject: [PATCH 2/8] ima: evaluate error in init_ima() Date: Mon, 27 Jan 2020 18:04:37 +0100 Message-ID: <20200127170443.21538-3-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200127170443.21538-1-roberto.sassu@huawei.com> References: <20200127170443.21538-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.65.160] X-CFilter-Loop: Reflected Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Evaluate error in init_ima() before register_blocking_lsm_notifier() and return if not zero. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 9fe949c6a530..2f95b133f246 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -791,6 +791,9 @@ static int __init init_ima(void) error = ima_init(); } + if (error) + return error; + error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier); if (error) pr_warn("Couldn't register LSM notifier, error %d\n", error); From patchwork Mon Jan 27 17:04:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 11352947 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2098A1395 for ; Mon, 27 Jan 2020 17:06:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0829924658 for ; Mon, 27 Jan 2020 17:06:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726181AbgA0RGf (ORCPT ); Mon, 27 Jan 2020 12:06:35 -0500 Received: from lhrrgout.huawei.com ([185.176.76.210]:2303 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725972AbgA0RGf (ORCPT ); Mon, 27 Jan 2020 12:06:35 -0500 Received: from LHREML710-CAH.china.huawei.com (unknown [172.18.7.106]) by Forcepoint Email with ESMTP id 0E65B5F49ACE8965F7F0; Mon, 27 Jan 2020 17:06:34 +0000 (GMT) Received: from roberto-HP-EliteDesk-800-G2-DM-65W.huawei.com (10.204.65.160) by smtpsuk.huawei.com (10.201.108.33) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 27 Jan 2020 17:06:25 +0000 From: Roberto Sassu To: , , , CC: , , , Roberto Sassu Subject: [PATCH 3/8] ima: store template digest directly in ima_template_entry Date: Mon, 27 Jan 2020 18:04:38 +0100 Message-ID: <20200127170443.21538-4-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200127170443.21538-1-roberto.sassu@huawei.com> References: <20200127170443.21538-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.65.160] X-CFilter-Loop: Reflected Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org In preparation for the patch that calculates a digest for each allocated PCR bank, this patch passes to ima_calc_field_array_hash() the ima_template_entry structure, so that digests can be directly stored in that structure instead of ima_digest_data. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 3 +-- security/integrity/ima/ima_api.c | 12 +----------- security/integrity/ima/ima_crypto.c | 18 +++++++----------- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6bb3152b3e24..6238c50ae44e 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -138,8 +138,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); int ima_calc_buffer_hash(const void *buf, loff_t len, struct ima_digest_data *hash); int ima_calc_field_array_hash(struct ima_field_data *field_data, - struct ima_template_desc *desc, int num_fields, - struct ima_digest_data *hash); + struct ima_template_entry *entry); int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); void ima_add_violation(struct file *file, const unsigned char *filename, struct integrity_iint_cache *iint, diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index f6bc00914aa5..2ef5a40c7ca5 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -96,26 +96,16 @@ int ima_store_template(struct ima_template_entry *entry, static const char audit_cause[] = "hashing_error"; char *template_name = entry->template_desc->name; int result; - struct { - struct ima_digest_data hdr; - char digest[TPM_DIGEST_SIZE]; - } hash; if (!violation) { - int num_fields = entry->template_desc->num_fields; - - /* this function uses default algo */ - hash.hdr.algo = HASH_ALGO_SHA1; result = ima_calc_field_array_hash(&entry->template_data[0], - entry->template_desc, - num_fields, &hash.hdr); + entry); if (result < 0) { integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, template_name, op, audit_cause, result, 0); return result; } - memcpy(entry->digest, hash.hdr.digest, hash.hdr.length); } entry->pcr = pcr; result = ima_add_template_entry(entry, violation, op, inode, filename); diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 7967a6904851..f2d9d4b18499 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -466,18 +466,16 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) * Calculate the hash of template data */ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, - struct ima_template_desc *td, - int num_fields, - struct ima_digest_data *hash, + struct ima_template_entry *entry, struct crypto_shash *tfm) { SHASH_DESC_ON_STACK(shash, tfm); + struct ima_template_desc *td = entry->template_desc; + int num_fields = entry->template_desc->num_fields; int rc, i; shash->tfm = tfm; - hash->length = crypto_shash_digestsize(tfm); - rc = crypto_shash_init(shash); if (rc != 0) return rc; @@ -506,24 +504,22 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, } if (!rc) - rc = crypto_shash_final(shash, hash->digest); + rc = crypto_shash_final(shash, entry->digest); return rc; } int ima_calc_field_array_hash(struct ima_field_data *field_data, - struct ima_template_desc *desc, int num_fields, - struct ima_digest_data *hash) + struct ima_template_entry *entry) { struct crypto_shash *tfm; int rc; - tfm = ima_alloc_tfm(hash->algo); + tfm = ima_alloc_tfm(HASH_ALGO_SHA1); if (IS_ERR(tfm)) return PTR_ERR(tfm); - rc = ima_calc_field_array_hash_tfm(field_data, desc, num_fields, - hash, tfm); + rc = ima_calc_field_array_hash_tfm(field_data, entry, tfm); ima_free_tfm(tfm); From patchwork Mon Jan 27 17:04:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 11352951 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8C8DE1395 for ; Mon, 27 Jan 2020 17:06:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6B45821739 for ; Mon, 27 Jan 2020 17:06:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725938AbgA0RGq (ORCPT ); Mon, 27 Jan 2020 12:06:46 -0500 Received: from lhrrgout.huawei.com ([185.176.76.210]:2304 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725828AbgA0RGq (ORCPT ); Mon, 27 Jan 2020 12:06:46 -0500 Received: from LHREML710-CAH.china.huawei.com (unknown [172.18.7.107]) by Forcepoint Email with ESMTP id 33F51C280A4E7B1B8816; Mon, 27 Jan 2020 17:06:44 +0000 (GMT) Received: from roberto-HP-EliteDesk-800-G2-DM-65W.huawei.com (10.204.65.160) by smtpsuk.huawei.com (10.201.108.33) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 27 Jan 2020 17:06:35 +0000 From: Roberto Sassu To: , , , CC: , , , Roberto Sassu Subject: [PATCH 4/8] ima: switch to dynamically allocated buffer for template digests Date: Mon, 27 Jan 2020 18:04:39 +0100 Message-ID: <20200127170443.21538-5-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200127170443.21538-1-roberto.sassu@huawei.com> References: <20200127170443.21538-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.65.160] X-CFilter-Loop: Reflected Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org This patch dynamically allocates the array of tpm_digest structures in ima_alloc_init_template() and ima_restore_template_data(). It also allocates an item in addition to the number of allocated PCR banks, to store a SHA1 digest when the SHA1 PCR bank is not allocated. Calculating the SHA1 digest is mandatory, as SHA1 still remains the default hash algorithm for the measurement list. When IMA will support the Crypto Agile format, remaining digests will be also provided. The position in the array of the SHA1 digest is stored in the ima_sha1_idx global variable and it is determined at IMA initialization time. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 3 ++- security/integrity/ima/ima_api.c | 8 ++++++++ security/integrity/ima/ima_crypto.c | 3 ++- security/integrity/ima/ima_fs.c | 4 ++-- security/integrity/ima/ima_main.c | 2 ++ security/integrity/ima/ima_queue.c | 10 ++++++---- security/integrity/ima/ima_template.c | 12 ++++++++++-- 7 files changed, 32 insertions(+), 10 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6238c50ae44e..d959dab5bcce 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -50,6 +50,7 @@ extern int ima_policy_flag; /* set during initialization */ extern int ima_hash_algo; +extern int ima_sha1_idx; extern int ima_appraise; extern struct tpm_chip *ima_tpm_chip; @@ -92,7 +93,7 @@ struct ima_template_desc { struct ima_template_entry { int pcr; - u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */ + struct tpm_digest *digests; struct ima_template_desc *template_desc; /* template descriptor */ u32 template_data_len; struct ima_field_data template_data[0]; /* template related data */ diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 2ef5a40c7ca5..ebaf0056735c 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -27,6 +27,7 @@ void ima_free_template_entry(struct ima_template_entry *entry) for (i = 0; i < entry->template_desc->num_fields; i++) kfree(entry->template_data[i].data); + kfree(entry->digests); kfree(entry); } @@ -50,6 +51,13 @@ int ima_alloc_init_template(struct ima_event_data *event_data, if (!*entry) return -ENOMEM; + (*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 1, + sizeof(*(*entry)->digests), GFP_NOFS); + if (!(*entry)->digests) { + result = -ENOMEM; + goto out; + } + (*entry)->template_desc = template_desc; for (i = 0; i < template_desc->num_fields; i++) { const struct ima_template_field *field = diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index f2d9d4b18499..57b06321d5c8 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -504,7 +504,8 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, } if (!rc) - rc = crypto_shash_final(shash, entry->digest); + rc = crypto_shash_final(shash, + entry->digests[ima_sha1_idx].digest); return rc; } diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 2000e8df0301..2b79581d0e25 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -152,7 +152,7 @@ int ima_measurements_show(struct seq_file *m, void *v) ima_putc(m, &pcr, sizeof(e->pcr)); /* 2nd: template digest */ - ima_putc(m, e->digest, TPM_DIGEST_SIZE); + ima_putc(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE); /* 3rd: template name size */ namelen = !ima_canonical_fmt ? strlen(template_name) : @@ -235,7 +235,7 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v) seq_printf(m, "%2d ", e->pcr); /* 2nd: SHA1 template hash */ - ima_print_digest(m, e->digest, TPM_DIGEST_SIZE); + ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE); /* 3th: template name */ seq_printf(m, " %s", template_name); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2f95b133f246..c068067a0c47 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -30,6 +30,8 @@ #include "ima.h" +int ima_sha1_idx; + #ifdef CONFIG_IMA_APPRAISE int ima_appraise = IMA_APPRAISE_ENFORCE; #else diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 1ce8b1701566..bcd99db9722c 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -57,7 +57,8 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, key = ima_hash_key(digest_value); rcu_read_lock(); hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) { - rc = memcmp(qe->entry->digest, digest_value, TPM_DIGEST_SIZE); + rc = memcmp(qe->entry->digests[ima_sha1_idx].digest, + digest_value, TPM_DIGEST_SIZE); if ((rc == 0) && (qe->entry->pcr == pcr)) { ret = qe; break; @@ -77,7 +78,7 @@ static int get_binary_runtime_size(struct ima_template_entry *entry) int size = 0; size += sizeof(u32); /* pcr */ - size += sizeof(entry->digest); + size += TPM_DIGEST_SIZE; size += sizeof(int); /* template name size field */ size += strlen(entry->template_desc->name); size += sizeof(entry->template_data_len); @@ -109,7 +110,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, atomic_long_inc(&ima_htable.len); if (update_htable) { - key = ima_hash_key(entry->digest); + key = ima_hash_key(entry->digests[ima_sha1_idx].digest); hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]); } @@ -173,7 +174,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, mutex_lock(&ima_extend_list_mutex); if (!violation) { - memcpy(digest, entry->digest, sizeof(digest)); + memcpy(digest, entry->digests[ima_sha1_idx].digest, + sizeof(digest)); if (ima_lookup_digest_entry(digest, entry->pcr)) { audit_cause = "hash_exists"; result = -EEXIST; diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 6aa6408603e3..2e9c5d99e70e 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -311,11 +311,19 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc, if (!*entry) return -ENOMEM; + (*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 1, + sizeof(*(*entry)->digests), GFP_NOFS); + if (!(*entry)->digests) { + kfree(*entry); + return -ENOMEM; + } + ret = ima_parse_buf(template_data, template_data + template_data_size, NULL, template_desc->num_fields, (*entry)->template_data, NULL, NULL, ENFORCE_FIELDS | ENFORCE_BUFEND, "template data"); if (ret < 0) { + kfree((*entry)->digests); kfree(*entry); return ret; } @@ -447,8 +455,8 @@ int ima_restore_measurement_list(loff_t size, void *buf) if (ret < 0) break; - memcpy(entry->digest, hdr[HDR_DIGEST].data, - hdr[HDR_DIGEST].len); + memcpy(entry->digests[ima_sha1_idx].digest, + hdr[HDR_DIGEST].data, hdr[HDR_DIGEST].len); entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) : le32_to_cpu(*(hdr[HDR_PCR].data)); ret = ima_restore_measurement_entry(entry); From patchwork Mon Jan 27 17:04:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 11352957 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3ED8E924 for ; Mon, 27 Jan 2020 17:07:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1D38224125 for ; Mon, 27 Jan 2020 17:07:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726205AbgA0RG4 (ORCPT ); Mon, 27 Jan 2020 12:06:56 -0500 Received: from lhrrgout.huawei.com ([185.176.76.210]:2305 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725828AbgA0RGz (ORCPT ); Mon, 27 Jan 2020 12:06:55 -0500 Received: from LHREML710-CAH.china.huawei.com (unknown [172.18.7.108]) by Forcepoint Email with ESMTP id 562261ED25860A715952; Mon, 27 Jan 2020 17:06:54 +0000 (GMT) Received: from roberto-HP-EliteDesk-800-G2-DM-65W.huawei.com (10.204.65.160) by smtpsuk.huawei.com (10.201.108.33) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 27 Jan 2020 17:06:45 +0000 From: Roberto Sassu To: , , , CC: , , , Roberto Sassu Subject: [PATCH 5/8] ima: allocate and initialize tfm for each PCR bank Date: Mon, 27 Jan 2020 18:04:40 +0100 Message-ID: <20200127170443.21538-6-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200127170443.21538-1-roberto.sassu@huawei.com> References: <20200127170443.21538-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.65.160] X-CFilter-Loop: Reflected Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org This patch creates a crypto_shash structure for each allocated PCR bank and for SHA1 if a bank with that algorithm is not currently allocated. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima_crypto.c | 137 +++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 24 deletions(-) diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 57b06321d5c8..63fb4bdf80b0 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -59,7 +59,14 @@ MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size"); static struct crypto_shash *ima_shash_tfm; static struct crypto_ahash *ima_ahash_tfm; -int __init ima_init_crypto(void) +struct ima_algo_desc { + struct crypto_shash *tfm; + enum hash_algo algo; +}; + +static struct ima_algo_desc *ima_algo_array; + +int __init ima_init_ima_crypto(void) { long rc; @@ -78,26 +85,116 @@ int __init ima_init_crypto(void) static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) { struct crypto_shash *tfm = ima_shash_tfm; - int rc; + int rc, i; if (algo < 0 || algo >= HASH_ALGO__LAST) algo = ima_hash_algo; - if (algo != ima_hash_algo) { - tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); - if (IS_ERR(tfm)) { - rc = PTR_ERR(tfm); - pr_err("Can not allocate %s (reason: %d)\n", - hash_algo_name[algo], rc); - } + if (algo == ima_hash_algo) + return tfm; + + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) + if (ima_algo_array[i].algo == algo && ima_algo_array[i].tfm) + return ima_algo_array[i].tfm; + + tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); + if (IS_ERR(tfm)) { + rc = PTR_ERR(tfm); + pr_err("Can not allocate %s (reason: %d)\n", + hash_algo_name[algo], rc); } return tfm; } +int __init ima_init_crypto(void) +{ + enum hash_algo algo; + long rc; + int i; + + rc = ima_init_ima_crypto(); + if (rc) + return rc; + + ima_algo_array = kmalloc_array(ima_tpm_chip->nr_allocated_banks + 1, + sizeof(*ima_algo_array), GFP_KERNEL); + if (!ima_algo_array) { + rc = -ENOMEM; + goto out; + } + + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) { + ima_algo_array[i].tfm = NULL; + ima_algo_array[i].algo = HASH_ALGO__LAST; + } + + ima_sha1_idx = -1; + + for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) { + algo = ima_tpm_chip->allocated_banks[i].crypto_id; + ima_algo_array[i].algo = algo; + + /* unknown TPM algorithm */ + if (algo == HASH_ALGO__LAST) + continue; + + if (algo == HASH_ALGO_SHA1) + ima_sha1_idx = i; + + if (algo == ima_hash_algo) { + ima_algo_array[i].tfm = ima_shash_tfm; + continue; + } + + ima_algo_array[i].tfm = ima_alloc_tfm(algo); + if (IS_ERR(ima_algo_array[i].tfm)) { + if (algo == HASH_ALGO_SHA1) { + rc = PTR_ERR(ima_algo_array[i].tfm); + ima_algo_array[i].tfm = NULL; + goto out_array; + } + + ima_algo_array[i].tfm = NULL; + } + } + + if (ima_sha1_idx < 0) { + ima_algo_array[i].tfm = ima_alloc_tfm(HASH_ALGO_SHA1); + if (IS_ERR(ima_algo_array[i].tfm)) { + rc = PTR_ERR(ima_algo_array[i].tfm); + goto out_array; + } + + ima_sha1_idx = i; + ima_algo_array[i].algo = HASH_ALGO_SHA1; + } + + return 0; +out_array: + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) { + if (!ima_algo_array[i].tfm || + ima_algo_array[i].tfm == ima_shash_tfm) + continue; + + crypto_free_shash(ima_algo_array[i].tfm); + } +out: + crypto_free_shash(ima_shash_tfm); + return rc; +} + static void ima_free_tfm(struct crypto_shash *tfm) { - if (tfm != ima_shash_tfm) - crypto_free_shash(tfm); + int i; + + if (tfm == ima_shash_tfm) + return; + + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) + if (ima_algo_array[i].tfm == tfm) + return; + + crypto_free_shash(tfm); } /** @@ -467,14 +564,14 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) */ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, struct ima_template_entry *entry, - struct crypto_shash *tfm) + int tfm_idx) { - SHASH_DESC_ON_STACK(shash, tfm); + SHASH_DESC_ON_STACK(shash, ima_algo_array[tfm_idx].tfm); struct ima_template_desc *td = entry->template_desc; int num_fields = entry->template_desc->num_fields; int rc, i; - shash->tfm = tfm; + shash->tfm = ima_algo_array[tfm_idx].tfm; rc = crypto_shash_init(shash); if (rc != 0) @@ -505,7 +602,7 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, if (!rc) rc = crypto_shash_final(shash, - entry->digests[ima_sha1_idx].digest); + entry->digests[tfm_idx].digest); return rc; } @@ -513,17 +610,9 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, int ima_calc_field_array_hash(struct ima_field_data *field_data, struct ima_template_entry *entry) { - struct crypto_shash *tfm; int rc; - tfm = ima_alloc_tfm(HASH_ALGO_SHA1); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - rc = ima_calc_field_array_hash_tfm(field_data, entry, tfm); - - ima_free_tfm(tfm); - + rc = ima_calc_field_array_hash_tfm(field_data, entry, ima_sha1_idx); return rc; } From patchwork Mon Jan 27 17:04:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 11352959 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8D60F1395 for ; Mon, 27 Jan 2020 17:07:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6BC0822522 for ; Mon, 27 Jan 2020 17:07:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727250AbgA0RHG (ORCPT ); Mon, 27 Jan 2020 12:07:06 -0500 Received: from lhrrgout.huawei.com ([185.176.76.210]:2306 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725828AbgA0RHG (ORCPT ); Mon, 27 Jan 2020 12:07:06 -0500 Received: from LHREML710-CAH.china.huawei.com (unknown [172.18.7.107]) by Forcepoint Email with ESMTP id 7872152ABF15CF361A38; Mon, 27 Jan 2020 17:07:04 +0000 (GMT) Received: from roberto-HP-EliteDesk-800-G2-DM-65W.huawei.com (10.204.65.160) by smtpsuk.huawei.com (10.201.108.33) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 27 Jan 2020 17:06:55 +0000 From: Roberto Sassu To: , , , CC: , , , Roberto Sassu Subject: [PATCH 6/8] ima: calculate and extend PCR with digests in ima_template_entry Date: Mon, 27 Jan 2020 18:04:41 +0100 Message-ID: <20200127170443.21538-7-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200127170443.21538-1-roberto.sassu@huawei.com> References: <20200127170443.21538-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.65.160] X-CFilter-Loop: Reflected Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org This patch modifies ima_calc_field_array_hash() to calculate a template digest for each allocated PCR bank and SHA1. It also passes the tpm_digest array of the template entry to ima_pcr_extend() or in case of a violation, the pre-initialized digests array filled with 0xff. Padding with zeros is still done if the mapping between TPM algorithm ID and crypto ID is unknown. This patch calculates again the template digest when a measurement list is restored. Copying only the SHA1 digest (due to the limitation of the current measurement list format) is not sufficient, as hash collision detection will be done on the digest calculated with the default IMA hash algorithm. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima_crypto.c | 26 ++++++++++++++++++++++- security/integrity/ima/ima_queue.c | 30 ++++++++++++++++----------- security/integrity/ima/ima_template.c | 14 +++++++++++-- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 63fb4bdf80b0..786340feebbb 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -610,9 +610,33 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, int ima_calc_field_array_hash(struct ima_field_data *field_data, struct ima_template_entry *entry) { - int rc; + u16 alg_id; + int rc, i; rc = ima_calc_field_array_hash_tfm(field_data, entry, ima_sha1_idx); + if (rc) + return rc; + + entry->digests[ima_sha1_idx].alg_id = TPM_ALG_SHA1; + + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) { + if (i == ima_sha1_idx) + continue; + + alg_id = ima_tpm_chip->allocated_banks[i].alg_id; + entry->digests[i].alg_id = alg_id; + + if (!ima_algo_array[i].tfm) { + memcpy(entry->digests[i].digest, + entry->digests[ima_sha1_idx].digest, + TPM_DIGEST_SIZE); + continue; + } + + rc = ima_calc_field_array_hash_tfm(field_data, entry, i); + if (rc) + return rc; + } return rc; } diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index bcd99db9722c..7f7509774b85 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -137,18 +137,14 @@ unsigned long ima_get_binary_runtime_size(void) return binary_runtime_size + sizeof(struct ima_kexec_hdr); }; -static int ima_pcr_extend(const u8 *hash, int pcr) +static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) { int result = 0; - int i; if (!ima_tpm_chip) return result; - for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) - memcpy(digests[i].digest, hash, TPM_DIGEST_SIZE); - - result = tpm_pcr_extend(ima_tpm_chip, pcr, digests); + result = tpm_pcr_extend(ima_tpm_chip, pcr, digests_arg); if (result != 0) pr_err("Error Communicating to TPM chip, result: %d\n", result); return result; @@ -166,7 +162,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, const unsigned char *filename) { - u8 digest[TPM_DIGEST_SIZE]; + u8 *digest = entry->digests[ima_sha1_idx].digest; + struct tpm_digest *digests_arg = entry->digests; const char *audit_cause = "hash_added"; char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX]; int audit_info = 1; @@ -174,8 +171,6 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, mutex_lock(&ima_extend_list_mutex); if (!violation) { - memcpy(digest, entry->digests[ima_sha1_idx].digest, - sizeof(digest)); if (ima_lookup_digest_entry(digest, entry->pcr)) { audit_cause = "hash_exists"; result = -EEXIST; @@ -191,9 +186,9 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, } if (violation) /* invalidate pcr */ - memset(digest, 0xff, sizeof(digest)); + digests_arg = digests; - tpmresult = ima_pcr_extend(digest, entry->pcr); + tpmresult = ima_pcr_extend(digests_arg, entry->pcr); if (tpmresult != 0) { snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TPM_error(%d)", tpmresult); @@ -219,6 +214,8 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry) int __init ima_init_digests(void) { + u16 digest_size; + u16 crypto_id; int i; if (!ima_tpm_chip) @@ -229,8 +226,17 @@ int __init ima_init_digests(void) if (!digests) return -ENOMEM; - for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) + for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) { digests[i].alg_id = ima_tpm_chip->allocated_banks[i].alg_id; + digest_size = ima_tpm_chip->allocated_banks[i].digest_size; + crypto_id = ima_tpm_chip->allocated_banks[i].crypto_id; + + /* for unmapped TPM algorithms digest is still a padded SHA1 */ + if (crypto_id == HASH_ALGO__LAST) + digest_size = SHA1_DIGEST_SIZE; + + memset(digests[i].digest, 0xff, digest_size); + } return 0; } diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 2e9c5d99e70e..a9e1390c8e12 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -356,6 +356,7 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc, int ima_restore_measurement_list(loff_t size, void *buf) { char template_name[MAX_TEMPLATE_NAME_LEN]; + unsigned char zero[TPM_DIGEST_SIZE] = { 0 }; struct ima_kexec_hdr *khdr = buf; struct ima_field_data hdr[HDR__LAST] = { @@ -455,8 +456,17 @@ int ima_restore_measurement_list(loff_t size, void *buf) if (ret < 0) break; - memcpy(entry->digests[ima_sha1_idx].digest, - hdr[HDR_DIGEST].data, hdr[HDR_DIGEST].len); + if (memcmp(hdr[HDR_DIGEST].data, zero, sizeof(zero))) { + ret = ima_calc_field_array_hash( + &entry->template_data[0], + entry); + if (ret < 0) { + pr_err("cannot calculate template digest\n"); + ret = -EINVAL; + break; + } + } + entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) : le32_to_cpu(*(hdr[HDR_PCR].data)); ret = ima_restore_measurement_entry(entry); From patchwork Mon Jan 27 17:04:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 11352965 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E780D1395 for ; Mon, 27 Jan 2020 17:07:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C4F1220720 for ; Mon, 27 Jan 2020 17:07:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726772AbgA0RHQ (ORCPT ); Mon, 27 Jan 2020 12:07:16 -0500 Received: from lhrrgout.huawei.com ([185.176.76.210]:2307 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725828AbgA0RHQ (ORCPT ); Mon, 27 Jan 2020 12:07:16 -0500 Received: from LHREML710-CAH.china.huawei.com (unknown [172.18.7.107]) by Forcepoint Email with ESMTP id 9A8BFAB328A26817DD6D; Mon, 27 Jan 2020 17:07:14 +0000 (GMT) Received: from roberto-HP-EliteDesk-800-G2-DM-65W.huawei.com (10.204.65.160) by smtpsuk.huawei.com (10.201.108.33) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 27 Jan 2020 17:07:05 +0000 From: Roberto Sassu To: , , , CC: , , , Roberto Sassu Subject: [PATCH 7/8] ima: use ima_hash_algo for collision detection in the measurement list Date: Mon, 27 Jan 2020 18:04:42 +0100 Message-ID: <20200127170443.21538-8-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200127170443.21538-1-roberto.sassu@huawei.com> References: <20200127170443.21538-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.65.160] X-CFilter-Loop: Reflected Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Before calculating a digest for each PCR bank, collisions were detected with a SHA1 digest. This patch includes ima_hash_algo among the algorithms used to calculate the template digest and checks collisions on that digest. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_api.c | 2 +- security/integrity/ima/ima_crypto.c | 25 ++++++++++++++++++------- security/integrity/ima/ima_main.c | 1 + security/integrity/ima/ima_queue.c | 8 ++++---- security/integrity/ima/ima_template.c | 2 +- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index d959dab5bcce..3e1afa5150bc 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -51,6 +51,7 @@ extern int ima_policy_flag; /* set during initialization */ extern int ima_hash_algo; extern int ima_sha1_idx; +extern int ima_hash_algo_idx; extern int ima_appraise; extern struct tpm_chip *ima_tpm_chip; diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index ebaf0056735c..a9bb45de6db9 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -51,7 +51,7 @@ int ima_alloc_init_template(struct ima_event_data *event_data, if (!*entry) return -ENOMEM; - (*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 1, + (*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 2, sizeof(*(*entry)->digests), GFP_NOFS); if (!(*entry)->digests) { result = -ENOMEM; diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 786340feebbb..f84dfd8fc5ca 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -93,7 +93,7 @@ static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) if (algo == ima_hash_algo) return tfm; - for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++) if (ima_algo_array[i].algo == algo && ima_algo_array[i].tfm) return ima_algo_array[i].tfm; @@ -116,19 +116,20 @@ int __init ima_init_crypto(void) if (rc) return rc; - ima_algo_array = kmalloc_array(ima_tpm_chip->nr_allocated_banks + 1, + ima_algo_array = kmalloc_array(ima_tpm_chip->nr_allocated_banks + 2, sizeof(*ima_algo_array), GFP_KERNEL); if (!ima_algo_array) { rc = -ENOMEM; goto out; } - for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) { + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++) { ima_algo_array[i].tfm = NULL; ima_algo_array[i].algo = HASH_ALGO__LAST; } ima_sha1_idx = -1; + ima_hash_algo_idx = -1; for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) { algo = ima_tpm_chip->allocated_banks[i].crypto_id; @@ -143,6 +144,7 @@ int __init ima_init_crypto(void) if (algo == ima_hash_algo) { ima_algo_array[i].tfm = ima_shash_tfm; + ima_hash_algo_idx = i; continue; } @@ -166,12 +168,21 @@ int __init ima_init_crypto(void) } ima_sha1_idx = i; - ima_algo_array[i].algo = HASH_ALGO_SHA1; + if (ima_hash_algo == HASH_ALGO_SHA1) + ima_hash_algo_idx = i; + + ima_algo_array[i++].algo = HASH_ALGO_SHA1; + } + + if (ima_hash_algo_idx < 0) { + ima_algo_array[i].tfm = ima_shash_tfm; + ima_algo_array[i].algo = ima_hash_algo; + ima_hash_algo_idx = i; } return 0; out_array: - for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) { + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++) { if (!ima_algo_array[i].tfm || ima_algo_array[i].tfm == ima_shash_tfm) continue; @@ -190,7 +201,7 @@ static void ima_free_tfm(struct crypto_shash *tfm) if (tfm == ima_shash_tfm) return; - for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++) if (ima_algo_array[i].tfm == tfm) return; @@ -619,7 +630,7 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, entry->digests[ima_sha1_idx].alg_id = TPM_ALG_SHA1; - for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 1; i++) { + for (i = 0; i < ima_tpm_chip->nr_allocated_banks + 2; i++) { if (i == ima_sha1_idx) continue; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index c068067a0c47..6963d6c31bf1 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -31,6 +31,7 @@ #include "ima.h" int ima_sha1_idx; +int ima_hash_algo_idx; #ifdef CONFIG_IMA_APPRAISE int ima_appraise = IMA_APPRAISE_ENFORCE; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 7f7509774b85..58983d0f0214 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -57,8 +57,8 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, key = ima_hash_key(digest_value); rcu_read_lock(); hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) { - rc = memcmp(qe->entry->digests[ima_sha1_idx].digest, - digest_value, TPM_DIGEST_SIZE); + rc = memcmp(qe->entry->digests[ima_hash_algo_idx].digest, + digest_value, hash_digest_size[ima_hash_algo]); if ((rc == 0) && (qe->entry->pcr == pcr)) { ret = qe; break; @@ -110,7 +110,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, atomic_long_inc(&ima_htable.len); if (update_htable) { - key = ima_hash_key(entry->digests[ima_sha1_idx].digest); + key = ima_hash_key(entry->digests[ima_hash_algo_idx].digest); hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]); } @@ -162,7 +162,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, const unsigned char *filename) { - u8 *digest = entry->digests[ima_sha1_idx].digest; + u8 *digest = entry->digests[ima_hash_algo_idx].digest; struct tpm_digest *digests_arg = entry->digests; const char *audit_cause = "hash_added"; char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX]; diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index a9e1390c8e12..f71b5ee44179 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -311,7 +311,7 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc, if (!*entry) return -ENOMEM; - (*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 1, + (*entry)->digests = kcalloc(ima_tpm_chip->nr_allocated_banks + 2, sizeof(*(*entry)->digests), GFP_NOFS); if (!(*entry)->digests) { kfree(*entry); From patchwork Mon Jan 27 17:04:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 11352969 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5B22D1395 for ; Mon, 27 Jan 2020 17:07:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 434E024672 for ; Mon, 27 Jan 2020 17:07:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727680AbgA0RH0 (ORCPT ); Mon, 27 Jan 2020 12:07:26 -0500 Received: from lhrrgout.huawei.com ([185.176.76.210]:2309 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727586AbgA0RH0 (ORCPT ); Mon, 27 Jan 2020 12:07:26 -0500 Received: from LHREML710-CAH.china.huawei.com (unknown [172.18.7.108]) by Forcepoint Email with ESMTP id BBBAF1FB86A83793CFCF; Mon, 27 Jan 2020 17:07:24 +0000 (GMT) Received: from roberto-HP-EliteDesk-800-G2-DM-65W.huawei.com (10.204.65.160) by smtpsuk.huawei.com (10.201.108.33) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 27 Jan 2020 17:07:15 +0000 From: Roberto Sassu To: , , , CC: , , , Roberto Sassu Subject: [PATCH 8/8] ima: switch to ima_hash_algo for boot aggregate Date: Mon, 27 Jan 2020 18:04:43 +0100 Message-ID: <20200127170443.21538-9-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200127170443.21538-1-roberto.sassu@huawei.com> References: <20200127170443.21538-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.65.160] X-CFilter-Loop: Reflected Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org boot_aggregate is the first entry of IMA measurement list. Its purpose is to link pre-boot measurements to IMA measurements. As IMA was designed to work with a TPM 1.2, the SHA1 PCR bank was always selected. Currently, even if a TPM 2.0 is used, the SHA1 PCR bank is selected. However, the assumption that the SHA1 PCR bank is always available is not correct, as PCR banks can be selected with the PCR_Allocate() TPM command. This patch tries to use ima_hash_algo as hash algorithm for boot_aggregate. If no PCR bank uses that algorithm, the patch scans the allocated PCR banks and selects the first for which the mapping between TPM algorithm ID and crypto algorithm ID is known. If no suitable algorithm is found, an error is returned. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima_crypto.c | 38 +++++++++++++++++------------ security/integrity/ima/ima_init.c | 6 ++--- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index f84dfd8fc5ca..9bf5e69945b7 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -780,25 +780,27 @@ static void __init ima_pcrread(u32 idx, struct tpm_digest *d) /* * Calculate the boot aggregate hash */ -static int __init ima_calc_boot_aggregate_tfm(char *digest, - struct crypto_shash *tfm) +static int __init ima_calc_boot_aggregate_tfm(char *digest, int bank_idx) { - struct tpm_digest d = { .alg_id = TPM_ALG_SHA1, .digest = {0} }; + struct tpm_digest d = { .digest = {0} }; int rc; u32 i; - SHASH_DESC_ON_STACK(shash, tfm); + SHASH_DESC_ON_STACK(shash, ima_algo_array[bank_idx].tfm); - shash->tfm = tfm; + shash->tfm = ima_algo_array[bank_idx].tfm; rc = crypto_shash_init(shash); if (rc != 0) return rc; + d.alg_id = ima_tpm_chip->allocated_banks[bank_idx].alg_id; + /* cumulative sha1 over tpm registers 0-7 */ for (i = TPM_PCR0; i < TPM_PCR8; i++) { ima_pcrread(i, &d); /* now accumulate with current aggregate */ - rc = crypto_shash_update(shash, d.digest, TPM_DIGEST_SIZE); + rc = crypto_shash_update(shash, d.digest, + ima_tpm_chip->allocated_banks[bank_idx].digest_size); } if (!rc) crypto_shash_final(shash, digest); @@ -807,17 +809,21 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest, int __init ima_calc_boot_aggregate(struct ima_digest_data *hash) { - struct crypto_shash *tfm; - int rc; + int bank_idx = ima_hash_algo_idx; - tfm = ima_alloc_tfm(hash->algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - hash->length = crypto_shash_digestsize(tfm); - rc = ima_calc_boot_aggregate_tfm(hash->digest, tfm); + if (bank_idx >= ima_tpm_chip->nr_allocated_banks) { + for (bank_idx = 0; bank_idx < ima_tpm_chip->nr_allocated_banks; + bank_idx++) + if (ima_algo_array[bank_idx].tfm) + break; - ima_free_tfm(tfm); + if (bank_idx == ima_tpm_chip->nr_allocated_banks) { + pr_err("No suitable algo found for boot aggregate\n"); + return -ENOENT; + } + } - return rc; + hash->algo = ima_algo_array[bank_idx].algo; + hash->length = crypto_shash_digestsize(ima_algo_array[bank_idx].tfm); + return ima_calc_boot_aggregate_tfm(hash->digest, bank_idx); } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 195cb4079b2b..b4da190a33ba 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -51,14 +51,14 @@ static int __init ima_add_boot_aggregate(void) int violation = 0; struct { struct ima_digest_data hdr; - char digest[TPM_DIGEST_SIZE]; + char digest[SHA512_DIGEST_SIZE]; } hash; memset(iint, 0, sizeof(*iint)); memset(&hash, 0, sizeof(hash)); iint->ima_hash = &hash.hdr; - iint->ima_hash->algo = HASH_ALGO_SHA1; - iint->ima_hash->length = SHA1_DIGEST_SIZE; + iint->ima_hash->algo = ima_hash_algo; + iint->ima_hash->length = hash_digest_size[ima_hash_algo]; if (ima_tpm_chip) { result = ima_calc_boot_aggregate(&hash.hdr);