From nobody Wed Nov 27 07:39:49 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=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1700708391; cv=none; d=zohomail.com; s=zohoarc; b=fUMzETqcm3QcKzteMucgeq5AOOPpy43Vw5eKD3nIXV2e1EEwZ33NqIrNnEjuRQLAAQbuXuDpAk5UIe/A0l1K6IAVzCHygxcVIuKGIsGYM4S031Hkjcv8Evgha7YLhQG73k5+SbIQxMOuBNyPvuylm8/ESHQhyPf77YZF1bSoA6o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1700708391; 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=83SQt3W6AQgNci/+XFKsfNNylqPiwaHIBR/GEEgqfuE=; b=VjT1H8nXNe1XoEGNvr7iYyrltKwTip70H6+E8T8VMGemRegRfqN1mxgq4iDgv/MQupKFRiUpUDB4CnpCcMnnoKAPK7w6S2cMS7kPQzYwAd5dDkmFU51YzFseeHrnSfPd86mOXi1HgbeGDD7jXM29PwkLHHZQXAu+3FA67nTHXkg= 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=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 170070839141474.98143252548573; Wed, 22 Nov 2023 18:59:51 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r5zvw-0001Y7-HH; Wed, 22 Nov 2023 21:59:16 -0500 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 1r5zvv-0001Xk-Q2; Wed, 22 Nov 2023 21:59:15 -0500 Received: from mail-pj1-x1029.google.com ([2607:f8b0:4864:20::1029]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1r5zvt-0000Sm-LZ; Wed, 22 Nov 2023 21:59:15 -0500 Received: by mail-pj1-x1029.google.com with SMTP id 98e67ed59e1d1-280200949c3so360260a91.0; Wed, 22 Nov 2023 18:59:13 -0800 (PST) Received: from toolbox.alistair23.me (2403-580b-97e8-0-321-6fb2-58f1-a1b1.ip6.aussiebb.net. [2403:580b:97e8:0:321:6fb2:58f1:a1b1]) by smtp.gmail.com with ESMTPSA id br17-20020a17090b0f1100b0027909a8994fsm476743pjb.13.2023.11.22.18.59.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Nov 2023 18:59:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700708352; x=1701313152; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=83SQt3W6AQgNci/+XFKsfNNylqPiwaHIBR/GEEgqfuE=; b=A7dcC06R1n3Ct793txGGXUp8ApCTKPZ7x909ObKy9+HiOBr0hC3K+C3XMitmjt3Kxu cWgasq5hrDrqb64SiFkaYvXFcgFiNzKSnQhKofgV+hbdkkZAzWOOmjEchXCIY9WiziTS a95TPZ1iw3CL/xSlUrDeopLa4xsfExHBCSbgbdJ65rlEmmgMrA4vjbIeA1TOZXqKFsnE l2SKV8sKrv/Bv6gRzBWsedPWkLi1grYG2CfMS0g3KCaLVbm83YzjLFCW38pzogXWK8Hq h9Z03BBCLP0BZeg3Apf6d2ADpIOAP7sBjJdMhswmtjgoPIqCUvIuH/ghSG526ioQ90Jk jp0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700708352; x=1701313152; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=83SQt3W6AQgNci/+XFKsfNNylqPiwaHIBR/GEEgqfuE=; b=gPXO7QDnigIePkgfW42vcY+1qcVnGBrnnHpJUYpl0nBklw01vmUsOdRbWnAfzZ9K/g MR+Kqo228OjfqNHItiWQ/gd4GlHoiUjxC00clU24xozKT2EQ7dAIgCj96DHfRcJrevsf pokjgGSS8d2zxUIVZd6SIS+QaikzexZ55qvl3BgI3xyVGN1+x2G3NLEOnib40NLyUyxG iEbHNDndOulLiA9ETyphY5+B6BpxX4N6y5plyZdwhL/iqxNt6yXzw13L+YCzHAlW1Frq F3kJjjyuUnzqdccg3lmMHcGcdPoD3I0uhLqqR3tPKyQbnoAn9tiW4o+M7Pmqcts8wTri MF0g== X-Gm-Message-State: AOJu0YxUByLxSgUZGoImZ6smgVsajHw7Av9LEfLUcFy5iXqxojFq6EtV k6Heh6LPG0Ic7moyt4E1gSk= X-Google-Smtp-Source: AGHT+IFMDNHRws6wuTWHGZxolNXUole61pbduwFyHmyPQcuob9xeEK+dRXk/2Tpkx0tMYlOFVMasBQ== X-Received: by 2002:a17:90b:1803:b0:285:6722:ac91 with SMTP id lw3-20020a17090b180300b002856722ac91mr205841pjb.30.1700708351899; Wed, 22 Nov 2023 18:59:11 -0800 (PST) From: Alistair Francis X-Google-Original-From: Alistair Francis To: marcel.apfelbaum@gmail.com, cbrowy@avery-design.com, its@irrelevant.dk, jiewen.yao@intel.com, wilfred.mallawa@wdc.com, Jonathan.Cameron@Huawei.com, lukas@wunner.de, hchkuo@avery-design.com.tw, kbusch@kernel.org, qemu-devel@nongnu.org, mst@redhat.com Cc: qemu-block@nongnu.org, alistair23@gmail.com, Paolo Bonzini , Jonathan Cameron , Jonathan Cameron , Alistair Francis Subject: [PATCH v3 2/3] backends: Initial support for SPDM socket support Date: Thu, 23 Nov 2023 12:58:46 +1000 Message-ID: <20231123025847.2538863-3-alistair.francis@wdc.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231123025847.2538863-1-alistair.francis@wdc.com> References: <20231123025847.2538863-1-alistair.francis@wdc.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=2607:f8b0:4864:20::1029; envelope-from=alistair23@gmail.com; helo=mail-pj1-x1029.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 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, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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 @gmail.com) X-ZM-MESSAGEID: 1700708392837100007 Content-Type: text/plain; charset="utf-8" From: Huai-Cheng Kuo SPDM enables authentication, attestation and key exchange to assist in providing infrastructure security enablement. It's a standard published by the DMTF [1]. SPDM supports multiple transports, including PCIe DOE and MCTP. This patch adds support to QEMU to connect to an external SPDM instance. SPDM support can be added to any QEMU device by exposing a TCP socket to a SPDM server. The server can then implement the SPDM decoding/encoding support, generally using libspdm [2]. This is similar to how the current TPM implementation works and means that the heavy lifting of setting up certificate chains, capabilities, measurements and complex crypto can be done outside QEMU by a well supported and tested library. 1: https://www.dmtf.org/standards/SPDM 2: https://github.com/DMTF/libspdm Signed-off-by: Huai-Cheng Kuo Signed-off-by: Chris Browy Co-developed-by: Jonathan Cameron Signed-off-by: Jonathan Cameron [ Changes by WM - Bug fixes from testing ] Signed-off-by: Wilfred Mallawa [ Changes by AF: - Convert to be more QEMU-ified - Move to backends as it isn't PCIe specific ] Signed-off-by: Alistair Francis --- include/sysemu/spdm-socket.h | 44 +++++++ backends/spdm-socket.c | 216 +++++++++++++++++++++++++++++++++++ backends/Kconfig | 4 + backends/meson.build | 2 + 4 files changed, 266 insertions(+) create mode 100644 include/sysemu/spdm-socket.h create mode 100644 backends/spdm-socket.c diff --git a/include/sysemu/spdm-socket.h b/include/sysemu/spdm-socket.h new file mode 100644 index 0000000000..24e6fccb83 --- /dev/null +++ b/include/sysemu/spdm-socket.h @@ -0,0 +1,44 @@ +/* + * QEMU SPDM socket support + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#ifndef SPDM_REQUESTER_H +#define SPDM_REQUESTER_H + +int spdm_socket_connect(uint16_t port, Error **errp); +uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type, + void *req, uint32_t req_len, + void *rsp, uint32_t rsp_len); +void spdm_socket_close(const int socket, uint32_t transport_type); + +#define SPDM_SOCKET_COMMAND_NORMAL 0x0001 +#define SPDM_SOCKET_COMMAND_OOB_ENCAP_KEY_UPDATE 0x8001 +#define SPDM_SOCKET_COMMAND_CONTINUE 0xFFFD +#define SPDM_SOCKET_COMMAND_SHUTDOWN 0xFFFE +#define SPDM_SOCKET_COMMAND_UNKOWN 0xFFFF +#define SPDM_SOCKET_COMMAND_TEST 0xDEAD + +#define SPDM_SOCKET_TRANSPORT_TYPE_MCTP 0x01 +#define SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE 0x02 + +#define SPDM_SOCKET_MAX_MESSAGE_BUFFER_SIZE 0x1200 + +#endif diff --git a/backends/spdm-socket.c b/backends/spdm-socket.c new file mode 100644 index 0000000000..d0663d696c --- /dev/null +++ b/backends/spdm-socket.c @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * QEMU SPDM socket support + * + * This is based on: + * https://github.com/DMTF/spdm-emu/blob/07c0a838bcc1c6207c656ac75885c0603= e344b6f/spdm_emu/spdm_emu_common/command.c + * but has been re-written to match QEMU style + * + * Copyright (c) 2021, DMTF. All rights reserved. + * Copyright (c) 2023. Western Digital Corporation or its affiliates. + */ + +#include "qemu/osdep.h" +#include "sysemu/spdm-socket.h" +#include "qapi/error.h" + +static bool read_bytes(const int socket, uint8_t *buffer, + size_t number_of_bytes) +{ + ssize_t number_received =3D 0; + ssize_t result; + + while (number_received < number_of_bytes) { + result =3D recv(socket, buffer + number_received, + number_of_bytes - number_received, 0); + if (result <=3D 0) { + return false; + } + number_received +=3D result; + } + return true; +} + +static bool read_data32(const int socket, uint32_t *data) +{ + bool result; + + result =3D read_bytes(socket, (uint8_t *)data, sizeof(uint32_t)); + if (!result) { + return result; + } + *data =3D ntohl(*data); + return true; +} + +static bool read_multiple_bytes(const int socket, uint8_t *buffer, + uint32_t *bytes_received, + uint32_t max_buffer_length) +{ + uint32_t length; + bool result; + + result =3D read_data32(socket, &length); + if (!result) { + return result; + } + + if (length > max_buffer_length) { + return false; + } + + if (bytes_received) { + *bytes_received =3D length; + } + + if (length =3D=3D 0) { + return true; + } + + return read_bytes(socket, buffer, length); +} + +static bool receive_platform_data(const int socket, + uint32_t transport_type, + uint32_t *command, + uint8_t *receive_buffer, + uint32_t *bytes_to_receive) +{ + bool result; + uint32_t response; + uint32_t bytes_received; + + result =3D read_data32(socket, &response); + if (!result) { + return result; + } + *command =3D response; + + result =3D read_data32(socket, &transport_type); + if (!result) { + return result; + } + + bytes_received =3D 0; + result =3D read_multiple_bytes(socket, receive_buffer, &bytes_received, + *bytes_to_receive); + if (!result) { + return result; + } + *bytes_to_receive =3D bytes_received; + + return result; +} + +static bool write_bytes(const int socket, const uint8_t *buffer, + uint32_t number_of_bytes) +{ + ssize_t number_sent =3D 0; + ssize_t result; + + while (number_sent < number_of_bytes) { + result =3D send(socket, buffer + number_sent, + number_of_bytes - number_sent, 0); + if (result =3D=3D -1) { + return false; + } + number_sent +=3D result; + } + return true; +} + +static bool write_data32(const int socket, uint32_t data) +{ + data =3D htonl(data); + return write_bytes(socket, (uint8_t *)&data, sizeof(uint32_t)); +} + +static bool write_multiple_bytes(const int socket, const uint8_t *buffer, + uint32_t bytes_to_send) +{ + bool result; + + result =3D write_data32(socket, bytes_to_send); + if (!result) { + return result; + } + + return write_bytes(socket, buffer, bytes_to_send); +} + +static bool send_platform_data(const int socket, + uint32_t transport_type, uint32_t command, + const uint8_t *send_buffer, size_t bytes_to= _send) +{ + bool result; + + result =3D write_data32(socket, command); + if (!result) { + return result; + } + + result =3D write_data32(socket, transport_type); + if (!result) { + return result; + } + + return write_multiple_bytes(socket, send_buffer, bytes_to_send); +} + +int spdm_socket_connect(uint16_t port, Error **errp) +{ + int client_socket; + struct sockaddr_in server_addr; + + client_socket =3D socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (client_socket < 0) { + error_setg(errp, "cannot create socket: %s", strerror(errno)); + return -1; + } + + memset((char *)&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family =3D AF_INET; + server_addr.sin_addr.s_addr =3D htonl(INADDR_LOOPBACK); + server_addr.sin_port =3D htons(port); + + + if (connect(client_socket, (struct sockaddr *)&server_addr, + sizeof(server_addr)) < 0) { + error_setg(errp, "cannot connect: %s", strerror(errno)); + close(client_socket); + return -1; + } + + return client_socket; +} + +uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type, + void *req, uint32_t req_len, + void *rsp, uint32_t rsp_len) +{ + uint32_t command; + bool result; + + result =3D send_platform_data(socket, transport_type, + SPDM_SOCKET_COMMAND_NORMAL, + req, req_len); + if (!result) { + return 0; + } + + result =3D receive_platform_data(socket, transport_type, &command, + (uint8_t *)rsp, &rsp_len); + if (!result) { + return 0; + } + + assert(command !=3D 0); + + return rsp_len; +} + +void spdm_socket_close(const int socket, uint32_t transport_type) +{ + send_platform_data(socket, transport_type, + SPDM_SOCKET_COMMAND_SHUTDOWN, NULL, 0); +} diff --git a/backends/Kconfig b/backends/Kconfig index f35abc1609..648e58a9b3 100644 --- a/backends/Kconfig +++ b/backends/Kconfig @@ -1 +1,5 @@ source tpm/Kconfig + +config SPDM_SOCKET + bool + default y diff --git a/backends/meson.build b/backends/meson.build index 914c7c4afb..77d48ffdaa 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -26,4 +26,6 @@ endif system_ss.add(when: gio, if_true: files('dbus-vmstate.c')) system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c')) =20 +system_ss.add(when: 'CONFIG_SPDM_SOCKET', if_true: files('spdm-socket.c')) + subdir('tpm') --=20 2.42.0