For each namespace do this calculation: tempPCR := HASH(tempPCR || tempValue); And finally extend the real PCR12P: PCR12 := PCR_Extend(PCR12,tempPCR); Then read the PCR12 and return its value to user-space. Signed-off-by: Denis Semakin <denis.semakin@xxxxxxxxxx> --- security/integrity/ima/ima.h | 2 +- security/integrity/ima/ima_fs.c | 46 ++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 81385aee04f1..257c60ffed23 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -27,7 +27,7 @@ enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN, IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII }; -enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; +enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10, TPM_PCR12 = 12 }; /* digest size for IMA, fits SHA1 or MD5 */ #define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index aaa65ee0d9d5..1fab4eed3692 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -559,6 +559,9 @@ static ssize_t ima_vpcr_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { struct vpcr_entry *vpcr; + struct tpm_digest *temp_tpm; + struct tpm_digest pcr12_digest; + struct tpm_chip *ns_tpm_chip; struct { struct ima_digest_data hdr; char digest[SHA256_DIGEST_SIZE]; @@ -568,17 +571,20 @@ static ssize_t ima_vpcr_read(struct file *filp, char __user *buf, size_t count, u8 dig[CPCR_PFX_LEN + SHA256_DIGEST_SIZE + 1]; } *vpcr_buff = NULL; - int ret, i = 0; + int ret, j, i = 0; size_t vpcr_buff_size = 0; loff_t size = SHA256_DIGEST_SIZE * 2; struct ima_namespace *init_ns = &init_ima_ns; struct ima_namespace *curr_ns = ima_ns_from_file(filp); + ns_tpm_chip = curr_ns->ima_tpm_chip; + if (*ppos != 0) return 0; temp_vpcr_hash.hdr.algo = HASH_ALGO_SHA256; temp_vpcr_hash.hdr.length = SHA256_DIGEST_SIZE; + pcr12_digest.alg_id = TPM_ALG_SHA256; if (mutex_lock_interruptible(&vpcr_list_mutex)) return -EINTR; @@ -616,6 +622,38 @@ static ssize_t ima_vpcr_read(struct file *filp, char __user *buf, size_t count, i++; } + /** + * TPM banks for extend + */ + temp_tpm = kcalloc(ns_tpm_chip->nr_allocated_banks, + sizeof(*curr_ns->digests), GFP_NOFS); + if (!temp_tpm) { + ret = -ENOMEM; + goto free_mem; + } + + for (j = 0; j < ns_tpm_chip->nr_allocated_banks; j++) { + temp_tpm[j].alg_id = ns_tpm_chip->allocated_banks[j].alg_id; + if (temp_tpm[j].alg_id == TPM_ALG_SHA256) + memcpy(&temp_tpm[j].digest, &temp_vpcr_hash.digest, + SHA256_DIGEST_SIZE); + else + memset(&temp_tpm[j].digest, 0, + hash_digest_size[ns_tpm_chip->allocated_banks[j].crypto_id]); + } + + ret = tpm_pcr_extend(ns_tpm_chip, TPM_PCR12, temp_tpm); + if (ret != 0) { + ret = -EINTR; + goto free_mem; + } + + ret = tpm_pcr_read(ns_tpm_chip, TPM_PCR12, &pcr12_digest); + if (ret != 0) { + ret = -EINTR; + goto free_mem; + } + vpcr_buff_size += PCR12_PFX_LEN + SHA256_DIGEST_SIZE + 1; vpcr_buff = krealloc(vpcr_buff, vpcr_buff_size, GFP_NOFS); if (!vpcr_buff) { @@ -624,10 +662,14 @@ static ssize_t ima_vpcr_read(struct file *filp, char __user *buf, size_t count, } memcpy(&vpcr_buff[i].dig, PCR12_PFX, PCR12_PFX_LEN); + memcpy(&vpcr_buff[i].dig[PCR12_PFX_LEN], &pcr12_digest.digest, + SHA256_DIGEST_SIZE); + mutex_unlock(&vpcr_list_mutex); ret = simple_read_from_buffer(buf, count, ppos, vpcr_buff, vpcr_buff_size); kfree(vpcr_buff); + kfree(temp_tpm); return ret; @@ -636,6 +678,8 @@ static ssize_t ima_vpcr_read(struct file *filp, char __user *buf, size_t count, if (vpcr_buff) kfree(vpcr_buff); + kfree(temp_tpm); + return ret; } -- 2.25.1