From: Roberto Sassu roberto.sassu@huawei.com
Goals =====
Support new key and signature formats with the same kernel component.
Verify the authenticity of system data with newly supported data formats.
Mitigate the risk of parsing arbitrary data in the kernel.
Motivation ==========
Adding new functionality to the kernel comes with an increased risk of introducing new bugs which, once exploited, can lead to a partial or full system compromise.
Parsing arbitrary data is particularly critical, since it allows an attacker to send a malicious sequence of bytes to exploit vulnerabilities in the parser code. The attacker might be able to overwrite kernel memory to bypass kernel protections, and obtain more privileges.
User Mode Drivers (UMDs) can effectively mitigate this risk. If the parser runs in user space, even if it has a bug, it won't allow the attacker to overwrite kernel memory.
The communication protocol between the UMD and the kernel should be simple enough, that the kernel can immediately recognize malformed data sent by an attacker controlling the UMD, and discard it.
Solution ========
Register a new parser of the asymmetric key type which, instead of parsing the key blob, forwards it to a UMD, and populates the key fields from the UMD response. That response contains the data for each field of the public key structure, defined in the kernel, and possibly a key description.
Supporting new data formats can be achieved by simply extending the UMD. As long as the UMD recognizes them, and provides the crypto material to the kernel Crypto API in the expected format, the kernel does not need to be aware of the UMD changes.
Add a new API to verify the authenticity of system data, similar to the one for PKCS#7 signatures. As for the key parser, send the signature to a UMD, and fill the public_key_signature structure from the UMD response.
The API still supports a very basic trust model, it accepts a key for signature verification if it is in the supplied keyring. The API can be extended later to support more sophisticated models.
Use cases =========
eBPF ----
The eBPF infrastructure already offers to eBPF programs the ability to verify PKCS#7 signatures, through the bpf_verify_pkcs7_signature() kfunc.
Add the new bpf_verify_umd_signature() kfunc, to allow eBPF programs verify signatures in a data format that is not PKCS#7 (for example PGP).
IMA Appraisal -------------
An alternative to appraising each file with its signature (Fedora 38) is to build a repository of reference file digests from signed RPM headers, and lookup the calculated digest of files being accessed in that repository (DIGLIM[1]).
With this patch set, the kernel can verify the authenticity of RPM headers from their PGP signature against the Linux distribution GPG keys. Once verified, RPM headers can be parsed with a UMD to build the repository of reference file digests.
With DIGLIM, Linux distributions are not required to change anything in their building infrastructure (no extra data in the RPM header, no new PKI for IMA signatures).
[1]: https://lore.kernel.org/linux-integrity/20210914163401.864635-1-roberto.sass...
UMD development ===============
The header file crypto/asymmetric_keys/umd_key_sig_umh.h contains the details of the communication protocol between the kernel and the UMD handler.
The UMD handler should implement the commands defined, CMD_KEY and CMD_SIG, should set the result of the processing, and fill the key and signature-specific structures umd_key_msg_out and umd_sig_msg_out.
The UMD handler should provide the key and signature blobs in a format that is understood by the kernel. For example, for RSA keys, it should provide them in ASN.1 format (SEQUENCE of INTEGER).
The auth IDs of the keys and signatures should match, for signature verification. Auth ID matching can be partial.
Patch set dependencies ======================
This patch set depends on 'usermode_driver: Add management library and API':
https://lore.kernel.org/bpf/20230317145240.363908-1-roberto.sassu@huaweiclou...
Patch set content =================
Patch 1 introduces the new parser for the asymmetric key type.
Patch 2 introduces the parser for signatures and its API.
Patch 3 introduces the system-level API for signature verification.
Patch 4 extends eBPF to use the new system-level API.
Patch 5 adds a test for UMD-parser signatures (not executed until the UMD supports PGP).
Patch 6 introduces the skeleton of the UMD handler.
PGP ===
A work in progress implementation of the PGP format (RFC 4880 and RFC 6637) in the UMD handler is available at:
https://github.com/robertosassu/linux/commits/pgp-signatures-umd-v1-devel-v2...
It is based on a previous work of David Howells, available at:
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-modsign.git/l...
The patches have been adapted for use in user space.
Roberto Sassu (6): KEYS: asymmetric: Introduce UMD-based asymmetric key parser KEYS: asymmetric: Introduce UMD-based asymmetric key signature parser verification: Introduce verify_umd_signature() and verify_umd_message_sig() bpf: Introduce bpf_verify_umd_signature() kfunc selftests/bpf: Prepare a test for UMD-parsed signatures KEYS: asymmetric: Add UMD handler
.gitignore | 3 + MAINTAINERS | 1 + certs/system_keyring.c | 125 ++++++ crypto/asymmetric_keys/Kconfig | 32 ++ crypto/asymmetric_keys/Makefile | 23 + crypto/asymmetric_keys/asymmetric_type.c | 3 +- crypto/asymmetric_keys/umd_key.h | 28 ++ crypto/asymmetric_keys/umd_key_parser.c | 203 +++++++++ crypto/asymmetric_keys/umd_key_sig_loader.c | 32 ++ crypto/asymmetric_keys/umd_key_sig_umh.h | 71 +++ crypto/asymmetric_keys/umd_key_sig_umh_blob.S | 7 + crypto/asymmetric_keys/umd_key_sig_umh_user.c | 84 ++++ crypto/asymmetric_keys/umd_sig_parser.c | 416 ++++++++++++++++++ include/crypto/umd_sig.h | 71 +++ include/keys/asymmetric-type.h | 1 + include/linux/verification.h | 48 ++ kernel/trace/bpf_trace.c | 69 ++- ...ify_pkcs7_sig.c => verify_pkcs7_umd_sig.c} | 109 +++-- ...kcs7_sig.c => test_verify_pkcs7_umd_sig.c} | 18 +- .../testing/selftests/bpf/verify_sig_setup.sh | 82 +++- 20 files changed, 1378 insertions(+), 48 deletions(-) create mode 100644 crypto/asymmetric_keys/umd_key.h create mode 100644 crypto/asymmetric_keys/umd_key_parser.c create mode 100644 crypto/asymmetric_keys/umd_key_sig_loader.c create mode 100644 crypto/asymmetric_keys/umd_key_sig_umh.h create mode 100644 crypto/asymmetric_keys/umd_key_sig_umh_blob.S create mode 100644 crypto/asymmetric_keys/umd_key_sig_umh_user.c create mode 100644 crypto/asymmetric_keys/umd_sig_parser.c create mode 100644 include/crypto/umd_sig.h rename tools/testing/selftests/bpf/prog_tests/{verify_pkcs7_sig.c => verify_pkcs7_umd_sig.c} (75%) rename tools/testing/selftests/bpf/progs/{test_verify_pkcs7_sig.c => test_verify_pkcs7_umd_sig.c} (82%)