Commit fad133c7 authored by Tom Lendacky's avatar Tom Lendacky Committed by Borislav Petkov (AMD)
Browse files

crypto: ccp: Add the SNP_COMMIT command



The SNP_COMMIT command is used to commit the currently installed version
of the SEV firmware. Once committed, the firmware cannot be replaced
with a previous firmware version (cannot be rolled back). This command
will also update the reported TCB to match that of the currently
installed firmware.

  [ mdr: Note the reported TCB update in the documentation/commit. ]

Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarMichael Roth <michael.roth@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20240126041126.1927228-25-michael.roth@amd.com
parent f5db8841
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -151,6 +151,17 @@ The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The
status includes API major, minor version and more. See the SEV-SNP
specification for further details.

2.5 SNP_COMMIT
--------------
:Technology: sev-snp
:Type: hypervisor ioctl cmd
:Returns (out): 0 on success, -negative on error

SNP_COMMIT is used to commit the currently installed firmware using the
SEV-SNP firmware SNP_COMMIT command. This prevents roll-back to a previously
committed firmware version. This will also update the reported TCB to match
that of the currently installed firmware.

3. SEV-SNP CPUID Enforcement
============================

+17 −0
Original line number Diff line number Diff line
@@ -222,6 +222,7 @@ static int sev_cmd_buffer_len(int cmd)
	case SEV_CMD_SNP_PLATFORM_STATUS:	return sizeof(struct sev_data_snp_addr);
	case SEV_CMD_SNP_GUEST_REQUEST:		return sizeof(struct sev_data_snp_guest_request);
	case SEV_CMD_SNP_CONFIG:		return sizeof(struct sev_user_data_snp_config);
	case SEV_CMD_SNP_COMMIT:		return sizeof(struct sev_data_snp_commit);
	default:				return 0;
	}

@@ -1990,6 +1991,19 @@ static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp)
	return ret;
}

static int sev_ioctl_do_snp_commit(struct sev_issue_cmd *argp)
{
	struct sev_device *sev = psp_master->sev_data;
	struct sev_data_snp_commit buf;

	if (!sev->snp_initialized)
		return -EINVAL;

	buf.len = sizeof(buf);

	return __sev_do_cmd_locked(SEV_CMD_SNP_COMMIT, &buf, &argp->error);
}

static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
@@ -2044,6 +2058,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
	case SNP_PLATFORM_STATUS:
		ret = sev_ioctl_do_snp_platform_status(&input);
		break;
	case SNP_COMMIT:
		ret = sev_ioctl_do_snp_commit(&input);
		break;
	default:
		ret = -EINVAL;
		goto out;
+9 −0
Original line number Diff line number Diff line
@@ -801,6 +801,15 @@ struct sev_platform_init_args {
	bool probe;
};

/**
 * struct sev_data_snp_commit - SNP_COMMIT structure
 *
 * @len: length of the command buffer read by the PSP
 */
struct sev_data_snp_commit {
	u32 len;
} __packed;

#ifdef CONFIG_CRYPTO_DEV_SP_PSP

/**
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ enum {
	SEV_GET_ID,	/* This command is deprecated, use SEV_GET_ID2 */
	SEV_GET_ID2,
	SNP_PLATFORM_STATUS,
	SNP_COMMIT,

	SEV_MAX,
};