[Skiboot] [PATCH 08/15] libstb: Add secure boot header structures
Claudio Carvalho
cclaudio at linux.vnet.ibm.com
Thu Sep 22 13:57:31 AEST 2016
On 09/14/2016 06:25 AM, Stewart Smith wrote:
> Claudio Carvalho <cclaudio at linux.vnet.ibm.com> writes:
>> This adds the secure boot header structures required by the secure and
>> trusted boot implementation in skiboot, and also implements some helper
>> routines related to containers.
>>
>> Signed-off-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
>> ---
>> Makefile.main | 3 +-
>> libstb/Makefile.inc | 11 +++++
>> libstb/container.c | 75 ++++++++++++++++++++++++++++
>> libstb/container.h | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 4 files changed, 227 insertions(+), 1 deletion(-)
>> create mode 100644 libstb/Makefile.inc
>> create mode 100644 libstb/container.c
>> create mode 100644 libstb/container.h
>
> This looks like a good candidate for a small unit test with some input
> data, preferably something that can be fuzzed (feel free to add test
> cases produced by afl-fuzz)
>
>> diff --git a/Makefile.main b/Makefile.main
>> index 159ce26..cc6cfdf 100644
>> --- a/Makefile.main
>> +++ b/Makefile.main
>> @@ -145,6 +145,7 @@ include $(SRC)/libpore/Makefile.inc
>> include $(SRC)/libc/Makefile.inc
>> include $(SRC)/ccan/Makefile.inc
>> include $(SRC)/$(DEVSRC)/Makefile.inc
>> +include $(SRC)/libstb/Makefile.inc
>>
>> # hack for travis-ci and coverity
>> gard:
>> @@ -158,7 +159,7 @@ pflash-coverity:
>>
>> all: $(SUBDIRS) $(TARGET).lid $(TARGET).lid.xz $(TARGET).map extract-gcov
>>
>> -OBJS := $(ASM) $(CORE) $(HW) $(PLATFORMS) $(LIBFDT) $(LIBFLASH)
>> +OBJS := $(ASM) $(CORE) $(HW) $(PLATFORMS) $(LIBFDT) $(LIBFLASH) $(LIBSTB)
>> ifeq ($(PORE),1)
>> OBJS += $(LIBPORE)
>> endif
>> diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc
>> new file mode 100644
>> index 0000000..15cdfbe
>> --- /dev/null
>> +++ b/libstb/Makefile.inc
>> @@ -0,0 +1,11 @@
>> +# -*-Makefile-*-
>> +
>> +LIBSTB_DIR = libstb
>> +
>> +SUBDIRS += $(LIBSTB_DIR)
>> +
>> +LIBSTB_SRCS = container.c
>> +LIBSTB_OBJS = $(LIBSTB_SRCS:%.c=%.o)
>> +LIBSTB = $(LIBSTB_DIR)/built-in.o
>> +
>> +$(LIBSTB): $(LIBSTB_OBJS:%=$(LIBSTB_DIR)/%)
>> diff --git a/libstb/container.c b/libstb/container.c
>> new file mode 100644
>> index 0000000..efa8511
>> --- /dev/null
>> +++ b/libstb/container.c
>> @@ -0,0 +1,75 @@
>> +/* 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 "container.h"
>> +
>> +const uint32_t* stb_payload_magic(const void *buf)
>> +{
>> + if (!stb_is_container(buf))
>> + return NULL;
>> +
>> + return (const uint32_t*) ((uint8_t*)buf + SECURE_BOOT_HEADERS_SIZE);
>> +}
>> +
>> +bool stb_is_container(const void *buf)
>> +{
>> + if (!buf)
>> + return false;
>> +
>> + if ( *((uint32_t*) buf) != ROM_MAGIC_NUMBER )
>> + return false;
>> +
>> + return true;
>> +}
>> +
>> +const sha2_hash_t* stb_sw_payload_hash(const void *buf)
>> +{
>> + const ROM_prefix_header_raw* prefix;
>> + const ROM_prefix_data_raw* hw_data;
>> + const ROM_sw_header_raw* header;
>> +
>> + if (!stb_is_container(buf))
>> + return NULL;
>> +
>> + prefix = (ROM_prefix_header_raw*) &((ROM_container_raw*)buf)->prefix;
>> + hw_data = (ROM_prefix_data_raw*) (prefix->ecid +
>> + prefix->ecid_count*ECID_SIZE);
>> + header = (ROM_sw_header_raw*) (hw_data->sw_pkey_p +
>> + prefix->sw_key_count*sizeof(ecc_key_t));
>> +
>> + return &header->payload_hash;
>> +}
>> +
>> +void stb_print_data(const void* data, size_t len)
>> +{
>> + int i, j;
>> + unsigned char *p;
>> + unsigned char hash[30];
>> +
>> + p = (unsigned char*) data;
>> + j = 0;
>> + for (i = 0; i < len; i++) {
>> + if (!(i%10) && i) {
>> + prlog(PR_NOTICE, "%s\n", hash);
>> + j=0;
>> + }
>> + snprintf(&hash[j], 30-j, "%02x ", p[i]);
>> + j+=3;
>> + }
>> + prlog(PR_NOTICE, "%s\n", hash);
>> +}
>> diff --git a/libstb/container.h b/libstb/container.h
>> new file mode 100644
>> index 0000000..8062ae1
>> --- /dev/null
>> +++ b/libstb/container.h
>> @@ -0,0 +1,139 @@
>> +/* 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.
>> + */
>> +
>> +#ifndef __STB_CONTAINER_H
>> +#define __STB_CONTAINER_H
>> +
>> +#include <stdint.h>
>> +
>> +#define SECURE_BOOT_HEADERS_SIZE 4096
>> +
>> +#define SHA256_DIGEST_LENGTH 32
>> +
>> +/**
>> + * The defines and structures below come from the secure ROM source code
>> + * (trusted_boot_rom). Here you will find only the ones required by the
>> + * secure and trusted boot implementation in skiboot.
>> + */
>> +
>> +/* From trusted_boot_rom/src/sha512.h */
>> +#define SHA512_DIGEST_LENGTH 64
>> +typedef uint8_t __attribute__((aligned(8))) sha2_hash_t[ SHA512_DIGEST_LENGTH / sizeof(uint8_t) ];
>> +typedef uint8_t sha2_byte; // Exactly 1 byte
>> +
>> +/* From trusted_boot_rom/src/hw_utils.h */
>> +#define ECID_SIZE 16
>> +
>> +/* From trusted_boot_rom/src/ecverify.h */
>> +#define EC_COORDBYTES 66 /* P-521 */
>> +typedef uint8_t ecc_key_t[2*EC_COORDBYTES];
>> +typedef uint8_t ecc_signature_t[2*EC_COORDBYTES];
>> +
>> +/* From trusted_boot_rom/src/ROM.h */
>> +#define ROM_MAGIC_NUMBER 0x17082011
>> +
>> +typedef struct {
>> + uint16_t version; /* (1: see versions above) */
>> + uint8_t hash_alg; /* (1: SHA-512) */
>> + uint8_t sig_alg; /* (1: SHA-512/ECDSA-521) */
>> +}__attribute__((packed)) ROM_version_raw;
>> +
>> +typedef struct {
>> + uint32_t magic_number; /* (17082011) */
>> + uint16_t version; /* (1: see versions above) */
>> + uint64_t container_size;/* filled by caller */
>> + uint64_t target_hrmor; /* filled by caller */
>> + uint64_t stack_pointer; /* filled by caller */
>> + /* bottom of stack -> 128k added by rom code to get real stack pointer */
>> + ecc_key_t hw_pkey_a;
>> + ecc_key_t hw_pkey_b;
>> + ecc_key_t hw_pkey_c;
>> + uint64_t prefix; /* prefix header place holder */
>> + /* followed by sw header (if not special prefix) */
>> + /* followed by optional unprotected payload data */
>> +}__attribute__((packed)) ROM_container_raw;
>> +
>> +typedef struct {
>> + ROM_version_raw ver_alg;
>> + uint64_t code_start_offset;
>> + uint64_t reserved;
>> + uint32_t flags;
>> + uint8_t sw_key_count;
>> + uint64_t payload_size;
>> + sha2_hash_t payload_hash;
>> + uint8_t ecid_count;
>> + uint8_t ecid[ECID_SIZE]; /* optional ecid place
>> + holder ecid_count * ecid_size(128 bits) */
>> + /* followed by prefix data (sig,keys) key raw */
>> +}__attribute__((packed)) ROM_prefix_header_raw;
>> +
>> +typedef struct {
>> + ecc_signature_t hw_sig_a;
>> + ecc_signature_t hw_sig_b;
>> + ecc_signature_t hw_sig_c;
>> + ecc_key_t sw_pkey_p;
>> + ecc_key_t sw_pkey_q;
>> + ecc_key_t sw_pkey_r;
>> +}__attribute__((packed)) ROM_prefix_data_raw;
>> +
>> +typedef struct {
>> + ROM_version_raw ver_alg;
>> + uint64_t code_start_offset;
>> + uint64_t reserved;
>> + uint32_t flags;
>> + uint8_t reserved_0;
>> + uint64_t payload_size;
>> + sha2_hash_t payload_hash;
>> + uint8_t ecid_count;
>> + uint8_t ecid[ECID_SIZE]; /* optional ecid place
>> + holder ecid_count * ecid_size(128 bits) */
>> + /* followed by sw sig raw */
>> +}__attribute__((packed)) ROM_sw_header_raw;
>> +
>> +typedef struct {
>> + ecc_signature_t sw_sig_p;
>> + ecc_signature_t sw_sig_q;
>> + ecc_signature_t sw_sig_r;
>> + /* followed by zero's padding to 4K */
>> + /* followed by protected sw payload_data */
>> + /* followed by unprotected sw payload_text */
>> +}__attribute__((packed)) ROM_sw_sig_raw;
>> +
>> +typedef enum { ROM_DONE, ROM_FAILED, PHYP_PARTIAL } ROM_response;
>> +
>> +typedef struct {
>> + sha2_hash_t hw_key_hash;
>> + uint8_t my_ecid[ECID_SIZE];
>> + uint64_t entry_point;
>> + uint64_t log;
>> +}__attribute__((packed)) ROM_hw_params;
>> +
>> +/**
>> + * Helper functions
>> + */
>> +
>> +/* Get the pointer for the container payload eyecatcher */
>> +const uint32_t* stb_payload_magic(const void *buf);
>> +
>> +/* Check if buf is a secure boot container */
>> +bool stb_is_container(const void* buf);
>> +
>> +/* Get the pointer for the sw-payload-hash field of the container header */
>> +const sha2_hash_t* stb_sw_payload_hash(const void* buf);
>
> I generally like a size_t parameter to go along with any void* buf, at
> least as a sanity check.
size_t parameter added to each of these functions.
>
> Later on, in tb_measure(), if buf was, say len=1, then you'd access
> beyond the end of the buffer (and hope that what's after the buffer
> wasn't magically something that was kind of valid or could be
> manipulated to do something bad), when instead you should error out.
>
More information about the Skiboot
mailing list