From patchwork Sun Mar 23 14:08:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026523 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D2FB38F82 for ; Sun, 23 Mar 2025 14:10:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739007; cv=none; b=SZaws+w4nQqu+3rlLwhyoJh+P6An9N6MEIa5WQHAEdjETVyHrxMtO14qY87h8o4Du/x3n0Mn6JifSZUfOqQ6UctS3XHxlQ+ccGNG+BRFyPh4h9gjwJ1XaTib+3caWoAvzMk/QC9z5JL5c34G0Ds5T8f1DsnpdOWuwmI/KZm2Ta8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739007; c=relaxed/simple; bh=GrpZgBg9X31Q08DVZDNHHA9FFHFSziClFTOti4a+eOI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OZZ7OeA2/HaPzI8VG+sL6i2YnTfqxKTGOdiXLStRpRTIUli9QPPswuEZhhe4IFLfZJIPtNARg3cAl+aeaSCa0DGyej/6nTgyZATLd7BUppsKPHiHRQdb/JRqJHfQ7p4g/1Vh84eKtOMlhO+uojWuGnKXtFavYBqMgo0oq9AT3SU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=Msp+r5hv; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=qTC2GHtz; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=fg7rPlzo; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=91MZuBoe; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="Msp+r5hv"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="qTC2GHtz"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="fg7rPlzo"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="91MZuBoe" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id B35B6211A7; Sun, 23 Mar 2025 14:10:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739003; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/JiaCkjwv9/bflnepr5RWyBmkqWpeSpFXriQoiCmfWU=; b=Msp+r5hvvYBcjJHYoQ++4HMEdsUB8C9qYg40uMgGLz6t45jRGHXUm6iUEh55QRcqbaXTWN lndxAfcedINzWV2Xl6qnQ6PlMiRsTq6m2LiF1+x06etB4/AtzDT3kpHZ2EYhWBrRZfstZ8 9bFn3qQMr0tKvcgw5KOoLCylaOvvHxw= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739003; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/JiaCkjwv9/bflnepr5RWyBmkqWpeSpFXriQoiCmfWU=; b=qTC2GHtzosmLPYrRF3k1tKDgEuLuy1FlOzni1nYB75rNhtn0EO1eosY6WYaDQouCZ40QML gviV957qAIkCGHAA== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739002; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/JiaCkjwv9/bflnepr5RWyBmkqWpeSpFXriQoiCmfWU=; b=fg7rPlzoIdiMzxvGsaDy3AnbIzzZqakCI6MnfEo1Q3b1LDgsrWNywg4UWlew4K+xchKQeM eO3q5W0OlSIGMKCo6I8I7CEX96+WuAqRloAk0Uw54Qbjuw7Fvr7U9eWXOsRBVw2RLbJH2k g44HfRd8rlfTaQZkTY55+XNWY/kh1Zg= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739002; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/JiaCkjwv9/bflnepr5RWyBmkqWpeSpFXriQoiCmfWU=; b=91MZuBoedm5OcUjVGlU0/ycs/p6NWfea+p6EzhUjrxDccHJIu22s+I+CVQEQTNjAQxxAhk WP05ArbAfRGvn5Cw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id A332C1339F; Sun, 23 Mar 2025 14:10:02 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id wbmpJjoW4GeQPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:02 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 01/13] ima: don't expose runtime_measurements for unsupported hashes Date: Sun, 23 Mar 2025 15:08:59 +0100 Message-ID: <20250323140911.226137-2-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -5.30 X-Spamd-Result: default: False [-5.30 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-0.997]; MIME_GOOD(-0.10)[text/plain]; RCPT_COUNT_SEVEN(0.00)[10]; FREEMAIL_TO(0.00)[linux.ibm.com,huawei.com,gmail.com]; MIME_TRACE(0.00)[0:+]; TAGGED_RCPT(0.00)[]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; URIBL_BLOCKED(0.00)[imap1.dmz-prg2.suse.org:helo,suse.de:mid,suse.de:email]; RCVD_COUNT_TWO(0.00)[2]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid,suse.de:email]; FREEMAIL_ENVRCPT(0.00)[gmail.com] X-Spam-Flag: NO X-Spam-Level: IMA creates one runtime_measurements_ sysfs file for every TPM bank + for SHA1 if not covered by any such. These differ only in that the template hash value for each record is of the file's associated algorithm each. The kernel does not necessarily support each hash algorithm associated with some TPM bank though -- the most common case probably being that the algorithm is not built-in, but provided as a module, if at all, and thus not available at IMA init time yet. If that happens to be the case, the behavior is a bit counter-intuitive: probably for historic reasons and to still extend the TPM bank with something, a record's template hash is filled with the padded SHA1 value. That is, it is perfectly possible that runtime_measurements_sha256 contains padded SHA1 template hashes if SHA-256 was unavailable at IMA init. I would argue that it's likely that no existing userspace tool is relying on this fallback logic -- they either wouldn't consume the hash value from the measurement list directly but recreate it by themselves, as is required for verification against PCRs, or, if they did, they would somehow assume a hash algorithm and expect the hashes in the measurement list to be of that type. If of the latter kind, this could even lead to hard to debug verification failures. For example, from looking at keylime's current code, the verifier logic seems to assume that the template hashes found in the provided measurement list are of the configured 'ima_log_hash_alg' type. In particular, it does not check against padded SHA1 upon mismatch. That being said, there's also another dimension: currently IMA has a hard requirement on SHA-1 and subsequent patches in this series will attempt to get rid of that. If SHA-1 is not available at IMA init though, it would also mean that padded SHA-1 values cannot get filled in as a fallback for other unsupported algorithms. Substituting something like hard coded all-zeroes or all-ones would be dangerous, because some application or user scripts could perhaps (ab)use the template hashes from the exported measurement lists for some kind of fingerprinting scheme or so. In conclusion, I think it's best to not create the runtime_measurements_ sysfs files for hash algorithms not supported by the kernel. That way, applications expecting a certain hash algorithm for the measurement list and which are not able to handle the padded-SHA1 fallback scheme would fail with a clear indication on what the problem is. Furthermore, as digests for unsupported banks are not getting exposed to userspace anymore, we'll have all flexibility to set it to any value internally, including all-ones as will be needed in a subsequent patch when addressing PCR extend for unsupported banks. So, do not create runtime_measurements_ sysfs files for unsupported hash algorithms. Likewise for their ascii counterparts. Note that at this point, SHA-1 is still mandatory, and thus, runtime_measurements_sha1 as well as the "runtime_measurements" will remain there, even though the code has provisions already to skip their creation as well in case SHA-1 was unavailable. Signed-off-by: Nicolai Stange Reviewed-by: Mimi Zohar --- security/integrity/ima/ima_fs.c | 35 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index e4a79a9b2d58..a8df2fe5f4cb 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -454,6 +454,9 @@ static int __init create_securityfs_measurement_lists(void) return -ENOMEM; for (i = 0; i < securityfs_measurement_list_count; i++) { + if (!ima_algo_array[i].tfm) + continue; + algo = ima_algo_array[i].algo; sprintf(file_name, "ascii_runtime_measurements_%s", @@ -573,20 +576,26 @@ int __init ima_fs_init(void) if (ret != 0) goto out; - binary_runtime_measurements = - securityfs_create_symlink("binary_runtime_measurements", ima_dir, - "binary_runtime_measurements_sha1", NULL); - if (IS_ERR(binary_runtime_measurements)) { - ret = PTR_ERR(binary_runtime_measurements); - goto out; - } + if (ima_algo_array[ima_sha1_idx].tfm) { + binary_runtime_measurements = + securityfs_create_symlink("binary_runtime_measurements", + ima_dir, + "binary_runtime_measurements_sha1", + NULL); + if (IS_ERR(binary_runtime_measurements)) { + ret = PTR_ERR(binary_runtime_measurements); + goto out; + } - ascii_runtime_measurements = - securityfs_create_symlink("ascii_runtime_measurements", ima_dir, - "ascii_runtime_measurements_sha1", NULL); - if (IS_ERR(ascii_runtime_measurements)) { - ret = PTR_ERR(ascii_runtime_measurements); - goto out; + ascii_runtime_measurements = + securityfs_create_symlink("ascii_runtime_measurements", + ima_dir, + "ascii_runtime_measurements_sha1", + NULL); + if (IS_ERR(ascii_runtime_measurements)) { + ret = PTR_ERR(ascii_runtime_measurements); + goto out; + } } runtime_measurements_count = From patchwork Sun Mar 23 14:09:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026524 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D580EEA8 for ; Sun, 23 Mar 2025 14:10:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739008; cv=none; b=Fw3NTAORnjiEFkViOcBj9z3BQkwOjV1pKk2T+1JdTeA0thRSEoXLW2lRrpJjTj/GHZGjV9FqIyT+owhx6iWt5+bAXuYKdSns/3X/JdH4OcKEKu+DqdU9r3PUvLLi+gBSESvFH0ITDuz7SbsqZ1jy4SSnyk3ojfQId7Ljyo6zSv4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739008; c=relaxed/simple; bh=PUpwA3nhwZdwqXKivSydzyS3A4qMsnQtuTuuQGus5BA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=X59fI2z0kQOF3oV+nTsdSmnIIvDwmkCYjcNKtsfJatrnUApBCVId84krMiBsLV/UNvpWM7UNfJfns8v5oomcnr+OJxxTUTSGc0EVPkzGiN2VLkdqayZDgOBb4Qgoc/DkaUiWUi4xlfSAnnWCzG82okvLviaIpFZoscPl+JNniTA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id A6C291F445; Sun, 23 Mar 2025 14:10:04 +0000 (UTC) Authentication-Results: smtp-out2.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 93C6C1339F; Sun, 23 Mar 2025 14:10:04 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id KTzjIjwW4GeUPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:04 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 02/13] ima: always create runtime_measurements sysfs file for ima_hash Date: Sun, 23 Mar 2025 15:09:00 +0100 Message-ID: <20250323140911.226137-3-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Spamd-Result: default: False [-4.00 / 50.00]; REPLY(-4.00)[]; TAGGED_RCPT(0.00)[] X-Spam-Flag: NO X-Spam-Score: -4.00 X-Rspamd-Queue-Id: A6C291F445 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Action: no action X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Level: runtime_measurements_ sysfs files are getting created for each PCR bank + for SHA-1. Now that runtime_measurements_ sysfs file creation is being skipped for unsupported hash algorithms, it will become possible that no such file would be provided at all once SHA-1 is made optional in a later patch. Always create the file for the 'ima_hash' algorithm, even if it's not associated with any of the PCR banks. As IMA initialization will continue to fail if the ima_hash algorithm is not available to the kernel, this guarantees that at least one such file will always be there. Signed-off-by: Nicolai Stange --- security/integrity/ima/ima_fs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index a8df2fe5f4cb..f030ff7f56da 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -436,10 +436,8 @@ static int __init create_securityfs_measurement_lists(void) u16 algo; int i; - securityfs_measurement_list_count = NR_BANKS(ima_tpm_chip); - - if (ima_sha1_idx >= NR_BANKS(ima_tpm_chip)) - securityfs_measurement_list_count++; + securityfs_measurement_list_count = + NR_BANKS(ima_tpm_chip) + ima_extra_slots; ascii_securityfs_measurement_lists = kcalloc(securityfs_measurement_list_count, sizeof(struct dentry *), From patchwork Sun Mar 23 14:09:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026526 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 25B96136E37 for ; Sun, 23 Mar 2025 14:10:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739015; cv=none; b=sAd5JY0buPQK+2kIw4h5u8CbF86lIm3yAWB+W3WLpj074RVi6cnG1cW+FHLkfjHFi5T4L7s/FQ5PkdLls40Xdhhcvmx4Vwhp4M/0jqVJCpfOsouVjU2N5F/9FBPCP3LAyhWGJtrF/OT76iFqF18iWjZS29Ybxv07RFhVCTFPNmU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739015; c=relaxed/simple; bh=zLfYHYzKHZZUziJQ2voZBXjm67Fh/DrkSqq60SrZLlA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aQqISJYdXHeiKCOIxs4nkQzFhebSa6tWyqeQgEEbdsjv3hKzWaAm9PGe1m8EtINp0/ZFMztr2bDVUEcBNkQk49RIhJNQsYNhyw2AEYTufWeDJqTluu46ZtEbKI2/EE8TD5KskxucduvuCyX57iyys1IiWu0jDEPUqT+m7f9O06Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=rhL80bl3; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=hr82Tufh; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=rhL80bl3; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=hr82Tufh; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="rhL80bl3"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="hr82Tufh"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="rhL80bl3"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="hr82Tufh" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 264071F458; Sun, 23 Mar 2025 14:10:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739006; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pzlaUYsL4gaBxvghA6DZt5QXZeorfSSYq5S6SNCMBN8=; b=rhL80bl3rX8BCxCCh4dxEeCspqEZfhl4PxTM75X+IejAjkZ+R98a3oaVPSUab5VfF91F6F RpCa+GPaoIuZocJQdjZ/GWqrf8JSkrgxD4NuAoGKuwpgCo+WaPhkmYJPDff4207Ujnq9x4 WHXRy81cRhFJLvR5RCBcAOW5TpmmF9k= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739006; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pzlaUYsL4gaBxvghA6DZt5QXZeorfSSYq5S6SNCMBN8=; b=hr82TufhCgx5dpw3Wz2ZBC6TsIxYg2P4u6pVdMGMDuUbo6w0vNpUB7f3Fduie2IwDYKl0U WE9O/yrsCyN1AvAw== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739006; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pzlaUYsL4gaBxvghA6DZt5QXZeorfSSYq5S6SNCMBN8=; b=rhL80bl3rX8BCxCCh4dxEeCspqEZfhl4PxTM75X+IejAjkZ+R98a3oaVPSUab5VfF91F6F RpCa+GPaoIuZocJQdjZ/GWqrf8JSkrgxD4NuAoGKuwpgCo+WaPhkmYJPDff4207Ujnq9x4 WHXRy81cRhFJLvR5RCBcAOW5TpmmF9k= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739006; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pzlaUYsL4gaBxvghA6DZt5QXZeorfSSYq5S6SNCMBN8=; b=hr82TufhCgx5dpw3Wz2ZBC6TsIxYg2P4u6pVdMGMDuUbo6w0vNpUB7f3Fduie2IwDYKl0U WE9O/yrsCyN1AvAw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 15E4B1339F; Sun, 23 Mar 2025 14:10:06 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id jp8kBD4W4GeYPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:06 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 03/13] ima: invalidate unsupported PCR banks Date: Sun, 23 Mar 2025 15:09:01 +0100 Message-ID: <20250323140911.226137-4-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -5.30 X-Spamd-Result: default: False [-5.30 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCPT_COUNT_SEVEN(0.00)[10]; FREEMAIL_TO(0.00)[linux.ibm.com,huawei.com,gmail.com]; MIME_TRACE(0.00)[0:+]; TAGGED_RCPT(0.00)[]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; URIBL_BLOCKED(0.00)[suse.de:mid,suse.de:email,imap1.dmz-prg2.suse.org:helo]; RCVD_COUNT_TWO(0.00)[2]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid,suse.de:email]; FREEMAIL_ENVRCPT(0.00)[gmail.com] X-Spam-Flag: NO X-Spam-Level: Normally IMA would extend a template hash of each bank's associated algorithm into a PCR. However, if a bank's hash algorithm is unavailable to the kernel at IMA init time, it would fallback to extending padded SHA1 hashes instead. That is, if e.g. SHA-256 was missing at IMA init, it would extend padded SHA1 template hashes into a PCR's SHA-256 bank. The ima_measurement command (marked as experimental) from ima-evm-utils would accordingly try both variants when attempting to verify a measurement list against PCRs. keylime OTOH doesn't seem to -- it expects the template hash type to match the PCR bank algorithm. I would argue that for the latter case, the fallback scheme could potentially cause hard to debug verification failures. There's another problem with the fallback scheme: right now, SHA-1 availability is a hard requirement for IMA, and it would be good for a number of reasons to get rid of that. However, if SHA-1 is not available to the kernel, it can hardly provide padded SHA-1 template hashes for PCR banks with unsupported algos. There are several more or less reasonable alternatives possible, among them are: a.) Instead of padded SHA-1, use padded/truncated ima_hash template hashes. b.) Don't extend unsupported banks at all. c.) Record every event as a violation, i.e. extend unsupported banks with 0xffs. d.) Invalidate unsupported banks at least once by extending with a unique constant (e.g. with 0xfes). a.) would make verification from tools like ima_measurement nearly impossible, as it would have to guess or somehow determine ima_hash. b.) is a security risk, because the bank would validate an empty measurement list. c.) isn't ideal security-wise either, because an unsupported bank would then validate an all-violations measurement log. d.) is the only remaining viable option: extending unsupported PCR banks at least once with a unique constant of 0xfe ... fe not used for anything else would make those not to validate anything from that point on. For this last alternative d.), there are some variations possible, which differ in the number of times the magic 0xfe ... fe gets extended into unsupported banks for invalidation purposes. Among the practical ones are: - invalidate each unsupported bank over and over again for each new measurement log entry or - invalidate each unsupported bank exactly once. The second option has the advantage over the first that it would enable tools like ima-evm-utils' ima_measurement to recognize unsupported banks in O(1) time, just by comparing the PCR bank value against the constant HASH(00 .. 00 | fe .. fe). Note that if OTOH a bank got invalidated over and over again for each single log entry, and assuming that it's desired to report unsupported banks as such instead of just failing their validation, ima_measurement would have to try to match yet another PCR extension candidate sequence for the 0xfe .. fe over the complete measurement list, as it's currently being done for the padded SHA1s template hashes already. As appealing as the scheme to invalidate each unsupported bank exactly once might seem at first glance though, there's also the clear drawback of an additional tracking burden with a significant complexity on the kernel side: because IMA can't know ahead of time which out of all possible PCRs would ever get referenced from some policy rules, it cannot simply run the invalidation of unsupported banks upfront at __init, but would have to do it lazily upon a given PCR's first extension. The need for carrying the required state across kexecs, with the possibility of different kernels in the kexec chain potentially supporting different sets of hash algorithms, doesn't exactly make things easier either. So, to move towards the original goal of disentangling IMA from its hard dependency on SHA-1, go with the more straightforward route for now to invalidate unsupported PCR banks over and over again for each new measurement list entry recorded. The more sophisticated "invalidate-exactly-once" scheme will be left to future patches, if to be implemented at all. As this potentially breaks existing userspace, i.e. the current implementation of ima_measurement, put it behind a Kconfig option, "IMA_COMPAT_FALLBACK_TPM_EXTEND". If set to "y", the original behavior of extending with padded SHA-1 is retained. Otherwise the new scheme to invalidate unsupported PCR banks by extending with constant 0xfe ... fe will be effective. As ima_measurement is marked as experimental and I find it unlikely that other existing tools depend on the padded SHA-1 fallback scheme, make the IMA_COMPAT_FALLBACK_TPM_EXTEND Kconfig option default to "n". For IMA_COMPAT_FALLBACK_TPM_EXTEND=n, - to cover PCR extensions for "regular" measurement list entries, make ima_calc_field_array_hash() to fill the digests corresponding to banks with unsupported hash algorithms with 0xfes, - to cover PCR extensions for violation entries, make ima_init_digest() to likewise provision the digests[] elements corresponding to unsupported banks with 0xfes. [1] https://github.com/linux-integrity/ima-evm-utils Signed-off-by: Nicolai Stange --- security/integrity/ima/Kconfig | 14 ++++++++++++++ security/integrity/ima/ima_crypto.c | 19 ++++++++++++++++++- security/integrity/ima/ima_queue.c | 12 ++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 475c32615006..c8f12a4a4edf 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -122,6 +122,20 @@ config IMA_DEFAULT_HASH default "wp512" if IMA_DEFAULT_HASH_WP512 default "sm3" if IMA_DEFAULT_HASH_SM3 +config IMA_COMPAT_FALLBACK_TPM_EXTEND + bool "Enable compatibility TPM PCR extend for unsupported banks" + default n + help + In case a TPM PCR hash algorithm is not supported by the kernel, + retain the old behaviour to extend the bank with padded SHA1 template + digests. + + If Y, IMA will be unavailable when SHA1 is missing from the kernel. + If N, existing tools may fail to verify IMA measurement lists against + TPM PCR banks corresponding to hashes not supported by the kernel. + + If unsure, say N. + config IMA_WRITE_POLICY bool "Enable multiple writes to the IMA policy" default n diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 6f5696d999d0..a43080fb8edc 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -625,26 +625,43 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, u16 alg_id; int rc, i; +#if IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) 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; +#endif for (i = 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) { +#if IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) if (i == ima_sha1_idx) continue; +#endif if (i < NR_BANKS(ima_tpm_chip)) { alg_id = ima_tpm_chip->allocated_banks[i].alg_id; entry->digests[i].alg_id = alg_id; } - /* for unmapped TPM algorithms digest is still a padded SHA1 */ + /* + * For unmapped TPM algorithms, the digest is still a + * padded SHA1 if backwards-compatibility fallback PCR + * extension is enabled. Otherwise fill with + * 0xfes. This is the value to invalidate unsupported + * PCR banks with. Also, a non-all-zeroes value serves + * as an indicator to kexec measurement restoration + * that the entry is not a violation and all its + * template digests need to get recomputed. + */ if (!ima_algo_array[i].tfm) { +#if IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) memcpy(entry->digests[i].digest, entry->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE); +#else + memset(entry->digests[i].digest, 0xfe, TPM_DIGEST_SIZE); +#endif continue; } diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 83d53824aa98..0cc1189446a8 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -274,11 +274,23 @@ int __init ima_init_digests(void) digest_size = ima_tpm_chip->allocated_banks[i].digest_size; crypto_id = ima_tpm_chip->allocated_banks[i].crypto_id; +#if IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) /* 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); +#else + if (ima_algo_array[i].tfm) { + memset(digests[i].digest, 0xff, digest_size); + } else { + /* + * Unsupported banks are invalidated with 0xfe ... fe + * to disambiguate from violations. + */ + memset(digests[i].digest, 0xfe, digest_size); + } +#endif } return 0; From patchwork Sun Mar 23 14:09:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026525 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 466921BC3C for ; Sun, 23 Mar 2025 14:10:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739013; cv=none; b=Iqd/WCj6g8L7Cn2DQQyZ9ZSVcF4iD6VXMSnM5Mz8fq/1gkx3qhemKShAYRsqEfTSY48IiTe0YgpOylRhXoLyNmsCkqIymzMnDWq2PWGw3U8lKXX4v/AJz75ZBNxYCyZLGC79PUs3hRBgzXb8xT0jZ6uoToMLirpMnuZ0gJWwTNc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739013; c=relaxed/simple; bh=E5xHeWqwEMBWbhWZ6KioF73ArpDp2/VqSRyTVBw53Ro=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LaYtECONKXGXC7d+rh8h88pn/UrP8nw+f3l8AMIDh5k9O6Q1JZv4efli5dsDkpJuweE013Y2Gap8YUgaDqAs2/rBNpP1/4YHA6T36Of5nDHRlifVb/NgJxpKmxHgsz7/gZ7XBOO6aviwFtE6mIZEKgnoDvcBT0GhwJs+60844e0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=jGDiMxfG; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=zRiN7euq; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=jGDiMxfG; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=zRiN7euq; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="jGDiMxfG"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="zRiN7euq"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="jGDiMxfG"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="zRiN7euq" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 85741211AA; Sun, 23 Mar 2025 14:10:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739007; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sNQMJd6JsgYTvQGaU1pBMeiOJcpneqS16mWiPW6rVgE=; b=jGDiMxfGQKUvTIA53UPRdNpQzHhW9nVEaWWRUMHc1VNmBdhZqZSwD/lBFnmHhKRD2Gnc/h snBZdFtY7QGx3dQSB42H8ya1J3l4Q1dnon3ABEG5cvCroktLNS+MNQKJ4WqPxUCJ+ljD4x Eh6fV6nZYX1PvKt1HqamTroMESeupck= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739007; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sNQMJd6JsgYTvQGaU1pBMeiOJcpneqS16mWiPW6rVgE=; b=zRiN7euq4QOwNdUB/+VK52HcxGVbdofHxABT5LYX+o9389/3DVQecExFd6raYqQ2/mXeIu TOFT7XpPI3GWEuDg== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739007; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sNQMJd6JsgYTvQGaU1pBMeiOJcpneqS16mWiPW6rVgE=; b=jGDiMxfGQKUvTIA53UPRdNpQzHhW9nVEaWWRUMHc1VNmBdhZqZSwD/lBFnmHhKRD2Gnc/h snBZdFtY7QGx3dQSB42H8ya1J3l4Q1dnon3ABEG5cvCroktLNS+MNQKJ4WqPxUCJ+ljD4x Eh6fV6nZYX1PvKt1HqamTroMESeupck= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739007; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sNQMJd6JsgYTvQGaU1pBMeiOJcpneqS16mWiPW6rVgE=; b=zRiN7euq4QOwNdUB/+VK52HcxGVbdofHxABT5LYX+o9389/3DVQecExFd6raYqQ2/mXeIu TOFT7XpPI3GWEuDg== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 7278B1339F; Sun, 23 Mar 2025 14:10:07 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id v/HnGj8W4GebPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:07 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 04/13] ima: make SHA1 non-mandatory Date: Sun, 23 Mar 2025 15:09:02 +0100 Message-ID: <20250323140911.226137-5-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -5.30 X-Spamd-Result: default: False [-5.30 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-0.998]; MIME_GOOD(-0.10)[text/plain]; URIBL_BLOCKED(0.00)[imap1.dmz-prg2.suse.org:helo,suse.de:mid,suse.de:email]; TO_MATCH_ENVRCPT_ALL(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; ARC_NA(0.00)[]; FREEMAIL_TO(0.00)[linux.ibm.com,huawei.com,gmail.com]; MIME_TRACE(0.00)[0:+]; FREEMAIL_ENVRCPT(0.00)[gmail.com]; RCVD_TLS_ALL(0.00)[]; R_RATELIMIT(0.00)[to_ip_from(RL6owce66jwsk5yhus1j8gn7jo)]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TAGGED_RCPT(0.00)[]; RCPT_COUNT_SEVEN(0.00)[10]; RCVD_VIA_SMTP_AUTH(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid,suse.de:email] X-Spam-Flag: NO X-Spam-Level: For CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND=n, SHA-1 is not a hard requirement anymore. Make ima_init_crypto() continue on SHA-1 instantiation errors. Note that the configured ima_hash must still be available. If that happened to be set to SHA-1 and SHA-1 was missing, then IMA would still fail to initialize. Signed-off-by: Nicolai Stange --- security/integrity/ima/ima_crypto.c | 59 +++++++++++++---------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index a43080fb8edc..4ac4138d98de 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -145,53 +145,47 @@ int __init ima_init_crypto(void) goto out; } + ima_algo_array[ima_hash_algo_idx].tfm = ima_shash_tfm; + ima_algo_array[ima_hash_algo_idx].algo = ima_hash_algo; + + if (ima_hash_algo != HASH_ALGO_SHA1) { + ima_algo_array[ima_sha1_idx].tfm = + ima_alloc_tfm(HASH_ALGO_SHA1); + if (IS_ERR(ima_algo_array[ima_sha1_idx].tfm)) { +#if IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) + /* + * For backwards compatible fallback PCR + * extension, SHA1 is the fallback for missing + * algos. + */ + rc = PTR_ERR(ima_algo_array[ima_sha1_idx].tfm); + goto out_array; +#endif + ima_algo_array[ima_sha1_idx].tfm = NULL; + } + ima_algo_array[ima_sha1_idx].algo = HASH_ALGO_SHA1; + } + for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) { algo = ima_tpm_chip->allocated_banks[i].crypto_id; ima_algo_array[i].algo = algo; + /* Initialized separately above. */ + if (i == ima_hash_algo_idx || i == ima_sha1_idx) + continue; + /* unknown TPM algorithm */ if (algo == HASH_ALGO__LAST) continue; - 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 >= NR_BANKS(ima_tpm_chip)) { - if (ima_hash_algo == HASH_ALGO_SHA1) { - ima_algo_array[ima_sha1_idx].tfm = ima_shash_tfm; - } else { - ima_algo_array[ima_sha1_idx].tfm = - ima_alloc_tfm(HASH_ALGO_SHA1); - if (IS_ERR(ima_algo_array[ima_sha1_idx].tfm)) { - rc = PTR_ERR(ima_algo_array[ima_sha1_idx].tfm); - goto out_array; - } - } - - ima_algo_array[ima_sha1_idx].algo = HASH_ALGO_SHA1; - } - - if (ima_hash_algo_idx >= NR_BANKS(ima_tpm_chip) && - ima_hash_algo_idx != ima_sha1_idx) { - ima_algo_array[ima_hash_algo_idx].tfm = ima_shash_tfm; - ima_algo_array[ima_hash_algo_idx].algo = ima_hash_algo; - } - return 0; +#if IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) out_array: for (i = 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) { if (!ima_algo_array[i].tfm || @@ -201,6 +195,7 @@ int __init ima_init_crypto(void) crypto_free_shash(ima_algo_array[i].tfm); } kfree(ima_algo_array); +#endif out: crypto_free_shash(ima_shash_tfm); return rc; From patchwork Sun Mar 23 14:09:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026528 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1A014142E86 for ; Sun, 23 Mar 2025 14:10:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739021; cv=none; b=boj79pKGbHnC0oo/8o6pkl6Q8Nn/b1JgIE6NftWR3hzqQHZhXTPfHnKuMjN1uzWjT6k8aYRjl5qIwYdNRxbBoCRNRnSfBVZD7EjuIADKFDYM7CVE18wfseIAH930n8Ias9GSWiWYKKcCwAtdnDi23PL+sOiy4A63THA5Ye7NwIc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739021; c=relaxed/simple; bh=aZgDOZteqtNB2LWsQj+sAqYVWYwsREihcCBt3EKYs7g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lZym1MX247Zqz83kUQBbGEmRMFy/06/+WslBn0L1RVj61VquZ+/FTRKo7lZY1LN2yxJ9yX7O8lDexIRIXmYCg0rwGrmtQ4YErL+YVS00ZWgSAbDHr4c23qIRHWDtTd0CX8wEeUliKEXoPmTir/kVb5l7zv8F2VAQBBRwV3//Qlo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=SmB4NETP; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=SiI+EYuY; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=aSwIKQ5c; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=4IFCt1nL; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="SmB4NETP"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="SiI+EYuY"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="aSwIKQ5c"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="4IFCt1nL" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id F0F141F45A; Sun, 23 Mar 2025 14:10:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739009; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6aPUpL5BmfCGVFe96Yt0mlxardWQteHrb5+eH77hyXI=; b=SmB4NETPf36o0Te3DAlhdP4UvUGqq80Jz2IfVp7ir2MJm/q01zzRE6YYov9WVDW6lekadb z6NGS1RLRz/0OVNAsPDEn+srScwspN1ebTUe5jwpEQOcuKEut3u6LHQdzgeMLgp+nVx85y asyno+rAmrvkUWBx+GNiaVwvZ6eZPKo= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739009; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6aPUpL5BmfCGVFe96Yt0mlxardWQteHrb5+eH77hyXI=; b=SiI+EYuY6aS3QW619pWScVFYCksjllL4B9kzk+2W4ZJRvv3EHGD65Tn974ObsN7/Fj7OJU PxqTHIeZ2xqTbrDA== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739008; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6aPUpL5BmfCGVFe96Yt0mlxardWQteHrb5+eH77hyXI=; b=aSwIKQ5c+5WjgwxLmYTQkswQADFG4xPkbgURCovF0JrC8dEkMh8KTIcWjrW/J1NGm9H1YC qdEaCQWQd2HTsQBBtPZYa1h+Q8DZg5F7OzkfwDOCWbzlpko/GrAYmlmYAXfggV1t0TUu8v wvrwx0gSSLzMyQ+WJ+N2fyIElgPwEtY= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739008; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6aPUpL5BmfCGVFe96Yt0mlxardWQteHrb5+eH77hyXI=; b=4IFCt1nLYkNWarIeLpvzr44zGy+T2JYYTvXYwmMuyWuGZoK9Ai57/0wePyg+F3VKmSTkjx iLWrIWAUm4DaIPCw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id E19DE1339F; Sun, 23 Mar 2025 14:10:08 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id MLbkNUAW4GedPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:08 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 05/13] ima: select CRYPTO_SHA256 from Kconfig Date: Sun, 23 Mar 2025 15:09:03 +0100 Message-ID: <20250323140911.226137-6-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-5.30 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[99.99%]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-0.998]; MIME_GOOD(-0.10)[text/plain]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_HAS_DN(0.00)[]; ARC_NA(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; MIME_TRACE(0.00)[0:+]; TAGGED_RCPT(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; RCPT_COUNT_SEVEN(0.00)[10]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:email,suse.de:mid]; RCVD_COUNT_TWO(0.00)[2]; FREEMAIL_TO(0.00)[linux.ibm.com,huawei.com,gmail.com]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; R_RATELIMIT(0.00)[to_ip_from(RL6owce66jwsk5yhus1j8gn7jo)]; FUZZY_BLOCKED(0.00)[rspamd.com]; FREEMAIL_ENVRCPT(0.00)[gmail.com] X-Spam-Score: -5.30 X-Spam-Flag: NO Since recently, IMA would not record measurement list entries into PCR banks for which it doesn't have a corresponding in-kernel hash algorithm implementation available anymore (for CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND=n). With TPM 2.0, the only hash algorithms guaranteed to be implemented on a TPM are SHA-256/384, c.f. "TCG PC Client Platform TPM Profile Specification for TPM 2.0", sec. 4.6 "PCR Requirements". In particular, sha1 is not mandatory, and thus, the CRYPTO_SHA1 dependency of IMA is not sufficient anymore for ensuring that IMA would find at least one usable PCR bank. So, in order to make sure that IMA has access to at least one usable bank on platforms featuring a TPM 2.0 device, make it depend on CRYPTO_SHA256. Keep the dependency on CRYPTO_SHA1 for the TPM 1 case. Signed-off-by: Nicolai Stange --- security/integrity/ima/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index c8f12a4a4edf..8a7e74dc1477 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -7,6 +7,7 @@ config IMA select CRYPTO select CRYPTO_HMAC select CRYPTO_SHA1 + select CRYPTO_SHA256 select CRYPTO_HASH_INFO select SECURITY_PATH select TCG_TPM if HAS_IOMEM From patchwork Sun Mar 23 14:09:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026530 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8411484D08 for ; Sun, 23 Mar 2025 14:10:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739027; cv=none; b=deihdt8WDCZV/P1mgU1D98nVi546JOkqG4YJVPM3nO8YHXLSSRmPGcbo3NoqhvDSh7sj1ZPoDxgJgL1CeQd/S6Oyo2Tgr3nZCY39MGbHOQfyda4HxxievW3SLkRhMHkYjQXdSLK3fOdbs8vSYvVjInU0PzuFSVuNsvxDdFzmBPU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739027; c=relaxed/simple; bh=T0PoZeJmBgvjPiLh0/yVeEy/YsIJz7XgpipDRZ7o+xA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=roO4cV2Dk1P7exXob3+E+9/wG/FZ5e4m3qyIdqLezAF8rv7ur6b8G+asS8/aI6HhKBrLk+NzUfYiCeEOvOlmGUIm61R8s9XAiIdpMj2d8CtvOtI0IkLH//89SsbyOO876foVA6KtG3+ahHAmpwGi89RDfaYzrXgXqUgsffasGKM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=af9Skywd; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=fEaqYM7p; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=af9Skywd; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=fEaqYM7p; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="af9Skywd"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="fEaqYM7p"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="af9Skywd"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="fEaqYM7p" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 73DA51F45B; Sun, 23 Mar 2025 14:10:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739010; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6Gqo9YcEkZlK70DQeUhxU0UqBpCo/yuzbSGr69XBndA=; b=af9SkywdZnsxzeiMGsZrJEsgiFMJioTSuNYeImu9XsRw10ozI47azfiqA3WZdHwMkgx9Gd 8b3xTKjUgH7iPgS+LTDZESPZbHFWBn5LdonlPyMNkdVJX+2XtyL/HNEr1neaoduhjWRzt8 7HmFkfnBboG/oApyQIr7r3Qbzy6yOas= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739010; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6Gqo9YcEkZlK70DQeUhxU0UqBpCo/yuzbSGr69XBndA=; b=fEaqYM7pa2WkjdfntrjHQedwlt5ukTkZkKJ67L63U6onJxlhVgrk6WdcKrU2R2dR2Axb/7 WMeQXwr8VeFrydDw== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739010; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6Gqo9YcEkZlK70DQeUhxU0UqBpCo/yuzbSGr69XBndA=; b=af9SkywdZnsxzeiMGsZrJEsgiFMJioTSuNYeImu9XsRw10ozI47azfiqA3WZdHwMkgx9Gd 8b3xTKjUgH7iPgS+LTDZESPZbHFWBn5LdonlPyMNkdVJX+2XtyL/HNEr1neaoduhjWRzt8 7HmFkfnBboG/oApyQIr7r3Qbzy6yOas= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739010; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6Gqo9YcEkZlK70DQeUhxU0UqBpCo/yuzbSGr69XBndA=; b=fEaqYM7pa2WkjdfntrjHQedwlt5ukTkZkKJ67L63U6onJxlhVgrk6WdcKrU2R2dR2Axb/7 WMeQXwr8VeFrydDw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 61F9B1339F; Sun, 23 Mar 2025 14:10:10 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 97S6FkIW4GeiPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:10 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 06/13] ima: move INVALID_PCR() to ima.h Date: Sun, 23 Mar 2025 15:09:04 +0100 Message-ID: <20250323140911.226137-7-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -5.30 X-Spamd-Result: default: False [-5.30 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-0.998]; MIME_GOOD(-0.10)[text/plain]; URIBL_BLOCKED(0.00)[imap1.dmz-prg2.suse.org:helo,suse.de:mid,suse.de:email]; TO_MATCH_ENVRCPT_ALL(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; ARC_NA(0.00)[]; FREEMAIL_TO(0.00)[linux.ibm.com,huawei.com,gmail.com]; MIME_TRACE(0.00)[0:+]; FREEMAIL_ENVRCPT(0.00)[gmail.com]; RCVD_TLS_ALL(0.00)[]; R_RATELIMIT(0.00)[to_ip_from(RL6owce66jwsk5yhus1j8gn7jo)]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TAGGED_RCPT(0.00)[]; RCPT_COUNT_SEVEN(0.00)[10]; RCVD_VIA_SMTP_AUTH(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid,suse.de:email] X-Spam-Flag: NO X-Spam-Level: Make the INVALID_PCR() #define available to other compilation units by moving it from ima_policy.c to ima.h and renaming it to IMA_INVALID_PCR() in the course. Signed-off-by: Nicolai Stange --- security/integrity/ima/ima.h | 4 ++++ security/integrity/ima/ima_policy.c | 5 +---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index a4f284bd846c..1158a7b8bf6b 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -198,6 +198,10 @@ struct ima_iint_cache { struct ima_digest_data *ima_hash; }; +#define IMA_INVALID_PCR(a) (((a) < 0) || \ + (a) >= (sizeof_field(struct ima_iint_cache, measured_pcrs) * 8)) + + extern struct lsm_blob_sizes ima_blob_sizes; static inline struct ima_iint_cache * diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 128fab897930..d9e4210ea814 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -48,9 +48,6 @@ #define HASH 0x0100 #define DONT_HASH 0x0200 -#define INVALID_PCR(a) (((a) < 0) || \ - (a) >= (sizeof_field(struct ima_iint_cache, measured_pcrs) * 8)) - int ima_policy_flag; static int temp_ima_appraise; static int build_ima_appraise __ro_after_init; @@ -1855,7 +1852,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ima_log_string(ab, "pcr", args[0].from); result = kstrtoint(args[0].from, 10, &entry->pcr); - if (result || INVALID_PCR(entry->pcr)) + if (result || IMA_INVALID_PCR(entry->pcr)) result = -EINVAL; else entry->flags |= IMA_PCR; From patchwork Sun Mar 23 14:09:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026527 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF02F481DD for ; Sun, 23 Mar 2025 14:10:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739020; cv=none; b=o0PDOVRDUC3aT2neDLWQczaeMZnOsUJBK7rua7fjCZrJe8VTAk0TUHhMtGaPgdQIudbBNAhw60EkesKMOk4V5P8IxU2j9sYkOzE2fzzjQq/rnTrUtjqx6Cn+/hVDAZg0cBkaHp5zTkKFfc+Xy1GEi/rxrQ2pnFq1kld4J8n1HXY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739020; c=relaxed/simple; bh=L5sIx5bpO6PtncF8T4SEFBw7PybTVFGOr0/LuCv+KGQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aHoyscN+dwcQnlog0AVW40pbKMeWplbD/OqsnKD57l9UOb6Y4UQCUHZgJsjLIMNEubFA87e1G55dI+A3s8p7tLAlpSAa2Ual38qcetEU++6B7I+T9mvaqDaBMHPLFui3zsADbY4BQx9a59UBwygWn2/e5LASPLREfg7hYJBC4Vo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id D2475211AB; Sun, 23 Mar 2025 14:10:12 +0000 (UTC) Authentication-Results: smtp-out1.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id C001D1339F; Sun, 23 Mar 2025 14:10:12 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id UBSzLUQW4GekPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:12 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 07/13] tpm: enable bank selection for PCR extend Date: Sun, 23 Mar 2025 15:09:05 +0100 Message-ID: <20250323140911.226137-8-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Spamd-Result: default: False [-4.00 / 50.00]; REPLY(-4.00)[]; TAGGED_RCPT(0.00)[] X-Spam-Flag: NO X-Spam-Score: -4.00 X-Rspamd-Queue-Id: D2475211AB X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Action: no action X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Level: The existing tpm_pcr_extend() extends all of a PCR's allocated banks with the corresponding digest from the provided digests[] argument. An upcoming code change to IMA will introduce the need to skip over those banks it does not have a hash algorithm implementation available for. Introduce tpm_pcr_extend_sel() to support this. tpm_pcr_extend_sel() also expects a digests[] array, always being the number of allocated PCR banks in size, just as it's the case for the existing tpm_pcr_extend(). In addition to that however, it takes a 'banks_skip_mask', and will skip the extension of any bank having its corresponding bit set there. Signed-off-by: Nicolai Stange --- drivers/char/tpm/tpm-interface.c | 29 +++++++++++++++++++++++++++-- drivers/char/tpm/tpm.h | 3 ++- drivers/char/tpm/tpm2-cmd.c | 29 +++++++++++++++++++++++++++-- include/linux/tpm.h | 3 +++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index b1daa0d7b341..88b4496de1df 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -314,6 +314,26 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read); */ int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digests) +{ + return tpm_pcr_extend_sel(chip, pcr_idx, digests, 0); +} +EXPORT_SYMBOL_GPL(tpm_pcr_extend); + +/** + * tpm_pcr_extend_sel - extend a PCR value into selected banks. + * @chip: a &struct tpm_chip instance, %NULL for the default chip + * @pcr_idx: the PCR to be retrieved + * @digests: array of tpm_digest structures used to extend PCRs + * @banks_skip_mask: pcr banks to skip + * + * Note: callers must pass a digest for every allocated PCR bank, in the same + * order of the banks in chip->allocated_banks. + * + * Return: same as with tpm_transmit_cmd() + */ +int tpm_pcr_extend_sel(struct tpm_chip *chip, u32 pcr_idx, + struct tpm_digest *digests, + unsigned long banks_skip_mask) { int rc; int i; @@ -330,7 +350,13 @@ int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, } if (chip->flags & TPM_CHIP_FLAG_TPM2) { - rc = tpm2_pcr_extend(chip, pcr_idx, digests); + rc = tpm2_pcr_extend(chip, pcr_idx, digests, banks_skip_mask); + goto out; + } + + /* There's only one SHA1 bank with TPM 1. */ + if (banks_skip_mask & 1) { + rc = 0; goto out; } @@ -341,7 +367,6 @@ int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, tpm_put_ops(chip); return rc; } -EXPORT_SYMBOL_GPL(tpm_pcr_extend); int tpm_auto_startup(struct tpm_chip *chip) { diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 7bb87fa5f7a1..f4ed49cb4101 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -291,7 +291,8 @@ int tpm2_get_timeouts(struct tpm_chip *chip); int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digest, u16 *digest_size_ptr); int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, - struct tpm_digest *digests); + struct tpm_digest *digests, + unsigned long banks_skip_mask); int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max); ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, const char *desc); diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index dfdcbd009720..23ded8ea47dc 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -226,16 +226,34 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, * @chip: TPM chip to use. * @pcr_idx: index of the PCR. * @digests: list of pcr banks and corresponding digest values to extend. + * @banks_skip_mask: pcr banks to skip * * Return: Same as with tpm_transmit_cmd. */ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, - struct tpm_digest *digests) + struct tpm_digest *digests, + unsigned long banks_skip_mask) { struct tpm_buf buf; + unsigned long skip_mask; + u32 banks_count; int rc; int i; + banks_count = 0; + skip_mask = banks_skip_mask; + for (i = 0; i < chip->nr_allocated_banks; i++) { + const bool skip_bank = skip_mask & 1; + + skip_mask >>= 1; + if (skip_bank) + continue; + banks_count++; + } + + if (banks_count == 0) + return 0; + if (!disable_pcr_integrity) { rc = tpm2_start_auth_session(chip); if (rc) @@ -257,9 +275,16 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, tpm_buf_append_auth(chip, &buf, 0, NULL, 0); } - tpm_buf_append_u32(&buf, chip->nr_allocated_banks); + tpm_buf_append_u32(&buf, banks_count); + skip_mask = banks_skip_mask; for (i = 0; i < chip->nr_allocated_banks; i++) { + const bool skip_bank = skip_mask & 1; + + skip_mask >>= 1; + if (skip_bank) + continue; + tpm_buf_append_u16(&buf, digests[i].alg_id); tpm_buf_append(&buf, (const unsigned char *)&digests[i].digest, chip->allocated_banks[i].digest_size); diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 20a40ade8030..7587eecc82fd 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -447,6 +447,9 @@ extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digest); extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digests); +extern int tpm_pcr_extend_sel(struct tpm_chip *chip, u32 pcr_idx, + struct tpm_digest *digests, + unsigned long banks_skip_mask); extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max); extern struct tpm_chip *tpm_default_chip(void); void tpm2_flush_context(struct tpm_chip *chip, u32 handle); From patchwork Sun Mar 23 14:09:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026529 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E8501519B8 for ; Sun, 23 Mar 2025 14:10:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739026; cv=none; b=CUN5BmZDTZSJ9BpDdMeB15OehnKM/V+SilOraOjS5JQBQh8c2gg2B6HRjlTM6Bq8VGVgIOXP96KT6904jnEa1BmTesiKTrsiT33sHhqNp2cbLjDxZLQ89oBRdbhVIvDDX6fzrd5G+tc63/ILXGYCEJ9Cr6dfsW7r5gH9sduIGmQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739026; c=relaxed/simple; bh=cZDI1XugvOeFP1ILeyqBbilL5frkSex2NgY1F2eJUqc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MyyLmkkytdQmPYuMrzf6zE7bTbabP21NGzH897nUV8o9pO9rKccCoBsBF7G7I/RkQgHwImNpYH0nIe3i6WrFjkKABDd/1z2NSCFrXBUHFOjnDO4gm4fpfg3ERnRm++udRP4rKZgIWct4xsfCPtpEZ4K1jZZkigwRdC2xBnJdjRM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=NDEYx4LN; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=8ryjcKdK; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=NDEYx4LN; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=8ryjcKdK; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="NDEYx4LN"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="8ryjcKdK"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="NDEYx4LN"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="8ryjcKdK" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id B10D5211AC; Sun, 23 Mar 2025 14:10:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739014; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=44tClsKTm9qmPcLEvqqp56Ijx7dz9J8weJK+foMELhc=; b=NDEYx4LNQFAiTAxZlRwM5/hYCLbqi0q7sCz458jI+YSiv5G/nEPErewHCGSzqy+6CSVNqE chfmTfY7bhRepUPXIOIVjGhll6Z1J0ivE2dr7oEngja5JKoJgZ2cV+wvLjzLihtEV1I/nF sgdeoedVeyNIi8UJBlpmaw3/VRDOcUs= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739014; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=44tClsKTm9qmPcLEvqqp56Ijx7dz9J8weJK+foMELhc=; b=8ryjcKdKMwkaz/4Nmgh4Mw7FJn0WbXjy4tQeelLvgK2BZIFJ63wG2TW09tAFCL+oASzmql cUReLFKp8WAbnyDQ== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1742739014; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=44tClsKTm9qmPcLEvqqp56Ijx7dz9J8weJK+foMELhc=; b=NDEYx4LNQFAiTAxZlRwM5/hYCLbqi0q7sCz458jI+YSiv5G/nEPErewHCGSzqy+6CSVNqE chfmTfY7bhRepUPXIOIVjGhll6Z1J0ivE2dr7oEngja5JKoJgZ2cV+wvLjzLihtEV1I/nF sgdeoedVeyNIi8UJBlpmaw3/VRDOcUs= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1742739014; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=44tClsKTm9qmPcLEvqqp56Ijx7dz9J8weJK+foMELhc=; b=8ryjcKdKMwkaz/4Nmgh4Mw7FJn0WbXjy4tQeelLvgK2BZIFJ63wG2TW09tAFCL+oASzmql cUReLFKp8WAbnyDQ== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 9F1821339F; Sun, 23 Mar 2025 14:10:14 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 9umXJUYW4GemPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:14 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 08/13] ima: track the set of PCRs ever extended Date: Sun, 23 Mar 2025 15:09:06 +0100 Message-ID: <20250323140911.226137-9-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -5.30 X-Spamd-Result: default: False [-5.30 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-0.997]; MIME_GOOD(-0.10)[text/plain]; URIBL_BLOCKED(0.00)[suse.de:mid,suse.de:email,imap1.dmz-prg2.suse.org:helo]; TO_MATCH_ENVRCPT_ALL(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; ARC_NA(0.00)[]; FREEMAIL_TO(0.00)[linux.ibm.com,huawei.com,gmail.com]; MIME_TRACE(0.00)[0:+]; FREEMAIL_ENVRCPT(0.00)[gmail.com]; RCVD_TLS_ALL(0.00)[]; R_RATELIMIT(0.00)[to_ip_from(RL6owce66jwsk5yhus1j8gn7jo)]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TAGGED_RCPT(0.00)[]; RCPT_COUNT_SEVEN(0.00)[10]; RCVD_VIA_SMTP_AUTH(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid,suse.de:email] X-Spam-Flag: NO X-Spam-Level: Right now, PCR banks with unsupported hash algorithms are getting invalidated over and over again for each new measurement list entry recorded. A subsequent patch will make IMA to invalidate PCR banks associated with unsupported hash algorithms only once at a PCR's first use. To prepare for that, make it track the set of PCRs ever extended. Maintain the set of touched PCRs in an unsigned long bitmask, 'ima_extended_pcrs_mask'. Amend the IMA_INVALID_PCR() #define to check that a given PCR can get represented in that bitmask. Note that this is only for improving code maintainablity, it does not actually constain the set of allowed PCR indices any further. Make ima_pcr_extend() to maintain the ima_extended_pcrs_mask, i.e. to set the currently extented PCR's corresponding bit. Note that at this point there's no provision to restore the ima_extended_pcrs_mask value after kexecs yet, that will be the subject of later patches. Signed-off-by: Nicolai Stange --- security/integrity/ima/ima.h | 8 ++++++-- security/integrity/ima/ima_queue.c | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 1158a7b8bf6b..f99b1f81b35c 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "../integrity.h" @@ -62,6 +63,8 @@ extern int ima_hash_algo_idx __ro_after_init; extern int ima_extra_slots __ro_after_init; extern struct ima_algo_desc *ima_algo_array __ro_after_init; +extern unsigned long ima_extended_pcrs_mask; + extern int ima_appraise; extern struct tpm_chip *ima_tpm_chip; extern const char boot_aggregate_name[]; @@ -198,8 +201,9 @@ struct ima_iint_cache { struct ima_digest_data *ima_hash; }; -#define IMA_INVALID_PCR(a) (((a) < 0) || \ - (a) >= (sizeof_field(struct ima_iint_cache, measured_pcrs) * 8)) +#define IMA_INVALID_PCR(a) (((a) < 0) || \ + (a) >= (8 * min(sizeof_field(struct ima_iint_cache, measured_pcrs), \ + sizeof(ima_extended_pcrs_mask)))) extern struct lsm_blob_sizes ima_blob_sizes; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 0cc1189446a8..6e8a7514d9f6 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -51,6 +51,11 @@ static DEFINE_MUTEX(ima_extend_list_mutex); */ static bool ima_measurements_suspended; +/* + * Set of PCRs ever extended by IMA. + */ +unsigned long ima_extended_pcrs_mask; + /* lookup up the digest value in the hash table, and return the entry */ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, int pcr) @@ -144,15 +149,19 @@ unsigned long ima_get_binary_runtime_size(void) static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) { - int result = 0; + int result; if (!ima_tpm_chip) - return result; + return 0; result = tpm_pcr_extend(ima_tpm_chip, pcr, digests_arg); - if (result != 0) + if (result != 0) { pr_err("Error Communicating to TPM chip, result: %d\n", result); - return result; + return result; + } + + ima_extended_pcrs_mask |= BIT(pcr); + return 0; } /* From patchwork Sun Mar 23 14:09:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026531 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 74CC412FF6F for ; Sun, 23 Mar 2025 14:10:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739032; cv=none; b=c/nDOu+Eo+BD7VS9GJOWQi3HlMY/SWifIkaJibtOWTPn1+MKwU8lFcxed424+iEE5XEqyObbvKvlqUTscO0+CHVURO3X1R/KvSuRw9dciWWSVON8cReDC+MvD5xfcE9wYh2ZhLP5ChdeYpLVOAx/CMe2QrcWu2/BifI+yiCx8e8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739032; c=relaxed/simple; bh=IzP6QKoVhZwNqwbkC/6zkiAnPo2TojmeLMtdlXFS8BA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZzxpIiPxhP3mlz0MbFVFUGAhtgxKMhBGtOfmLYOPGM3+x4Vs3TxRbi5k+eXLwv/7nkgKnl6LVxveMy2s2zUx/pfuFHJSokj2rZC89Or+R7K8nX8PSlmGFXYeo4rxXgSHkwECxbVIVw+me3A03q95KjEhtbXk3t45Iq+6wMz7/S0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 39C3F211B0; Sun, 23 Mar 2025 14:10:21 +0000 (UTC) Authentication-Results: smtp-out1.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 299161339F; Sun, 23 Mar 2025 14:10:21 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id kKkGCU0W4GevPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:21 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 09/13] ima: invalidate unsupported PCR banks only once Date: Sun, 23 Mar 2025 15:09:07 +0100 Message-ID: <20250323140911.226137-10-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Spamd-Result: default: False [-4.00 / 50.00]; REPLY(-4.00)[]; TAGGED_RCPT(0.00)[] X-Spam-Flag: NO X-Spam-Score: -4.00 X-Rspamd-Queue-Id: 39C3F211B0 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Action: no action X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Level: As it currently stands, IMA would invalidate a PCR bank corresponding to an unsupported hash algorithm over and over again by extending it with 0xfe ... fe for each measurement list entry recorded (for CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND=n). This however, makes the problem of deciding from the PCR bank value whether or not the bank had been invalidated or not linear in the measurement list length: one would have to reproduce the potential invalidation extension sequence incrementally for each event recorded and compare whether the PCR bank value would match at any given point. From a soundness POV, the repeated invalidations are not needed: a single one would suffice to ensure no verifier would (wrongly) verify any measurement list against the invalidated PCR bank value. With only a single invalidation, an invalidated PCR bank value can get recognized easily in O(1) by comparing against HASH(0x00 ... 00 | fe ... fe), i.e. the value a PCR bank would have if invalidated once in its initial state. This would potentially help userspace tools such as ima-evm-utils ima_measurement ([1]) which might want to filter unmaintained PCR banks and also, it will enable the kernel to log some meaningful meassages when the set of supported hash algorithm differs between kernel instances in a kexec chain. Start out by invalidating unsupported PCR banks exactly once from each kernel in a kexec chain. Skipping re-invalidations from subsequent kernels in a kexec chain will be the subject of a future patch. Make IMA's crypto __init code to fill in a bitmask of banks with unsupported hash algorithms, ima_unsupported_pcr_banks_mask. ima_unsupported_pcr_banks_mask has been chosen to be of type unsigned long, with the expectation that it will be sufficient to represent all banks allocated on a TPM in practice -- note that 32 > the number of hash algorithm identifiers defined by the TCG. If not, the code would implictly fall back to re-invalidating "excess" banks over and over again, so it is always sound. Make ima_pcr_extend() to skip the extension of a PCR's unsupported banks in case the given PCR had not been extend before, as already tracked in the ima_extended_pcrs_mask introduced by a previous patch. That is, invalidate unsupported banks only once at any given PCR's first extension. Note that ima_extended_pcrs_mask is not retained across kernels in a kexec chain, so each booted kernel would re-invalidate the unsupported banks again. As said above, taking care of this as well will be handled in a separate patch. [1] https://github.com/linux-integrity/ima-evm-utils.git Signed-off-by: Nicolai Stange --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_crypto.c | 21 +++++++++++++++++---- security/integrity/ima/ima_queue.c | 18 +++++++++++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index f99b1f81b35c..7ad4a1eefd94 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -62,6 +62,7 @@ extern int ima_sha1_idx __ro_after_init; extern int ima_hash_algo_idx __ro_after_init; extern int ima_extra_slots __ro_after_init; extern struct ima_algo_desc *ima_algo_array __ro_after_init; +extern unsigned long ima_unsupported_pcr_banks_mask __ro_after_init; extern unsigned long ima_extended_pcrs_mask; diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 4ac4138d98de..c78bf4872b6a 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -67,6 +67,8 @@ int ima_extra_slots __ro_after_init; struct ima_algo_desc *ima_algo_array __ro_after_init; +unsigned long ima_unsupported_pcr_banks_mask __ro_after_init; + static int __init ima_init_ima_crypto(void) { long rc; @@ -184,6 +186,16 @@ int __init ima_init_crypto(void) } } + for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) { + if (i >= BITS_PER_LONG) { + pr_warn("Too many TPM PCR banks, invalidation tracking capped"); + break; + } + + if (!ima_algo_array[i].tfm) + ima_unsupported_pcr_banks_mask |= BIT(i); + } + return 0; #if IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) out_array: @@ -644,10 +656,11 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, * padded SHA1 if backwards-compatibility fallback PCR * extension is enabled. Otherwise fill with * 0xfes. This is the value to invalidate unsupported - * PCR banks with. Also, a non-all-zeroes value serves - * as an indicator to kexec measurement restoration - * that the entry is not a violation and all its - * template digests need to get recomputed. + * PCR banks with once at first use. Also, a + * non-all-zeroes value serves as an indicator to + * kexec measurement restoration that the entry is not + * a violation and all its template digests need to + * get recomputed. */ if (!ima_algo_array[i].tfm) { #if IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 6e8a7514d9f6..83d5c7034919 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -150,11 +150,27 @@ unsigned long ima_get_binary_runtime_size(void) static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) { int result; + unsigned long pcr_banks_skip_mask; if (!ima_tpm_chip) return 0; - result = tpm_pcr_extend(ima_tpm_chip, pcr, digests_arg); +#if !IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) + pcr_banks_skip_mask = ima_unsupported_pcr_banks_mask; + if (!(ima_extended_pcrs_mask & BIT(pcr))) { + /* + * Invalidate unsupported banks once upon a PCR's + * first usage. Note that the digests_arg[] entries for + * unsupported algorithms have been filled with 0xfes. + */ + pcr_banks_skip_mask = 0; + } +#else + pcr_banks_skip_mask = 0; +#endif + + result = tpm_pcr_extend_sel(ima_tpm_chip, pcr, digests_arg, + pcr_banks_skip_mask); if (result != 0) { pr_err("Error Communicating to TPM chip, result: %d\n", result); return result; From patchwork Sun Mar 23 14:09:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026532 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C360F14375C for ; Sun, 23 Mar 2025 14:10:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739033; cv=none; b=OgtcbpwPWOo8CWu+55QnxaOKRg6vFRqF6jpVC9VRCzwZzURO58O5KXEE+TmvDZYz9Ms3qSpxpLogc4Ce5v1s//QymYjchmfk1WcN0dEb+h3mzALfMQp3Tj9QQ3B7TGLEnpX8pTtN8KacuOVPgSaRv6l94Bktd/WkIYjygyo4aGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739033; c=relaxed/simple; bh=mE1eC9HPwNvEBAaoGkNzNse2enTafjWo2svKTu4Z+SM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VshMek78i6YuQ8iT9Jxt7hms8gT9I9CHgtY5IEzc1AwC4cleeLsuglEgaHEO9x141Be77hpoJ/8+S6HHHu+2m1XM4UK1JqWzOXqHlTOaP5IaDo3tJsFxlSed7padOGHh82jDgGBqr+ubF+e/q97ge/lqQeFHMFiTN5gv23ramvY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id DA31E1F455; Sun, 23 Mar 2025 14:10:23 +0000 (UTC) Authentication-Results: smtp-out2.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id C8ACC1339F; Sun, 23 Mar 2025 14:10:23 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id uhnFL08W4GeyPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:23 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 10/13] tpm: authenticate tpm2_pcr_read() Date: Sun, 23 Mar 2025 15:09:08 +0100 Message-ID: <20250323140911.226137-11-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Spamd-Result: default: False [-4.00 / 50.00]; REPLY(-4.00)[]; TAGGED_RCPT(0.00)[] X-Spam-Flag: NO X-Spam-Score: -4.00 X-Rspamd-Queue-Id: DA31E1F455 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Action: no action X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Level: PCR reads aren't currently authenticated even with CONFIG_TCG_TPM2_HMAC=y yet. It is probably desirable though, as e.g. IMA does some PCR reads to form the cumulative boot digest subsequently extended into PCR 10 (an operation which *is* authenticated). Furthermore, a subsequent patch will make IMA to skip certain PCR bank re-invalidations (which are implemented with extensions) upon kexec based on the value read back at boot. In order to not weaken the overall security posture in this case, it will be required to establish the same level of trust into PCR reads as there is already for the extensions. Make tpm2_pcr_read() to protect the command with a HMAC auth session, using the already existing infrastructure. As the TPM2_PCR_Read command doesn't have any authorizations defined, and neither of TPM2_SA_ENCRYPT/TPM2_SA_DECRYPT is needed, use TPM2_SA_AUDIT, even though no auditing functionality is actually being required. Since the TPM will set TPM2_SA_AUDIT_EXCLUSIVE in its response with this single-use session, set it upfront so that tpm_buf_check_hmac_response() would expect it for the HMAC verification. Now that tpm2_pcr_read() depends on the driver's session infrastructure, note that the first call to tpm2_pcr_read() at init time gets issued from tpm_chip_bootstrap() -> tpm_get_pcr_allocation() -> tpm2_get_pcr_allocation() -> tpm2_init_bank_info() -> tpm2_pcr_read() after tpm_chip_bootstrap() -> tpm_auto_startup() -> tpm2_auto_startup() -> tpm2_sessions_init(), so there won't be any issues with that. Signed-off-by: Nicolai Stange --- drivers/char/tpm/tpm2-cmd.c | 46 +++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 23ded8ea47dc..e16772bbc5c8 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -168,6 +168,8 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, int i; int rc; struct tpm_buf buf; + struct tpm_header *head; + int offset_p; struct tpm2_pcr_read_out *out; u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0}; u16 digest_size; @@ -187,9 +189,30 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, expected_digest_size = chip->allocated_banks[i].digest_size; } - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); - if (rc) - return rc; + if (IS_ENABLED(CONFIG_TCG_TPM2_HMAC) && !disable_pcr_integrity) { + rc = tpm2_start_auth_session(chip); + if (rc) + return rc; + + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_READ); + if (rc) { + tpm2_end_auth_session(chip); + return rc; + } + + /* + * Exclusivity is not needed, but set in the response. + * Set it here too, so that the HMAC verification + * won't fail. + */ + tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_AUDIT + | TPM2_SA_AUDIT_EXCLUSIVE, + NULL, 0); + } else { + rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); + if (rc) + return rc; + } pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); @@ -199,11 +222,24 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, tpm_buf_append(&buf, (const unsigned char *)pcr_select, sizeof(pcr_select)); + if (!disable_pcr_integrity) + tpm_buf_fill_hmac_session(chip, &buf); rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to read a pcr value"); if (rc) goto out; + if (!disable_pcr_integrity) { + rc = tpm_buf_check_hmac_response(chip, &buf, rc); + if (rc) + goto out; + } + + head = (struct tpm_header *)buf.data; + offset_p = TPM_HEADER_SIZE; + /* Skip the parameter size field: */ + if (be16_to_cpu(head->tag) == TPM2_ST_SESSIONS) + offset_p += 4; + out = (struct tpm2_pcr_read_out *)&buf.data[offset_p]; - out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE]; digest_size = be16_to_cpu(out->digest_size); if (digest_size > sizeof(digest->digest) || (!digest_size_ptr && digest_size != expected_digest_size)) { @@ -216,6 +252,8 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, memcpy(digest->digest, out->digest, digest_size); out: + if (!disable_pcr_integrity) + tpm2_end_auth_session(chip); tpm_buf_destroy(&buf); return rc; } From patchwork Sun Mar 23 14:09:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026533 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8881B1779AE for ; Sun, 23 Mar 2025 14:10:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739038; cv=none; b=KnmQOY1AvX/Z/283o+RJHEE+PF5WPFOz3Mn+6Sbac3jByschk8y4/8BmKW1zAulsDkfIdpWtkBvzpS8MhE3I9ZL8Vx+KcGr6nGV3WByPEgefL9sxC2gaEQrNlPwyD5T2hAY3lI3EX3w3eRXlRZH/XcnseWvsj4BP745rlwNDues= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739038; c=relaxed/simple; bh=ilkcgqMawpbRXVpG7EBIu+pEGcey+Q1f2F/+6j21r+Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pdhsyQzIMpgMORGiETA+gIlVixJombiPHVKsdHYSIwvWq4VM4uee2DoSlj4zsC8yEZkFP+cU58ksC7MQDf/NVRG07Tn6xZYkcpHcB/JBVgDszxlYJfuhzYrXZctydCTcq6v7MR0d2nS+sqN0ug7f/m050Nyn+tsBaU+cts+O6AM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id D5326211B4; Sun, 23 Mar 2025 14:10:29 +0000 (UTC) Authentication-Results: smtp-out1.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id BED1C1339F; Sun, 23 Mar 2025 14:10:29 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id Ng1sLVUW4Ge2PAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:29 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 11/13] ima: introduce ima_pcr_invalidated_banks() helper Date: Sun, 23 Mar 2025 15:09:09 +0100 Message-ID: <20250323140911.226137-12-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Spam-Level: X-Spamd-Result: default: False [-4.00 / 50.00]; REPLY(-4.00)[]; TAGGED_RCPT(0.00)[] X-Spam-Score: -4.00 X-Spam-Flag: NO X-Rspamd-Queue-Id: D5326211B4 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Action: no action X-Rspamd-Server: rspamd2.dmz-prg2.suse.org At the current stage, IMA would invalidate PCR banks corresponding to unsupported hash algorithms exactly once by extending with the special 0xfe ... fe from each kernel in a kexec chain. In order to work towards the goal of doing that only once for the overall chain, subsequent kernels must be able to recognize already invalidated PCR banks. PCR banks invalidated when in their initial reset state would have a value of HASH(0x00 ... 00 | fe ... fe). Introduce the ima_pcr_invalidated_banks() implementing this comparison for a couple of selected hash algorithms, namely the set the current TPM driver code knows about. Note that false positives would be fatal as far as soundness is concerned, as a future patch will make IMA to skip invalidations for banks reported to have been invalidated already. False negatives however will only cause superfluous re-invalidations, i.e. a PCR bank would not be recognizable as unsupported anymore, but any attempt to verify a measurement list against it would still fail. Thus, ima_pcr_invalidated_banks() doesn't necessarily need to support every hash algorithm possible and in particular, failure to keep it in sync with the TPM driver code, should the latter learn about some more hash algorithms in the future, would not be an issue. Let ima_pcr_invalidated_banks() read back all of a given PCR's bank digests from the TPM. Attempt to compare each against the well-known value of HASH(0x00 ... 00 | fe ... fe) and, in case of a match, set the corresponding bit in a bitmask returned eventually back to the caller. The type chosen for the returned bitmask is unsigned long. If the number of allocated banks exceeds its width, stop early after BITS_PER_LONG banks have been examined -- as mention earlier false negatives aren't fatal. In order to enable ima_pcr_invalidated_banks() to make comparisons against those well-known HASH(...) values from above, even in the scenario of interest here where the kernel's crypto API is lacking a usable implementation for some hash, provide them as pre-computed values in a lookup table for a number of selected hash algorithms, namely those recognized by the current TPM driver code. Lastly a word of caution towards the cherry-pickers among us: you will likely also want that other patch to the TPM driver code making tpm2_pcr_read() to authenticate the TPM response -- otherwise an interposer could potentially trick IMA to skip a needed PCR bank invalidation from a kexeced kernel even with CONFIG_TCG_TPM2_HMAC=y. Signed-off-by: Nicolai Stange --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_crypto.c | 125 ++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 7ad4a1eefd94..67b78f5512f1 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -274,6 +274,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, struct ima_iint_cache *iint, const char *op, const char *cause); int ima_init_crypto(void); +unsigned long ima_pcr_invalidated_banks(u32 pcr); void ima_putc(struct seq_file *m, void *data, int datalen); void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); int template_desc_init_fields(const char *template_fmt, diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index c78bf4872b6a..c1d9cd85a66d 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -900,3 +900,128 @@ int ima_calc_boot_aggregate(struct ima_digest_data *hash) return rc; } + +/* + * Expected values for unsupported PCR banks after invalidating once + * with 0xfe ... fe, i.e. HASH(0x00 ... 00 fe ... fe). + * The list might not be exhaustive as far as the set of recognized + * algorithms is concerned. + */ +static const struct { + u16 tpm_alg_id; + u8 digest_length; + const u8 *digest; +} unsupported_pcr_bank_values[] = { + { + TPM_ALG_SHA1, 20, + (const u8[]) { + 0x74, 0x43, 0x5f, 0x39, 0xb5, 0x05, 0x21, 0x26, + 0x9d, 0xaa, 0xfd, 0x3e, 0x11, 0x1b, 0xf1, 0xd9, + 0x14, 0x1d, 0x9a, 0x5f, + }, + }, + { + TPM_ALG_SHA256, 32, + (const u8[]) { + 0x7a, 0x42, 0xe1, 0xf2, 0x6c, 0x07, 0x82, 0x7f, + 0xaa, 0x54, 0x87, 0x47, 0x62, 0xfd, 0x7f, 0xe7, + 0xa1, 0xdf, 0xbb, 0x8f, 0xfa, 0x51, 0xbf, 0x53, + 0x22, 0xa7, 0x71, 0xd2, 0xc8, 0x80, 0xc5, 0x86, + }, + }, + { + TPM_ALG_SHA384, 48, + (const u8[]) { + 0x68, 0xaa, 0xdf, 0xd3, 0x3e, 0x54, 0x15, 0x40, + 0x73, 0xc8, 0x6a, 0x95, 0x8d, 0x5d, 0x7b, 0xb2, + 0x68, 0xf3, 0x0c, 0x14, 0x9e, 0x19, 0x6d, 0x08, + 0x24, 0x7d, 0x51, 0x26, 0x05, 0xe5, 0x1c, 0x40, + 0xdd, 0xc8, 0x44, 0x4e, 0x93, 0x8a, 0x37, 0x05, + 0xfc, 0xd6, 0xa2, 0x80, 0xe3, 0x27, 0x0d, 0x71, + }, + }, + { + TPM_ALG_SHA512, 64, + (const u8[]) { + 0x58, 0x8c, 0x38, 0x64, 0x06, 0xdb, 0x9b, 0xcc, + 0x26, 0xa4, 0x13, 0x9c, 0x8a, 0xff, 0x6a, 0x10, + 0xf4, 0xe6, 0x5a, 0x92, 0xbd, 0xed, 0x9d, 0x62, + 0xbe, 0x92, 0x1b, 0x40, 0xf6, 0x7d, 0x9b, 0xc3, + 0x0d, 0x07, 0xc8, 0xfb, 0x1a, 0x8d, 0x56, 0xfa, + 0xa4, 0xf2, 0x05, 0xb6, 0x81, 0x29, 0x14, 0x5f, + 0xf6, 0x71, 0x32, 0xbb, 0x0d, 0x31, 0xca, 0xf3, + 0x5e, 0x8e, 0x95, 0xd9, 0xd8, 0x55, 0x28, 0x95, + }, + }, + { + TPM_ALG_SM3_256, 32, + (const u8[]) { + 0x05, 0xff, 0xaf, 0x59, 0x7e, 0x50, 0x39, 0x5b, + 0xaf, 0x69, 0xc0, 0xdc, 0x19, 0xb0, 0xe0, 0xfe, + 0x3f, 0x6b, 0x6f, 0x03, 0xcd, 0x04, 0xf6, 0x80, + 0x6c, 0x59, 0xdc, 0xd2, 0x06, 0xbf, 0x38, 0x78 + }, + }, +}; + +/* + * Return true if the supplied PCR digest can get confirmed to match + * the expected value a bank with unsupported associated hash algorithm + * would have after invalidating it exactly once. + * Otherwise, return false. + * + * False negatives are tolerable from a soundness POV, but would + * potentially cause additional re-invalidations e.g. after kexec. + */ +static bool is_pcr_bank_invalidated(const struct tpm_digest * const digest) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(unsupported_pcr_bank_values); ++i) { + if (unsupported_pcr_bank_values[i].tpm_alg_id == digest->alg_id) + break; + } + + if (i == ARRAY_SIZE(unsupported_pcr_bank_values)) + return false; + + return memcmp(unsupported_pcr_bank_values[i].digest, digest->digest, + unsupported_pcr_bank_values[i].digest_length) == 0; +} + +/* + * Read all of a PCR's banks and check which of those have a value + * matching the expected digest after invalidating once for + * unsupported algorithms. + * + * A bitmask of banks found to have been invalidated is getting + * returned. The set is not guaranteed to be complete. + */ +unsigned long ima_pcr_invalidated_banks(u32 pcr) +{ + int i, r; + struct tpm_digest d; + unsigned long invalidated_banks_mask = 0; + + for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) { + if (i >= BITS_PER_LONG) + break; + + d.alg_id = ima_tpm_chip->allocated_banks[i].alg_id; + r = tpm_pcr_read(ima_tpm_chip, pcr, &d); + if (r) { + /* + * Failure to read is non-fatal, emit a + * warning only and move on to the next bank. + */ + pr_warn("TPM PCR read failed %d, pcr=%d, bank=0x%02x\n", + r, pcr, + ima_tpm_chip->allocated_banks[i].alg_id); + } + + if (is_pcr_bank_invalidated(&d)) + invalidated_banks_mask |= BIT(i); + } + + return invalidated_banks_mask; +} From patchwork Sun Mar 23 14:09:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026534 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C7CB136658 for ; Sun, 23 Mar 2025 14:10:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739044; cv=none; b=ELhjF4Sp9gg3nbRuo8TsPhgXYD3LXK4V3d17KDc/X42iXUx5V7ZyCRJA6ZJ/rpuXiQNRQwyJ9tnMbNXjjz0zBieUovqWu5QapLufkPAHDZB5Z6Z857EI865JbTzusHhR2Pb/08hwRdLn+Z58KfTLTECtokmVqaAjhu26BujNUHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739044; c=relaxed/simple; bh=Bnh0y4ehBp3MIlxHWbGU4cCavGIhNCtorFgrkVQGg+M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=npidDvEJns9SUcaDrEen1Q4/koFMq8PkOXi3JALqygGozLanmmsj9/21kFN9JeWps02b3UXDUZMTiNrQI9eZPSkJJBn3WIn+FVi5pkbUgIkha/kq+8fPWEmDKAquzrpMNfqxwLkVzjC/SqawO4v02n/Bdjg1HeAPR5+GA3hvHJA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 1FCB8211B8; Sun, 23 Mar 2025 14:10:36 +0000 (UTC) Authentication-Results: smtp-out1.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 048261339F; Sun, 23 Mar 2025 14:10:35 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id SeOOO1sW4GfKPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:35 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 12/13] ima: make ima_free_tfm()'s linkage extern Date: Sun, 23 Mar 2025 15:09:10 +0100 Message-ID: <20250323140911.226137-13-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Spamd-Result: default: False [-4.00 / 50.00]; REPLY(-4.00)[]; TAGGED_RCPT(0.00)[] X-Spam-Flag: NO X-Spam-Score: -4.00 X-Rspamd-Queue-Id: 1FCB8211B8 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Action: no action X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Level: Upon recognizing previously unmaintained PCR banks at __init after kexec, a subsequent commit will make IMA to disable the corresponding hashes for the current boot as well. For this, access to ima_free_tfm() from outside its compilation unit is needed. Make its linkage extern. Signed-off-by: Nicolai Stange --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_crypto.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 67b78f5512f1..9bfe045ac9d5 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -274,6 +274,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, struct ima_iint_cache *iint, const char *op, const char *cause); int ima_init_crypto(void); +void ima_free_tfm(struct crypto_shash *tfm); unsigned long ima_pcr_invalidated_banks(u32 pcr); void ima_putc(struct seq_file *m, void *data, int datalen); void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index c1d9cd85a66d..716bb302e75d 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -213,7 +213,7 @@ int __init ima_init_crypto(void) return rc; } -static void ima_free_tfm(struct crypto_shash *tfm) +void ima_free_tfm(struct crypto_shash *tfm) { int i; From patchwork Sun Mar 23 14:09:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolai Stange X-Patchwork-Id: 14026535 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D49813B29B for ; Sun, 23 Mar 2025 14:10:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739050; cv=none; b=rDW2ckMUy0sqw09hxYdOr2xTZz4/lFaZs6kufOW4GQIB5R5mK88KrKfJleqCz83queW6lCK3tT5EhNfwI9uItumRHlYQYCqqz962+A+eWBrc1UODQiFWiy2lCa33UmSOO8KPA/6PNOkr836QDwBwnKdthNNZtMXaIjywwDa/tXU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742739050; c=relaxed/simple; bh=0Nt9HZ9wCJFanHsxL0NL0Mf8URg62LPUrJzWZX4vW9g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZtZ1iB9AR7Kmv+DCOVCjB6g2X7Vja2uARSkNwM1oDHWwpyfd0ynGZvOOX+ufnspy23RA3Ie08bbMtqqa5Psp4dmj5WwW9WfAoCqA8qUFh+hBp/sFwbi47ID+e8Kw0H0/OTv0pdHPcEeSgNM26adc2PvUvX7c0DZrrWsYtTIYuaA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 28376211BA; Sun, 23 Mar 2025 14:10:38 +0000 (UTC) Authentication-Results: smtp-out1.suse.de; none Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 153951339F; Sun, 23 Mar 2025 14:10:38 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id USQKBF4W4GfOPAAAD6G6ig (envelope-from ); Sun, 23 Mar 2025 14:10:38 +0000 From: Nicolai Stange To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin Cc: Eric Snowberg , Jarkko Sakkinen , James Bottomley , linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC PATCH v2 13/13] ima: don't re-invalidate unsupported PCR banks after kexec Date: Sun, 23 Mar 2025 15:09:11 +0100 Message-ID: <20250323140911.226137-14-nstange@suse.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250323140911.226137-1-nstange@suse.de> References: <20250323140911.226137-1-nstange@suse.de> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Spam-Level: X-Spamd-Result: default: False [-4.00 / 50.00]; REPLY(-4.00)[]; TAGGED_RCPT(0.00)[] X-Spam-Score: -4.00 X-Spam-Flag: NO X-Rspamd-Queue-Id: 28376211BA X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Rspamd-Action: no action X-Rspamd-Server: rspamd2.dmz-prg2.suse.org Currently, IMA would invalidate a PCR bank corresponding to an unsupported hash algorithm by extending it with 0xfe ... fe exactly once. The idea is, that banks corresponding to such algorithms would be readily recognizable by comparing against HASH(0x00 ... 00 | fe ... fe), i.e. the value they'd have if extended once when in their initial state after reset. However, PCRs don't get reset at kexec, yet each kernel in a kexec chain would do the (re-)invalidation again. That means that a PCR's bank would have a value of e.g. HASH(HASH(0x00 ... 00 | fe ... fe) | fe ... fe) after a re-invalidation from the second kernel in the chain and so on. In this scenario, it's not anymore immediate from the PCR bank value alone whether an invalidation has happened or not. Don't re-invalidate banks found to have a value of HASH(0x00 ... 00 | fe ... fe) again after kexec. Note that the assumption implicit to the example above was that all kernels in a kexec chain wouldn't have support for a given hash algorithm. However, as it's pointless to start extending some already invalidated bank somewhere in the middle of a kexec chain, an even more general approach is possible: don't /extend/ banks found to have a value of HASH(0x00 ... 00 | fe ... fe) ever again after kexec. With that, any bank corresponding to a hash algorithm not supported by the initial kernel in a kexec chain will retain its HASH(0x00 ... 00 | fe ... fe) value, independent of whether subsequent kernels do or do not support the algorithm in question (assuming all kernels in the chain implement this logic, of course). If some bank's hash algorithm is initially supported by one or more kernels at the head of the kexec chain, but ceases to do so at a certain later point, it necessarily must get invalidated then. As the PCR bank cannot get moved to the magic of HASH(0x00 ... 00 | fe ... fe) by design of how PCRs work anyway, it doesn't matter how many times it's getting invalidated, as long as it's being done at least once. For practicality reasons, the choice has been made to re-invalidate such "discontinued" banks for every new measurement list entry over and over again. (Otherwise, if those banks were e.g. to get invalidated exactly once from each kernel not supporting their hashes, the information to get tracked per PCR would become a tristate: never extended before, extended by a previous kernel or extended by the current one already -- the sets of banks to invalidate upon measurement list entry addition would potentially all be different for each case.) So in summary: - don't touch banks not supported by the initial kernel ever again and keep them at their magic HASH(0x00 ... 00 | fe ... fe) values, - (re-)invalidate any additional bank not supported by the current kernel over and over again for each new measurement list entry added. Regarding the implementation: - Make ima_restore_measurement_list() to determine the set of banks in magic HASH(0x00 ... 00 | fe ... fe) state for each PCR referenced from any entry in the preexisting measurement list after kexec. This is being done by reading back via the ima_pcr_invalidated_banks() helper introduced with a previous patch. The result of this step is the set of banks found invalidated for all the PCRs referenced, kept in the local always_invalidated_pcrs_banks_mask bitmask. While walking the measurement list, make ima_restore_measurement_list() to also update the already existing global ima_extended_pcrs_mask to record every PCR seen. - After walking through the measurement list, always_invalidated_pcrs_banks_mask represents the set of banks whose associated hash algorithms had not been supported by the first kernel in the kexec chain and thus, not been updated by any subsequent kernel between the first and the current one accordingly. At that point, ima_unsupported_pcr_banks_mask corresponds to the set of banks whose associated hash algorithms aren't supported by the current kernel, as per the initialization in ima_init_crypto(). The set difference between the two, i.e. ima_unsupported_pcr_banks_mask & ~always_invalidated_pcrs_banks_mask represents the set of "discontinued" banks, i.e. banks that had been supported and extended before, but which the current kernel cannot maintain any further. As explained above, this set of banks will be subject to re-invalidation upon each new measurement list entry addition. Store it away in new global ima_discontinued_pcr_banks_mask. - After ima_unsupported_pcr_banks_mask has been computed, update ima_unsupported_pcr_banks_mask to the union of itself (the algorithms not supported by the current kernel) with the set of algorithms found to not have been supported by the first kernel in the kexec chain, as represented by the always_invalidated_pcrs_banks_mask from above. At this point, the set banks to not extend any further (for any PCR already encountered before) is ima_unsupported_pcr_banks_mask & ~ima_discontinued_pcr_banks_mask. For clarification: for the first kernel in a kexec chain ima_discontinued_pcr_banks_mask is zero and the result of the expression above is ima_unsupported_pcr_banks_mask. For a subsequent kernel however, this effectively evaluates to the always_invalidated_pcrs_banks_mask found above, which should in turn likewise match the set of algorithms not supported by the initial kernel. Either way, make ima_pcr_extend() to skip over banks in the set represented by the above expression, instead of over the plain ima_unsupported_pcr_banks_mask as before. - The last missing piece is to handle PCRs never encountered before correctly. When subsequently extended for the first time, these must get all their banks in ima_unsupported_pcr_banks_mask invalidated, hence extended with 0xfe ... fe. IMA's template hash computation primitives (more specifically ima_calc_field_array_hash() and ima_init_digests()) would substitute 0xfe ... fe for a bank iff the associated ima_algo_array[]'s entry's ->tfm is NULL. Make ima_restore_measurement_list() to reset any ->tfm potentially non-NULL but in ima_unsupported_pcr_banks_mask. That is, make it reset ->tfm's for which the current kernel does have an implementation available, but the first kernel in the kexec chain did not. As a welcomed side-effect this will also suppress the creation of the {binary,ascii}_runtime_measurements_ sysfs files for any bank never maintained throughout the kexec chain. - Lastly, while iterating over the banks and resetting ->tfm's as appropriate, log some useful information: - inform about banks found unsupported throughout the kexec chain, i.e. in magic HASH(0x00 ... 00 | fe ... fe) state, - print an error if the bank associated with ima_hash is among those - and warn about discontinued banks. With that, any unsupported bank will leave a trace at least once in a kernel log somewhere in the kexec chain (assuming all the kernels are implementing this logic, of course). Signed-off-by: Nicolai Stange --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_crypto.c | 6 ++ security/integrity/ima/ima_queue.c | 9 ++- security/integrity/ima/ima_template.c | 84 ++++++++++++++++++++++++++- 4 files changed, 98 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 9bfe045ac9d5..2b5351cbf6bd 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -63,6 +63,7 @@ extern int ima_hash_algo_idx __ro_after_init; extern int ima_extra_slots __ro_after_init; extern struct ima_algo_desc *ima_algo_array __ro_after_init; extern unsigned long ima_unsupported_pcr_banks_mask __ro_after_init; +extern unsigned long ima_discontinued_pcr_banks_mask __ro_after_init; extern unsigned long ima_extended_pcrs_mask; diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 716bb302e75d..58829c98a69b 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -69,6 +69,12 @@ struct ima_algo_desc *ima_algo_array __ro_after_init; unsigned long ima_unsupported_pcr_banks_mask __ro_after_init; +/* + * Subset of unsupported banks that had (possibly) been supported and + * maintained by some previous kernel in a kexec chain. + */ +unsigned long ima_discontinued_pcr_banks_mask __ro_after_init; + static int __init ima_init_ima_crypto(void) { long rc; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 83d5c7034919..4aa94584957e 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -156,7 +156,14 @@ static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) return 0; #if !IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) - pcr_banks_skip_mask = ima_unsupported_pcr_banks_mask; + /* + * Don't invalidate unsupported PCR banks more than once in + * general, with the exception of discontinued banks possibly + * maintained by a previous kernel in a kexec chain and now in + * indeterminate state. + */ + pcr_banks_skip_mask = ima_unsupported_pcr_banks_mask & + ~ima_discontinued_pcr_banks_mask; if (!(ima_extended_pcrs_mask & BIT(pcr))) { /* * Invalidate unsupported banks once upon a PCR's diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 04c49f05cb74..4584cfc416f4 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -428,7 +428,9 @@ int ima_restore_measurement_list(loff_t size, void *buf) struct ima_template_desc *template_desc; DECLARE_BITMAP(hdr_mask, HDR__LAST); unsigned long count = 0; - int ret = 0; + unsigned long always_invalidated_pcrs_banks_mask = ~0UL; + unsigned long ever_invalidated_pcrs_banks_mask = 0; + int i, ret = 0; if (!buf || size < sizeof(*khdr)) return 0; @@ -527,10 +529,90 @@ int ima_restore_measurement_list(loff_t size, void *buf) entry->pcr = !ima_canonical_fmt ? *(u32 *)(hdr[HDR_PCR].data) : le32_to_cpu(*(__le32 *)(hdr[HDR_PCR].data)); + if (IMA_INVALID_PCR(entry->pcr)) { + pr_err("invalid measurement PCR index"); + ret = -EINVAL; + break; + } + ret = ima_restore_measurement_entry(entry); if (ret < 0) break; +#if !IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND) + if (ima_tpm_chip && + !(ima_extended_pcrs_mask & BIT(entry->pcr))) { + unsigned long invalidated_pcr_banks_mask; + + invalidated_pcr_banks_mask = + ima_pcr_invalidated_banks(entry->pcr); + always_invalidated_pcrs_banks_mask &= + invalidated_pcr_banks_mask; + ever_invalidated_pcrs_banks_mask |= + invalidated_pcr_banks_mask; + } + ima_extended_pcrs_mask |= BIT(entry->pcr); +#endif } + + always_invalidated_pcrs_banks_mask &= ever_invalidated_pcrs_banks_mask; + /* + * Banks that had (possibly) been maintained by a previous + * kernel in the kexec chain, but aren't anymore now, are + * considered "discontinued" and in indeterminate + * state. Re-invalidate unconditionally at each PCR extend. + */ + if (ima_extended_pcrs_mask != 0) { + ima_discontinued_pcr_banks_mask = ima_unsupported_pcr_banks_mask + & ~always_invalidated_pcrs_banks_mask; + } + + /* + * Banks consistently found invalidated for having been + * unsupported before, are kept in the "unsupported" state and + * never re-invalidated again, so that they retain their + * easily recognizable, well-known digest value. + */ + ima_unsupported_pcr_banks_mask |= always_invalidated_pcrs_banks_mask; + + for (i = 0; i < NR_BANKS(ima_tpm_chip); ++i) { + if (i >= BITS_PER_LONG) + break; + + /* + * Don't clutter the logs with unrecognized algos, + * these would always get reported as "discontinued" + * otherwise. + */ + if (ima_algo_array[i].algo == HASH_ALGO__LAST) + continue; + + if (ima_discontinued_pcr_banks_mask & BIT(i)) { + pr_warn("Discontinuing unsupported TPM %s PCR bank\n", + hash_algo_name[ima_algo_array[i].algo]); + } else if (i == ima_hash_algo_idx && + ever_invalidated_pcrs_banks_mask & BIT(i)) { + pr_err("Continuing on stale ima_hash TPM PCR bank\n"); + + /* Force back to supported. */ + ima_unsupported_pcr_banks_mask &= ~BIT(i); + } else if (always_invalidated_pcrs_banks_mask & BIT(i)) { + struct crypto_shash *tfm; + + pr_info("Masking previously unsupported TPM %s PCR bank\n", + hash_algo_name[ima_algo_array[i].algo]); + + /* + * Remove the ->tfm so that any not yet + * extended PCRs will get their corresponding + * bank invalidated as well upon first use. + */ + tfm = ima_algo_array[i].tfm; + ima_algo_array[i].tfm = NULL; + if (tfm) + ima_free_tfm(tfm); + } + } + return ret; }