File Index
Files and directories
Sign in
FILE

efi_secret.c

File preview with syntax highlighting.

linux-6.19.14/drivers/virt/coco/efi_secret/efi_secret.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * efi_secret module
  4 *
  5 * Copyright (C) 2022 IBM Corporation
  6 * Author: Dov Murik <dovmurik@linux.ibm.com>
  7 */
  8
  9/**
 10 * DOC: efi_secret: Allow reading EFI confidential computing (coco) secret area
 11 * via securityfs interface.
 12 *
 13 * When the module is loaded (and securityfs is mounted, typically under
 14 * /sys/kernel/security), a "secrets/coco" directory is created in securityfs.
 15 * In it, a file is created for each secret entry.  The name of each such file
 16 * is the GUID of the secret entry, and its content is the secret data.
 17 */
 18
 19#include <linux/platform_device.h>
 20#include <linux/seq_file.h>
 21#include <linux/fs.h>
 22#include <linux/kernel.h>
 23#include <linux/init.h>
 24#include <linux/module.h>
 25#include <linux/io.h>
 26#include <linux/security.h>
 27#include <linux/efi.h>
 28#include <linux/cacheflush.h>
 29
 30#define EFI_SECRET_NUM_FILES 64
 31
 32struct efi_secret {
 33	struct dentry *secrets_dir;
 34	void __iomem *secret_data;
 35	u64 secret_data_len;
 36};
 37
 38/*
 39 * Structure of the EFI secret area
 40 *
 41 * Offset   Length
 42 * (bytes)  (bytes)  Usage
 43 * -------  -------  -----
 44 *       0       16  Secret table header GUID (must be 1e74f542-71dd-4d66-963e-ef4287ff173b)
 45 *      16        4  Length of bytes of the entire secret area
 46 *
 47 *      20       16  First secret entry's GUID
 48 *      36        4  First secret entry's length in bytes (= 16 + 4 + x)
 49 *      40        x  First secret entry's data
 50 *
 51 *    40+x       16  Second secret entry's GUID
 52 *    56+x        4  Second secret entry's length in bytes (= 16 + 4 + y)
 53 *    60+x        y  Second secret entry's data
 54 *
 55 * (... and so on for additional entries)
 56 *
 57 * The GUID of each secret entry designates the usage of the secret data.
 58 */
 59
 60/**
 61 * struct secret_header - Header of entire secret area; this should be followed
 62 * by instances of struct secret_entry.
 63 * @guid:	Must be EFI_SECRET_TABLE_HEADER_GUID
 64 * @len:	Length in bytes of entire secret area, including header
 65 */
 66struct secret_header {
 67	efi_guid_t guid;
 68	u32 len;
 69} __attribute((packed));
 70
 71/**
 72 * struct secret_entry - Holds one secret entry
 73 * @guid:	Secret-specific GUID (or NULL_GUID if this secret entry was deleted)
 74 * @len:	Length of secret entry, including its guid and len fields
 75 * @data:	The secret data (full of zeros if this secret entry was deleted)
 76 */
 77struct secret_entry {
 78	efi_guid_t guid;
 79	u32 len;
 80	u8 data[];
 81} __attribute((packed));
 82
 83static size_t secret_entry_data_len(struct secret_entry *e)
 84{
 85	return e->len - sizeof(*e);
 86}
 87
 88static struct efi_secret the_efi_secret;
 89
 90static inline struct efi_secret *efi_secret_get(void)
 91{
 92	return &the_efi_secret;
 93}
 94
 95static int efi_secret_bin_file_show(struct seq_file *file, void *data)
 96{
 97	struct secret_entry *e = file->private;
 98
 99	if (e)
100		seq_write(file, e->data, secret_entry_data_len(e));
101
102	return 0;
103}
104DEFINE_SHOW_ATTRIBUTE(efi_secret_bin_file);
105
106/*
107 * Overwrite memory content with zeroes, and ensure that dirty cache lines are
108 * actually written back to memory, to clear out the secret.
109 */
110static void wipe_memory(void *addr, size_t size)
111{
112	memzero_explicit(addr, size);
113#ifdef CONFIG_X86
114	clflush_cache_range(addr, size);
115#endif
116}
117
118static int efi_secret_unlink(struct inode *dir, struct dentry *dentry)
119{
120	struct inode *inode = d_inode(dentry);
121	struct secret_entry *e = (struct secret_entry *)inode->i_private;
122
123	if (e) {
124		/* Zero out the secret data */
125		wipe_memory(e->data, secret_entry_data_len(e));
126		e->guid = NULL_GUID;
127	}
128
129	inode->i_private = NULL;
130
131	return simple_unlink(inode, dentry);
132}
133
134static const struct inode_operations efi_secret_dir_inode_operations = {
135	.lookup         = simple_lookup,
136	.unlink         = efi_secret_unlink,
137};
138
139static int efi_secret_map_area(struct platform_device *dev)
140{
141	int ret;
142	struct efi_secret *s = efi_secret_get();
143	struct linux_efi_coco_secret_area *secret_area;
144
145	if (efi.coco_secret == EFI_INVALID_TABLE_ADDR) {
146		dev_err(&dev->dev, "Secret area address is not available\n");
147		return -EINVAL;
148	}
149
150	secret_area = memremap(efi.coco_secret, sizeof(*secret_area), MEMREMAP_WB);
151	if (secret_area == NULL) {
152		dev_err(&dev->dev, "Could not map secret area EFI config entry\n");
153		return -ENOMEM;
154	}
155	if (!secret_area->base_pa || secret_area->size < sizeof(struct secret_header)) {
156		dev_err(&dev->dev,
157			"Invalid secret area memory location (base_pa=0x%llx size=0x%llx)\n",
158			secret_area->base_pa, secret_area->size);
159		ret = -EINVAL;
160		goto unmap;
161	}
162
163	s->secret_data = ioremap_encrypted(secret_area->base_pa, secret_area->size);
164	if (s->secret_data == NULL) {
165		dev_err(&dev->dev, "Could not map secret area\n");
166		ret = -ENOMEM;
167		goto unmap;
168	}
169
170	s->secret_data_len = secret_area->size;
171	ret = 0;
172
173unmap:
174	memunmap(secret_area);
175	return ret;
176}
177
178static void efi_secret_securityfs_teardown(struct platform_device *dev)
179{
180	struct efi_secret *s = efi_secret_get();
181
182	securityfs_remove(s->secrets_dir);
183	s->secrets_dir = NULL;
184
185	dev_dbg(&dev->dev, "Removed securityfs entries\n");
186}
187
188static int efi_secret_securityfs_setup(struct platform_device *dev)
189{
190	struct efi_secret *s = efi_secret_get();
191	int ret = 0, i = 0, bytes_left;
192	unsigned char *ptr;
193	struct secret_header *h;
194	struct secret_entry *e;
195	struct dentry *dent, *dir;
196	char guid_str[EFI_VARIABLE_GUID_LEN + 1];
197
198	ptr = (void __force *)s->secret_data;
199	h = (struct secret_header *)ptr;
200	if (efi_guidcmp(h->guid, EFI_SECRET_TABLE_HEADER_GUID)) {
201		/*
202		 * This is not an error: it just means that EFI defines secret
203		 * area but it was not populated by the Guest Owner.
204		 */
205		dev_dbg(&dev->dev, "EFI secret area does not start with correct GUID\n");
206		return -ENODEV;
207	}
208	if (h->len < sizeof(*h)) {
209		dev_err(&dev->dev, "EFI secret area reported length is too small\n");
210		return -EINVAL;
211	}
212	if (h->len > s->secret_data_len) {
213		dev_err(&dev->dev, "EFI secret area reported length is too big\n");
214		return -EINVAL;
215	}
216
217	s->secrets_dir = NULL;
218
219	dent = securityfs_create_dir("secrets", NULL);
220	if (IS_ERR(dent)) {
221		dev_err(&dev->dev, "Error creating secrets securityfs directory entry err=%ld\n",
222			PTR_ERR(dent));
223		return PTR_ERR(dent);
224	}
225	s->secrets_dir = dent;
226
227	dir = securityfs_create_dir("coco", s->secrets_dir);
228	if (IS_ERR(dir)) {
229		dev_err(&dev->dev, "Error creating coco securityfs directory entry err=%ld\n",
230			PTR_ERR(dir));
231		return PTR_ERR(dir);
232	}
233	d_inode(dir)->i_op = &efi_secret_dir_inode_operations;
234
235	bytes_left = h->len - sizeof(*h);
236	ptr += sizeof(*h);
237	while (bytes_left >= (int)sizeof(*e) && i < EFI_SECRET_NUM_FILES) {
238		e = (struct secret_entry *)ptr;
239		if (e->len < sizeof(*e) || e->len > (unsigned int)bytes_left) {
240			dev_err(&dev->dev, "EFI secret area is corrupted\n");
241			ret = -EINVAL;
242			goto err_cleanup;
243		}
244
245		/* Skip deleted entries (which will have NULL_GUID) */
246		if (efi_guidcmp(e->guid, NULL_GUID)) {
247			efi_guid_to_str(&e->guid, guid_str);
248
249			dent = securityfs_create_file(guid_str, 0440, dir, (void *)e,
250						      &efi_secret_bin_file_fops);
251			if (IS_ERR(dent)) {
252				dev_err(&dev->dev, "Error creating efi_secret securityfs entry\n");
253				ret = PTR_ERR(dent);
254				goto err_cleanup;
255			}
256			i++;
257		}
258		ptr += e->len;
259		bytes_left -= e->len;
260	}
261
262	dev_info(&dev->dev, "Created %d entries in securityfs secrets/coco\n", i);
263	return 0;
264
265err_cleanup:
266	efi_secret_securityfs_teardown(dev);
267	return ret;
268}
269
270static void efi_secret_unmap_area(void)
271{
272	struct efi_secret *s = efi_secret_get();
273
274	if (s->secret_data) {
275		iounmap(s->secret_data);
276		s->secret_data = NULL;
277		s->secret_data_len = 0;
278	}
279}
280
281static int efi_secret_probe(struct platform_device *dev)
282{
283	int ret;
284
285	ret = efi_secret_map_area(dev);
286	if (ret)
287		return ret;
288
289	ret = efi_secret_securityfs_setup(dev);
290	if (ret)
291		goto err_unmap;
292
293	return ret;
294
295err_unmap:
296	efi_secret_unmap_area();
297	return ret;
298}
299
300static void efi_secret_remove(struct platform_device *dev)
301{
302	efi_secret_securityfs_teardown(dev);
303	efi_secret_unmap_area();
304}
305
306static struct platform_driver efi_secret_driver = {
307	.probe = efi_secret_probe,
308	.remove = efi_secret_remove,
309	.driver = {
310		.name = "efi_secret",
311	},
312};
313
314module_platform_driver(efi_secret_driver);
315
316MODULE_DESCRIPTION("Confidential computing EFI secret area access");
317MODULE_AUTHOR("IBM");
318MODULE_LICENSE("GPL");
319MODULE_ALIAS("platform:efi_secret");
~/ Read-only file preview.