From nobody Sun Nov 24 22:50:12 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1720005020; cv=none; d=zohomail.com; s=zohoarc; b=U1hEIPWV5tIYb6BIbdrZ8tukVnp74FvGjHnVqwddLnyJqxCfcwd85T/pK3gaohu5MHcFdIh4w8IWUWuKrCnpfb1MlFKZrqHWrPRxv+TUux1i3vZf+Rt3fQAOqQF1DWuQ8MzHbCEATkOY5VQ7+Hi0to9Ce2w5Oc6/EJ9jQOMlKos= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1720005020; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=PQXVWUdXey3UblcHhqhCe3IoKgwzb9XZQHg/4KUubl4=; b=YiFvTGER1ZdzA2Sz+bx4laY1YgWPAe9A9WioWRfZd28SjuT1VNvJ67pQ6EGDUW5Naa7YnnOClyJDHIeTsUB6KOTRftCGJATblpHk1k7zlyEw0bQCf1rx/rZ/zn/8Nkkzr2e2ofwVwKVMPv92hfn/mBTGrreyUhF55yl7sJX/Qv8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1720005019927242.36584388393464; Wed, 3 Jul 2024 04:10:19 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sOxpI-00054f-9j; Wed, 03 Jul 2024 07:07:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sOxox-0004tZ-36 for qemu-devel@nongnu.org; Wed, 03 Jul 2024 07:06:43 -0400 Received: from smtp-out2.suse.de ([195.135.223.131]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sOxop-0006Xg-EV for qemu-devel@nongnu.org; Wed, 03 Jul 2024 07:06:41 -0400 Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id C078E1FCE1; Wed, 3 Jul 2024 11:06:29 +0000 (UTC) Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 09A4A13A7F; Wed, 3 Jul 2024 11:06:29 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id IMdUALUwhWZ6cgAAD6G6ig (envelope-from ); Wed, 03 Jul 2024 11:06:29 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1720004789; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PQXVWUdXey3UblcHhqhCe3IoKgwzb9XZQHg/4KUubl4=; b=Qz50jpV0aW1r/5QOf592DtMKdGsKu/hqZIrrFiWlGhaqlXQ7u4apTAusgWo4cOyknR+Zch AKQs4/ql1XhNo9I43DDohxvwr8toleyEq/9Y9b18ym70bgHikSY/ic5odnNDER1a3FIAD2 k2J6wYaJiX0L+FZ12H1pVux7+TtIt0o= Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1720004789; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PQXVWUdXey3UblcHhqhCe3IoKgwzb9XZQHg/4KUubl4=; b=Qz50jpV0aW1r/5QOf592DtMKdGsKu/hqZIrrFiWlGhaqlXQ7u4apTAusgWo4cOyknR+Zch AKQs4/ql1XhNo9I43DDohxvwr8toleyEq/9Y9b18ym70bgHikSY/ic5odnNDER1a3FIAD2 k2J6wYaJiX0L+FZ12H1pVux7+TtIt0o= From: Roy Hopkins To: qemu-devel@nongnu.org Cc: Roy Hopkins , Paolo Bonzini , =?UTF-8?q?Daniel=20P=20=2E=20Berrang=C3=A9?= , Stefano Garzarella , Marcelo Tosatti , "Michael S . Tsirkin" , Cornelia Huck , Marcel Apfelbaum , Sergio Lopez , Eduardo Habkost , Alistair Francis , Peter Xu , David Hildenbrand , Igor Mammedov , Tom Lendacky , Michael Roth , Ani Sinha , =?UTF-8?q?J=C3=B6rg=20Roedel?= Subject: [PATCH v4 15/17] backends/igvm: Handle policy for SEV guests Date: Wed, 3 Jul 2024 12:05:53 +0100 Message-ID: <003ab7e3fe0334e18bc6dcf4e575518e35211538.1720004383.git.roy.hopkins@suse.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -1.30 X-Spamd-Result: default: False [-1.30 / 50.00]; BAYES_HAM(-3.00)[100.00%]; SUSPICIOUS_RECIPS(1.50)[]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; TAGGED_RCPT(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:helo,suse.com:email]; RCPT_COUNT_TWELVE(0.00)[19]; MIME_TRACE(0.00)[0:+]; TO_DN_SOME(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; FREEMAIL_CC(0.00)[suse.com,redhat.com,gmail.com,habkost.net,alistair23.me,amd.com]; FROM_HAS_DN(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_TLS_ALL(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; R_RATELIMIT(0.00)[to_ip_from(RLm8d31jk6dhzwhww9bgqrb1jt)]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FREEMAIL_ENVRCPT(0.00)[gmail.com] Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=195.135.223.131; envelope-from=roy.hopkins@suse.com; helo=smtp-out2.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1720005020326100001 Content-Type: text/plain; charset="utf-8" Adds a handler for the guest policy initialization IGVM section and builds an SEV policy based on this information and the ID block directive if present. The policy is applied using by calling 'set_guest_policy()' on the ConfidentialGuestSupport object. Signed-off-by: Roy Hopkins --- backends/igvm.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/backends/igvm.c b/backends/igvm.c index fa074b9107..3589f977ca 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -28,6 +28,33 @@ typedef struct IgvmParameterData { uint32_t index; } IgvmParameterData; =20 +/* + * Some directives are specific to particular confidential computing platf= orms. + * Define required types for each of those platforms here. + */ + +/* SEV/SEV-ES/SEV-SNP */ +struct QEMU_PACKED sev_id_block { + uint8_t ld[48]; + uint8_t family_id[16]; + uint8_t image_id[16]; + uint32_t version; + uint32_t guest_svn; + uint64_t policy; +}; + +struct QEMU_PACKED sev_id_authentication { + uint32_t id_key_alg; + uint32_t auth_key_algo; + uint8_t reserved[56]; + uint8_t id_block_sig[512]; + uint8_t id_key[1028]; + uint8_t reserved2[60]; + uint8_t id_key_sig[512]; + uint8_t author_key[1028]; + uint8_t reserved3[892]; +}; + /* * QemuIgvm contains the information required during processing * of a single IGVM file. @@ -39,6 +66,17 @@ typedef struct QemuIgvm { uint32_t compatibility_mask; unsigned current_header_index; QTAILQ_HEAD(, IgvmParameterData) parameter_data; + IgvmPlatformType platform_type; + + /* + * SEV-SNP platforms can contain an ID block and authentication + * that should be verified by the guest. + */ + struct sev_id_block *id_block; + struct sev_id_authentication *id_auth; + + /* Define the guest policy for SEV guests */ + uint64_t sev_policy; =20 /* These variables keep track of contiguous page regions */ IGVM_VHS_PAGE_DATA region_prev_page_data; @@ -64,6 +102,11 @@ static int directive_environment_info(QemuIgvm *ctx, co= nst uint8_t *header_data, Error **errp); static int directive_required_memory(QemuIgvm *ctx, const uint8_t *header_= data, Error **errp); +static int directive_snp_id_block(QemuIgvm *ctx, const uint8_t *header_dat= a, + Error **errp); +static int initialization_guest_policy(QemuIgvm *ctx, + const uint8_t *header_data, + Error **errp); =20 struct IGVMHandler { uint32_t type; @@ -87,6 +130,10 @@ static struct IGVMHandler handlers[] =3D { directive_environment_info }, { IGVM_VHT_REQUIRED_MEMORY, IGVM_HEADER_SECTION_DIRECTIVE, directive_required_memory }, + { IGVM_VHT_SNP_ID_BLOCK, IGVM_HEADER_SECTION_DIRECTIVE, + directive_snp_id_block }, + { IGVM_VHT_GUEST_POLICY, IGVM_HEADER_SECTION_INITIALIZATION, + initialization_guest_policy }, }; =20 static int handler(QemuIgvm *ctx, uint32_t type, Error **errp) @@ -627,6 +674,70 @@ static int directive_required_memory(QemuIgvm *ctx, co= nst uint8_t *header_data, return 0; } =20 +static int directive_snp_id_block(QemuIgvm *ctx, const uint8_t *header_dat= a, + Error **errp) +{ + const IGVM_VHS_SNP_ID_BLOCK *igvm_id =3D + (const IGVM_VHS_SNP_ID_BLOCK *)header_data; + + if (!(igvm_id->compatibility_mask & ctx->compatibility_mask)) { + return 0; + } + + if (ctx->id_block) { + error_setg(errp, "IGVM: Multiple ID blocks encountered " + "in IGVM file."); + return -1; + } + ctx->id_block =3D g_new0(struct sev_id_block, 1); + ctx->id_auth =3D g_new0(struct sev_id_authentication, 1); + + memcpy(ctx->id_block->family_id, igvm_id->family_id, + sizeof(ctx->id_block->family_id)); + memcpy(ctx->id_block->image_id, igvm_id->image_id, + sizeof(ctx->id_block->image_id)); + ctx->id_block->guest_svn =3D igvm_id->guest_svn; + ctx->id_block->version =3D 1; + memcpy(ctx->id_block->ld, igvm_id->ld, sizeof(ctx->id_block->ld)); + + ctx->id_auth->id_key_alg =3D igvm_id->id_key_algorithm; + memcpy(ctx->id_auth->id_block_sig, &igvm_id->id_key_signature, + sizeof(igvm_id->id_key_signature)); + + ctx->id_auth->auth_key_algo =3D igvm_id->author_key_algorithm; + memcpy(ctx->id_auth->id_key_sig, &igvm_id->author_key_signature, + sizeof(igvm_id->author_key_signature)); + + /* + * SEV and IGVM public key structure population are slightly different. + * See SEV Secure Nested Paging Firmware ABI Specification, Chapter 10. + */ + *((uint32_t *)ctx->id_auth->id_key) =3D igvm_id->id_public_key.curve; + memcpy(&ctx->id_auth->id_key[4], &igvm_id->id_public_key.qx, 72); + memcpy(&ctx->id_auth->id_key[76], &igvm_id->id_public_key.qy, 72); + + *((uint32_t *)ctx->id_auth->author_key) =3D + igvm_id->author_public_key.curve; + memcpy(&ctx->id_auth->author_key[4], &igvm_id->author_public_key.qx, + 72); + memcpy(&ctx->id_auth->author_key[76], &igvm_id->author_public_key.qy, + 72); + + return 0; +} + +static int initialization_guest_policy(QemuIgvm *ctx, + const uint8_t *header_data, Error *= *errp) +{ + const IGVM_VHS_GUEST_POLICY *guest =3D + (const IGVM_VHS_GUEST_POLICY *)header_data; + + if (guest->compatibility_mask & ctx->compatibility_mask) { + ctx->sev_policy =3D guest->policy; + } + return 0; +} + static int supported_platform_compat_mask(QemuIgvm *ctx, Error **errp) { int32_t header_count; @@ -696,12 +807,16 @@ static int supported_platform_compat_mask(QemuIgvm *c= tx, Error **errp) /* Choose the strongest supported isolation technology */ if (compatibility_mask_sev_snp !=3D 0) { ctx->compatibility_mask =3D compatibility_mask_sev_snp; + ctx->platform_type =3D IGVM_PLATFORM_TYPE_SEV_SNP; } else if (compatibility_mask_sev_es !=3D 0) { ctx->compatibility_mask =3D compatibility_mask_sev_es; + ctx->platform_type =3D IGVM_PLATFORM_TYPE_SEV_ES; } else if (compatibility_mask_sev !=3D 0) { ctx->compatibility_mask =3D compatibility_mask_sev; + ctx->platform_type =3D IGVM_PLATFORM_TYPE_SEV; } else if (compatibility_mask !=3D 0) { ctx->compatibility_mask =3D compatibility_mask; + ctx->platform_type =3D IGVM_PLATFORM_TYPE_NATIVE; } else { error_setg( errp, @@ -711,6 +826,23 @@ static int supported_platform_compat_mask(QemuIgvm *ct= x, Error **errp) return 0; } =20 +static int handle_policy(QemuIgvm *ctx, Error **errp) +{ + if (ctx->platform_type =3D=3D IGVM_PLATFORM_TYPE_SEV_SNP) { + int id_block_len =3D 0; + int id_auth_len =3D 0; + if (ctx->id_block) { + ctx->id_block->policy =3D ctx->sev_policy; + id_block_len =3D sizeof(struct sev_id_block); + id_auth_len =3D sizeof(struct sev_id_authentication); + } + return ctx->cgsc->set_guest_policy(GUEST_POLICY_SEV, ctx->sev_poli= cy, + ctx->id_block, id_block_len, + ctx->id_auth, id_auth_len, errp); + } + return 0; +} + static IgvmHandle igvm_file_init(char *filename, Error **errp) { IgvmHandle igvm; @@ -809,12 +941,18 @@ int igvm_process_file(IgvmCfgState *cfg, Confidential= GuestSupport *cgs, */ retval =3D process_mem_page(&ctx, NULL, errp); =20 + if (retval =3D=3D 0) { + retval =3D handle_policy(&ctx, errp); + } + cleanup: QTAILQ_FOREACH(parameter, &ctx.parameter_data, next) { g_free(parameter->data); parameter->data =3D NULL; } + g_free(ctx.id_block); + g_free(ctx.id_auth); =20 return retval; } --=20 2.43.0