Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: ccp - Add GET_ID SEV command

The GET_ID command, added as of SEV API v0.16, allows the SEV firmware
to be queried about a unique CPU ID. This unique ID can then be used
to obtain the public certificate containing the Chip Endorsement Key
(CEK) public key signed by the AMD SEV Signing Key (ASK).

For more information please refer to "Section 5.12 GET_ID" of
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Signed-off-by: Janakarajan Natarajan <Janakarajan.Natarajan@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Janakarajan Natarajan and committed by
Herbert Xu
0b3a830b edd303ff

+67
+44
drivers/crypto/ccp/psp-dev.c
··· 119 119 case SEV_CMD_RECEIVE_UPDATE_VMSA: return sizeof(struct sev_data_receive_update_vmsa); 120 120 case SEV_CMD_LAUNCH_UPDATE_SECRET: return sizeof(struct sev_data_launch_secret); 121 121 case SEV_CMD_DOWNLOAD_FIRMWARE: return sizeof(struct sev_data_download_firmware); 122 + case SEV_CMD_GET_ID: return sizeof(struct sev_data_get_id); 122 123 default: return 0; 123 124 } 124 125 ··· 511 510 return ret; 512 511 } 513 512 513 + static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp) 514 + { 515 + struct sev_data_get_id *data; 516 + u64 data_size, user_size; 517 + void *id_blob, *mem; 518 + int ret; 519 + 520 + /* SEV GET_ID available from SEV API v0.16 and up */ 521 + if (!SEV_VERSION_GREATER_OR_EQUAL(0, 16)) 522 + return -ENOTSUPP; 523 + 524 + /* SEV FW expects the buffer it fills with the ID to be 525 + * 8-byte aligned. Memory allocated should be enough to 526 + * hold data structure + alignment padding + memory 527 + * where SEV FW writes the ID. 528 + */ 529 + data_size = ALIGN(sizeof(struct sev_data_get_id), 8); 530 + user_size = sizeof(struct sev_user_data_get_id); 531 + 532 + mem = kzalloc(data_size + user_size, GFP_KERNEL); 533 + if (!mem) 534 + return -ENOMEM; 535 + 536 + data = mem; 537 + id_blob = mem + data_size; 538 + 539 + data->address = __psp_pa(id_blob); 540 + data->len = user_size; 541 + 542 + ret = __sev_do_cmd_locked(SEV_CMD_GET_ID, data, &argp->error); 543 + if (!ret) { 544 + if (copy_to_user((void __user *)argp->data, id_blob, data->len)) 545 + ret = -EFAULT; 546 + } 547 + 548 + kfree(mem); 549 + 550 + return ret; 551 + } 552 + 514 553 static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp) 515 554 { 516 555 struct sev_user_data_pdh_cert_export input; ··· 687 646 break; 688 647 case SEV_PDH_CERT_EXPORT: 689 648 ret = sev_ioctl_do_pdh_export(&input); 649 + break; 650 + case SEV_GET_ID: 651 + ret = sev_ioctl_do_get_id(&input); 690 652 break; 691 653 default: 692 654 ret = -EINVAL;
+11
include/linux/psp-sev.h
··· 55 55 SEV_CMD_PDH_GEN = 0x009, 56 56 SEV_CMD_DF_FLUSH = 0x00A, 57 57 SEV_CMD_DOWNLOAD_FIRMWARE = 0x00B, 58 + SEV_CMD_GET_ID = 0x00C, 58 59 59 60 /* Guest commands */ 60 61 SEV_CMD_DECOMMISSION = 0x020, ··· 142 141 u32 len; /* In */ 143 142 } __packed; 144 143 144 + /** 145 + * struct sev_data_get_id - GET_ID command parameters 146 + * 147 + * @address: physical address of region to place unique CPU ID(s) 148 + * @len: len of the region 149 + */ 150 + struct sev_data_get_id { 151 + u64 address; /* In */ 152 + u32 len; /* In/Out */ 153 + } __packed; 145 154 /** 146 155 * struct sev_data_pdh_cert_export - PDH_CERT_EXPORT command parameters 147 156 *
+12
include/uapi/linux/psp-sev.h
··· 30 30 SEV_PDH_GEN, 31 31 SEV_PDH_CERT_EXPORT, 32 32 SEV_PEK_CERT_IMPORT, 33 + SEV_GET_ID, 33 34 34 35 SEV_MAX, 35 36 }; ··· 122 121 __u32 pdh_cert_len; /* In/Out */ 123 122 __u64 cert_chain_address; /* In */ 124 123 __u32 cert_chain_len; /* In/Out */ 124 + } __packed; 125 + 126 + /** 127 + * struct sev_user_data_get_id - GET_ID command parameters 128 + * 129 + * @socket1: Buffer to pass unique ID of first socket 130 + * @socket2: Buffer to pass unique ID of second socket 131 + */ 132 + struct sev_user_data_get_id { 133 + __u8 socket1[64]; /* Out */ 134 + __u8 socket2[64]; /* Out */ 125 135 } __packed; 126 136 127 137 /**