Skip to content

Commit ccba26c

Browse files
committed
spdm: Allow control of next requester nonce through sysfs
Remote attestation services may mistrust the kernel to always use a fresh nonce for SPDM authentication. So allow user space to set the next requester nonce by writing to a sysfs attribute. Signed-off-by: Lukas Wunner <[email protected]> Cc: James Bottomley <[email protected]> Cc: Jérôme Glisse <[email protected]> Cc: Jason Gunthorpe <[email protected]>
1 parent f5e7161 commit ccba26c

File tree

5 files changed

+76
-1
lines changed

5 files changed

+76
-1
lines changed

Documentation/ABI/testing/sysfs-devices-spdm

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,32 @@ Description:
215215
necessary to parse the SPDM messages in the transcript to find
216216
and extract the nonces, which is cumbersome. That's why they
217217
are exposed as separate files.
218+
219+
220+
What: /sys/devices/.../signatures/next_requester_nonce
221+
Date: June 2024
222+
Contact: Lukas Wunner <[email protected]>
223+
Description:
224+
If you do not trust the kernel to always use a fresh nonce,
225+
write 32 bytes to this file to set the requester nonce used
226+
in the next SPDM authentication sequence.
227+
228+
Meant for remote attestation services. You are responsible
229+
for providing a nonce with sufficient entropy. The kernel
230+
only uses the nonce once, so provide a new one every time
231+
you reauthenticate the device. If you do not provide a
232+
nonce, the kernel generates a random one.
233+
234+
After the nonce has been consumed, it becomes readable as
235+
the newest [0-9]*_requester_nonce, which proves its usage::
236+
237+
# dd if=/dev/random bs=32 count=1 | \
238+
tee signatures/next_requester_nonce | hexdump
239+
0000000 e0 77 91 54 bd 56 99 c2 ea 4f 0b 1a 7f ba 6e 59
240+
0000010 8f ee f6 b2 26 82 58 34 9e e5 8c 8a 31 58 29 7e
241+
242+
# echo re > authenticated
243+
244+
# hexdump $(\ls -t signatures/[0-9]*_requester_nonce | head -1)
245+
0000000 e0 77 91 54 bd 56 99 c2 ea 4f 0b 1a 7f ba 6e 59
246+
0000010 8f ee f6 b2 26 82 58 34 9e e5 8c 8a 31 58 29 7e

lib/spdm/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ void spdm_destroy(struct spdm_state *spdm_state)
433433
spdm_reset(spdm_state);
434434
spdm_destroy_log(spdm_state);
435435
mutex_destroy(&spdm_state->lock);
436+
kfree(spdm_state->next_nonce);
436437
kfree(spdm_state);
437438
}
438439
EXPORT_SYMBOL_GPL(spdm_destroy);

lib/spdm/req-authenticate.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,13 @@ static int spdm_challenge(struct spdm_state *spdm_state, u8 slot, bool verify)
626626
};
627627
int rc, length;
628628

629-
get_random_bytes(&req.nonce, sizeof(req.nonce));
629+
if (spdm_state->next_nonce) {
630+
memcpy(&req.nonce, spdm_state->next_nonce, sizeof(req.nonce));
631+
kfree(spdm_state->next_nonce);
632+
spdm_state->next_nonce = NULL;
633+
} else {
634+
get_random_bytes(&req.nonce, sizeof(req.nonce));
635+
}
630636

631637
if (spdm_state->version <= 0x12)
632638
req_sz = offsetofend(typeof(req), nonce);

lib/spdm/req-sysfs.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,48 @@ const struct attribute_group spdm_certificates_group = {
177177

178178
/* signatures attributes */
179179

180+
static umode_t spdm_signatures_are_visible(struct kobject *kobj,
181+
const struct bin_attribute *a, int n)
182+
{
183+
struct device *dev = kobj_to_dev(kobj);
184+
struct spdm_state *spdm_state = dev_to_spdm_state(dev);
185+
186+
if (IS_ERR_OR_NULL(spdm_state))
187+
return SYSFS_GROUP_INVISIBLE;
188+
189+
return a->attr.mode;
190+
}
191+
192+
static ssize_t next_requester_nonce_write(struct file *file,
193+
struct kobject *kobj,
194+
struct bin_attribute *attr,
195+
char *buf, loff_t off, size_t count)
196+
{
197+
struct device *dev = kobj_to_dev(kobj);
198+
struct spdm_state *spdm_state = dev_to_spdm_state(dev);
199+
200+
guard(mutex)(&spdm_state->lock);
201+
202+
if (!spdm_state->next_nonce) {
203+
spdm_state->next_nonce = kmalloc(SPDM_NONCE_SZ, GFP_KERNEL);
204+
if (!spdm_state->next_nonce)
205+
return -ENOMEM;
206+
}
207+
208+
memcpy(spdm_state->next_nonce + off, buf, count);
209+
return count;
210+
}
211+
static BIN_ATTR_WO(next_requester_nonce, SPDM_NONCE_SZ);
212+
180213
static struct bin_attribute *spdm_signatures_bin_attrs[] = {
214+
&bin_attr_next_requester_nonce,
181215
NULL
182216
};
183217

184218
const struct attribute_group spdm_signatures_group = {
185219
.name = "signatures",
186220
.bin_attrs = spdm_signatures_bin_attrs,
221+
.is_bin_visible = spdm_signatures_are_visible,
187222
};
188223

189224
static unsigned int spdm_max_log_sz = SZ_16M; /* per device */

lib/spdm/spdm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,9 @@ struct spdm_error_rsp {
475475
* itself and the transcript with trailing signature.
476476
* @log_counter: Number of generated log entries so far. Will be prefixed to
477477
* the sysfs files of the next generated log entry.
478+
* @next_nonce: Requester nonce to be used for the next authentication
479+
* sequence. Populated from user space through sysfs.
480+
* If user space does not provide a nonce, the kernel uses a random one.
478481
*/
479482
struct spdm_state {
480483
struct device *dev;
@@ -521,6 +524,7 @@ struct spdm_state {
521524
struct list_head log;
522525
size_t log_sz;
523526
u32 log_counter;
527+
u8 *next_nonce;
524528
};
525529

526530
extern struct list_head spdm_state_list;

0 commit comments

Comments
 (0)