Received: by 2002:a25:23cc:0:0:0:0:0 with SMTP id j195csp79047ybj; Mon, 4 May 2020 16:28:06 -0700 (PDT) X-Google-Smtp-Source: APiQypJ4GVKGn6u99xuIiRyH/tg2YYxLrcoLKXrlOhBbfxe7l0XgfcB9U94+Uj8tDWxeiY04bJuU X-Received: by 2002:a05:6402:154:: with SMTP id s20mr416530edu.224.1588634886522; Mon, 04 May 2020 16:28:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588634886; cv=none; d=google.com; s=arc-20160816; b=kgH7YEfWiOlJmNGGYmf1zwpKkFyRmdCAFO8WQtXobpN37mf0Ul/DUhflVi+3xhrDQ6 EPOibvNQQEdI5t6HJzBQMcC2DLgQflTpntt/6OAKJfUjjvtHlaah+1WIqoGT1cud8xd8 drR2ZvV+J1xV2U5VjwYngwTpG/68Pf0oMGBL9DbteaBgaQiWNOwXPKRgKnmfu1+TSn7f b9417vtbGv6xgKKyo3ZkXbPzUlT2S5cbc2Cpyx3i3Irx+tKKCB3O79YMgscShCPcikvq obMJjN63Z2kfCYlnxYLycxUaKCqZZsl1XCvjLbi76ymdma1FI6tbeExeGh1pMVS5ctWE nPpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=R0wqtFdhHPWyxkeH774P5glzvKGkY+n3t2Jlub0gYr8=; b=o9wBsym9qgma6cjN5jOyHjy2ES2PxvwNuT95nxuenWXz7EyBJKYrNaI7DSV9+cBY7W GwnIAKpWABYVdeoWqYdh55IDEHAZHbi54HuejY1HRG+C4Nu+D4NQPT/pWi/Gkn5WHZPx mP8sTdrC6ZOwNLUs/LE4li683UGsWaRwT8QhR/x8vGqliPZRdbKLpixcVE1JRwQKqjR/ ZNnchyRKWRuIGK7vzj5E/cEN3p/keRG6mNs7eH7B21Coj1wmKlCMd3gxDCn1vuRTYsTB cYcX0hFC66B+pjjAlqchbVnMUxwBIB80GYKZu2BAo7LIFh+pK0koiKQDfydBvOA8vYuL enUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@oracle.com header.s=corp-2020-01-29 header.b=K8OKRjqT; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oracle.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u13si287006edb.6.2020.05.04.16.27.43; Mon, 04 May 2020 16:28:06 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@oracle.com header.s=corp-2020-01-29 header.b=K8OKRjqT; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728455AbgEDXXu (ORCPT + 99 others); Mon, 4 May 2020 19:23:50 -0400 Received: from aserp2120.oracle.com ([141.146.126.78]:51028 "EHLO aserp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728428AbgEDXXs (ORCPT ); Mon, 4 May 2020 19:23:48 -0400 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 044NNOlk100259; Mon, 4 May 2020 23:23:24 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2020-01-29; bh=R0wqtFdhHPWyxkeH774P5glzvKGkY+n3t2Jlub0gYr8=; b=K8OKRjqTDVOYIjHyuVDzNeY5MSZ/15M4am+PenRjKqMSG+7QFUWwtPCLoCv1rhyHct3e vcb570kOn6/d2dRZnX0z/9ct8Xtk6PleKLQMwr1Wpc59UiJ//wVX90f7nSWjnIVbQd8o giyLY8PizWvVN3eXu2QgpnYAEqokqNHqDHZIT7OG8vfaDmdkHjCW59Fu24pO03jqQ6Do BfuCFjJeruGuQBr42etk0ZshTobnkLEMtqXFDLZBv4ecU27knZ6rYwIt1rkALlVrnrcr HopSDEWx+md37OfltkJuDviuLPpOPImGq59jX/ZOIkUPdaB/O+e1vu28kdMg1HZ929Bz dg== Received: from userp3030.oracle.com (userp3030.oracle.com [156.151.31.80]) by aserp2120.oracle.com with ESMTP id 30s0tm9t44-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 04 May 2020 23:23:24 +0000 Received: from pps.filterd (userp3030.oracle.com [127.0.0.1]) by userp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 044NLciC140002; Mon, 4 May 2020 23:23:23 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userp3030.oracle.com with ESMTP id 30t1r3j23g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 04 May 2020 23:23:23 +0000 Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id 044NNLZJ003803; Mon, 4 May 2020 23:23:22 GMT Received: from tomti.i.net-space.pl (/10.175.189.148) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 04 May 2020 16:23:21 -0700 From: Daniel Kiper To: grub-devel@gnu.org, linux-kernel@vger.kernel.org, trenchboot-devel@googlegroups.com, x86@kernel.org Cc: alexander.burmashev@oracle.com, andrew.cooper3@citrix.com, ard.biesheuvel@linaro.org, dpsmith@apertussolutions.com, eric.snowberg@oracle.com, javierm@redhat.com, kanth.ghatraju@oracle.com, konrad.wilk@oracle.com, krystian.hebel@3mdeb.com, lukasz.hawrylko@linux.intel.com, michal.zygowski@3mdeb.com, mjg59@google.com, phcoder@gmail.com, pirot.krol@3mdeb.com, pjones@redhat.com, ross.philipson@oracle.com Subject: [GRUB PATCH RFC 17/18] i386/txt: Add Intel TXT verification routines Date: Tue, 5 May 2020 01:21:31 +0200 Message-Id: <20200504232132.23570-18-daniel.kiper@oracle.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200504232132.23570-1-daniel.kiper@oracle.com> References: <20200504232132.23570-1-daniel.kiper@oracle.com> X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9611 signatures=668687 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 bulkscore=0 adultscore=0 suspectscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 phishscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005040182 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9611 signatures=668687 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxscore=0 priorityscore=1501 lowpriorityscore=0 spamscore=0 suspectscore=0 phishscore=0 clxscore=1015 bulkscore=0 mlxlogscore=999 adultscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005040182 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ross Philipson Signed-off-by: Ross Philipson Signed-off-by: Daniel Kiper --- grub-core/loader/i386/txt/verify.c | 297 +++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 grub-core/loader/i386/txt/verify.c diff --git a/grub-core/loader/i386/txt/verify.c b/grub-core/loader/i386/txt/verify.c new file mode 100644 index 000000000..97f3b325d --- /dev/null +++ b/grub-core/loader/i386/txt/verify.c @@ -0,0 +1,297 @@ +/* + * verify.c: verify that platform and processor supports Intel(r) TXT + * + * Copyright (c) 2003-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020 Oracle and/or its affiliates. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Current max that the secure launch can handle */ +#define TXT_MAX_CPUS 512 + +static grub_err_t +verify_bios_spec_ver_elt (struct grub_txt_heap_ext_data_element *elt) +{ + grub_uint8_t *ptr = (grub_uint8_t *)elt; + struct grub_txt_heap_bios_spec_ver_element *bios_spec_ver_elt = + (struct grub_txt_heap_bios_spec_ver_element *)ptr; + + if ( elt->size != sizeof(*elt) + sizeof(*bios_spec_ver_elt) ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("HEAP_BIOS_SPEC_VER element has wrong size (%d)"), + elt->size); + + /* Any values are allowed */ + return GRUB_ERR_NONE; +} + +static grub_err_t +verify_acm_elt (struct grub_txt_heap_ext_data_element *elt) +{ + grub_uint8_t *ptr = ((grub_uint8_t *)elt + sizeof(*elt)); + struct grub_txt_heap_acm_element *acm_elt = + (struct grub_txt_heap_acm_element *)ptr; + grub_uint64_t *acm_addrs; + grub_uint32_t i; + + if ( elt->size != sizeof(*elt) + sizeof(*acm_elt) + + acm_elt->num_acms*sizeof(grub_uint64_t) ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("HEAP_ACM element has wrong size (%d)"), + elt->size); + + /* No addrs is not error, but print warning. */ + if ( acm_elt->num_acms == 0 ) + grub_printf ("WARNING: HEAP_ACM element has no ACM addrs\n"); + + acm_addrs = (grub_uint64_t *)(ptr + sizeof(*acm_elt)); + for ( i = 0; i < acm_elt->num_acms; i++ ) + { + if ( acm_addrs[i] == 0 ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("HEAP_ACM element ACM addr (%d) is NULL"), i); + + if ( acm_addrs[i] >= 0x100000000UL ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("HEAP_ACM element ACM addr (%d) is >4GB"), i); + + /* Not going to check if ACM addrs are valid ACMs */ + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +verify_custom_elt (struct grub_txt_heap_ext_data_element *elt) +{ + grub_uint8_t *ptr = (grub_uint8_t *)elt; + struct grub_txt_heap_custom_element *custom_elt = + (struct grub_txt_heap_custom_element *)ptr; + + if ( elt->size < sizeof(*elt) + sizeof(*custom_elt) ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("HEAP_CUSTOM element has wrong size (%d)"), + elt->size); + + /* Any values are allowed */ + + return GRUB_ERR_NONE; +} + +static grub_err_t +verify_evt_log_ptr_elt (struct grub_txt_heap_ext_data_element *elt) +{ + grub_uint8_t *ptr = (grub_uint8_t *)elt; + struct grub_txt_heap_tpm_event_log_element *elog_elt = + (struct grub_txt_heap_tpm_event_log_element *)ptr; + + if ( elt->size != sizeof(*elt) + sizeof(*elog_elt) ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("HEAP_EVENT_LOG_POINTER element has wrong size (%d)"), + elt->size); + + /* TODO: Sort out how to do this verifier once the event log handling is in place + * + * return verify_evt_log((event_log_container_t *)(unsigned long) + * elog_elt->event_log_phys_addr); + */ + + return GRUB_ERR_NONE; +} + +static grub_err_t +verify_ext_data_elts(struct grub_txt_heap_ext_data_element *elts, + grub_uint64_t elts_size) +{ + struct grub_txt_heap_ext_data_element *elt = elts; + grub_err_t err; + + if ( elts_size < sizeof(*elt) ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("TXT heap ext data elements too small")); + + for ( ; ; ) + { + if ( elts_size < elt->size || elt->size == 0 ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("TXT heap invalid element size: type: %d, size: %d"), + elt->type, elt->size); + + switch ( elt->type ) + { + case GRUB_TXT_HEAP_EXTDATA_TYPE_END: + return GRUB_ERR_NONE; + case GRUB_TXT_HEAP_EXTDATA_TYPE_BIOS_SPEC_VER: + err = verify_bios_spec_ver_elt (elt); + if ( err ) + return err; + break; + case GRUB_TXT_HEAP_EXTDATA_TYPE_ACM: + err = verify_acm_elt (elt); + if ( err ) + return err; + break; + case GRUB_TXT_HEAP_EXTDATA_TYPE_STM: + /* Nothing to check, platform specific */ + break; + case GRUB_TXT_HEAP_EXTDATA_TYPE_CUSTOM: + err = verify_custom_elt (elt); + if ( err ) + return err; + break; + case GRUB_TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR: + err = verify_evt_log_ptr_elt (elt); + if ( err ) + return err; + break; + case GRUB_TXT_HEAP_EXTDATA_TYPE_MADT: + /* Copy of ACPI MADT, not validating */ + break; + case GRUB_TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1: + /* TODO TBOOT did not verify this, not sure why or how to do it */ + break; + case GRUB_TXT_HEAP_EXTDATA_TYPE_MCFG: + /* Copy of ACPI MCFG, not validating */ + break; + default: + /* TODO: What kind of element??? Improve the message. */ + grub_printf ("WARNING: unknown element: type: %u, size: %u\n", elt->type, elt->size); + break; + } + + elts_size -= elt->size; + elt = (struct grub_txt_heap_ext_data_element *)((grub_uint8_t *)elt + elt->size); + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_txt_verify_platform (void) +{ + grub_uint8_t *txt_heap; + grub_uint32_t eax, ebx, ecx, edx; + grub_uint64_t bios_size, heap_base, heap_size, msr; + grub_err_t err = GRUB_ERR_NONE; + struct grub_txt_bios_data *bios_data; + struct grub_txt_heap_ext_data_element *elts; + + grub_cpuid (GRUB_X86_CPUID_FEATURES, eax, ebx, ecx, edx); + + if (!(ecx & GRUB_SMX_CPUID_FEATURE)) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("CPU does not support SMX")); + + msr = grub_rdmsr (GRUB_MSR_X86_FEATURE_CONTROL); + + if ((msr & (GRUB_MSR_X86_SENTER_FUNCTIONS | GRUB_MSR_X86_SENTER_ENABLE)) != + (GRUB_MSR_X86_SENTER_FUNCTIONS | GRUB_MSR_X86_SENTER_ENABLE)) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("GETSEC[SENTER] is not enabled")); + + /* + * TODO + * TXT Specification + * 4.5 SGX Requirement for TXT Platform + * Secure Launch currently does not support interop with SGX since it does + * not have TPM support to write the SE NVRAM index. + * Eventually need the verify_IA32_se_svn_status routine to be called here. + */ + + if (grub_txt_reg_pub_readq (GRUB_TXT_ESTS) & GRUB_TXT_ESTS_TXT_RESET) + return grub_error (GRUB_ERR_BAD_DEVICE, + N_("TXT_RESET.STS is set and GETSEC[SENTER] is disabled")); + + /* + * Verify that the BIOS information in the TXT heap that was setup by the + * BIOS ACM is sane. + */ + + txt_heap = grub_txt_get_heap (); + heap_base = grub_txt_reg_pub_readq (GRUB_TXT_HEAP_BASE); + heap_size = grub_txt_reg_pub_readq (GRUB_TXT_HEAP_SIZE); + + if ( txt_heap == NULL || heap_base == 0 || heap_size == 0 ) + return grub_error (GRUB_ERR_BAD_DEVICE, + N_("TXT heap is not configured correctly")); + + bios_size = grub_txt_bios_data_size (txt_heap); + if ( bios_size == 0 || bios_size > heap_size ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("invalid size of the TXT heap BIOS data table")); + + bios_data = grub_txt_bios_data_start (txt_heap); + + /* Check version */ + if ( bios_data->version < 5 ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("unsupported BIOS data version (%d)"), bios_data->version); + + if ( bios_data->num_logical_procs > TXT_MAX_CPUS ) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("BIOS reports too many CPUs for secure launch (%d)"), + bios_data->num_logical_procs); + + if ( bios_data->version >= 4 && bios_size > sizeof(*bios_data) + sizeof(bios_size) ) + { + elts = (struct grub_txt_heap_ext_data_element *) ((grub_uint8_t *)bios_data + sizeof(*bios_data)); + err = verify_ext_data_elts(elts, bios_size - sizeof(*bios_data)); + } + + return err; +} -- 2.11.0