diff options
Diffstat (limited to 'libstb/stb.c')
-rw-r--r-- | libstb/stb.c | 328 |
1 files changed, 0 insertions, 328 deletions
diff --git a/libstb/stb.c b/libstb/stb.c deleted file mode 100644 index f798bcb..0000000 --- a/libstb/stb.c +++ /dev/null @@ -1,328 +0,0 @@ -/* Copyright 2013-2016 IBM Corp. - * - * 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. - */ - -#include <skiboot.h> -#include <device.h> -#include <platform.h> -#include <string.h> -#include <stdio.h> -#include <nvram.h> -#include "stb.h" -#include "status_codes.h" -#include "container.h" -#include "rom.h" -#include "tpm_chip.h" - -/* For debugging only */ -//#define STB_DEBUG -//#define STB_FORCE_SECURE_MODE -//#define STB_FORCE_TRUSTED_MODE - -static bool secure_mode = false; -static bool trusted_mode = false; - -static struct rom_driver_ops *rom_driver = NULL; - -#define MAX_RESOURCE_NAME 15 - -/* - * This maps a PCR for each resource we can measure. The PCR number is - * mapped according to the TCG PC Client Platform Firmware Profile - * specification, Revision 00.21 - * Only resources included in this whitelist can be measured. - */ -static struct { - - /* PNOR partition id */ - enum resource_id id; - - /* PCR mapping for the resource id */ - TPM_Pcr pcr; - - /* Resource name */ - const char name[MAX_RESOURCE_NAME+1]; - -} resource_map[] = { - { RESOURCE_ID_KERNEL, PCR_4, "BOOTKERNEL" }, - { RESOURCE_ID_CAPP, PCR_2, "CAPP"}, -}; - -struct event_hash { - const unsigned char *sha1; - const unsigned char *sha256; -}; - -/* - * Event Separator - digest of 0xFFFFFFFF - */ -static struct event_hash evFF = { - .sha1 = "\xd9\xbe\x65\x24\xa5\xf5\x04\x7d\xb5\x86" - "\x68\x13\xac\xf3\x27\x78\x92\xa7\xa3\x0a", - - .sha256 = "\xad\x95\x13\x1b\xc0\xb7\x99\xc0\xb1\xaf" - "\x47\x7f\xb1\x4f\xcf\x26\xa6\xa9\xf7\x60" - "\x79\xe4\x8b\xf0\x90\xac\xb7\xe8\x36\x7b" - "\xfd\x0e" -}; - -static int stb_resource_lookup(enum resource_id id) -{ - int i; - for (i = 0; i < ARRAY_SIZE(resource_map); i++) - if (resource_map[i].id == id) - return i; - return -1; -} - -static void sb_enforce(void) -{ - /* - * TODO: Ideally, the BMC should decide what security policy to apply - * (power off, reboot, switch PNOR sides, etc). We may need - * to provide extra info to BMC other than just abort. - * Terminate Immediate Attention ? (TI) - */ - prlog(PR_EMERG, "STB: Secure mode enforced, aborting.\n"); - abort(); -} - -void stb_init(void) -{ - struct dt_node *ibm_secureboot; - /* - * The ibm,secureboot device tree properties are documented in - * 'doc/device-tree/ibm,secureboot.rst' - */ - ibm_secureboot = dt_find_by_path(dt_root, "/ibm,secureboot"); - if (ibm_secureboot == NULL) { - prlog(PR_NOTICE,"STB: secure and trusted boot not supported\n"); - return; - } - -#ifdef STB_FORCE_SECURE_MODE - secure_mode = true; - prlog(PR_NOTICE, "STB: secure mode on (forced!)\n"); -#else - secure_mode = dt_has_node_property(ibm_secureboot, "secure-enabled", - NULL); - - if (nvram_query_eq("force-secure-mode", "always")) { - prlog(PR_NOTICE, "STB: secure mode on (FORCED by nvram)\n"); - secure_mode = true; - } else if (secure_mode) { - prlog(PR_NOTICE, "STB: secure mode on.\n"); - } else { - prlog(PR_NOTICE, "STB: secure mode off\n"); - } -#endif - -#ifdef STB_FORCE_TRUSTED_MODE - trusted_mode = true; - prlog(PR_NOTICE, "STB: trusted mode on (forced!)\n"); -#else - trusted_mode = dt_has_node_property(ibm_secureboot, "trusted-enabled", - NULL); - if (nvram_query_eq("force-trusted-mode", "true")) { - prlog(PR_NOTICE, "STB: trusted mode ON (from NVRAM)\n"); - trusted_mode = true; - } - prlog(PR_NOTICE, "STB: trusted mode %s\n", - trusted_mode ? "on" : "off"); -#endif - - if (!secure_mode && !trusted_mode) - return; - rom_driver = rom_init(ibm_secureboot); - if (secure_mode && !rom_driver) { - prlog(PR_EMERG, "STB: compatible romcode driver not found\n"); - sb_enforce(); - } - if (trusted_mode) - tpm_init(); -} - -int stb_final(void) -{ - uint32_t pcr; - int rc; - bool failed; - - rc = 0; - failed = false; - - if (trusted_mode) { -#ifdef STB_DEBUG - prlog(PR_NOTICE, "STB: evFF.sha1:\n"); - stb_print_data((uint8_t*) evFF.sha1, TPM_ALG_SHA1_SIZE); - prlog(PR_NOTICE, "STB: evFF.sha256:\n"); - stb_print_data((uint8_t*) evFF.sha256, TPM_ALG_SHA256_SIZE); -#endif - /* - * We are done. Extending the digest of 0xFFFFFFFF - * in PCR[0-7], and recording an EV_SEPARATOR event in - * event log as defined in the TCG Platform Firmware Profile - * specification, Revision 00.21 - */ - for (pcr = 0; pcr < 8; pcr++) { - rc = tpm_extendl(pcr, TPM_ALG_SHA256, - (uint8_t*) evFF.sha256, - TPM_ALG_SHA256_SIZE, TPM_ALG_SHA1, - (uint8_t*) evFF.sha1, - TPM_ALG_SHA1_SIZE, EV_SEPARATOR, - "Skiboot Boot"); - if (rc) - failed = true; - } - tpm_add_status_property(); - } - if (rom_driver) { - rom_driver->cleanup(); - rom_driver = NULL; - } - tpm_cleanup(); - secure_mode = false; - trusted_mode = false; - return (failed) ? STB_MEASURE_FAILED : 0; -} - -int tb_measure(enum resource_id id, void *buf, size_t len) -{ - int r; - uint8_t digest[SHA512_DIGEST_LENGTH]; - const uint8_t *digestp; - - digestp = NULL; - if (!trusted_mode) { - prlog(PR_INFO, "STB: %s skipped resource %d, " - "trusted_mode=0\n", __func__, id); - return STB_TRUSTED_MODE_DISABLED; - } - r = stb_resource_lookup(id); - if (r == -1) { - /** - * @fwts-label STBMeasureResourceNotMapped - * @fwts-advice The resource is not registered in the resource_map[] - * array, but it should be otherwise the resource cannot be - * measured if trusted mode is on. - */ - prlog(PR_ERR, "STB: %s failed, resource %d not mapped\n", - __func__, id); - return STB_ARG_ERROR; - } - if (!buf) { - /** - * @fwts-label STBNullResourceReceived - * @fwts-advice Null resource passed to tb_measure. This has - * come from the resource load framework and likely indicates a - * bug in the framework. - */ - prlog(PR_ERR, "STB: %s failed: resource %s, buf null\n", - __func__, resource_map[r].name); - return STB_ARG_ERROR; - } - memset(digest, 0, SHA512_DIGEST_LENGTH); - /* - * In secure mode we can use the sw-payload-hash from the container - * header to measure the container payload. Otherwise we must calculate - * the hash of the container payload (if it's a container) or the image - * (if it's not a container) - */ - if (stb_is_container(buf, len)) { - digestp = stb_sw_payload_hash(buf, len); - if(!digestp) { - prlog(PR_EMERG, "STB Container is corrupt, can't find hash\n"); - abort(); - } - - rom_driver->sha512( - (void*)((uint8_t*)buf + SECURE_BOOT_HEADERS_SIZE), - len - SECURE_BOOT_HEADERS_SIZE, digest); - - prlog(PR_INFO, "STB: %s sha512 hash re-calculated\n", - resource_map[r].name); - if (memcmp(digestp, digest, TPM_ALG_SHA256_SIZE) != 0) { - prlog(PR_ALERT, "STB: HASH IN CONTAINER DOESN'T MATCH CONTENT!\n"); - prlog(PR_ALERT, "STB: Container hash:\n"); - stb_print_data(digestp, TPM_ALG_SHA256_SIZE); - prlog(PR_ALERT, "STB: Computed hash (on %lx bytes):\n", len); - stb_print_data(digest, TPM_ALG_SHA256_SIZE); - - if (secure_mode) - abort(); - } - } else { - rom_driver->sha512(buf, len, digest); - prlog(PR_INFO, "STB: %s sha512 hash calculated\n", - resource_map[r].name); - } - -#ifdef STB_DEBUG - /* print the payload/image hash */ - prlog(PR_NOTICE, "STB: %s hash:\n", resource_map[r].name); - stb_print_data(digest, TPM_ALG_SHA256_SIZE); -#endif - /* - * Measure the resource. Since the ROM code doesn't provide a sha1 hash - * algorithm, the sha512 hash is truncated to match the size required - * by each PCR bank. - */ - return tpm_extendl(resource_map[r].pcr, - TPM_ALG_SHA256, digest, TPM_ALG_SHA256_SIZE, - TPM_ALG_SHA1, digest, TPM_ALG_SHA1_SIZE, - EV_ACTION, resource_map[r].name); -} - -int sb_verify(enum resource_id id, void *buf, size_t len) -{ - int r; - const char *name = NULL; - - if (!secure_mode) { - prlog(PR_INFO, "STB: %s skipped resource %d, " - "secure_mode=0\n", __func__, id); - return STB_SECURE_MODE_DISABLED; - } - r = stb_resource_lookup(id); - if (r == -1) - /** - * @fwts-label STBVerifyResourceNotMapped - * @fwts-advice Unregistered resources can be verified, but not - * measured. The resource should be registered in the - * resource_map[] array, otherwise the resource cannot be - * measured if trusted mode is on. - */ - prlog(PR_WARNING, "STB: verifying the non-expected " - "resource %d\n", id); - else - name = resource_map[r].name; - if (!rom_driver || !rom_driver->verify) { - prlog(PR_EMERG, "STB: secure boot not initialized\n"); - sb_enforce(); - } - if (!buf || len < SECURE_BOOT_HEADERS_SIZE) { - prlog(PR_EMERG, "STB: %s arg error: id %d, buf %p, len %zd\n", - __func__, id, buf, len); - sb_enforce(); - } - if (rom_driver->verify(buf)) { - prlog(PR_EMERG, "STB: %s failed: resource %s, " - "eyecatcher 0x%016llx\n", __func__, name, - *((uint64_t*)buf)); - sb_enforce(); - } - prlog(PR_NOTICE, "STB: %s verified\n", name); - return 0; -} |