forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PCI/CMA: Authenticate devices on enumeration
This currently very much a PoC. Currently the SPDM library only provides a single function to allow a challenge / authentication of the PCI EP. SPDM exchanges must occur in one of a small set of valid squences over which the message digest used in authentication is built up. Placing that complexity in the SPDM library seems like a good way to enforce that logic, without having to do it for each transport. Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Lukas Wunner <lukas@wunner.de>
- Loading branch information
Showing
5 changed files
with
114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Component Measurement and Authentication (CMA/SPDM, PCIe r6.0 sec 6.31) | ||
* | ||
* Copyright (C) 2021 Huawei | ||
* Jonathan Cameron <Jonathan.Cameron@huawei.com> | ||
* | ||
* Copyright (C) 2022 Intel Corporation | ||
*/ | ||
|
||
#define dev_fmt(fmt) "CMA: " fmt | ||
|
||
#include <linux/module.h> | ||
#include <linux/pci.h> | ||
#include <linux/pci-doe.h> | ||
#include <linux/pm_runtime.h> | ||
#include <linux/spdm.h> | ||
|
||
#include "pci.h" | ||
|
||
#define PCI_DOE_PROTOCOL_CMA 1 | ||
|
||
/* Keyring that userspace can poke certs into */ | ||
static struct key *cma_keyring; | ||
|
||
static int spdm_doe_transport(void *priv, struct device *dev, | ||
void *request, size_t request_sz, | ||
void *response, size_t response_sz) | ||
{ | ||
struct pci_doe_mb *doe = priv; | ||
int rc; | ||
|
||
/* | ||
* CMA/SPDM operation in non-D0 states is optional (PCIe r6.0 | ||
* sec 6.31.3). The spec does not define a way to determine | ||
* if it's supported, so resume to D0. | ||
*/ | ||
rc = pm_runtime_resume_and_get(dev); | ||
if (rc) | ||
return rc; | ||
|
||
rc = pci_doe(doe, PCI_VENDOR_ID_PCI_SIG, PCI_DOE_PROTOCOL_CMA, | ||
request, request_sz, response, response_sz); | ||
|
||
pm_runtime_put(dev); | ||
|
||
return rc; | ||
} | ||
|
||
void pci_cma_init(struct pci_dev *pdev) | ||
{ | ||
struct spdm_state *spdm_state; | ||
struct pci_doe_mb *doe; | ||
int rc; | ||
|
||
if (!pci_is_pcie(pdev)) | ||
return; | ||
|
||
/* CMA/SPDM does not apply to Root Ports (PCIe r6.0 sec 6.31.3) */ | ||
if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) | ||
return; | ||
|
||
doe = pci_find_doe_mailbox(pdev, PCI_VENDOR_ID_PCI_SIG, | ||
PCI_DOE_PROTOCOL_CMA); | ||
if (!doe) | ||
return; | ||
|
||
spdm_state = spdm_create(spdm_doe_transport, doe, &pdev->dev, | ||
cma_keyring); | ||
if (!spdm_state) | ||
return; | ||
|
||
rc = spdm_authenticate(spdm_state); | ||
if (rc) | ||
pci_info(pdev, "No CMA support\n"); | ||
else | ||
pci_info(pdev, "Attestation passed\n"); | ||
|
||
kfree(spdm_state); | ||
} | ||
|
||
__init static int cma_keyring_init(void) | ||
{ | ||
cma_keyring = keyring_alloc("_cma", | ||
KUIDT_INIT(0), KGIDT_INIT(0), | ||
current_cred(), | ||
(KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH, | ||
KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_SET_KEEP, NULL, NULL); | ||
if (IS_ERR(cma_keyring)) | ||
pr_err("Could not allocate cma keyring\n"); | ||
|
||
return 0; | ||
} | ||
device_initcall(cma_keyring_init); | ||
|
||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters