Lines Matching +full:asp +full:- +full:v2
1 // SPDX-License-Identifier: GPL-2.0-only
21 #include <linux/psp-sev.h>
22 #include <uapi/linux/sev-guest.h>
23 #include <uapi/linux/psp-sev.h>
28 #include "sev-guest.h"
30 #define DEVICE_NAME "sev-guest"
53 * Avoid information leakage by double-buffering shared messages
80 if (snp_dev->vmpck) in is_vmpck_empty()
81 return !memcmp(snp_dev->vmpck, zero_key, VMPCK_KEY_LEN); in is_vmpck_empty()
87 * If an error is received from the host or AMD Secure Processor (ASP) there
91 * This is because in the current encryption scheme GHCB v2 uses AES-GCM to
95 * The ASP FW v1.51 only increments the sequence numbers on a successful
96 * guest<->ASP back and forth and only accepts messages at its exact sequence
100 * vulnerable. If the sequence number were incremented for a fresh IV the ASP
105 dev_alert(snp_dev->dev, "Disabling vmpck_id %d to prevent IV reuse.\n", in snp_disable_vmpck()
107 memzero_explicit(snp_dev->vmpck, VMPCK_KEY_LEN); in snp_disable_vmpck()
108 snp_dev->vmpck = NULL; in snp_disable_vmpck()
118 count = *snp_dev->os_area_msg_seqno; in __snp_get_msg_seqno()
123 /* Return a non-zero on success */
129 * The message sequence counter for the SNP guest request is a 64-bit in snp_get_msg_seqno()
130 * value but the version 2 of GHCB specification defines a 32-bit storage in snp_get_msg_seqno()
131 * for it. If the counter exceeds the 32-bit value then return zero. in snp_get_msg_seqno()
137 dev_err(snp_dev->dev, "request message sequence counter overflow\n"); in snp_get_msg_seqno()
150 *snp_dev->os_area_msg_seqno += 2; in snp_inc_msg_seqno()
155 struct miscdevice *dev = file->private_data; in to_snp_dev()
168 crypto->tfm = crypto_alloc_aead("gcm(aes)", 0, 0); in init_crypto()
169 if (IS_ERR(crypto->tfm)) in init_crypto()
172 if (crypto_aead_setkey(crypto->tfm, key, keylen)) in init_crypto()
175 crypto->iv_len = crypto_aead_ivsize(crypto->tfm); in init_crypto()
176 crypto->iv = kmalloc(crypto->iv_len, GFP_KERNEL_ACCOUNT); in init_crypto()
177 if (!crypto->iv) in init_crypto()
180 if (crypto_aead_authsize(crypto->tfm) > MAX_AUTHTAG_LEN) { in init_crypto()
181 if (crypto_aead_setauthsize(crypto->tfm, MAX_AUTHTAG_LEN)) { in init_crypto()
182 dev_err(snp_dev->dev, "failed to set authsize to %d\n", MAX_AUTHTAG_LEN); in init_crypto()
187 crypto->a_len = crypto_aead_authsize(crypto->tfm); in init_crypto()
188 crypto->authtag = kmalloc(crypto->a_len, GFP_KERNEL_ACCOUNT); in init_crypto()
189 if (!crypto->authtag) in init_crypto()
195 kfree(crypto->iv); in init_crypto()
197 crypto_free_aead(crypto->tfm); in init_crypto()
206 crypto_free_aead(crypto->tfm); in deinit_crypto()
207 kfree(crypto->iv); in deinit_crypto()
208 kfree(crypto->authtag); in deinit_crypto()
215 struct snp_guest_msg_hdr *hdr = &msg->hdr; in enc_dec_message()
221 req = aead_request_alloc(crypto->tfm, GFP_KERNEL); in enc_dec_message()
223 return -ENOMEM; in enc_dec_message()
227 * +------ AAD -------+------- DATA -----+---- AUTHTAG----+ in enc_dec_message()
228 * | msg header | plaintext | hdr->authtag | in enc_dec_message()
229 * | bytes 30h - 5Fh | or | | in enc_dec_message()
231 * +------------------+------------------+----------------+ in enc_dec_message()
234 sg_set_buf(&src[0], &hdr->algo, AAD_LEN); in enc_dec_message()
235 sg_set_buf(&src[1], src_buf, hdr->msg_sz); in enc_dec_message()
236 sg_set_buf(&src[2], hdr->authtag, crypto->a_len); in enc_dec_message()
239 sg_set_buf(&dst[0], &hdr->algo, AAD_LEN); in enc_dec_message()
240 sg_set_buf(&dst[1], dst_buf, hdr->msg_sz); in enc_dec_message()
241 sg_set_buf(&dst[2], hdr->authtag, crypto->a_len); in enc_dec_message()
244 aead_request_set_tfm(req, crypto->tfm); in enc_dec_message()
247 aead_request_set_crypt(req, src, dst, len, crypto->iv); in enc_dec_message()
257 struct snp_guest_crypto *crypto = snp_dev->crypto; in __enc_payload()
258 struct snp_guest_msg_hdr *hdr = &msg->hdr; in __enc_payload()
260 memset(crypto->iv, 0, crypto->iv_len); in __enc_payload()
261 memcpy(crypto->iv, &hdr->msg_seqno, sizeof(hdr->msg_seqno)); in __enc_payload()
263 return enc_dec_message(crypto, msg, plaintext, msg->payload, len, true); in __enc_payload()
269 struct snp_guest_crypto *crypto = snp_dev->crypto; in dec_payload()
270 struct snp_guest_msg_hdr *hdr = &msg->hdr; in dec_payload()
273 memset(crypto->iv, 0, crypto->iv_len); in dec_payload()
274 memcpy(crypto->iv, &hdr->msg_seqno, sizeof(hdr->msg_seqno)); in dec_payload()
276 return enc_dec_message(crypto, msg, msg->payload, plaintext, len, false); in dec_payload()
281 struct snp_guest_crypto *crypto = snp_dev->crypto; in verify_and_dec_payload()
282 struct snp_guest_msg *resp = &snp_dev->secret_response; in verify_and_dec_payload()
283 struct snp_guest_msg *req = &snp_dev->secret_request; in verify_and_dec_payload()
284 struct snp_guest_msg_hdr *req_hdr = &req->hdr; in verify_and_dec_payload()
285 struct snp_guest_msg_hdr *resp_hdr = &resp->hdr; in verify_and_dec_payload()
287 dev_dbg(snp_dev->dev, "response [seqno %lld type %d version %d sz %d]\n", in verify_and_dec_payload()
288 resp_hdr->msg_seqno, resp_hdr->msg_type, resp_hdr->msg_version, resp_hdr->msg_sz); in verify_and_dec_payload()
291 memcpy(resp, snp_dev->response, sizeof(*resp)); in verify_and_dec_payload()
294 if (unlikely(resp_hdr->msg_seqno != (req_hdr->msg_seqno + 1))) in verify_and_dec_payload()
295 return -EBADMSG; in verify_and_dec_payload()
298 if (resp_hdr->msg_type != (req_hdr->msg_type + 1) || in verify_and_dec_payload()
299 resp_hdr->msg_version != req_hdr->msg_version) in verify_and_dec_payload()
300 return -EBADMSG; in verify_and_dec_payload()
306 if (unlikely((resp_hdr->msg_sz + crypto->a_len) > sz)) in verify_and_dec_payload()
307 return -EBADMSG; in verify_and_dec_payload()
310 return dec_payload(snp_dev, resp, payload, resp_hdr->msg_sz + crypto->a_len); in verify_and_dec_payload()
316 struct snp_guest_msg *req = &snp_dev->secret_request; in enc_payload()
317 struct snp_guest_msg_hdr *hdr = &req->hdr; in enc_payload()
321 hdr->algo = SNP_AEAD_AES_256_GCM; in enc_payload()
322 hdr->hdr_version = MSG_HDR_VER; in enc_payload()
323 hdr->hdr_sz = sizeof(*hdr); in enc_payload()
324 hdr->msg_type = type; in enc_payload()
325 hdr->msg_version = version; in enc_payload()
326 hdr->msg_seqno = seqno; in enc_payload()
327 hdr->msg_vmpck = vmpck_id; in enc_payload()
328 hdr->msg_sz = sz; in enc_payload()
330 /* Verify the sequence number is non-zero */ in enc_payload()
331 if (!hdr->msg_seqno) in enc_payload()
332 return -ENOSR; in enc_payload()
334 dev_dbg(snp_dev->dev, "request [seqno %lld type %d version %d sz %d]\n", in enc_payload()
335 hdr->msg_seqno, hdr->msg_type, hdr->msg_version, hdr->msg_sz); in enc_payload()
355 rc = snp_issue_guest_request(exit_code, &snp_dev->input, rio); in __handle_guest_request()
357 case -ENOSPC: in __handle_guest_request()
365 override_npages = snp_dev->input.data_npages; in __handle_guest_request()
390 case -EAGAIN: in __handle_guest_request()
391 if (jiffies - req_start > SNP_REQ_MAX_RETRY_DURATION) { in __handle_guest_request()
392 rc = -ETIMEDOUT; in __handle_guest_request()
408 rio->exitinfo2 = override_err; in __handle_guest_request()
413 * prevent IV reuse. If the standard request was successful, return -EIO in __handle_guest_request()
417 rc = -EIO; in __handle_guest_request()
421 snp_dev->input.data_npages = override_npages; in __handle_guest_request()
434 /* Get message sequence and verify that its a non-zero */ in handle_guest_request()
437 return -EIO; in handle_guest_request()
440 memset(snp_dev->response, 0, sizeof(struct snp_guest_msg)); in handle_guest_request()
442 /* Encrypt the userspace provided payload in snp_dev->secret_request. */ in handle_guest_request()
443 rc = enc_payload(snp_dev, seqno, rio->msg_version, type, req_buf, req_sz); in handle_guest_request()
451 memcpy(snp_dev->request, &snp_dev->secret_request, in handle_guest_request()
452 sizeof(snp_dev->secret_request)); in handle_guest_request()
456 if (rc == -EIO && in handle_guest_request()
457 rio->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN)) in handle_guest_request()
460 dev_alert(snp_dev->dev, in handle_guest_request()
461 "Detected error from ASP request. rc: %d, exitinfo2: 0x%llx\n", in handle_guest_request()
462 rc, rio->exitinfo2); in handle_guest_request()
470 dev_alert(snp_dev->dev, "Detected unexpected decode failure from ASP. rc: %d\n", rc); in handle_guest_request()
480 struct snp_guest_crypto *crypto = snp_dev->crypto; in get_report()
481 struct snp_report_req *req = &snp_dev->req.report; in get_report()
487 if (!arg->req_data || !arg->resp_data) in get_report()
488 return -EINVAL; in get_report()
490 if (copy_from_user(req, (void __user *)arg->req_data, sizeof(*req))) in get_report()
491 return -EFAULT; in get_report()
498 resp_len = sizeof(resp->data) + crypto->a_len; in get_report()
501 return -ENOMEM; in get_report()
504 SNP_MSG_REPORT_REQ, req, sizeof(*req), resp->data, in get_report()
509 if (copy_to_user((void __user *)arg->resp_data, resp, sizeof(*resp))) in get_report()
510 rc = -EFAULT; in get_report()
519 struct snp_derived_key_req *req = &snp_dev->req.derived_key; in get_derived_key()
520 struct snp_guest_crypto *crypto = snp_dev->crypto; in get_derived_key()
528 if (!arg->req_data || !arg->resp_data) in get_derived_key()
529 return -EINVAL; in get_derived_key()
536 resp_len = sizeof(resp.data) + crypto->a_len; in get_derived_key()
538 return -ENOMEM; in get_derived_key()
540 if (copy_from_user(req, (void __user *)arg->req_data, sizeof(*req))) in get_derived_key()
541 return -EFAULT; in get_derived_key()
549 if (copy_to_user((void __user *)arg->resp_data, &resp, sizeof(resp))) in get_derived_key()
550 rc = -EFAULT; in get_derived_key()
560 struct snp_ext_report_req *req = &snp_dev->req.ext_report; in get_ext_report()
561 struct snp_guest_crypto *crypto = snp_dev->crypto; in get_ext_report()
567 if (!arg->req_data || !arg->resp_data) in get_ext_report()
568 return -EINVAL; in get_ext_report()
570 if (copy_from_user(req, (void __user *)arg->req_data, sizeof(*req))) in get_ext_report()
571 return -EFAULT; in get_ext_report()
574 if (!req->certs_len || !req->certs_address) in get_ext_report()
577 if (req->certs_len > SEV_FW_BLOB_MAX_SIZE || in get_ext_report()
578 !IS_ALIGNED(req->certs_len, PAGE_SIZE)) in get_ext_report()
579 return -EINVAL; in get_ext_report()
581 if (!access_ok((const void __user *)req->certs_address, req->certs_len)) in get_ext_report()
582 return -EFAULT; in get_ext_report()
590 memset(snp_dev->certs_data, 0, req->certs_len); in get_ext_report()
591 npages = req->certs_len >> PAGE_SHIFT; in get_ext_report()
598 resp_len = sizeof(resp->data) + crypto->a_len; in get_ext_report()
601 return -ENOMEM; in get_ext_report()
603 snp_dev->input.data_npages = npages; in get_ext_report()
605 SNP_MSG_REPORT_REQ, &req->data, in get_ext_report()
606 sizeof(req->data), resp->data, resp_len); in get_ext_report()
609 if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) { in get_ext_report()
610 req->certs_len = snp_dev->input.data_npages << PAGE_SHIFT; in get_ext_report()
612 if (copy_to_user((void __user *)arg->req_data, req, sizeof(*req))) in get_ext_report()
613 ret = -EFAULT; in get_ext_report()
620 copy_to_user((void __user *)req->certs_address, snp_dev->certs_data, in get_ext_report()
621 req->certs_len)) { in get_ext_report()
622 ret = -EFAULT; in get_ext_report()
626 if (copy_to_user((void __user *)arg->resp_data, resp, sizeof(*resp))) in get_ext_report()
627 ret = -EFAULT; in get_ext_report()
639 int ret = -ENOTTY; in snp_guest_ioctl()
642 return -EFAULT; in snp_guest_ioctl()
646 /* Message version must be non-zero */ in snp_guest_ioctl()
648 return -EINVAL; in snp_guest_ioctl()
654 dev_err_ratelimited(snp_dev->dev, "VMPCK is disabled\n"); in snp_guest_ioctl()
656 return -ENOTTY; in snp_guest_ioctl()
676 return -EFAULT; in snp_guest_ioctl()
729 *seqno = &layout->os_area.msg_seqno_0; in get_vmpck()
730 key = layout->vmpck0; in get_vmpck()
733 *seqno = &layout->os_area.msg_seqno_1; in get_vmpck()
734 key = layout->vmpck1; in get_vmpck()
737 *seqno = &layout->os_area.msg_seqno_2; in get_vmpck()
738 key = layout->vmpck2; in get_vmpck()
741 *seqno = &layout->os_area.msg_seqno_3; in get_vmpck()
742 key = layout->vmpck3; in get_vmpck()
755 struct device *dev = &pdev->dev; in sev_guest_probe()
762 return -ENODEV; in sev_guest_probe()
764 if (!dev->platform_data) in sev_guest_probe()
765 return -ENODEV; in sev_guest_probe()
767 data = (struct sev_guest_platform_data *)dev->platform_data; in sev_guest_probe()
768 mapping = ioremap_encrypted(data->secrets_gpa, PAGE_SIZE); in sev_guest_probe()
770 return -ENODEV; in sev_guest_probe()
774 ret = -ENOMEM; in sev_guest_probe()
775 snp_dev = devm_kzalloc(&pdev->dev, sizeof(struct snp_guest_dev), GFP_KERNEL); in sev_guest_probe()
779 ret = -EINVAL; in sev_guest_probe()
780 snp_dev->vmpck = get_vmpck(vmpck_id, layout, &snp_dev->os_area_msg_seqno); in sev_guest_probe()
781 if (!snp_dev->vmpck) { in sev_guest_probe()
793 snp_dev->dev = dev; in sev_guest_probe()
794 snp_dev->layout = layout; in sev_guest_probe()
797 snp_dev->request = alloc_shared_pages(dev, sizeof(struct snp_guest_msg)); in sev_guest_probe()
798 if (!snp_dev->request) in sev_guest_probe()
801 snp_dev->response = alloc_shared_pages(dev, sizeof(struct snp_guest_msg)); in sev_guest_probe()
802 if (!snp_dev->response) in sev_guest_probe()
805 snp_dev->certs_data = alloc_shared_pages(dev, SEV_FW_BLOB_MAX_SIZE); in sev_guest_probe()
806 if (!snp_dev->certs_data) in sev_guest_probe()
809 ret = -EIO; in sev_guest_probe()
810 snp_dev->crypto = init_crypto(snp_dev, snp_dev->vmpck, VMPCK_KEY_LEN); in sev_guest_probe()
811 if (!snp_dev->crypto) in sev_guest_probe()
814 misc = &snp_dev->misc; in sev_guest_probe()
815 misc->minor = MISC_DYNAMIC_MINOR; in sev_guest_probe()
816 misc->name = DEVICE_NAME; in sev_guest_probe()
817 misc->fops = &snp_guest_fops; in sev_guest_probe()
820 snp_dev->input.req_gpa = __pa(snp_dev->request); in sev_guest_probe()
821 snp_dev->input.resp_gpa = __pa(snp_dev->response); in sev_guest_probe()
822 snp_dev->input.data_gpa = __pa(snp_dev->certs_data); in sev_guest_probe()
832 free_shared_pages(snp_dev->certs_data, SEV_FW_BLOB_MAX_SIZE); in sev_guest_probe()
834 free_shared_pages(snp_dev->response, sizeof(struct snp_guest_msg)); in sev_guest_probe()
836 free_shared_pages(snp_dev->request, sizeof(struct snp_guest_msg)); in sev_guest_probe()
846 free_shared_pages(snp_dev->certs_data, SEV_FW_BLOB_MAX_SIZE); in sev_guest_remove()
847 free_shared_pages(snp_dev->response, sizeof(struct snp_guest_msg)); in sev_guest_remove()
848 free_shared_pages(snp_dev->request, sizeof(struct snp_guest_msg)); in sev_guest_remove()
849 deinit_crypto(snp_dev->crypto); in sev_guest_remove()
850 misc_deregister(&snp_dev->misc); in sev_guest_remove()
858 * with the SEV-SNP support, it is named "sev-guest".
863 .name = "sev-guest",
873 MODULE_ALIAS("platform:sev-guest");