From 3ab91fbec937830f184108a244795a2e05cb275c Mon Sep 17 00:00:00 2001 From: Claudio Carvalho Date: Sat, 9 Dec 2017 02:52:19 -0200 Subject: libstb/secureboot.c: import sb_verify() from stb.c This imports the sb_verify() function from stb.c, but now it calls the CVC verify wrapper in order to verify signed firmware images. The hw-key-hash and hw-key-hash-size initialized in secureboot.c are passed to the CVC verify function wrapper. In secureboot.c, the sb_verify() is renamed to secureboot_verify(). The sb_verify() calls are updated in a subsequent patch. Signed-off-by: Claudio Carvalho Signed-off-by: Stewart Smith --- asm/Makefile.inc | 2 +- asm/cvc_entry.S | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ asm/rom_entry.S | 52 ------------------------------------------------ libstb/cvc.c | 44 +++++++++++++++++++++++++++++++++++++++- libstb/cvc.h | 20 +++++++++++++++++++ libstb/drivers/romcode.c | 4 ++-- libstb/secureboot.c | 52 +++++++++++++++++++++++++++++++++++++++++++++--- libstb/secureboot.h | 17 ++++++++++++++++ 8 files changed, 184 insertions(+), 59 deletions(-) create mode 100644 asm/cvc_entry.S delete mode 100644 asm/rom_entry.S diff --git a/asm/Makefile.inc b/asm/Makefile.inc index 34e2b28..2828caf 100644 --- a/asm/Makefile.inc +++ b/asm/Makefile.inc @@ -1,7 +1,7 @@ # -*-Makefile-*- SUBDIRS += asm -ASM_OBJS = head.o misc.o kernel-wrapper.o rom_entry.o +ASM_OBJS = head.o misc.o kernel-wrapper.o cvc_entry.o ASM=asm/built-in.o # Add extra dependency to the kernel wrapper diff --git a/asm/cvc_entry.S b/asm/cvc_entry.S new file mode 100644 index 0000000..ccca006 --- /dev/null +++ b/asm/cvc_entry.S @@ -0,0 +1,52 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/secureboot/base/rom_entry.S $ +# +# OpenPOWER HostBoot Project +# +# COPYRIGHT International Business Machines Corp. 2013,2016 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +#.include "kernel/ppcconsts.S" + +.section .text + +.global __cvc_verify_v1 +.global call_rom_SHA512 + +__cvc_verify_v1: +call_rom_SHA512: + +call_rom_entry: + std %r2, 40(%r1) + mflr %r0 + std %r0, 16(%r1) + stdu %r1, -128(%r1) + li %r2, 0 + mtctr %r3 + mr %r3, %r4 + mr %r4, %r5 + mr %r5, %r6 + mr %r6, %r7 + mr %r7, %r8 + bctrl + addi %r1, %r1, 128 + ld %r2, 40(%r1) + ld %r0, 16(%r1) + mtlr %r0 + blr + diff --git a/asm/rom_entry.S b/asm/rom_entry.S deleted file mode 100644 index 26d1b96..0000000 --- a/asm/rom_entry.S +++ /dev/null @@ -1,52 +0,0 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/usr/secureboot/base/rom_entry.S $ -# -# OpenPOWER HostBoot Project -# -# COPYRIGHT International Business Machines Corp. 2013,2016 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG - -#.include "kernel/ppcconsts.S" - -.section .text - -.global call_rom_verify -.global call_rom_SHA512 - -call_rom_verify: -call_rom_SHA512: - -call_rom_entry: - std %r2, 40(%r1) - mflr %r0 - std %r0, 16(%r1) - stdu %r1, -128(%r1) - li %r2, 0 - mtctr %r3 - mr %r3, %r4 - mr %r4, %r5 - mr %r5, %r6 - mr %r6, %r7 - mr %r7, %r8 - bctrl - addi %r1, %r1, 128 - ld %r2, 40(%r1) - ld %r0, 16(%r1) - mtlr %r0 - blr - diff --git a/libstb/cvc.c b/libstb/cvc.c index 86d292d..96c48f4 100644 --- a/libstb/cvc.c +++ b/libstb/cvc.c @@ -20,12 +20,20 @@ #include #include +#include #include #include #include #include "secureboot.h" #include "cvc.h" +/* + * Assembly interfaces to call into the Container Verification Code. + * func_ptr: CVC base address + offset + */ +ROM_response __cvc_verify_v1(void *func_ptr, ROM_container_raw *container, + ROM_hw_params *params); + struct container_verification_code { uint64_t start_addr; uint64_t end_addr; @@ -189,6 +197,40 @@ int cvc_init(void) __func__); return -1; } - return rc; } + +int call_cvc_verify(void *container, size_t len, const void *hw_key_hash, + size_t hw_key_hash_size, uint64_t *log) +{ + ROM_hw_params hw_params; + ROM_response rc; + struct cvc_service *service; + + if (!container || len < SECURE_BOOT_HEADERS_SIZE || + !hw_key_hash || hw_key_hash_size <= 0) + return OPAL_PARAMETER; + + service = cvc_find_service(CVC_VERIFY_SERVICE); + + if (!service) + return OPAL_UNSUPPORTED; + + memset(&hw_params, 0, sizeof(ROM_hw_params)); + memcpy(&hw_params.hw_key_hash, hw_key_hash, hw_key_hash_size); + + if (service->version == 1) + rc = __cvc_verify_v1((void*) service->addr, + (ROM_container_raw*) container, + &hw_params); + else + return OPAL_UNSUPPORTED; + + if (log) + *log = hw_params.log; + + if (rc != ROM_DONE) + return OPAL_PARTIAL; + + return OPAL_SUCCESS; +} diff --git a/libstb/cvc.h b/libstb/cvc.h index 3d7079e..14e8cd2 100644 --- a/libstb/cvc.h +++ b/libstb/cvc.h @@ -24,4 +24,24 @@ enum cvc_service_id { int cvc_init(void); +/************************************************************************ + * Wrappers for the services provided by the Container-Verification-Code + ************************************************************************/ + +/* + * call_cvc_verify - Call the CVC-verify service to verify the container fetched + * from PNOR. + * + * @buf - buffer that has the firmware component to be verified + * @size - number of bytes allocated for @buf + * @hw_key_hash - hash of the three harware public keys trusted by the platform + * owner + * @hw_key_hash_size - number of bytes allocated for @hw_key_hash + * @log - hexadecimal returned by the CVC. In case of verification failure, it + * indicates what checking failed + * + */ +int call_cvc_verify(void *buf, size_t size, const void *hw_key_hash, + size_t hw_key_hash_size, uint64_t *log); + #endif /* __CVC_H */ diff --git a/libstb/drivers/romcode.c b/libstb/drivers/romcode.c index 94bd42c..d914ba1 100644 --- a/libstb/drivers/romcode.c +++ b/libstb/drivers/romcode.c @@ -42,7 +42,7 @@ static sha2_hash_t *hw_key_hash = NULL; * func_ptr is the ROM code function address, followed * by additional parameters as necessary */ -ROM_response call_rom_verify(void *func_ptr, ROM_container_raw *container, +ROM_response __cvc_verify_v1(void *func_ptr, ROM_container_raw *container, ROM_hw_params *params); void call_rom_SHA512(void *func_ptr, const uint8_t *data, size_t len, uint8_t *digest); @@ -54,7 +54,7 @@ static int romcode_verify(void *container) memset(&hw_params, 0, sizeof(ROM_hw_params)); memcpy(&hw_params.hw_key_hash, hw_key_hash, sizeof(sha2_hash_t)); - rc = call_rom_verify(romcode_base_addr + ROMCODE_VERIFY_OFFSET, + rc = __cvc_verify_v1(romcode_base_addr + ROMCODE_VERIFY_OFFSET, (ROM_container_raw*) container, &hw_params); if (rc != ROM_DONE) { /* diff --git a/libstb/secureboot.c b/libstb/secureboot.c index cdb6ea5..2787951 100644 --- a/libstb/secureboot.c +++ b/libstb/secureboot.c @@ -21,9 +21,9 @@ #include #include #include +#include +#include #include "secureboot.h" -#include "container.h" -#include "cvc.h" static const void* hw_key_hash = NULL; static size_t hw_key_hash_size; @@ -48,7 +48,7 @@ static void secureboot_enforce(void) * extra info to BMC other than just abort. Terminate Immediate * Attention ? (TI) */ - prlog(PR_EMERG, "enforcing secure mode ...\n"); + prlog(PR_EMERG, "secure mode enforced, aborting.\n"); abort(); } @@ -146,3 +146,49 @@ void secureboot_init(void) if (cvc_init()) secureboot_enforce(); } + +int secureboot_verify(enum resource_id id, void *buf, size_t len) +{ + const char *name; + uint64_t log; + int rc = -1; + + if (!secure_mode) + return 0; + + name = flash_map_resource_name(id); + if (!name) { + prlog(PR_EMERG, "container NOT VERIFIED, resource_id=%d " + "unknown\n", id); + secureboot_enforce(); + } + + rc = call_cvc_verify(buf, len, hw_key_hash, hw_key_hash_size, &log); + + if (rc == OPAL_SUCCESS) { + prlog(PR_INFO, "%s verified\n", name); + } else if (rc == OPAL_PARTIAL) { + /* + * The value returned in log indicates what checking has + * failed. Return codes defined in + * /hostboot/src/include/securerom/status_codes.H + */ + prlog(PR_EMERG, "%s verification FAILED. log=0x%" PRIx64 "\n", + name, be64_to_cpu(log)); + secureboot_enforce(); + } else if (rc == OPAL_PARAMETER) { + prlog(PR_EMERG, "%s NOT VERIFIED, invalid param. buf=%p, " + "len=%zd key-hash=%p hash-size=%zd\n", name, buf, len, + hw_key_hash, hw_key_hash_size); + secureboot_enforce(); + } else if (rc == OPAL_UNSUPPORTED) { + prlog(PR_EMERG, "%s NOT VERIFIED, CVC-verify service not " + "supported\n", name); + secureboot_enforce(); + } else { + prlog(PR_EMERG, "%s NOT VERIFIED, unknown CVC-verify error. " + "rc=%d\n", name, rc); + secureboot_enforce(); + } + return 0; +} diff --git a/libstb/secureboot.h b/libstb/secureboot.h index 6643160..ea97ed7 100644 --- a/libstb/secureboot.h +++ b/libstb/secureboot.h @@ -17,6 +17,7 @@ #ifndef __SECUREBOOT_H #define __SECUREBOOT_H +#include #include #include "container.h" #include "cvc.h" @@ -28,4 +29,20 @@ enum secureboot_version { bool secureboot_is_compatible(struct dt_node *node, int *version, const char **compat); void secureboot_init(void); +/** + * secureboot_verify - verify a PNOR partition content + * @id : PNOR partition id + * @buf : PNOR partition content to be verified + * @len : @buf length + * + * This verifies the integrity and authenticity of @buf downloaded from PNOR if + * secure mode is on. The verification is done by the Container Verification + * Code (CVC) flashed in ROM. + * + * For more information refer to 'doc/stb.rst' + * + * returns: 0 otherwise the boot process is aborted + */ +int secureboot_verify(enum resource_id id, void *buf, size_t len); + #endif /* __SECUREBOOT_H */ -- cgit v1.1