// SPDX-License-Identifier: GPL-2.0 /* * efi_secret module * * Copyright (C) 2022 IBM Corporation * Author: Dov Murik <[email protected]> */ /** * DOC: efi_secret: Allow reading EFI confidential computing (coco) secret area * via securityfs interface. * * When the module is loaded (and securityfs is mounted, typically under * /sys/kernel/security), a "secrets/coco" directory is created in securityfs. * In it, a file is created for each secret entry. The name of each such file * is the GUID of the secret entry, and its content is the secret data. */ #include <linux/platform_device.h> #include <linux/seq_file.h> #include <linux/fs.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/io.h> #include <linux/security.h> #include <linux/efi.h> #include <linux/cacheflush.h> #define EFI_SECRET_NUM_FILES … struct efi_secret { … }; /* * Structure of the EFI secret area * * Offset Length * (bytes) (bytes) Usage * ------- ------- ----- * 0 16 Secret table header GUID (must be 1e74f542-71dd-4d66-963e-ef4287ff173b) * 16 4 Length of bytes of the entire secret area * * 20 16 First secret entry's GUID * 36 4 First secret entry's length in bytes (= 16 + 4 + x) * 40 x First secret entry's data * * 40+x 16 Second secret entry's GUID * 56+x 4 Second secret entry's length in bytes (= 16 + 4 + y) * 60+x y Second secret entry's data * * (... and so on for additional entries) * * The GUID of each secret entry designates the usage of the secret data. */ /** * struct secret_header - Header of entire secret area; this should be followed * by instances of struct secret_entry. * @guid: Must be EFI_SECRET_TABLE_HEADER_GUID * @len: Length in bytes of entire secret area, including header */ struct secret_header { … } __attribute((packed)); /** * struct secret_entry - Holds one secret entry * @guid: Secret-specific GUID (or NULL_GUID if this secret entry was deleted) * @len: Length of secret entry, including its guid and len fields * @data: The secret data (full of zeros if this secret entry was deleted) */ struct secret_entry { … } __attribute((packed)); static size_t secret_entry_data_len(struct secret_entry *e) { … } static struct efi_secret the_efi_secret; static inline struct efi_secret *efi_secret_get(void) { … } static int efi_secret_bin_file_show(struct seq_file *file, void *data) { … } DEFINE_SHOW_ATTRIBUTE(…); /* * Overwrite memory content with zeroes, and ensure that dirty cache lines are * actually written back to memory, to clear out the secret. */ static void wipe_memory(void *addr, size_t size) { … } static int efi_secret_unlink(struct inode *dir, struct dentry *dentry) { … } static const struct inode_operations efi_secret_dir_inode_operations = …; static int efi_secret_map_area(struct platform_device *dev) { … } static void efi_secret_securityfs_teardown(struct platform_device *dev) { … } static int efi_secret_securityfs_setup(struct platform_device *dev) { … } static void efi_secret_unmap_area(void) { … } static int efi_secret_probe(struct platform_device *dev) { … } static void efi_secret_remove(struct platform_device *dev) { … } static struct platform_driver efi_secret_driver = …; module_platform_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …; MODULE_ALIAS(…) …;