diff options
author | Claudio Carvalho <cclaudio@linux.vnet.ibm.com> | 2017-12-09 02:52:19 -0200 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-12-18 21:30:57 -0600 |
commit | 3ab91fbec937830f184108a244795a2e05cb275c (patch) | |
tree | b98fb42fb1d4d72cc88c669a9bef4a1cf19c4131 /libstb | |
parent | 060ff18d4ddcfb87e9aa31fc5eadaf4318bca9bb (diff) | |
download | skiboot-3ab91fbec937830f184108a244795a2e05cb275c.zip skiboot-3ab91fbec937830f184108a244795a2e05cb275c.tar.gz skiboot-3ab91fbec937830f184108a244795a2e05cb275c.tar.bz2 |
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 <cclaudio@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'libstb')
-rw-r--r-- | libstb/cvc.c | 44 | ||||
-rw-r--r-- | libstb/cvc.h | 20 | ||||
-rw-r--r-- | libstb/drivers/romcode.c | 4 | ||||
-rw-r--r-- | libstb/secureboot.c | 52 | ||||
-rw-r--r-- | libstb/secureboot.h | 17 |
5 files changed, 131 insertions, 6 deletions
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 <skiboot.h> #include <string.h> +#include <opal-api.h> #include <chip.h> #include <xscom.h> #include <inttypes.h> #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 <skiboot.h> #include <device.h> #include <nvram.h> +#include <opal-api.h> +#include <inttypes.h> #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 <platform.h> #include <device.h> #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 */ |