Lines Matching +full:asp +full:- +full:v2

1 // SPDX-License-Identifier: GPL-2.0-only
22 #include <linux/psp-sev.h>
26 #include <uapi/linux/sev-guest.h>
27 #include <uapi/linux/psp-sev.h>
32 #include "sev-guest.h"
34 #define DEVICE_NAME "sev-guest"
57 * Avoid information leakage by double-buffering shared messages
84 if (snp_dev->vmpck) in is_vmpck_empty()
85 return !memcmp(snp_dev->vmpck, zero_key, VMPCK_KEY_LEN); in is_vmpck_empty()
91 * If an error is received from the host or AMD Secure Processor (ASP) there
95 * This is because in the current encryption scheme GHCB v2 uses AES-GCM to
99 * The ASP FW v1.51 only increments the sequence numbers on a successful
100 * guest<->ASP back and forth and only accepts messages at its exact sequence
104 * vulnerable. If the sequence number were incremented for a fresh IV the ASP
109 dev_alert(snp_dev->dev, "Disabling vmpck_id %d to prevent IV reuse.\n", in snp_disable_vmpck()
111 memzero_explicit(snp_dev->vmpck, VMPCK_KEY_LEN); in snp_disable_vmpck()
112 snp_dev->vmpck = NULL; in snp_disable_vmpck()
122 count = *snp_dev->os_area_msg_seqno; in __snp_get_msg_seqno()
127 /* Return a non-zero on success */
133 * The message sequence counter for the SNP guest request is a 64-bit in snp_get_msg_seqno()
134 * value but the version 2 of GHCB specification defines a 32-bit storage in snp_get_msg_seqno()
135 * for it. If the counter exceeds the 32-bit value then return zero. in snp_get_msg_seqno()
141 dev_err(snp_dev->dev, "request message sequence counter overflow\n"); in snp_get_msg_seqno()
154 *snp_dev->os_area_msg_seqno += 2; in snp_inc_msg_seqno()
159 struct miscdevice *dev = file->private_data; in to_snp_dev()
172 crypto->tfm = crypto_alloc_aead("gcm(aes)", 0, 0); in init_crypto()
173 if (IS_ERR(crypto->tfm)) in init_crypto()
176 if (crypto_aead_setkey(crypto->tfm, key, keylen)) in init_crypto()
179 crypto->iv_len = crypto_aead_ivsize(crypto->tfm); in init_crypto()
180 crypto->iv = kmalloc(crypto->iv_len, GFP_KERNEL_ACCOUNT); in init_crypto()
181 if (!crypto->iv) in init_crypto()
184 if (crypto_aead_authsize(crypto->tfm) > MAX_AUTHTAG_LEN) { in init_crypto()
185 if (crypto_aead_setauthsize(crypto->tfm, MAX_AUTHTAG_LEN)) { in init_crypto()
186 dev_err(snp_dev->dev, "failed to set authsize to %d\n", MAX_AUTHTAG_LEN); in init_crypto()
191 crypto->a_len = crypto_aead_authsize(crypto->tfm); in init_crypto()
192 crypto->authtag = kmalloc(crypto->a_len, GFP_KERNEL_ACCOUNT); in init_crypto()
193 if (!crypto->authtag) in init_crypto()
199 kfree(crypto->iv); in init_crypto()
201 crypto_free_aead(crypto->tfm); in init_crypto()
210 crypto_free_aead(crypto->tfm); in deinit_crypto()
211 kfree(crypto->iv); in deinit_crypto()
212 kfree(crypto->authtag); in deinit_crypto()
219 struct snp_guest_msg_hdr *hdr = &msg->hdr; in enc_dec_message()
225 req = aead_request_alloc(crypto->tfm, GFP_KERNEL); in enc_dec_message()
227 return -ENOMEM; in enc_dec_message()
231 * +------ AAD -------+------- DATA -----+---- AUTHTAG----+ in enc_dec_message()
232 * | msg header | plaintext | hdr->authtag | in enc_dec_message()
233 * | bytes 30h - 5Fh | or | | in enc_dec_message()
235 * +------------------+------------------+----------------+ in enc_dec_message()
238 sg_set_buf(&src[0], &hdr->algo, AAD_LEN); in enc_dec_message()
239 sg_set_buf(&src[1], src_buf, hdr->msg_sz); in enc_dec_message()
240 sg_set_buf(&src[2], hdr->authtag, crypto->a_len); in enc_dec_message()
243 sg_set_buf(&dst[0], &hdr->algo, AAD_LEN); in enc_dec_message()
244 sg_set_buf(&dst[1], dst_buf, hdr->msg_sz); in enc_dec_message()
245 sg_set_buf(&dst[2], hdr->authtag, crypto->a_len); in enc_dec_message()
248 aead_request_set_tfm(req, crypto->tfm); in enc_dec_message()
251 aead_request_set_crypt(req, src, dst, len, crypto->iv); in enc_dec_message()
261 struct snp_guest_crypto *crypto = snp_dev->crypto; in __enc_payload()
262 struct snp_guest_msg_hdr *hdr = &msg->hdr; in __enc_payload()
264 memset(crypto->iv, 0, crypto->iv_len); in __enc_payload()
265 memcpy(crypto->iv, &hdr->msg_seqno, sizeof(hdr->msg_seqno)); in __enc_payload()
267 return enc_dec_message(crypto, msg, plaintext, msg->payload, len, true); in __enc_payload()
273 struct snp_guest_crypto *crypto = snp_dev->crypto; in dec_payload()
274 struct snp_guest_msg_hdr *hdr = &msg->hdr; in dec_payload()
277 memset(crypto->iv, 0, crypto->iv_len); in dec_payload()
278 memcpy(crypto->iv, &hdr->msg_seqno, sizeof(hdr->msg_seqno)); in dec_payload()
280 return enc_dec_message(crypto, msg, msg->payload, plaintext, len, false); in dec_payload()
285 struct snp_guest_crypto *crypto = snp_dev->crypto; in verify_and_dec_payload()
286 struct snp_guest_msg *resp = &snp_dev->secret_response; in verify_and_dec_payload()
287 struct snp_guest_msg *req = &snp_dev->secret_request; in verify_and_dec_payload()
288 struct snp_guest_msg_hdr *req_hdr = &req->hdr; in verify_and_dec_payload()
289 struct snp_guest_msg_hdr *resp_hdr = &resp->hdr; in verify_and_dec_payload()
291 dev_dbg(snp_dev->dev, "response [seqno %lld type %d version %d sz %d]\n", in verify_and_dec_payload()
292 resp_hdr->msg_seqno, resp_hdr->msg_type, resp_hdr->msg_version, resp_hdr->msg_sz); in verify_and_dec_payload()
295 memcpy(resp, snp_dev->response, sizeof(*resp)); in verify_and_dec_payload()
298 if (unlikely(resp_hdr->msg_seqno != (req_hdr->msg_seqno + 1))) in verify_and_dec_payload()
299 return -EBADMSG; in verify_and_dec_payload()
302 if (resp_hdr->msg_type != (req_hdr->msg_type + 1) || in verify_and_dec_payload()
303 resp_hdr->msg_version != req_hdr->msg_version) in verify_and_dec_payload()
304 return -EBADMSG; in verify_and_dec_payload()
310 if (unlikely((resp_hdr->msg_sz + crypto->a_len) > sz)) in verify_and_dec_payload()
311 return -EBADMSG; in verify_and_dec_payload()
314 return dec_payload(snp_dev, resp, payload, resp_hdr->msg_sz + crypto->a_len); in verify_and_dec_payload()
320 struct snp_guest_msg *req = &snp_dev->secret_request; in enc_payload()
321 struct snp_guest_msg_hdr *hdr = &req->hdr; in enc_payload()
325 hdr->algo = SNP_AEAD_AES_256_GCM; in enc_payload()
326 hdr->hdr_version = MSG_HDR_VER; in enc_payload()
327 hdr->hdr_sz = sizeof(*hdr); in enc_payload()
328 hdr->msg_type = type; in enc_payload()
329 hdr->msg_version = version; in enc_payload()
330 hdr->msg_seqno = seqno; in enc_payload()
331 hdr->msg_vmpck = vmpck_id; in enc_payload()
332 hdr->msg_sz = sz; in enc_payload()
334 /* Verify the sequence number is non-zero */ in enc_payload()
335 if (!hdr->msg_seqno) in enc_payload()
336 return -ENOSR; in enc_payload()
338 dev_dbg(snp_dev->dev, "request [seqno %lld type %d version %d sz %d]\n", in enc_payload()
339 hdr->msg_seqno, hdr->msg_type, hdr->msg_version, hdr->msg_sz); in enc_payload()
359 rc = snp_issue_guest_request(exit_code, &snp_dev->input, rio); in __handle_guest_request()
361 case -ENOSPC: in __handle_guest_request()
369 override_npages = snp_dev->input.data_npages; in __handle_guest_request()
394 case -EAGAIN: in __handle_guest_request()
395 if (jiffies - req_start > SNP_REQ_MAX_RETRY_DURATION) { in __handle_guest_request()
396 rc = -ETIMEDOUT; in __handle_guest_request()
412 rio->exitinfo2 = override_err; in __handle_guest_request()
417 * prevent IV reuse. If the standard request was successful, return -EIO in __handle_guest_request()
421 rc = -EIO; in __handle_guest_request()
425 snp_dev->input.data_npages = override_npages; in __handle_guest_request()
438 /* Get message sequence and verify that its a non-zero */ in handle_guest_request()
441 return -EIO; in handle_guest_request()
444 memset(snp_dev->response, 0, sizeof(struct snp_guest_msg)); in handle_guest_request()
446 /* Encrypt the userspace provided payload in snp_dev->secret_request. */ in handle_guest_request()
447 rc = enc_payload(snp_dev, seqno, rio->msg_version, type, req_buf, req_sz); in handle_guest_request()
455 memcpy(snp_dev->request, &snp_dev->secret_request, in handle_guest_request()
456 sizeof(snp_dev->secret_request)); in handle_guest_request()
460 if (rc == -EIO && in handle_guest_request()
461 rio->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN)) in handle_guest_request()
464 dev_alert(snp_dev->dev, in handle_guest_request()
465 "Detected error from ASP request. rc: %d, exitinfo2: 0x%llx\n", in handle_guest_request()
466 rc, rio->exitinfo2); in handle_guest_request()
474 dev_alert(snp_dev->dev, "Detected unexpected decode failure from ASP. rc: %d\n", rc); in handle_guest_request()
489 struct snp_guest_crypto *crypto = snp_dev->crypto; in get_report()
490 struct snp_report_req *req = &snp_dev->req.report; in get_report()
496 if (!arg->req_data || !arg->resp_data) in get_report()
497 return -EINVAL; in get_report()
499 if (copy_from_user(req, (void __user *)arg->req_data, sizeof(*req))) in get_report()
500 return -EFAULT; in get_report()
507 resp_len = sizeof(resp->data) + crypto->a_len; in get_report()
510 return -ENOMEM; in get_report()
513 SNP_MSG_REPORT_REQ, req, sizeof(*req), resp->data, in get_report()
518 if (copy_to_user((void __user *)arg->resp_data, resp, sizeof(*resp))) in get_report()
519 rc = -EFAULT; in get_report()
528 struct snp_derived_key_req *req = &snp_dev->req.derived_key; in get_derived_key()
529 struct snp_guest_crypto *crypto = snp_dev->crypto; in get_derived_key()
537 if (!arg->req_data || !arg->resp_data) in get_derived_key()
538 return -EINVAL; in get_derived_key()
545 resp_len = sizeof(resp.data) + crypto->a_len; in get_derived_key()
547 return -ENOMEM; in get_derived_key()
549 if (copy_from_user(req, (void __user *)arg->req_data, sizeof(*req))) in get_derived_key()
550 return -EFAULT; in get_derived_key()
558 if (copy_to_user((void __user *)arg->resp_data, &resp, sizeof(resp))) in get_derived_key()
559 rc = -EFAULT; in get_derived_key()
571 struct snp_ext_report_req *req = &snp_dev->req.ext_report; in get_ext_report()
572 struct snp_guest_crypto *crypto = snp_dev->crypto; in get_ext_report()
579 if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data)) in get_ext_report()
580 return -EINVAL; in get_ext_report()
582 if (copy_from_sockptr(req, io->req_data, sizeof(*req))) in get_ext_report()
583 return -EFAULT; in get_ext_report()
586 if (!req->certs_len || !req->certs_address) in get_ext_report()
589 if (req->certs_len > SEV_FW_BLOB_MAX_SIZE || in get_ext_report()
590 !IS_ALIGNED(req->certs_len, PAGE_SIZE)) in get_ext_report()
591 return -EINVAL; in get_ext_report()
593 if (sockptr_is_kernel(io->resp_data)) { in get_ext_report()
594 certs_address = KERNEL_SOCKPTR((void *)req->certs_address); in get_ext_report()
596 certs_address = USER_SOCKPTR((void __user *)req->certs_address); in get_ext_report()
597 if (!access_ok(certs_address.user, req->certs_len)) in get_ext_report()
598 return -EFAULT; in get_ext_report()
607 memset(snp_dev->certs_data, 0, req->certs_len); in get_ext_report()
608 npages = req->certs_len >> PAGE_SHIFT; in get_ext_report()
615 resp_len = sizeof(resp->data) + crypto->a_len; in get_ext_report()
618 return -ENOMEM; in get_ext_report()
620 snp_dev->input.data_npages = npages; in get_ext_report()
622 SNP_MSG_REPORT_REQ, &req->data, in get_ext_report()
623 sizeof(req->data), resp->data, resp_len); in get_ext_report()
626 if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) { in get_ext_report()
627 req->certs_len = snp_dev->input.data_npages << PAGE_SHIFT; in get_ext_report()
629 if (copy_to_sockptr(io->req_data, req, sizeof(*req))) in get_ext_report()
630 ret = -EFAULT; in get_ext_report()
636 if (npages && copy_to_sockptr(certs_address, snp_dev->certs_data, req->certs_len)) { in get_ext_report()
637 ret = -EFAULT; in get_ext_report()
641 if (copy_to_sockptr(io->resp_data, resp, sizeof(*resp))) in get_ext_report()
642 ret = -EFAULT; in get_ext_report()
655 int ret = -ENOTTY; in snp_guest_ioctl()
658 return -EFAULT; in snp_guest_ioctl()
662 /* Message version must be non-zero */ in snp_guest_ioctl()
664 return -EINVAL; in snp_guest_ioctl()
670 dev_err_ratelimited(snp_dev->dev, "VMPCK is disabled\n"); in snp_guest_ioctl()
672 return -ENOTTY; in snp_guest_ioctl()
685 * kernel internal path (configfs-tsm), decorate the passed in snp_guest_ioctl()
699 return -EFAULT; in snp_guest_ioctl()
752 *seqno = &layout->os_area.msg_seqno_0; in get_vmpck()
753 key = layout->vmpck0; in get_vmpck()
756 *seqno = &layout->os_area.msg_seqno_1; in get_vmpck()
757 key = layout->vmpck1; in get_vmpck()
760 *seqno = &layout->os_area.msg_seqno_2; in get_vmpck()
761 key = layout->vmpck2; in get_vmpck()
764 *seqno = &layout->os_area.msg_seqno_3; in get_vmpck()
765 key = layout->vmpck3; in get_vmpck()
789 struct tsm_desc *desc = &report->desc; in sev_report_new()
797 if (desc->inblob_len != SNP_REPORT_USER_DATA_SIZE) in sev_report_new()
798 return -EINVAL; in sev_report_new()
802 return -ENOMEM; in sev_report_new()
808 dev_err_ratelimited(snp_dev->dev, "VMPCK is disabled\n"); in sev_report_new()
809 return -ENOTTY; in sev_report_new()
814 .data = { .vmpl = desc->privlevel }, in sev_report_new()
818 memcpy(&ext_req.data.user_data, desc->inblob, desc->inblob_len); in sev_report_new()
837 return -EINVAL; in sev_report_new()
839 return -EINVAL; in sev_report_new()
841 return -ENXIO; in sev_report_new()
843 return -ENOMEM; in sev_report_new()
847 return -ENOMEM; in sev_report_new()
850 report->outblob = no_free_ptr(rbuf); in sev_report_new()
851 report->outblob_len = hdr.report_size; in sev_report_new()
857 if (guid_is_null(&ent->guid) && !ent->offset && !ent->length) in sev_report_new()
859 certs_size = max(certs_size, ent->offset + ent->length); in sev_report_new()
864 dev_warn_ratelimited(snp_dev->dev, "certificate slots conveyed without size\n"); in sev_report_new()
873 dev_warn_ratelimited(snp_dev->dev, "certificate data truncated\n"); in sev_report_new()
879 return -ENOMEM; in sev_report_new()
882 report->auxblob = no_free_ptr(cbuf); in sev_report_new()
883 report->auxblob_len = certs_size; in sev_report_new()
902 struct device *dev = &pdev->dev; in sev_guest_probe()
909 return -ENODEV; in sev_guest_probe()
911 if (!dev->platform_data) in sev_guest_probe()
912 return -ENODEV; in sev_guest_probe()
914 data = (struct sev_guest_platform_data *)dev->platform_data; in sev_guest_probe()
915 mapping = ioremap_encrypted(data->secrets_gpa, PAGE_SIZE); in sev_guest_probe()
917 return -ENODEV; in sev_guest_probe()
921 ret = -ENOMEM; in sev_guest_probe()
922 snp_dev = devm_kzalloc(&pdev->dev, sizeof(struct snp_guest_dev), GFP_KERNEL); in sev_guest_probe()
926 ret = -EINVAL; in sev_guest_probe()
927 snp_dev->vmpck = get_vmpck(vmpck_id, layout, &snp_dev->os_area_msg_seqno); in sev_guest_probe()
928 if (!snp_dev->vmpck) { in sev_guest_probe()
940 snp_dev->dev = dev; in sev_guest_probe()
941 snp_dev->layout = layout; in sev_guest_probe()
944 snp_dev->request = alloc_shared_pages(dev, sizeof(struct snp_guest_msg)); in sev_guest_probe()
945 if (!snp_dev->request) in sev_guest_probe()
948 snp_dev->response = alloc_shared_pages(dev, sizeof(struct snp_guest_msg)); in sev_guest_probe()
949 if (!snp_dev->response) in sev_guest_probe()
952 snp_dev->certs_data = alloc_shared_pages(dev, SEV_FW_BLOB_MAX_SIZE); in sev_guest_probe()
953 if (!snp_dev->certs_data) in sev_guest_probe()
956 ret = -EIO; in sev_guest_probe()
957 snp_dev->crypto = init_crypto(snp_dev, snp_dev->vmpck, VMPCK_KEY_LEN); in sev_guest_probe()
958 if (!snp_dev->crypto) in sev_guest_probe()
961 misc = &snp_dev->misc; in sev_guest_probe()
962 misc->minor = MISC_DYNAMIC_MINOR; in sev_guest_probe()
963 misc->name = DEVICE_NAME; in sev_guest_probe()
964 misc->fops = &snp_guest_fops; in sev_guest_probe()
967 snp_dev->input.req_gpa = __pa(snp_dev->request); in sev_guest_probe()
968 snp_dev->input.resp_gpa = __pa(snp_dev->response); in sev_guest_probe()
969 snp_dev->input.data_gpa = __pa(snp_dev->certs_data); in sev_guest_probe()
975 ret = devm_add_action_or_reset(&pdev->dev, unregister_sev_tsm, NULL); in sev_guest_probe()
987 free_shared_pages(snp_dev->certs_data, SEV_FW_BLOB_MAX_SIZE); in sev_guest_probe()
989 free_shared_pages(snp_dev->response, sizeof(struct snp_guest_msg)); in sev_guest_probe()
991 free_shared_pages(snp_dev->request, sizeof(struct snp_guest_msg)); in sev_guest_probe()
1001 free_shared_pages(snp_dev->certs_data, SEV_FW_BLOB_MAX_SIZE); in sev_guest_remove()
1002 free_shared_pages(snp_dev->response, sizeof(struct snp_guest_msg)); in sev_guest_remove()
1003 free_shared_pages(snp_dev->request, sizeof(struct snp_guest_msg)); in sev_guest_remove()
1004 deinit_crypto(snp_dev->crypto); in sev_guest_remove()
1005 misc_deregister(&snp_dev->misc); in sev_guest_remove()
1011 * with the SEV-SNP support, it is named "sev-guest".
1016 .name = "sev-guest",
1026 MODULE_ALIAS("platform:sev-guest");