From patchwork Mon Jun 21 19:05:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dov Murik X-Patchwork-Id: 12335529 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4C40DC4743C for ; Mon, 21 Jun 2021 19:09:11 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BE1596124B for ; Mon, 21 Jun 2021 19:09:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BE1596124B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:60830 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lvPID-0004jT-Sq for qemu-devel@archiver.kernel.org; Mon, 21 Jun 2021 15:09:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33930) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lvPFN-0000mj-MO for qemu-devel@nongnu.org; Mon, 21 Jun 2021 15:06:13 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:45286 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lvPFL-0004lH-Ju for qemu-devel@nongnu.org; Mon, 21 Jun 2021 15:06:13 -0400 Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 15LJ3gh1023109; Mon, 21 Jun 2021 15:06:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=NQzDLDP1laRCLkR8rW/PE9zGfyyFe6NPZhPwywtJrQs=; b=Ie2lyO6becMBJMzulIarvntO8IAUq/V5lkLa1C6693Qwn3vv8kjrI9QWPgfsBm+pMyMU Z6qboWgl+jVAF074P5EMfSSNH7ZJlFcoZnGap1Y8nwhVpGytsBntfPgcTVrc7gQXUj1w jZj01wcQMaxegY0+eB+wvPL6HwjI4SacdujRmXclw1fhaJIS0ZotUdhnWb/k2uAweTsy YRb5Hek4qTH6AK+KFMtxpK/eau6ZGbTlcBnf3gm7aNwSYq597yZIrcYaAcHI53pSGjca 9p6SHY4b4wC+7SnaIrWFRhEAOClLa3uLuDQhzSIdQ97YLKFkAtSnxH2U4YxSYsVHRFpT OQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 39b0jd02rk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 21 Jun 2021 15:06:08 -0400 Received: from m0098420.ppops.net (m0098420.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 15LJ67ZZ033261; Mon, 21 Jun 2021 15:06:07 -0400 Received: from ppma01dal.us.ibm.com (83.d6.3fa9.ip4.static.sl-reverse.com [169.63.214.131]) by mx0b-001b2d01.pphosted.com with ESMTP id 39b0jd02qp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 21 Jun 2021 15:06:07 -0400 Received: from pps.filterd (ppma01dal.us.ibm.com [127.0.0.1]) by ppma01dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 15LJ3jB4031184; Mon, 21 Jun 2021 19:06:07 GMT Received: from b03cxnp07028.gho.boulder.ibm.com (b03cxnp07028.gho.boulder.ibm.com [9.17.130.15]) by ppma01dal.us.ibm.com with ESMTP id 399879dwcm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 21 Jun 2021 19:06:06 +0000 Received: from b03ledav003.gho.boulder.ibm.com (b03ledav003.gho.boulder.ibm.com [9.17.130.234]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 15LJ65TW28639546 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 21 Jun 2021 19:06:05 GMT Received: from b03ledav003.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3DE656A04D; Mon, 21 Jun 2021 19:06:05 +0000 (GMT) Received: from b03ledav003.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D0A5C6A04F; Mon, 21 Jun 2021 19:06:03 +0000 (GMT) Received: from localhost.localdomain (unknown [9.2.130.16]) by b03ledav003.gho.boulder.ibm.com (Postfix) with ESMTP; Mon, 21 Jun 2021 19:06:03 +0000 (GMT) From: Dov Murik To: qemu-devel@nongnu.org Subject: [PATCH v2 1/2] sev/i386: Introduce sev_add_kernel_loader_hashes for measured linux boot Date: Mon, 21 Jun 2021 19:05:52 +0000 Message-Id: <20210621190553.1763020-2-dovmurik@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210621190553.1763020-1-dovmurik@linux.ibm.com> References: <20210621190553.1763020-1-dovmurik@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: BFGfl6dbqsLioJr4n6UFO_aLI7I8et7k X-Proofpoint-ORIG-GUID: yN2MD8HALHHJX0JUZkbLK71nlNLlx05E X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.790 definitions=2021-06-21_10:2021-06-21, 2021-06-21 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 phishscore=0 malwarescore=0 spamscore=0 bulkscore=0 mlxscore=0 adultscore=0 mlxlogscore=999 lowpriorityscore=0 impostorscore=0 clxscore=1015 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2106210112 Received-SPF: pass client-ip=148.163.158.5; envelope-from=dovmurik@linux.ibm.com; helo=mx0a-001b2d01.pphosted.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tom Lendacky , Ashish Kalra , Brijesh Singh , Eduardo Habkost , "Michael S. Tsirkin" , Connor Kuehl , Laszlo Ersek , James Bottomley , Richard Henderson , "Dr. David Alan Gilbert" , Dov Murik , Tobin Feldman-Fitzthum , Jim Cadden , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add the sev_add_kernel_loader_hashes function to calculate the hashes of the kernel/initrd/cmdline and fill a designated OVMF encrypted hash table area. For this to work, OVMF must support an encrypted area to place the data which is advertised via a special GUID in the OVMF reset table. The hashes of each of the files is calculated (or the string in the case of the cmdline with trailing '\0' included). Each entry in the hashes table is GUID identified and since they're passed through the sev_encrypt_flash interface, the hashes will be accumulated by the PSP measurement (SEV_LAUNCH_MEASURE). Co-developed-by: James Bottomley Signed-off-by: James Bottomley Signed-off-by: Dov Murik --- target/i386/sev-stub.c | 5 ++ target/i386/sev.c | 121 +++++++++++++++++++++++++++++++++++++++++ target/i386/sev_i386.h | 12 ++++ 3 files changed, 138 insertions(+) diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c index 0227cb5177..2b5e42d644 100644 --- a/target/i386/sev-stub.c +++ b/target/i386/sev-stub.c @@ -81,3 +81,8 @@ sev_get_attestation_report(const char *mnonce, Error **errp) error_setg(errp, "SEV is not available in this QEMU"); return NULL; } + +bool sev_add_kernel_loader_hashes(KernelLoaderContext *ctx, Error **errp) +{ + return false; +} diff --git a/target/i386/sev.c b/target/i386/sev.c index 83df8c09f6..8e3f601bb6 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -23,6 +23,7 @@ #include "qemu/base64.h" #include "qemu/module.h" #include "qemu/uuid.h" +#include "crypto/hash.h" #include "sysemu/kvm.h" #include "sev_i386.h" #include "sysemu/sysemu.h" @@ -83,6 +84,29 @@ typedef struct __attribute__((__packed__)) SevInfoBlock { uint32_t reset_addr; } SevInfoBlock; +#define SEV_HASH_TABLE_RV_GUID "7255371f-3a3b-4b04-927b-1da6efa8d454" +typedef struct __attribute__((__packed__)) SevHashTableDescriptor { + /* SEV hash table area guest address */ + uint32_t base; + /* SEV hash table area size (in bytes) */ + uint32_t size; +} SevHashTableDescriptor; + +/* hard code sha256 digest size */ +#define HASH_SIZE 32 + +typedef struct __attribute__((__packed__)) SevHashTableEntry { + uint8_t guid[16]; + uint16_t len; + uint8_t hash[HASH_SIZE]; +} SevHashTableEntry; + +typedef struct __attribute__((__packed__)) SevHashTable { + uint8_t guid[16]; + uint16_t len; + SevHashTableEntry entries[]; +} SevHashTable; + static SevGuestState *sev_guest; static Error *sev_mig_blocker; @@ -1077,6 +1101,103 @@ int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size) return 0; } +static const uint8_t sev_hash_table_header_guid[] = + UUID_LE(0x9438d606, 0x4f22, 0x4cc9, 0xb4, 0x79, 0xa7, 0x93, + 0xd4, 0x11, 0xfd, 0x21); + +static const uint8_t sev_kernel_entry_guid[] = + UUID_LE(0x4de79437, 0xabd2, 0x427f, 0xb8, 0x35, 0xd5, 0xb1, + 0x72, 0xd2, 0x04, 0x5b); +static const uint8_t sev_initrd_entry_guid[] = + UUID_LE(0x44baf731, 0x3a2f, 0x4bd7, 0x9a, 0xf1, 0x41, 0xe2, + 0x91, 0x69, 0x78, 0x1d); +static const uint8_t sev_cmdline_entry_guid[] = + UUID_LE(0x97d02dd8, 0xbd20, 0x4c94, 0xaa, 0x78, 0xe7, 0x71, + 0x4d, 0x36, 0xab, 0x2a); + +static void fill_sev_hash_table_entry(SevHashTableEntry *e, const uint8_t *guid, + const uint8_t *hash, size_t hash_len) +{ + memcpy(e->guid, guid, sizeof(e->guid)); + e->len = sizeof(*e); + memcpy(e->hash, hash, hash_len); +} + +/* + * Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page + * which is included in SEV's initial memory measurement. + */ +bool sev_add_kernel_loader_hashes(KernelLoaderContext *ctx, Error **errp) +{ + uint8_t *data; + SevHashTableDescriptor *area; + SevHashTable *ht; + SevHashTableEntry *e; + uint8_t hash_buf[HASH_SIZE]; + uint8_t *hash = hash_buf; + size_t hash_len = sizeof(hash_buf); + int ht_index = 0; + int aligned_len; + + if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) { + error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid"); + return false; + } + area = (SevHashTableDescriptor *)data; + + ht = qemu_map_ram_ptr(NULL, area->base); + + /* Populate the hashes table header */ + memcpy(ht->guid, sev_hash_table_header_guid, sizeof(ht->guid)); + ht->len = sizeof(*ht); + + /* Calculate hash of kernel command-line */ + if (qcrypto_hash_bytes(QCRYPTO_HASH_ALG_SHA256, ctx->cmdline_data, + ctx->cmdline_size, + &hash, &hash_len, errp) < 0) { + return false; + } + e = &ht->entries[ht_index++]; + fill_sev_hash_table_entry(e, sev_cmdline_entry_guid, hash, hash_len); + + /* Calculate hash of initrd */ + if (ctx->initrd_data) { + if (qcrypto_hash_bytes(QCRYPTO_HASH_ALG_SHA256, ctx->initrd_data, + ctx->initrd_size, &hash, &hash_len, errp) < 0) { + return false; + } + e = &ht->entries[ht_index++]; + fill_sev_hash_table_entry(e, sev_initrd_entry_guid, hash, hash_len); + } + + /* Calculate hash of the kernel */ + struct iovec iov[2] = { + { .iov_base = ctx->setup_data, .iov_len = ctx->setup_size }, + { .iov_base = ctx->kernel_data, .iov_len = ctx->kernel_size } + }; + if (qcrypto_hash_bytesv(QCRYPTO_HASH_ALG_SHA256, iov, 2, + &hash, &hash_len, errp) < 0) { + return false; + } + e = &ht->entries[ht_index++]; + fill_sev_hash_table_entry(e, sev_kernel_entry_guid, hash, hash_len); + + /* now we have all the possible entries, finalize the hashes table */ + ht->len += ht_index * sizeof(*e); + /* SEV len has to be 16 byte aligned */ + aligned_len = ROUND_UP(ht->len, 16); + if (aligned_len != ht->len) { + /* zero the excess data so the measurement can be reliably calculated */ + memset(&ht->entries[ht_index], 0, aligned_len - ht->len); + } + + if (sev_encrypt_flash((uint8_t *)ht, aligned_len, errp) < 0) { + return false; + } + + return true; +} + static void sev_register_types(void) { diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h index ae6d840478..deb3eec409 100644 --- a/target/i386/sev_i386.h +++ b/target/i386/sev_i386.h @@ -28,6 +28,17 @@ #define SEV_POLICY_DOMAIN 0x10 #define SEV_POLICY_SEV 0x20 +typedef struct KernelLoaderContext { + char *setup_data; + size_t setup_size; + char *kernel_data; + size_t kernel_size; + char *initrd_data; + size_t initrd_size; + char *cmdline_data; + size_t cmdline_size; +} KernelLoaderContext; + extern bool sev_es_enabled(void); extern uint64_t sev_get_me_mask(void); extern SevInfo *sev_get_info(void); @@ -37,5 +48,6 @@ extern char *sev_get_launch_measurement(void); extern SevCapability *sev_get_capabilities(Error **errp); extern SevAttestationReport * sev_get_attestation_report(const char *mnonce, Error **errp); +extern bool sev_add_kernel_loader_hashes(KernelLoaderContext *ctx, Error **errp); #endif From patchwork Mon Jun 21 19:05:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dov Murik X-Patchwork-Id: 12335527 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 832B5C4743C for ; Mon, 21 Jun 2021 19:08:54 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F403C6124B for ; Mon, 21 Jun 2021 19:08:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F403C6124B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59652 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lvPHx-0003wG-2T for qemu-devel@archiver.kernel.org; Mon, 21 Jun 2021 15:08:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34082) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lvPGg-0002Jg-8o for qemu-devel@nongnu.org; Mon, 21 Jun 2021 15:07:34 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:61446) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lvPGb-0005cT-50 for qemu-devel@nongnu.org; Mon, 21 Jun 2021 15:07:34 -0400 Received: from pps.filterd (m0187473.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 15LJ7Eii134031; Mon, 21 Jun 2021 15:07:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=n7E7/m3dBQb9PHPdycRji51f7MhBCNbcHST6zKPSG+Y=; b=ay5jhjtEXiSGFZdQOWVXT2kL0Rb5oMubax5JpfGjw8HQ6A0vU0IZ3pMDzzagwLuaZ/2E tDPZ5NWzhV5HM8TMFlM9zwDeGWgevCrPFJvwMlqtCJMi/prNh9Rtrua9NIfQ9wj34Qit bMiXILRJxMUTqrs5cKjlU26VPBC324oQi2ceYmJU2b4sUeWTYWBYJJuWeCT3bedFfI6D VSVwfY8QlnR6fHKjeTa/vMnGRhrC1E9i3yBBDwZmUJ7zuPL4dEpwib7iZalKqmGao7b3 KmfPIRixSQv8ROAShdOSUb590w+yXuKY3H5J0sj3eodbcEj+GB+3vX3dWXd3NrbYua+D jg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 39b0ag8jc6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 21 Jun 2021 15:07:24 -0400 Received: from m0187473.ppops.net (m0187473.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 15LJ7O6l134901; Mon, 21 Jun 2021 15:07:24 -0400 Received: from ppma01wdc.us.ibm.com (fd.55.37a9.ip4.static.sl-reverse.com [169.55.85.253]) by mx0a-001b2d01.pphosted.com with ESMTP id 39b0ag8hq7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 21 Jun 2021 15:07:23 -0400 Received: from pps.filterd (ppma01wdc.us.ibm.com [127.0.0.1]) by ppma01wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 15LJ1qiw005550; Mon, 21 Jun 2021 19:06:10 GMT Received: from b03cxnp08028.gho.boulder.ibm.com (b03cxnp08028.gho.boulder.ibm.com [9.17.130.20]) by ppma01wdc.us.ibm.com with ESMTP id 399878hj65-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 21 Jun 2021 19:06:10 +0000 Received: from b03ledav003.gho.boulder.ibm.com (b03ledav003.gho.boulder.ibm.com [9.17.130.234]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 15LJ68B812386666 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 21 Jun 2021 19:06:09 GMT Received: from b03ledav003.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CDC4F6A067; Mon, 21 Jun 2021 19:06:08 +0000 (GMT) Received: from b03ledav003.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 764596A047; Mon, 21 Jun 2021 19:06:07 +0000 (GMT) Received: from localhost.localdomain (unknown [9.2.130.16]) by b03ledav003.gho.boulder.ibm.com (Postfix) with ESMTP; Mon, 21 Jun 2021 19:06:07 +0000 (GMT) From: Dov Murik To: qemu-devel@nongnu.org Subject: [PATCH v2 2/2] x86/sev: generate SEV kernel loader hashes in x86_load_linux Date: Mon, 21 Jun 2021 19:05:53 +0000 Message-Id: <20210621190553.1763020-3-dovmurik@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210621190553.1763020-1-dovmurik@linux.ibm.com> References: <20210621190553.1763020-1-dovmurik@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: lgcKb69GicbA9B0FUDWxt-D_nYN7Od9I X-Proofpoint-GUID: bzEcBxy5kAqrbNkw6z4e9a8yUEflyTPz X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.790 definitions=2021-06-21_11:2021-06-21, 2021-06-21 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 clxscore=1015 bulkscore=0 mlxlogscore=999 phishscore=0 priorityscore=1501 adultscore=0 mlxscore=0 lowpriorityscore=0 suspectscore=0 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2106210112 Received-SPF: pass client-ip=148.163.156.1; envelope-from=dovmurik@linux.ibm.com; helo=mx0a-001b2d01.pphosted.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tom Lendacky , Ashish Kalra , Brijesh Singh , Eduardo Habkost , "Michael S. Tsirkin" , Connor Kuehl , Laszlo Ersek , James Bottomley , Richard Henderson , "Dr. David Alan Gilbert" , Dov Murik , Tobin Feldman-Fitzthum , Jim Cadden , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" If SEV is enabled and a kernel is passed via -kernel, pass the hashes of kernel/initrd/cmdline in an encrypted guest page to OVMF for SEV measured boot. Co-developed-by: James Bottomley Signed-off-by: James Bottomley Signed-off-by: Dov Murik Reviewed-by: Connor Kuehl --- hw/i386/x86.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index ed796fe6ba..5c46463d9f 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -45,6 +45,7 @@ #include "hw/i386/fw_cfg.h" #include "hw/intc/i8259.h" #include "hw/rtc/mc146818rtc.h" +#include "target/i386/sev_i386.h" #include "hw/acpi/cpu_hotplug.h" #include "hw/irq.h" @@ -778,6 +779,7 @@ void x86_load_linux(X86MachineState *x86ms, const char *initrd_filename = machine->initrd_filename; const char *dtb_filename = machine->dtb; const char *kernel_cmdline = machine->kernel_cmdline; + KernelLoaderContext kernel_loader_context = {}; /* Align to 16 bytes as a paranoia measure */ cmdline_size = (strlen(kernel_cmdline) + 16) & ~15; @@ -924,6 +926,8 @@ void x86_load_linux(X86MachineState *x86ms, fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline) + 1); fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline); + kernel_loader_context.cmdline_data = (char *)kernel_cmdline; + kernel_loader_context.cmdline_size = strlen(kernel_cmdline) + 1; if (protocol >= 0x202) { stl_p(header + 0x228, cmdline_addr); @@ -1005,6 +1009,8 @@ void x86_load_linux(X86MachineState *x86ms, fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size); + kernel_loader_context.initrd_data = initrd_data; + kernel_loader_context.initrd_size = initrd_size; stl_p(header + 0x218, initrd_addr); stl_p(header + 0x21c, initrd_size); @@ -1063,15 +1069,32 @@ void x86_load_linux(X86MachineState *x86ms, load_image_size(dtb_filename, setup_data->data, dtb_size); } - memcpy(setup, header, MIN(sizeof(header), setup_size)); + /* + * If we're starting an encrypted VM, it will be OVMF based, which uses the + * efi stub for booting and doesn't require any values to be placed in the + * kernel header. We therefore don't update the header so the hash of the + * kernel on the other side of the fw_cfg interface matches the hash of the + * file the user passed in. + */ + if (!sev_enabled()) { + memcpy(setup, header, MIN(sizeof(header), setup_size)); + } fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size); + kernel_loader_context.kernel_data = (char *)kernel; + kernel_loader_context.kernel_size = kernel_size; fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size); + kernel_loader_context.setup_data = (char *)setup; + kernel_loader_context.setup_size = setup_size; + + if (sev_enabled()) { + sev_add_kernel_loader_hashes(&kernel_loader_context, &error_fatal); + } option_rom[nb_option_roms].bootindex = 0; option_rom[nb_option_roms].name = "linuxboot.bin";