import keylime-6.5.2-4.el9

This commit is contained in:
CentOS Sources 2023-05-09 05:30:25 +00:00 committed by Stepan Oksanichenko
parent 443bb1fa5a
commit 39cf484682
12 changed files with 235 additions and 1020 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
SOURCES/v6.5.1.tar.gz
SOURCES/keylime-selinux-1.0.0.tar.gz
SOURCES/v6.5.2.tar.gz

View File

@ -1 +1,2 @@
3205e290b09550a994237f067c41a72aab5289a9 SOURCES/v6.5.1.tar.gz
a1154fc19d2ae6f52b6b77a39e62d2420c0f4c5e SOURCES/keylime-selinux-1.0.0.tar.gz
1c311bc1d3ab6c8050fd819410c593392187c2fa SOURCES/v6.5.2.tar.gz

View File

@ -1,7 +1,7 @@
From 76cbd7bbcce1793db9a3d64d962cfdb518ef4eff Mon Sep 17 00:00:00 2001
From d6dd71e3a3fe8e822fbcaa0d88f19a0c3332cacd Mon Sep 17 00:00:00 2001
From: Sergio Correia <scorreia@redhat.com>
Date: Tue, 15 Nov 2022 07:09:13 -0300
Subject: [PATCH 4/4] Do not use default values that need reading the config in
Subject: [PATCH] Do not use default values that need reading the config in
methods
Following up from the recent refactoring that moved the EK validation
@ -52,7 +52,7 @@ index d2fc54d..3576c64 100644
"""
try:
diff --git a/keylime/tenant.py b/keylime/tenant.py
index dd9c09c..118f8c4 100644
index b574d04..076b849 100644
--- a/keylime/tenant.py
+++ b/keylime/tenant.py
@@ -430,7 +430,7 @@ class Tenant:
@ -78,7 +78,7 @@ index ff41837..df6222c 100644
@abstractmethod
diff --git a/keylime/tpm/tpm_main.py b/keylime/tpm/tpm_main.py
index 35f0a2f..09af0d0 100644
index e1d1cf8..e244dfa 100644
--- a/keylime/tpm/tpm_main.py
+++ b/keylime/tpm/tpm_main.py
@@ -776,12 +776,12 @@ class tpm(tpm_abstract.AbstractTPM):

View File

@ -1,42 +0,0 @@
From de8bbb63dca836bcf07586186218c3227749d2e7 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Fri, 4 Nov 2022 11:20:15 -0400
Subject: [PATCH] ima: Fix log evaluation on quick-succession execution of
scripts
In case the attested-to host quickly executes files measured by IMA we may
run into the case that the keylime agent retrieved the state of the PCR at
'state n' but then IMA appended the log with several entries leading to a
log representing 'state n + x' (with x>=1), which may not just be the
previously anticipated single additional entry (state n+1). Therefore,
remove the check for the number of entries in the log and always compare
the running_hash that iterative attestation was resumed with against the
provided PCR value from 'state n'.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
keylime/ima/ima.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/keylime/ima/ima.py b/keylime/ima/ima.py
index b88b1af..c4c2ae6 100644
--- a/keylime/ima/ima.py
+++ b/keylime/ima/ima.py
@@ -299,9 +299,11 @@ def _process_measurement_list(
# Iterative attestation may send us no log [len(lines) == 1]; compare last know PCR 10 state
# against current PCR state.
- # Since IMA log append and PCR extend is not atomic, we may get a quote that does not yet take
- # into account the next appended measurement's [len(lines) == 2] PCR extension.
- if not found_pcr and len(lines) <= 2:
+ # Since IMA's append to the log and PCR extend as well as Keylime's retrieval of the quote, reading
+ # of PCR 10 and retrieval of the log are not atomic, we may get a quote that does not yet take into
+ # account the next-appended measurements' [len(lines) >= 2] PCR extension(s). In fact, the value of
+ # the PCR may lag the log by several entries.
+ if not found_pcr:
found_pcr = running_hash == pcrval_bytes
for linenum, line in enumerate(lines):
--
2.37.3

View File

@ -0,0 +1,67 @@
From 1f9ee7437f5b712a892c6d13ac8d75e128c1a16f Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 22 Nov 2022 10:56:43 -0500
Subject: [PATCH] tests: Switch to sha256 hashes for signatures
Resolves: https://github.com/keylime/keylime/issues/1202
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
test/test_ima_ast.py | 4 ++--
test/test_ima_verification.py | 12 ++++++------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/test/test_ima_ast.py b/test/test_ima_ast.py
index cd54f95f9..e7d3841a7 100644
--- a/test/test_ima_ast.py
+++ b/test/test_ima_ast.py
@@ -14,11 +14,11 @@
VALID_ENTRIES = {
"ima-sig-rsa": (
ast.ImaSig,
- "10 50873c47693cf9458e87eb4a02dd4f594f7a0c0f ima-sig sha1:1350320e5f7f51553bac8aa403489a1b135bc101 /usr/bin/dd 030202f3452d23010084c2a6cf7de1aeefa119220df0da265a7c44d34380f0d97002e7c778d09cfcf88c018e6595df3ee70eda926851f159332f852e7981a8fca1bc5e959958d06d234a0896861f13cc60da825905c8ed234df26c1deecfa816d5aa9bfb11b905e2814084a86b588be60423afada8dd0dd5a143774c6d890b64195ac42fb47ef5a9a00f0d6c80711d8e0c2b843ec38c02f60fd46bc46c7b4c329ad2dbb1b7625293703f9c739dc4c2bf0769126a2f3cb2cd031d1881cd0af64bf20fd474a993b48620f103a5c14999a2f17d60721bcc019a896b4138a688a59f50cb6cd94a4cfe3b8052e82dec025fef4feabb08c7ce412e3de850f903797e293ec27c329f57fd84e0",
+ "10 1e70a3e1af66f42826ad63b761b4cb9c4df195e1 ima-sig sha256:d33d5d13792292e202dbf69a6f1b07bc8a02f01424db8489ba7bb7d43c0290ef /usr/bin/dd 030204f3452d2301009dd340c852f37e35748363586939d4199b6684be27e7c1236ca1528f708372ed9cd52a0d991f66448790f5616ed5bd7f9bbd22193b1e3e54f6bf29a1497945a34d1b418b24f4cbeaef897bf3cebca27065ebb8761b46bc2662fe76f141245b9186a5ac8493c7f4976cf0d6dfc085c3e503e3f771bc3ccb121230db76fd8aba4f45f060ad64ab3afd99b4e52824b9eba12e93e46f9dcb2fa01d9cef89f298a0da02a82a4fb56924afd3e3c277a1302d99f770d488449df2d43eb5b174a0a528827e6877b965c2f0b7c89cf1aa26a7417a892df4c2294e2872d62748b72ea04ecb0689b5d792e615a9bf9d56f6e0f298560bf9441df0a22729c5f23389f028c25f",
),
"ima-sig-ec": (
ast.ImaSig,
- "10 06e804489a77ddab51b9ef27e17053c0e5d503bd ima-sig sha1:1cb84b12db45d7da8de58ba6744187db84082f0e /usr/bin/zmore 030202531f402500483046022100bff9c02dc7b270c83cc94bfec10eecd42831de2cdcb04f024369a14623bc3a91022100cc4d015ae932fb98d6846645ed7d1bb1afd4621ec9089bc087126f191886dd31",
+ "10 5d4d5141ccd5066d50dc3f21d79ba02fedc24256 ima-sig sha256:b8ae0b8dd04a5935cd8165aa2260cd11b658bd71629bdb52256a675a1f73907b /usr/bin/zmore 030204531f402500483046022100fe24678d21083ead47660e1a2d553a592d777c478d1b0466de6ed484b54956b3022100cad3adb37f277bbb03544d6107751b4cd4f2289d8353fa36257400a99334d5c3",
),
"ima-sig-missing": (
ast.ImaSig,
diff --git a/test/test_ima_verification.py b/test/test_ima_verification.py
index bdb929c9c..d2fc9ef16 100644
--- a/test/test_ima_verification.py
+++ b/test/test_ima_verification.py
@@ -27,8 +27,8 @@
"/lib/modules/5.4.48-openpower1/kernel/drivers/gpu/drm/drm_panel_orientation_quirks.ko": [
"cd026b58efdf66658685430ff526490d54a430a3f0066a35ac26a8acab66c55d"
],
- "/usr/bin/dd": ["1350320e5f7f51553bac8aa403489a1b135bc101"],
- "/usr/bin/zmore": ["1cb84b12db45d7da8de58ba6744187db84082f0e"],
+ "/usr/bin/dd": ["d33d5d13792292e202dbf69a6f1b07bc8a02f01424db8489ba7bb7d43c0290ef"],
+ "/usr/bin/zmore": ["b8ae0b8dd04a5935cd8165aa2260cd11b658bd71629bdb52256a675a1f73907b"],
"/usr/bin/zless": ["233ad3a8e77c63a7d9a56063ec2cad1eafa58850"],
},
"keyrings": {
@@ -50,8 +50,8 @@
"version": 1,
},
"hashes": {
- "/usr/bin/dd": ["1350320e5f7f51553bac8aa403489a1b135bc102"],
- "/usr/bin/zmore": ["1cb84b12db45d7da8de58ba6744187db84082f01"],
+ "/usr/bin/dd": ["bad05d13792292e202dbf69a6f1b07bc8a02f01424db8489ba7bb7d43c0290ef"],
+ "/usr/bin/zmore": ["bad00b8dd04a5935cd8165aa2260cd11b658bd71629bdb52256a675a1f73907b"],
},
}
@@ -73,8 +73,8 @@
# 1st signature: RSA
# 2nd signature: EC
SIGNATURES = (
- "10 50873c47693cf9458e87eb4a02dd4f594f7a0c0f ima-sig sha1:1350320e5f7f51553bac8aa403489a1b135bc101 /usr/bin/dd 030202f3452d23010084c2a6cf7de1aeefa119220df0da265a7c44d34380f0d97002e7c778d09cfcf88c018e6595df3ee70eda926851f159332f852e7981a8fca1bc5e959958d06d234a0896861f13cc60da825905c8ed234df26c1deecfa816d5aa9bfb11b905e2814084a86b588be60423afada8dd0dd5a143774c6d890b64195ac42fb47ef5a9a00f0d6c80711d8e0c2b843ec38c02f60fd46bc46c7b4c329ad2dbb1b7625293703f9c739dc4c2bf0769126a2f3cb2cd031d1881cd0af64bf20fd474a993b48620f103a5c14999a2f17d60721bcc019a896b4138a688a59f50cb6cd94a4cfe3b8052e82dec025fef4feabb08c7ce412e3de850f903797e293ec27c329f57fd84e0\n"
- "10 06e804489a77ddab51b9ef27e17053c0e5d503bd ima-sig sha1:1cb84b12db45d7da8de58ba6744187db84082f0e /usr/bin/zmore 030202531f402500483046022100bff9c02dc7b270c83cc94bfec10eecd42831de2cdcb04f024369a14623bc3a91022100cc4d015ae932fb98d6846645ed7d1bb1afd4621ec9089bc087126f191886dd31\n"
+ "10 1e70a3e1af66f42826ad63b761b4cb9c4df195e1 ima-sig sha256:d33d5d13792292e202dbf69a6f1b07bc8a02f01424db8489ba7bb7d43c0290ef /usr/bin/dd 030204f3452d2301009dd340c852f37e35748363586939d4199b6684be27e7c1236ca1528f708372ed9cd52a0d991f66448790f5616ed5bd7f9bbd22193b1e3e54f6bf29a1497945a34d1b418b24f4cbeaef897bf3cebca27065ebb8761b46bc2662fe76f141245b9186a5ac8493c7f4976cf0d6dfc085c3e503e3f771bc3ccb121230db76fd8aba4f45f060ad64ab3afd99b4e52824b9eba12e93e46f9dcb2fa01d9cef89f298a0da02a82a4fb56924afd3e3c277a1302d99f770d488449df2d43eb5b174a0a528827e6877b965c2f0b7c89cf1aa26a7417a892df4c2294e2872d62748b72ea04ecb0689b5d792e615a9bf9d56f6e0f298560bf9441df0a22729c5f23389f028c25f\n"
+ "10 5d4d5141ccd5066d50dc3f21d79ba02fedc24256 ima-sig sha256:b8ae0b8dd04a5935cd8165aa2260cd11b658bd71629bdb52256a675a1f73907b /usr/bin/zmore 030204531f402500483046022100fe24678d21083ead47660e1a2d553a592d777c478d1b0466de6ed484b54956b3022100cad3adb37f277bbb03544d6107751b4cd4f2289d8353fa36257400a99334d5c3\n"
)
COMBINED = MEASUREMENTS + SIGNATURES

View File

@ -1,70 +0,0 @@
From 2fee03637d3a1d0c9c004b958af69f4b0e4b57f3 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Fri, 4 Nov 2022 17:41:31 +0100
Subject: [PATCH 2/2] tpm_bootlog_enrich: Get DevicePath length from
LengthOfDevicePath
In enrich_device_path(), get the length of DevicePath from the field
LengthOfDevicePath instead of calculating the length from the bytes
array.
This avoids a segmentation fault when processing the measured boot event
log in create_mb_refstate script.
This is called for the events "EV_EFI_BOOT_SERVICES_APPLICATION",
"EV_EFI_BOOT_SERVICES_DRIVER", and "EV_EFI_RUNTIME_SERVICES_DRIVER".
Fixes: #1153
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
---
keylime/tpm_bootlog_enrich.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/keylime/tpm_bootlog_enrich.py b/keylime/tpm_bootlog_enrich.py
index ef8e9f7..621bc67 100644
--- a/keylime/tpm_bootlog_enrich.py
+++ b/keylime/tpm_bootlog_enrich.py
@@ -46,14 +46,14 @@ yaml.add_representer(hexint, representer)
efivarlib_functions = CDLL(config.LIBEFIVAR)
-def getDevicePath(b):
- ret = efivarlib_functions.efidp_format_device_path(0, 0, b, len(b))
+def getDevicePath(b, l):
+ ret = efivarlib_functions.efidp_format_device_path(0, 0, b, l)
if ret < 0:
raise Exception(f"getDevicePath: efidp_format_device_path({b}) returned {ret}")
s = create_string_buffer(ret + 1)
- ret = efivarlib_functions.efidp_format_device_path(s, ret + 1, b, len(b))
+ ret = efivarlib_functions.efidp_format_device_path(s, ret + 1, b, l)
if ret < 0:
raise Exception(f"getDevicePath: efidp_format_device_path({b}) returned {ret}")
@@ -174,7 +174,7 @@ def getVar(event, b):
c = w.decode("utf-16", errors="ignore")
description += c
r["Description"] = description
- devicePath = getDevicePath(b[i:])
+ devicePath = getDevicePath(b[i:], len(b[i:]))
r["DevicePath"] = devicePath
return r
return None
@@ -184,10 +184,11 @@ def enrich_device_path(d: dict) -> None:
if isinstance(d.get("DevicePath"), str):
try:
b = bytes.fromhex(d["DevicePath"])
+ l = int(d["LengthOfDevicePath"])
except Exception:
return
try:
- p = getDevicePath(b)
+ p = getDevicePath(b, l)
# Deal with garbage devicePath
except Exception:
return
--
2.38.1

View File

@ -1,672 +0,0 @@
From 57c67e2b359e9544ecd5a0ba264adf7aa7c67991 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Mon, 14 Nov 2022 21:47:40 -0300
Subject: [PATCH 3/3] Backport upsteam PR#1156
From: https://github.com/keylime/keylime/pull/1156
We had partially addressed the issue we encountered when parsing some
certificates with python-cryptography by writing cert_utils module that
provided a single helper to parse the pubkey from a certificate.
However, we still were doing the EK validation in tpm_main using
python-cryptography, which means we would fall into the same parsing
problem again, since during the validation it would read all the certs
in the tpm cert store to check if it is signing the presented EK.
We address this issue by moving the EK cert verification to cert_utils:
we use the same approach as before, i.e. we parse the cert with pyasn1
when python-cryptography fails, and then use python-cryptography to do
the actual signature verification, as before.
By moving the method to cert_utils, it also becomes simpler to test it,
so in this commit we more tests to verify the methods work as expected.
Additionally, the updated EK verification is also capable of handling
ECDSA signatures
---
keylime.conf | 2 +
keylime/cert_utils.py | 144 ++++++++++++++++++++++++++++++++++--
keylime/registrar_common.py | 7 +-
keylime/tenant.py | 21 ++----
keylime/tpm/tpm_main.py | 47 +-----------
keylime/tpm_ek_ca.py | 10 +--
scripts/ek-openssl-verify | 98 ++++++++++++++++++++++++
test/run_tests.sh | 8 +-
test/test_cert_utils.py | 142 ++++++++++++++++++++++++++++++-----
9 files changed, 380 insertions(+), 99 deletions(-)
create mode 100755 scripts/ek-openssl-verify
diff --git a/keylime.conf b/keylime.conf
index 331e57a..d896f9f 100644
--- a/keylime.conf
+++ b/keylime.conf
@@ -501,6 +501,8 @@ require_ek_cert = True
# PROVKEYS - contains a json document containing EK, EKcert, and AIK from the
# provider. EK and AIK are in PEM format. The EKcert is in base64 encoded
# DER format.
+# TPM_CERT_STORE - contains the path to the TPM certificates store, e.g.:
+# "/var/lib/keylime/tpm_cert_store".
#
# Set to blank to disable this check. See warning above if require_ek_cert
# is "False".
diff --git a/keylime/cert_utils.py b/keylime/cert_utils.py
index d014aed..d2fc54d 100644
--- a/keylime/cert_utils.py
+++ b/keylime/cert_utils.py
@@ -1,13 +1,143 @@
-from cryptography.hazmat.primitives.serialization import load_der_public_key
+import io
+import os.path
+import subprocess
+import sys
+
+from cryptography import exceptions as crypto_exceptions
+from cryptography import x509
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives.asymmetric import ec, padding
+from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
from pyasn1.codec.der import decoder, encoder
-from pyasn1_modules import rfc2459
+from pyasn1_modules import pem, rfc2459
+from keylime import config, keylime_logging, tpm_ek_ca
# Issue #944 -- python-cryptography won't parse malformed certs,
# such as some Nuvoton ones we have encountered in the field.
# Unfortunately, we still have to deal with such certs anyway.
-# Let's read the EK cert with pyasn1 instead of python-cryptography.
-def read_x509_der_cert_pubkey(der_cert_data):
- """Returns the public key of a DER-encoded X.509 certificate"""
- der509 = decoder.decode(der_cert_data, asn1Spec=rfc2459.Certificate())[0]
- return load_der_public_key(encoder.encode(der509["tbsCertificate"]["subjectPublicKeyInfo"]))
+
+# Here we provide some helpers that use pyasn1 to parse the certificates
+# when parsing them with python-cryptography fails, and in this case, we
+# try to read the parsed certificate again into python-cryptograhy.
+
+logger = keylime_logging.init_logging("cert_utils")
+
+
+def x509_der_cert(der_cert_data: bytes):
+ """Load an x509 certificate provided in DER format
+ :param der_cert_data: the DER bytes of the certificate
+ :type der_cert_data: bytes
+ :returns: cryptography.x509.Certificate
+ """
+ try:
+ return x509.load_der_x509_certificate(data=der_cert_data, backend=default_backend())
+ except Exception as e:
+ logger.warning("Failed to parse DER data with python-cryptography: %s", e)
+ pyasn1_cert = decoder.decode(der_cert_data, asn1Spec=rfc2459.Certificate())[0]
+ return x509.load_der_x509_certificate(data=encoder.encode(pyasn1_cert), backend=default_backend())
+
+
+def x509_pem_cert(pem_cert_data: str):
+ """Load an x509 certificate provided in PEM format
+ :param pem_cert_data: the base-64 encoded PEM certificate
+ :type pem_cert_data: str
+ :returns: cryptography.x509.Certificate
+ """
+ try:
+ return x509.load_pem_x509_certificate(data=pem_cert_data.encode("utf-8"), backend=default_backend())
+ except Exception as e:
+ logger.warning("Failed to parse PEM data with python-cryptography: %s", e)
+ # Let's read the DER bytes from the base-64 PEM.
+ der_data = pem.readPemFromFile(io.StringIO(pem_cert_data))
+ # Now we can load it as we do in x509_der_cert().
+ pyasn1_cert = decoder.decode(der_data, asn1Spec=rfc2459.Certificate())[0]
+ return x509.load_der_x509_certificate(data=encoder.encode(pyasn1_cert), backend=default_backend())
+
+
+def verify_ek(ekcert, tpm_cert_store=config.get("tenant", "tpm_cert_store")):
+ """Verify that the provided EK certificate is signed by a trusted root
+ :param ekcert: The Endorsement Key certificate in DER format
+ :returns: True if the certificate can be verified, False otherwise
+ """
+ try:
+ trusted_certs = tpm_ek_ca.cert_loader(tpm_cert_store)
+ except Exception as e:
+ logger.warning("Error loading trusted certificates from the TPM cert store: %s", e)
+ return False
+
+ try:
+ ek509 = x509_der_cert(ekcert)
+ for cert_file, pem_cert in trusted_certs.items():
+ signcert = x509_pem_cert(pem_cert)
+ if ek509.issuer != signcert.subject:
+ continue
+
+ signcert_pubkey = signcert.public_key()
+ try:
+ if isinstance(signcert_pubkey, RSAPublicKey):
+ signcert_pubkey.verify(
+ ek509.signature,
+ ek509.tbs_certificate_bytes,
+ padding.PKCS1v15(),
+ ek509.signature_hash_algorithm,
+ )
+ elif isinstance(signcert_pubkey, EllipticCurvePublicKey):
+ signcert_pubkey.verify(
+ ek509.signature,
+ ek509.tbs_certificate_bytes,
+ ec.ECDSA(ek509.signature_hash_algorithm),
+ )
+ else:
+ logger.warning("Unsupported public key type: %s", type(signcert_pubkey))
+ continue
+ except crypto_exceptions.InvalidSignature:
+ continue
+
+ logger.debug("EK cert matched cert: %s", cert_file)
+ return True
+ except Exception as e:
+ # Log the exception so we don't lose the raw message
+ logger.exception(e)
+ raise Exception("Error processing ek/ekcert. Does this TPM have a valid EK?").with_traceback(sys.exc_info()[2])
+
+ logger.error("No Root CA matched EK Certificate")
+ return False
+
+
+def verify_ek_script(script, env, cwd):
+ if script is None:
+ logger.warning("External check script (%s) not specified", script)
+ return False
+
+ script_path = os.path.abspath(script)
+ if not os.path.isfile(script_path):
+ if cwd is None or not os.path.isfile(os.path.abspath(os.path.join(cwd, script))):
+ logger.warning("External check script (%s) not found; please make sure its path is correct", script)
+ return False
+ script_path = os.path.abspath(os.path.join(cwd, script))
+
+ try:
+ proc = subprocess.run(
+ [script_path],
+ env=env,
+ shell=False,
+ cwd=cwd,
+ stderr=subprocess.STDOUT,
+ stdout=subprocess.PIPE,
+ check=False,
+ )
+ if proc.returncode != 0:
+ errmsg = ""
+ if proc.stdout is not None:
+ errmsg = proc.stdout.decode("utf-8")
+ logger.error("External check script failed to validate EK: %s", errmsg)
+ return False
+ logger.debug("External check script successfully to validated EK")
+ if proc.stdout is not None:
+ logger.info("ek_check output: %s", proc.stdout.decode("utf-8"))
+ except subprocess.CalledProcessError as e:
+ logger.error("Error while trying to run external check script to validate EK: %s", e)
+ return False
+ return True
diff --git a/keylime/registrar_common.py b/keylime/registrar_common.py
index 2c32d19..fb37e5b 100644
--- a/keylime/registrar_common.py
+++ b/keylime/registrar_common.py
@@ -261,11 +261,8 @@ class UnprotectedHandler(BaseHTTPRequestHandler, SessionManager):
# Note, we don't validate the EKCert here, other than the implicit
# "is it a valid x509 cert" check. So it's still untrusted.
# This will be validated by the tenant.
- ek_tpm = base64.b64encode(
- tpm2_objects.ek_low_tpm2b_public_from_pubkey(
- cert_utils.read_x509_der_cert_pubkey(base64.b64decode(ekcert))
- )
- ).decode()
+ cert = cert_utils.x509_der_cert(base64.b64decode(ekcert))
+ ek_tpm = base64.b64encode(tpm2_objects.ek_low_tpm2b_public_from_pubkey(cert.public_key())).decode()
aik_attrs = tpm2_objects.get_tpm2b_public_object_attributes(
base64.b64decode(aik_tpm),
diff --git a/keylime/tenant.py b/keylime/tenant.py
index cc53623..dd9c09c 100644
--- a/keylime/tenant.py
+++ b/keylime/tenant.py
@@ -5,7 +5,6 @@ import io
import json
import logging
import os
-import subprocess
import sys
import tempfile
import time
@@ -15,7 +14,7 @@ import requests
from cryptography.hazmat.primitives import serialization as crypto_serialization
from keylime import api_version as keylime_api_version
-from keylime import ca_util, config, crypto, keylime_logging, registrar_client, signing, web_util
+from keylime import ca_util, cert_utils, config, crypto, keylime_logging, registrar_client, signing, web_util
from keylime.agentstates import AgentAttestState
from keylime.cli import options, policies
from keylime.cmd import user_data_encrypt
@@ -516,19 +515,11 @@ class Tenant:
env["EK_CERT"] = ""
env["PROVKEYS"] = json.dumps(self.registrar_data.get("provider_keys", {}))
- with subprocess.Popen(
- script, env=env, shell=True, cwd=config.WORK_DIR, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
- ) as proc:
- retval = proc.wait()
- if retval != 0:
- raise UserError("External check script failed to validate EK")
- logger.debug("External check script successfully to validated EK")
- while True:
- line = proc.stdout.readline().decode()
- if line == "":
- break
- logger.debug("ek_check output: %s", line.strip())
- return True
+
+ # Define the TPM cert store for the external script.
+ env["TPM_CERT_STORE"] = config.get("tenant", "tpm_cert_store")
+
+ return cert_utils.verify_ek_script(script, env, config.WORK_DIR)
def do_cv(self):
"""Initiate v, agent_id and ip and initiate the cloudinit sequence"""
diff --git a/keylime/tpm/tpm_main.py b/keylime/tpm/tpm_main.py
index 7bab4fd..35f0a2f 100644
--- a/keylime/tpm/tpm_main.py
+++ b/keylime/tpm/tpm_main.py
@@ -12,14 +12,10 @@ import time
import typing
import zlib
-from cryptography import exceptions as crypto_exceptions
-from cryptography import x509
-from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization as crypto_serialization
-from cryptography.hazmat.primitives.asymmetric import padding
from packaging.version import Version
-from keylime import cmd_exec, config, keylime_logging, secure_mount, tpm_ek_ca
+from keylime import cert_utils, cmd_exec, config, keylime_logging, secure_mount
from keylime.agentstates import TPMClockInfo
from keylime.common import algorithms, retry
from keylime.failure import Component, Failure
@@ -785,46 +781,7 @@ class tpm(tpm_abstract.AbstractTPM):
:param ekcert: The Endorsement Key certificate in DER format
:returns: True if the certificate can be verified, false otherwise
"""
- # openssl x509 -inform der -in certificate.cer -out certificate.pem
- try:
- tpm_ek_ca.check_tpm_cert_store()
-
- ek509 = x509.load_der_x509_certificate(
- data=ekcert,
- backend=default_backend(),
- )
-
- trusted_certs = tpm_ek_ca.cert_loader()
- for cert in trusted_certs:
- signcert = x509.load_pem_x509_certificate(
- data=cert.encode(),
- backend=default_backend(),
- )
-
- if ek509.issuer.rfc4514_string() != signcert.subject.rfc4514_string():
- continue
-
- try:
- signcert.public_key().verify(
- ek509.signature,
- ek509.tbs_certificate_bytes,
- padding.PKCS1v15(),
- ek509.signature_hash_algorithm,
- )
- except crypto_exceptions.InvalidSignature:
- continue
-
- logger.debug("EK cert matched cert: %s", cert)
- return True
- except Exception as e:
- # Log the exception so we don't lose the raw message
- logger.exception(e)
- raise Exception("Error processing ek/ekcert. Does this TPM have a valid EK?").with_traceback(
- sys.exc_info()[2]
- )
-
- logger.error("No Root CA matched EK Certificate")
- return False
+ return cert_utils.verify_ek(ekcert)
def get_tpm_manufacturer(self, output=None):
vendorStr = None
diff --git a/keylime/tpm_ek_ca.py b/keylime/tpm_ek_ca.py
index 3695f0b..fb66c07 100644
--- a/keylime/tpm_ek_ca.py
+++ b/keylime/tpm_ek_ca.py
@@ -7,8 +7,7 @@ logger = keylime_logging.init_logging("tpm_ek_ca")
trusted_certs = {}
-def check_tpm_cert_store():
- tpm_cert_store = config.get("tenant", "tpm_cert_store")
+def check_tpm_cert_store(tpm_cert_store=config.get("tenant", "tpm_cert_store")):
if not os.path.isdir(tpm_cert_store):
logger.error("The directory %s does not exist.", tpm_cert_store)
raise Exception(f"The directory {tpm_cert_store} does not exist.")
@@ -21,11 +20,10 @@ def check_tpm_cert_store():
raise Exception(f"The directory {tpm_cert_store} does not contain " f"any .pem files")
-def cert_loader():
- tpm_cert_store = config.get("tenant", "tpm_cert_store")
+def cert_loader(tpm_cert_store=config.get("tenant", "tpm_cert_store")):
file_list = glob.glob(os.path.join(tpm_cert_store, "*.pem"))
- my_trusted_certs = []
+ my_trusted_certs = {}
for file_path in file_list:
with open(file_path, encoding="utf-8") as f_input:
- my_trusted_certs.append(f_input.read())
+ my_trusted_certs[file_path] = f_input.read()
return my_trusted_certs
diff --git a/scripts/ek-openssl-verify b/scripts/ek-openssl-verify
new file mode 100755
index 0000000..f91e9b5
--- /dev/null
+++ b/scripts/ek-openssl-verify
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+# This script can be used as the `ek_check_script' (tenant configuration),
+# to attempt to verify a provided EK_CERT via env var using openssl.
+
+# EK - contains a PEM-encoded version of the public EK
+# EK_CERT - contains a base64 DER-encoded EK certificate if one is
+# available.
+# PROVKEYS - contains a json document containing EK, EKcert, and AIK
+# from the provider. EK and AIK are in PEM format. The
+# EKcert is in base64-encoded DER format
+# TPM_CERT_STORE - contains the path of the TPM certificate store.
+EK=${EK:-}
+EK_CERT=${EK_CERT:-}
+PROVKEYS=${PROVKEYS:-}
+
+EK_VERIFICATION_LOG=${EK_VERIFICATION_LOG:-/var/log/keylime/ek-verification.log}
+LOG="${EK_VERIFICATION_LOG}"
+
+# Setting log fallback in case we cannot write to the specified file.
+touch "${LOG}" 2>/dev/null || LOG=/dev/stderr
+
+log() {
+ _stderr=${2:-}
+ echo "[$(date)] ${1}" >&2 >> "${LOG}"
+ [ -n "${_stderr}" ] && [ "${LOG}" != '/dev/stderr' ] && echo "${1}" >&2
+}
+
+die() {
+ log "ERROR: ${1}" _
+ exit 1
+}
+
+command -v openssl >/dev/null \
+ || die "openssl CLI was not found in the PATH; please make sure it is installed"
+
+[ -n "${EK_CERT}" ] || die "EK_CERT was not provided as an env var"
+
+# Cert store directory. If one is not provided via TPM_CERT_STORE env var,
+# we start by attempting to read tenant.conf.
+CERT_STORE=${TPM_CERT_STORE:-}
+
+if [ -z "${CERT_STORE}" ]; then
+ KEYLIME_CONFIG_DIR=${KEYLIME_CONFIG_DIR:-/etc/keylime}
+ [ -d "${KEYLIME_CONFIG_DIR}" ] \
+ || die "KEYLIME_CONFIG_DIR (${KEYLIME_CONFIG_DIR}) does not seem to exist"
+
+ if [ -r "${KEYLIME_CONFIG_DIR}"/tenant.conf ]; then
+ CERT_STORE="$(grep -w ^tpm_cert_store "${KEYLIME_CONFIG_DIR}"/tenant.conf \
+ | tail -1 | cut -d'=' -f2 | tr -d "[:blank:]")"
+ fi
+
+ # Next we try to read any snippets in tenant.conf.d/
+ if [ -d "${KEYLIME_CONFIG_DIR}"/tenant.conf.d ]; then
+ for _s in "${KEYLIME_CONFIG_DIR}"/tenant.conf.d/*.conf; do
+ [ -e "${_s}" ] || continue
+ _store="$(grep -w ^tpm_cert_store "${_s}" \
+ | tail -1 | cut -d'=' -f2 | tr -d "[:blank:]")"
+ [ -n "${_store}" ] && CERT_STORE="${_store}"
+ done
+ fi
+fi
+
+[ -n "${CERT_STORE}" ] \
+ || die "It was not possible to determine the TPM cert store dir from tenant.conf or tenant.conf.d/ snippets"
+[ -d "${CERT_STORE}" ] \
+ || die "TPM cert store is not a valid directory (${CERT_STORE})"
+
+EK_VERIFICATION_TMPDIR=
+ek_verification_cleanup() {
+ [ -d "${EK_VERIFICATION_TMPDIR}" ] || return 0
+ rm -rf "${EK_VERIFICATION_TMPDIR}"
+}
+trap ek_verification_cleanup EXIT
+
+mkdir -p "${TMPDIR:-/tmp}"
+EK_VERIFICATION_TMPDIR="$(mktemp -d)" || \
+ die "Creating a temp dir for EK verification failed"
+
+EK_CERT_FILE_DER="${EK_VERIFICATION_TMPDIR}"/ek.der
+EK_CERT_FILE_PEM="${EK_VERIFICATION_TMPDIR}"/ek.pem
+
+printf '%s' "${EK_CERT}" > "${EK_CERT_FILE_DER}".b64
+base64 -d "${EK_CERT_FILE_DER}".b64 > "${EK_CERT_FILE_DER}"
+openssl x509 -inform der -in "${EK_CERT_FILE_DER}" > "${EK_CERT_FILE_PEM}"
+
+for c in "${CERT_STORE}"/*.pem; do
+ [ -e "${c}" ] || continue
+ log "Checking if ${c} is the issuer of EK cert..."
+ if openssl verify -partial_chain -CAfile "${c}" "${EK_CERT_FILE_PEM}" \
+ >>"${LOG}" 2>>"${LOG}"; then
+ log "${EK_CERT} successfully verified by $(basename "${c}")" _
+ exit 0
+ fi
+done
+
+die "EK signature did not match certificates from TPM cert store"
+# vim:set ts=2 sw=2 et:
diff --git a/test/run_tests.sh b/test/run_tests.sh
index fc43113..81a6dff 100755
--- a/test/run_tests.sh
+++ b/test/run_tests.sh
@@ -107,19 +107,19 @@ fi
# Set correct dependencies
# Fedora
if [ $PACKAGE_MGR = "dnf" ]; then
- PYTHON_PREIN="python3"
+ PYTHON_PREIN="python3 openssl"
PYTHON_DEPS="python3-pip python3-dbus"
# RHEL / CentOS etc
elif [ $PACKAGE_MGR = "yum" ]; then
- PYTHON_PREIN="epel-release python36"
+ PYTHON_PREIN="epel-release python36 openssl"
PYTHON_DEPS="python36-pip python36-dbus"
# Ubuntu / Debian
elif [ $PACKAGE_MGR = "apt-get" ]; then
- PYTHON_PREIN="python3"
+ PYTHON_PREIN="python3 openssl"
PYTHON_DEPS="python3-pip python3-dbus"
# SUSE
elif [ $PACKAGE_MGR = "zypper" ]; then
- PYTHON_PREIN="python3"
+ PYTHON_PREIN="python3 openssl"
PYTHON_DEPS="python3-pip python3-dbus"
else
echo "No recognized package manager found on this system!" 1>&2
diff --git a/test/test_cert_utils.py b/test/test_cert_utils.py
index 4666c0f..bdf6090 100644
--- a/test/test_cert_utils.py
+++ b/test/test_cert_utils.py
@@ -4,17 +4,19 @@ Copyright 2022 Red Hat, Inc.
"""
import base64
+import os
import unittest
-from keylime import cert_utils
+import cryptography
+from keylime import cert_utils, tpm_ek_ca
-class Cert_Utils_Test(unittest.TestCase):
- def test_read_x509_der_cert_pubkey(self):
- # The certificate listed in issue #944, from Nuvoton. It fails to
- # be parsed by python-cryptography with the following error:
- # ValueError: error parsing asn1 value: ParseError { kind: InvalidSetOrdering, location: ["RawCertificate::tbs_cert", "TbsCertificate::issuer", "0", "2"] }
- nuvoton_ecdsa_sha256_der = """\
+CERT_STORE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "tpm_cert_store"))
+
+# The certificate listed in issue #944, from Nuvoton. It fails to
+# be parsed by python-cryptography with the following error:
+# ValueError: error parsing asn1 value: ParseError { kind: InvalidSetOrdering, location: ["RawCertificate::tbs_cert", "TbsCertificate::issuer", "0", "2"] }
+nuvoton_ecdsa_sha256_der = """\
MIICBjCCAaygAwIBAgIIP5MvnZk8FrswCgYIKoZIzj0EAwIwVTFTMB8GA1UEAxMYTnV2b3RvbiBU
UE0gUm9vdCBDQSAyMTEwMCUGA1UEChMeTnV2b3RvbiBUZWNobm9sb2d5IENvcnBvcmF0aW9uMAkG
A1UEBhMCVFcwHhcNMTUxMDE5MDQzMjAwWhcNMzUxMDE1MDQzMjAwWjBVMVMwHwYDVQQDExhOdXZv
@@ -26,10 +28,10 @@ ajW+9zAfBgNVHSMEGDAWgBSfu3mqD1JieL7RUJKacXHpajW+9zAKBggqhkjOPQQDAgNIADBFAiEA
/jiywhOKpiMOUnTfDmXsXfDFokhKVNTXB6Xtqm7J8L4CICjT3/Y+rrSnf8zrBXqWeHDh8Wi41+w2
ppq6Ev9orZFI
"""
- # This cert from STMicroelectronics presents a different issue when
- # parsed by python-cryptography:
- # ValueError: error parsing asn1 value: ParseError { kind: ExtraData }
- st_sha256_with_rsa_der = """\
+# This cert from STMicroelectronics presents a different issue when
+# parsed by python-cryptography:
+# ValueError: error parsing asn1 value: ParseError { kind: ExtraData }
+st_sha256_with_rsa_der = """\
MIIEjTCCA3WgAwIBAgIUTL0P5h7nYu2yjVCyaPw1hv89XoIwDQYJKoZIhvcNAQELBQAwVTELMAkG
A1UEBhMCQ0gxHjAcBgNVBAoTFVNUTWljcm9lbGVjdHJvbmljcyBOVjEmMCQGA1UEAxMdU1RNIFRQ
TSBFSyBJbnRlcm1lZGlhdGUgQ0EgMDUwHhcNMTgwNzExMDAwMDAwWhcNMjgwNzExMDAwMDAwWjAA
@@ -60,10 +62,116 @@ rTJ1x4NA2ZtQMYyT29Yy1UlkjocAaXL5u0m3Hvz/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
/////w==
"""
- certs = [nuvoton_ecdsa_sha256_der, st_sha256_with_rsa_der]
- for c in certs:
+
+st_ecdsa_sha256_der = """\
+MIIDAzCCAqmgAwIBAgIUIymn2ai+UaVx1bM26/wU7I+sJd8wCgYIKoZIzj0EAwIwVjELMAkGA1UE
+BhMCQ0gxHjAcBgNVBAoTFVNUTWljcm9lbGVjdHJvbmljcyBOVjEnMCUGA1UEAxMeU1RNIFRQTSBF
+Q0MgSW50ZXJtZWRpYXRlIENBIDAxMB4XDTE4MDcyNjAwMDAwMFoXDTI4MDcyNjAwMDAwMFowADBZ
+MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBsTz5y2cedVZxG/GsbXQ9bL6EQylWNjx1b/SSp2EHlN
+aJjtn43iz2zb+qot2UOhQIwPxS5hMCXhasw4XsFXgnijggGpMIIBpTAfBgNVHSMEGDAWgBR+uDbO
++9+KY3H/czP5utcUYWyWyzBCBgNVHSAEOzA5MDcGBFUdIAAwLzAtBggrBgEFBQcCARYhaHR0cDov
+L3d3dy5zdC5jb20vVFBNL3JlcG9zaXRvcnkvMFkGA1UdEQEB/wRPME2kSzBJMRYwFAYFZ4EFAgEM
+C2lkOjUzNTQ0RDIwMRcwFQYFZ4EFAgIMDFNUMzNIVFBIQUhCNDEWMBQGBWeBBQIDDAtpZDowMDQ5
+MDAwNDBmBgNVHQkEXzBdMBYGBWeBBQIQMQ0wCwwDMi4wAgEAAgF0MEMGBWeBBQISMTowOAIBAAEB
+/6ADCgEBoQMKAQCiAwoBAKMQMA4WAzMuMQoBBAoBAgEB/6QPMA0WBTE0MC0yCgECAQEAMAwGA1Ud
+EwEB/wQCMAAwEAYDVR0lBAkwBwYFZ4EFCAEwDgYDVR0PAQH/BAQDAgMIMEsGCCsGAQUFBwEBBD8w
+PTA7BggrBgEFBQcwAoYvaHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNvbS9zdG10cG1lY2NpbnQw
+MS5jcnQwCgYIKoZIzj0EAwIDSAAwRQIgcNiZkn7poyk6J8Y1Cnwz4nV7YGPb5pBesBg6bk9n6KIC
+IQCE/jkHb/aPP/T3GtfLNHAdHL4JnofAbsDEuLQxAseeZA==
+"""
+
+
+def has_strict_x509_parsing():
+ """Indicates whether python-cryptography has strict x509 parsing."""
+
+ # Major release where python-cryptography started being strict
+ # when parsing x509 certificates.
+ PYCRYPTO_STRICT_X509_MAJOR = 35
+ return int(cryptography.__version__.split(".", maxsplit=1)[0]) >= PYCRYPTO_STRICT_X509_MAJOR
+
+
+def expectedFailureIf(condition):
+ """The test is marked as an expectedFailure if the condition is satisfied."""
+
+ def wrapper(func):
+ if condition:
+ return unittest.expectedFailure(func)
+ return func
+
+ return wrapper
+
+
+class Cert_Utils_Test(unittest.TestCase):
+ def test_tpm_cert_store(self):
+ tpm_ek_ca.check_tpm_cert_store(CERT_STORE_DIR)
+ my_trusted_certs = tpm_ek_ca.cert_loader(CERT_STORE_DIR)
+
+ self.assertNotEqual(len(my_trusted_certs), 0)
+
+ def test_cert_store_certs(self):
+ my_trusted_certs = tpm_ek_ca.cert_loader(CERT_STORE_DIR)
+ for fname, pem_cert in my_trusted_certs.items():
try:
- pubkey = cert_utils.read_x509_der_cert_pubkey(base64.b64decode(c))
- except Exception:
- self.fail("read_x509_der_cert_pubkey() is not expected to raise an exception here")
- self.assertIsNotNone(pubkey)
+ cert = cert_utils.x509_pem_cert(pem_cert)
+ except Exception as e:
+ self.fail(f"Failed to load certificate {fname}: {e}")
+ self.assertIsNotNone(cert)
+
+ def test_verify_ek(self):
+ tests = [
+ {"cert": st_sha256_with_rsa_der, "expected": True}, # RSA, signed by STM_RSA_05I.pem.
+ {"cert": st_ecdsa_sha256_der, "expected": True}, # ECC, signed by STM_ECC_01I.pem.
+ ]
+ for t in tests:
+ self.assertEqual(
+ cert_utils.verify_ek(base64.b64decode(t["cert"]), CERT_STORE_DIR),
+ t["expected"],
+ msg=f"Test failed for cert {t['cert']}; expected: {t['expected']}",
+ )
+
+ @expectedFailureIf(has_strict_x509_parsing())
+ def test_verify_ek_expected_failures(self):
+ # The following certificates are not compliant, and will fail the
+ # signature verification with python-cryptography, even though they
+ # should validate. Marking as expected failure for now.
+ tests = [
+ {"cert": nuvoton_ecdsa_sha256_der, "expected": True}, # ECC, signed by NUVO_2110.pem.
+ ]
+ for t in tests:
+ self.assertEqual(
+ cert_utils.verify_ek(base64.b64decode(t["cert"]), CERT_STORE_DIR),
+ t["expected"],
+ msg=f"Test failed for cert {t['cert']}; expected: {t['expected']}",
+ )
+
+ def test_verify_ek_script(self):
+ # We will be using `nuvoton_ecdsa_sha256_der', which is signed by
+ # NUVO_2110.pem but fails verification when using python-cryptography
+ # as it is a malformed cert -- it is the same one we use in
+ # test_verify_ek_expected_failures().
+ # With an external script `ek_script_check' that uses openssl, the
+ # validation works.
+ cert = nuvoton_ecdsa_sha256_der.replace("\n", "")
+
+ self.assertFalse(cert_utils.verify_ek_script(None, None, None))
+ self.assertFalse(cert_utils.verify_ek_script("/foo/bar", None, None))
+
+ script = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "scripts", "ek-openssl-verify"))
+ # Testing ek-openssl-verify script, but without specifying the
+ # EK_CERT env var.
+ self.assertFalse(cert_utils.verify_ek_script(script, None, None))
+
+ # Now let's specify the EK_CERT.
+ env = os.environ.copy()
+ env["EK_CERT"] = cert
+ env["TPM_CERT_STORE"] = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "tpm_cert_store"))
+ self.assertTrue(cert_utils.verify_ek_script(script, env, None))
+
+ # Now, let us specify the ek_check_script with a relative path.
+ script = "ek-openssl-verify"
+ cwd = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "scripts"))
+ self.assertTrue(cert_utils.verify_ek_script(script, env, cwd))
+
+ # And now we try a bad TPM cert store.
+ env["TPM_CERT_STORE"] = "/some/bad/directory"
+ self.assertFalse(cert_utils.verify_ek_script(script, env, cwd))
--
2.38.1

View File

@ -0,0 +1,136 @@
From eb5112dd597336b566378b3a157e76fe3cbbbfee Mon Sep 17 00:00:00 2001
From: Thore Sommer <mail@thson.de>
Date: Mon, 16 Jan 2023 07:26:08 -0300
Subject: [PATCH 3/3] logging: remove option to log into separate file
The implementation had the issue that only the main loggers were added and that
the permissions were not set strict enough. Users should use the logging
provided by systemd instead.
Signed-off-by: Thore Sommer <mail@thson.de>
---
keylime.conf | 10 ----------
keylime/keylime_logging.py | 31 ------------------------------
scripts/templates/2.0/registrar.j2 | 9 ---------
scripts/templates/2.0/verifier.j2 | 9 ---------
4 files changed, 59 deletions(-)
diff --git a/keylime.conf b/keylime.conf
index d896f9f..043b6a8 100644
--- a/keylime.conf
+++ b/keylime.conf
@@ -342,11 +342,6 @@ tomtou_errors = False
# signature check before storing them in the database.
require_allow_list_signatures = False
-# Destination for log output, in addition to console. Values can be 'file',
-# with the file being named after the "service" - cloud_verifier - created under
-# /var/log/keylime), 'stream' or it can be left empty (which results in
-# logging to console only, recommended when running inside a container)
-log_destination = file
#=============================================================================
[tenant]
@@ -595,11 +590,6 @@ auto_migrate_db = True
# The file to use for SQLite persistence of provider hypervisor data.
prov_db_filename = provider_reg_data.sqlite
-# Destination for log output, in addition to console. Values can be 'file',
-# with the file being named after the "service" - registrar - created under
-# /var/log/keylime), 'stream' or it can be left empty (which results in
-# logging to console only, recommended when running inside a container)
-log_destination = file
#=============================================================================
[ca]
diff --git a/keylime/keylime_logging.py b/keylime/keylime_logging.py
index bc8a11d..f7c7a8f 100644
--- a/keylime/keylime_logging.py
+++ b/keylime/keylime_logging.py
@@ -1,17 +1,10 @@
import logging
-import os
from logging import Logger
from logging import config as logging_config
from typing import Any, Callable, Dict
from keylime import config
-LOG_TO_FILE = set()
-LOG_TO_STREAM = set()
-LOGDIR = os.getenv("KEYLIME_LOGDIR", "/var/log/keylime")
-# not clear that this works right. console logging may not work
-LOGSTREAM = os.path.join(LOGDIR, "keylime-stream.log")
-
logging_config.fileConfig(config.get_config("logging"))
@@ -50,31 +43,7 @@ def log_http_response(logger: Logger, loglevel: int, response_body: Dict[str, An
def init_logging(loggername: str) -> Logger:
-
- if loggername in ("verifier", "registrar"):
- logdest = config.get(loggername, "log_destination", fallback="")
- if logdest == "file":
- LOG_TO_FILE.add(loggername)
- if logdest == "stream":
- LOG_TO_STREAM.add(loggername)
-
logger = logging.getLogger(f"keylime.{loggername}")
logging.getLogger("requests").setLevel(logging.WARNING)
- mainlogger = logging.getLogger("keylime")
- basic_formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
- if loggername in LOG_TO_FILE:
- logfilename = os.path.join(LOGDIR, f"{loggername}.log")
- if not os.path.exists(LOGDIR):
- os.makedirs(LOGDIR, 0o750)
- fh = logging.FileHandler(logfilename)
- fh.setLevel(logger.getEffectiveLevel())
- fh.setFormatter(basic_formatter)
- mainlogger.addHandler(fh)
-
- if loggername in LOG_TO_STREAM:
- fh = logging.FileHandler(filename=LOGSTREAM, mode="w")
- fh.setLevel(logger.getEffectiveLevel())
- fh.setFormatter(basic_formatter)
- mainlogger.addHandler(fh)
return logger
diff --git a/scripts/templates/2.0/registrar.j2 b/scripts/templates/2.0/registrar.j2
index 3d92303..8de7a50 100644
--- a/scripts/templates/2.0/registrar.j2
+++ b/scripts/templates/2.0/registrar.j2
@@ -71,12 +71,3 @@ auto_migrate_db = {{ registrar.auto_migrate_db }}
# The file to use for SQLite persistence of provider hypervisor data.
prov_db_filename: {{ registrar.prov_db_filename }}
-
-# Destination for log output, in addition to console. If left empty, the log
-# output will only be printed to console (recommended for containers to avoid
-# filling data storage). The accepted values are:
-# 'file': The log output will also be written to a file named after the
-# component in '/var/log/keylime/registrar.log'
-# 'stream': The log output will be written to a common file in
-# 'var/log/keylime/keylime-stream.log'
-log_destination = {{ registrar.log_destination }}
diff --git a/scripts/templates/2.0/verifier.j2 b/scripts/templates/2.0/verifier.j2
index d1584df..7a66cb1 100644
--- a/scripts/templates/2.0/verifier.j2
+++ b/scripts/templates/2.0/verifier.j2
@@ -196,12 +196,3 @@ zmq_port = {{ verifier.zmq_port }}
# Webhook url for revocation notifications.
webhook_url = {{ verifier.webhook_url }}
-
-# Destination for log output, in addition to console. If left empty, the log
-# output will only be printed to console (recommended for containers to avoid
-# filling data storage). The accepted values are:
-# 'file': The log output will also be written to a file named after the
-# component in '/var/log/keylime/verifier.log'
-# 'stream': The log output will be written to a common file in
-# 'var/log/keylime/keylime-stream.log'
-log_destination = {{ verifier.log_destination }}
--
2.38.1

View File

@ -1,24 +0,0 @@
/usr/bin/keylime_agent -- gen_context(system_u:object_r:keylime_agent_exec_t,s0)
/usr/bin/keylime_ima_emulator -- gen_context(system_u:object_r:keylime_agent_exec_t,s0)
/usr/bin/keylime_userdata_encrypt -- gen_context(system_u:object_r:keylime_agent_exec_t,s0)
/usr/bin/keylime_ca -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/bin/keylime_migrations_apply -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/bin/keylime_registrar -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/bin/keylime_verifier -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/bin/keylime_tenant -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/local/bin/keylime_agent -- gen_context(system_u:object_r:keylime_agent_exec_t,s0)
/usr/local/bin/keylime_ima_emulator -- gen_context(system_u:object_r:keylime_agent_exec_t,s0)
/usr/local/bin/keylime_userdata_encrypt -- gen_context(system_u:object_r:keylime_agent_exec_t,s0)
/usr/local/bin/keylime_ca -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/local/bin/keylime_migrations_apply -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/local/bin/keylime_registrar -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/local/bin/keylime_verifier -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/usr/local/bin/keylime_tenant -- gen_context(system_u:object_r:keylime_server_exec_t,s0)
/var/lib/keylime(/.*)? gen_context(system_u:object_r:keylime_var_lib_t,s0)
/var/lib/keylime-agent(/.*)? gen_context(system_u:object_r:keylime_var_lib_t,s0)
/var/log/keylime(/.*)? gen_context(system_u:object_r:keylime_log_t,s0)

View File

@ -1,37 +0,0 @@
## <summary>policy for keylime</summary>
########################################
## <summary>
## Add to specified type to keylime_type attribute .
## </summary>
## <param name="type">
## <summary>
## Type to be used for keylime domains.
## </summary>
## </param>
#
interface(`keylime_use_keylime_domain',`
gen_require(`
attribute keylime_domain;
')
typeattribute $1 keylime_domain;
')
########################################
## <summary>
## Mounton keylime lib directory.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`keylime_mounton_var_lib',`
gen_require(`
type keylime_var_lib_t;
')
allow $1 keylime_var_lib_t:dir mounton;
')

View File

@ -1,140 +0,0 @@
policy_module(keylime, 1.0.0)
########################################
#
# Declarations
#
attribute keylime_domain;
type keylime_agent_t;
keylime_use_keylime_domain(keylime_agent_t)
type keylime_agent_exec_t;
init_daemon_domain(keylime_agent_t, keylime_agent_exec_t)
type keylime_server_t;
keylime_use_keylime_domain(keylime_server_t)
type keylime_server_exec_t;
init_daemon_domain(keylime_server_t, keylime_server_exec_t)
type keylime_log_t;
logging_log_file(keylime_log_t)
type keylime_var_lib_t;
files_type(keylime_var_lib_t)
type keylime_tmp_t;
files_tmp_file(keylime_tmp_t)
########################################
#
# keylime domain policy
#
allow keylime_domain self:tcp_socket create_stream_socket_perms;
manage_dirs_pattern(keylime_domain, keylime_tmp_t, keylime_tmp_t)
manage_files_pattern(keylime_domain, keylime_tmp_t, keylime_tmp_t)
files_tmp_filetrans(keylime_domain, keylime_tmp_t, { dir file })
manage_dirs_pattern(keylime_domain, keylime_var_lib_t, keylime_var_lib_t)
manage_files_pattern(keylime_domain, keylime_var_lib_t, keylime_var_lib_t)
files_var_lib_filetrans(keylime_domain, keylime_var_lib_t, { dir file lnk_file })
corecmd_exec_bin(keylime_domain)
corenet_tcp_bind_generic_node(keylime_domain)
corenet_tcp_bind_all_ports(keylime_domain)
corenet_tcp_connect_all_unreserved_ports(keylime_domain)
dev_read_sysfs(keylime_domain)
fs_tmpfs_filetrans(keylime_domain, keylime_var_lib_t, { dir file })
init_named_socket_activation(keylime_domain, keylime_var_lib_t, "keylime")
miscfiles_read_generic_certs(keylime_domain)
sysnet_read_config(keylime_domain)
userdom_exec_user_tmp_files(keylime_domain)
userdom_manage_user_tmp_dirs(keylime_domain)
userdom_manage_user_tmp_files(keylime_domain)
########################################
#
# keylime server policy
#
allow keylime_server_t self:netlink_route_socket { create_stream_socket_perms nlmsg_read };
allow keylime_server_t self:udp_socket create_stream_socket_perms;
manage_dirs_pattern(keylime_server_t, keylime_log_t, keylime_log_t)
manage_files_pattern(keylime_server_t, keylime_log_t, keylime_log_t)
fs_rw_inherited_tmpfs_files(keylime_server_t)
optional_policy(`
gpg_exec(keylime_server_t)
')
optional_policy(`
kerberos_read_config(keylime_server_t)
kerberos_read_keytab(keylime_server_t)
')
optional_policy(`
sssd_run_stream_connect(keylime_server_t)
')
########################################
#
# keylime agent policy
#
#work with /var/lib/keylime/secure
allow keylime_agent_t self:capability { chown dac_override dac_read_search setgid setuid sys_nice sys_ptrace };
allow keylime_agent_t self:chr_file getattr;
#FIX ME, add to tabrmd policy interface related with this
allow keylime_agent_t domain:unix_stream_socket rw_stream_socket_perms; #selint-disable:W-001
dev_rw_tpm(keylime_agent_t)
exec_files_pattern(keylime_agent_t, keylime_var_lib_t, keylime_var_lib_t)
files_read_var_lib_files(keylime_agent_t)
fs_dontaudit_search_cgroup_dirs(keylime_agent_t)
fs_getattr_cgroup(keylime_agent_t)
fs_mount_tmpfs(keylime_agent_t)
fs_setattr_tmpfs_dirs(keylime_agent_t)
init_dontaudit_stream_connect(keylime_agent_t)
kernel_read_all_proc(keylime_agent_t)
userdom_dontaudit_search_user_home_dirs(keylime_agent_t)
auth_read_passwd(keylime_agent_t)
keylime_mounton_var_lib(keylime_agent_t)
mount_domtrans(keylime_agent_t)
selinux_read_policy(keylime_agent_t)
optional_policy(`
#FIX ME, add to tabrmd policy interface related with this
#https://github.com/tpm2-software/tpm2-abrmd/blob/master/selinux
dbus_chat_system_bus(keylime_agent_t)
')
optional_policy(`
dbus_stream_connect_system_dbusd(keylime_agent_t)
dbus_system_bus_client(keylime_agent_t)
')
optional_policy(`
systemd_userdbd_stream_connect(keylime_agent_t)
systemd_machined_stream_connect(keylime_agent_t)
')

View File

@ -1,4 +1,5 @@
%global srcname keylime
%global policy_version 1.0.0
%global with_selinux 1
%global selinuxtype targeted
@ -7,21 +8,18 @@
%global debug_package %{nil}
Name: keylime
Version: 6.5.1
Release: 1%{?dist}.4
Version: 6.5.2
Release: 4%{?dist}
Summary: Open source TPM software for Bootstrapping and Maintaining Trust
URL: https://github.com/keylime/keylime
Source0: https://github.com/keylime/keylime/archive/refs/tags/v%{version}.tar.gz
Source1: %{srcname}.sysusers
Source2: %{srcname}.te
Source3: %{srcname}.if
Source4: %{srcname}.fc
Source2: https://github.com/RedHat-SP-Security/%{name}-selinux/archive/v%{policy_version}/keylime-selinux-%{policy_version}.tar.gz
Patch: 0001-ima-Fix-log-evaluation-on-quick-succession-execution.patch
Patch: 0002-tpm_bootlog_enrich-Get-DevicePath-length-from-Length.patch
Patch: 0003-Backport-upsteam-PR-1156.patch
Patch: 0004-Do-not-use-default-values-that-need-reading-the-conf.patch
Patch: 0001-Do-not-use-default-values-that-need-reading-the-conf.patch
Patch: 0002-Switch-to-sha256-hashes-for-signatures.patch
Patch: 0003-logging-remove-option-to-log-into-separate-file.patch
License: ASL 2.0 and MIT
@ -145,15 +143,12 @@ Requires: python3-%{srcname} = %{version}-%{release}
The Keylime Tenant can be used to provision a Keylime Agent.
%prep
%autosetup -S git -n %{srcname}-%{version}
%autosetup -S git -n %{srcname}-%{version} -a2
%if 0%{?with_selinux}
# SELinux policy (originally from selinux-policy-contrib)
# this policy module will override the production module
mkdir selinux
cp -p %{SOURCE2} selinux/
cp -p %{SOURCE3} selinux/
cp -p %{SOURCE4} selinux/
make -f %{_datadir}/selinux/devel/Makefile %{srcname}.pp
bzip2 -9 %{srcname}.pp
@ -197,7 +192,7 @@ done
%if 0%{?with_selinux}
install -D -m 0644 %{srcname}.pp.bz2 %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype}/%{srcname}.pp.bz2
install -D -p -m 0644 selinux/%{srcname}.if %{buildroot}%{_datadir}/selinux/devel/include/distributed/%{srcname}.if
install -D -p -m 0644 keylime-selinux-%{policy_version}/%{srcname}.if %{buildroot}%{_datadir}/selinux/devel/include/distributed/%{srcname}.if
%endif
@ -325,6 +320,7 @@ fi
%{python3_sitelib}/%{srcname}
%{_datadir}/%{srcname}/scripts/create_mb_refstate
%{_datadir}/%{srcname}/scripts/create_policy
%{_bindir}/keylime_convert_ima_policy
%files base
%license LICENSE
@ -346,25 +342,24 @@ fi
%license LICENSE
%changelog
* Tue Nov 15 2022 Sergio Correia <scorreia@redhat.com> - 6.5.1-1.4
- Do not use default values that need reading the config in methods
Resolves: rhbz#2142033 - Registrar may crash during EK validation when require_ek_cert is enabled [rhel-9.1.0.z]
* Fri Jan 13 2023 Sergio Correia <scorreia@redhat.com> - 6.5.2-4
- Backport upstream PR#1240 - logging: remove option to log into separate file
Resolves: rhbz#2154584 - keylime verifier is not logging to /var/log/keylime
* Mon Nov 14 2022 Sergio Correia <scorreia@redhat.com> - 6.5.1-1.3
- Backport upstream PR#1156
Resolves: rhbz#2142033 - Registrar may crash during EK validation when require_ek_cert is enabled [rhel-9.1.0.z]
* Thu Dec 1 2022 Sergio Correia <scorreia@redhat.com> - 6.5.2-3
- Remove leftover policy file
Related: rhbz#2152135
* Mon Nov 14 2022 Sergio Correia <scorreia@redhat.com> - 6.5.1-1.2
- Segmentation fault in create_mb_refstate script
Resolves: rhbz#2142034 - Segmentation fault in /usr/share/keylime/create_mb_refstate script [rhel-9.1.0.z]
* Thu Dec 1 2022 Patrik Koncity <pkoncity@redhat.com> - 6.5.2-2
- Use keylime selinux policy from upstream.
Resolves: rhbz#2152135
* Mon Nov 14 2022 Sergio Correia <scorreia@redhat.com> - 6.5.1-1.1
- ima: Fix log evaluation on quick-succession execution of scripts
Resolves: rhbz#2142032 - agent fails IMA attestation when one scripts is executed quickly after the other [rhel-9.1.0.z]
* Thu Oct 13 2022 Sergio Correia <scorreia@redhat.com> - 6.5.1-1
- Update to 6.5.1
* Mon Nov 14 2022 Sergio Correia <scorreia@redhat.com> - 6.5.2-1
- Update to 6.5.2
Resolves: CVE-2022-3500
Resolves: rhbz#2138167 - agent fails IMA attestation when one scripts is executed quickly after the other
Resolves: rhbz#2140670 - Segmentation fault in /usr/share/keylime/create_mb_refstate script
Resolves: rhbz#142009 - Registrar may crash during EK validation when require_ek_cert is enabled
* Tue Sep 13 2022 Sergio Correia <scorreia@redhat.com> - 6.5.0-1
- Update to 6.5.0