[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