From d0f63ef62c76c932a2003eaa42c0b250065ae06f Mon Sep 17 00:00:00 2001 From: Ed Tanous Date: Wed, 31 Jul 2019 10:43:37 -0700 Subject: Update to internal 7-31-19 Signed-off-by: Ed Tanous --- .../recipes-intel/intel-pfr/files/blocksign | Bin 0 -> 58104 bytes .../recipes-intel/intel-pfr/files/bmc_config.xml | 47 ++++ .../recipes-intel/intel-pfr/files/csk_prv.pem | 8 + .../recipes-intel/intel-pfr/files/csk_pub.pem | 4 + .../recipes-intel/intel-pfr/files/pfm_config.xml | 47 ++++ .../intel-pfr/files/pfr_image-manifest.json | 63 +++++ .../recipes-intel/intel-pfr/files/pfr_image.py | 311 +++++++++++++++++++++ .../recipes-intel/intel-pfr/files/rk_prv.pem | 8 + .../recipes-intel/intel-pfr/files/rk_pub.pem | 4 + .../intel-pfr/intel-pfr-manager_git.bb | 22 ++ .../intel-pfr/obmc-intel-pfr-image-native.bb | 38 +++ 11 files changed, 552 insertions(+) create mode 100755 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/blocksign create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/bmc_config.xml create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/csk_prv.pem create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/csk_pub.pem create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfm_config.xml create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image-manifest.json create mode 100755 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/rk_prv.pem create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/rk_pub.pem create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-pfr-manager_git.bb create mode 100644 meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/obmc-intel-pfr-image-native.bb (limited to 'meta-openbmc-mods/meta-common/recipes-intel/intel-pfr') diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/blocksign b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/blocksign new file mode 100755 index 000000000..69d51d2ba Binary files /dev/null and b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/blocksign differ diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/bmc_config.xml b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/bmc_config.xml new file mode 100644 index 000000000..89c3d30ca --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/bmc_config.xml @@ -0,0 +1,47 @@ + + + + + + 0xB6EAFD19 + 4 + + + + 0xF27F28D7 + + + 0xA757A046 + 0xC7B88C74 + -1 + -1 + rk_pub.pem + + + + 0x14711C2F + 0xC7B88C74 + 8 + 1 + csk_pub.pem + 0xDE64437D + sha256 + rk_prv.pem + + + + + 0x15364367 + 0xDE64437D + sha256 + csk_prv.pem + + + + + + 1024 + + 128 + + diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/csk_prv.pem b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/csk_prv.pem new file mode 100644 index 000000000..a46fa2a2b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/csk_prv.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIFjPqxcb6tfFWyFVaQCVjeN9MtcISpYIbNlkQoODrHTUoAoGCCqGSM49 +AwEHoUQDQgAERGJveRnhIp7I5cvmjO74MJLbUJjTfvTDKlzK0hJB0WRBEFScpb9d +xWLrwj9TNcO+EexnNcjEkF1RYNs6lHavRQ== +-----END EC PRIVATE KEY----- diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/csk_pub.pem b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/csk_pub.pem new file mode 100644 index 000000000..cc70d6e28 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/csk_pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERGJveRnhIp7I5cvmjO74MJLbUJjT +fvTDKlzK0hJB0WRBEFScpb9dxWLrwj9TNcO+EexnNcjEkF1RYNs6lHavRQ== +-----END PUBLIC KEY----- diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfm_config.xml b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfm_config.xml new file mode 100644 index 000000000..215fe8783 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfm_config.xml @@ -0,0 +1,47 @@ + + + + + + 0xB6EAFD19 + 3 + + + + 0xF27F28D7 + + + 0xA757A046 + 0xC7B88C74 + -1 + -1 + rk_pub.pem + + + + 0x14711C2F + 0xC7B88C74 + 4 + 1 + csk_pub.pem + 0xDE64437D + sha256 + rk_prv.pem + + + + + 0x15364367 + 0xDE64437D + sha256 + csk_prv.pem + + + + + + 1024 + + 128 + + diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image-manifest.json b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image-manifest.json new file mode 100644 index 000000000..7890aa700 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image-manifest.json @@ -0,0 +1,63 @@ +{ + "image-parts": [{ + "name": "u-boot", + "index": 0, + "offset": "0", + "size": "0x80000", + "prot_mask": 31, + "pfm": 1, + "hash": 1, + "compress": 1 + }, + { + "name": "pfm", + "index": 1, + "offset": "0x80000", + "size": "0x20000", + "prot_mask": 31, + "pfm": 1, + "hash": 0, + "compress": 0 + }, + { + "name": "u-boot-env", + "index": 2, + "offset": "0xa0000", + "size": "0x20000", + "prot_mask": 29, + "pfm": 1, + "hash": 0, + "compress": 0 + }, + { + "name": "sofs", + "index": 3, + "offset": "0xc0000", + "size": "0x200000", + "prot_mask": 29, + "pfm": 1, + "hash": 0, + "compress": 0 + }, + { + "name": "rwfs", + "index": 4, + "offset": "0x2c0000", + "size": "0x840000", + "prot_mask": 29, + "pfm": 1, + "hash": 0, + "compress": 0 + }, + { + "name": "fit-image-a", + "index": 5, + "offset": "0xb00000", + "size": "0x1f00000", + "prot_mask": 31, + "pfm": 1, + "hash": 1, + "compress": 1 + } + ] +} \ No newline at end of file diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py new file mode 100755 index 000000000..e1a23c172 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py @@ -0,0 +1,311 @@ +#/usr/bin/env python3 +# coding: utf-8 +# our image is contained as parts, including the hash +# then it gets zipped up and signed again + +# this internal signature is for boot and recovery, but +# will be checked prior to writing to flash as well. + +# the internal signature format is a PFR-specific block +# including a hash bitmap, certificates (public keys), +# and the actual signature data as well, for both active +# and recovery images + +# TODO: figure out if active and recovery actually have different sigs +# TODO: build hashmap from payload manifest +# TODO: figure out exact struct layout for PFR metadata + +import os, hashlib, struct, json, sys, subprocess, mmap, io, array, binascii, copy, shutil, re +from array import array +from binascii import unhexlify +from six import b, print_, binary_type +from hashlib import sha1, sha256, sha512 +from shutil import copyfile +# Flash Map +# ----------------------------------------------- +# Start addr Contents +# 0x00000000 S U-Boot +# 0x00080000 S+ PFM +# 0x000a0000 U U-boot Env +# 0x000C0000 U SOFS +# 0x002c0000 U RWFS +# 0x00b00000 S fit-image +# 0x02a00000 S+ rc-image +# 0x04a00000 U staging-image +# * partially signed (not full 64k page) +# + unsigned, owned by pfr + +# TODO: The below defines should go to manifest files. +# Keeping it here hard coded for now. +# The pages to be skipped for HASH and PBC +# Pages: 0x80 to 0xaff - starting PFM region until fit-image +# Pages: 0x2a00 to 0x7FFF - starting RC-image until end of flash +EXCLUDE_PAGES =[[0x80, 0xaff],[0x2a00,0x7fff]] + +# SPI PFM globals +PFM_OFFSET = 0x80000 +PFM_SPI = 0x1 +SHA256 = 0x1 +SHA256_SIZE = 32 +PFM_DEF_SIZE = 16 +PFM_SPI_SIZE_DEF = 16 # 16 bytes of SPI PFM +PFM_SPI_SIZE_HASH = 32 # 32 bytes of SPI region HASH + +PAGE_SIZE = 0x1000 # 4KB size of page + +def load_manifest(fname): + manifest = {} + with open(fname, 'r') as fd: + manifest = json.load(fd) + return manifest + +class pfm_spi(object): + + def __init__(self, prot_mask, start_addr, end_addr, hash, hash_pres): + self.pfm = PFM_SPI + self.prot_mask = prot_mask + self.hash_pres = hash_pres + if hash_pres == 1: + self.spi_hash = hash + self.pfm_rsvd = 0xffffffff #b'\xff'*4 + self.start_addr = start_addr + self.end_addr = end_addr + + +class pfr_bmc_image(object): + +# json_file, update_file + def __init__(self, manifest, update_file, build_ver, build_num, build_hash): + + self.manifest = load_manifest(manifest) + self.update_file = update_file + self.build_version = build_ver + self.build_number = build_num + self.build_hash = build_hash + + self.pfr_rom_file = 'image-mtd-pfr' + open(self.pfr_rom_file, 'a').close() + + self.page_size = PAGE_SIZE + self.empty = b'\xff' * self.page_size + + self.image_parts = [] + for p in self.manifest['image-parts']: + # the json should have in the order- filename, index, offset, size and protection byte + self.image_parts.append((p['name'], p['index'], p['offset'], p['size'], p['prot_mask'], p['pfm'], p['hash'], p['compress'])) + print(self.image_parts) + + self.act_dgst = hashlib.sha256() + + # SPI regions PFM array + self.pfm_spi_regions = [] + self.pfm_bytes = PFM_DEF_SIZE # PFM definition bytes (SPI regions + SMBUS) + + # hash, erase and compression bit maps for 128MB + self.pbc_erase_bitmap = bytearray(4096) + self.pbc_comp_bitmap = bytearray(4096) + + self.pbc_comp_payload = 0 + self.sec_rev = 1 + + # fill in the calculated data + self.hash_and_map() + + def hash_compress_regions(self, p, upd): + + # JSON format as below + # 0. "name": + # 1. "index": 1, + # 2. "offset": , + # 3. "size": , + # 4. "prot_mask": , + # 5. "pfm": <1|0 -add in PFM or not>, + # 6. "hash": , + # 7. "compress": + + image_name = p[0] + start_addr = int(p[2],16) #image part start address + size = int(p[3],16) #size of the image part + pfm_prot_mask = p[4] # pfm protection mask + pfm_flag = p[5] # pfm needed? + hash_flag = p[6] #to be hashed? + compress = p[7] #compress flag + index = p[1] # image part index + # 1 page is 4KB + page = start_addr >> 12 + + if hash_flag == 1: + with open(self.update_file, "rb") as f: + f.seek(start_addr) + skip = False + # HASH for the region + hash_dgst = hashlib.sha256() + for chunk in iter(lambda: f.read(self.page_size), b''): + chunk_len = len(chunk) + if chunk_len != self.page_size: + chunk = b''.join([chunk, b'\xff' * (self.page_size - chunk_len)]) + + for p in EXCLUDE_PAGES: + if (page >= p[0]) and (page <= p[1]): + print("Exclude page={}".format(page)) + skip = True + break + + if not skip: + # add to the hash + self.act_dgst.update(chunk) + hash_dgst.update(chunk) + self.pbc_erase_bitmap[page >> 3] |= 1 << (7- (page % 8)) # Big endian bit map + + if compress == 1: + # add to the pbc map + if chunk != self.empty: + print("compressed page ={}".format(page)) + upd.write(chunk) + self.pbc_comp_bitmap[page >> 3] |= 1 << (7- (page % 8)) # Big Endian bit map + self.pbc_comp_payload += chunk_len # compressed payload bytes + + page += 1 + + if (page * self.page_size) >= (size + start_addr): + break + + if pfm_flag == 1: + self.pfm_bytes += PFM_SPI_SIZE_DEF + + hash = b'\x00' * 32 + hash_pres = 0 + + if hash_flag == 1: + # region's hash + hash = hash_dgst.hexdigest() + hash_pres = SHA256 + self.pfm_bytes += PFM_SPI_SIZE_HASH + + # append to SPI regions in PFM + self.pfm_spi_regions.append(pfm_spi(pfm_prot_mask, start_addr, (start_addr+size), hash, hash_pres)) + + def hash_and_map(self): + + # have copy of the update file for appending with PFR meta and compression + copyfile(self.update_file, self.pfr_rom_file) + with open("bmc_compressed.bin", "wb+") as upd: + for p in self.image_parts: + #filename, index, offset, size, protection. + print(p[0], p[1], p[2], p[3], p[4]) + self.hash_compress_regions(p, upd) + + # Generate PFM region binary - pfm.bin + self.build_pfm() + print("PFM build done") + + # Generate PBC region - pbc.bin + self.pbc_hdr() + print("PBC build done") + + def pbc_hdr(self): + ''' + typedef struct { + uint8_t tag[4]; /* PBC tag */ + uint32_t version; /* PBC Version- 0x0000_0002 */ + uint32_t page_size; /* NOR Flash page size = 0x0000_1000 */ + uint32_t pattern_size; /* 0xFF as pattern 1byte = 0x0000_0001 */ + uint32_t pattern; /* 0xFF pattern = 0x0000_00FF */ + uint32_t bitmap_size; /* 32768 pages for 128MB- 0x0000_8000 */ + uint32_t payload_length /* payload */ + uint8_t reserved[100]; /* Reserved 100bytes */ + uint8_t erase_bitmap[4096]; /* erase bit map for 32768 pages */ + uint8_t comp_bitmap[4096]; /* compression bit map for 32768 pages */ + uint8_t comp_payload; /* compressed payload */ + ''' + names = [ + 'tag', 'pbc_ver', 'page_sz', 'pattern_sz', 'pattern', 'bitmap_sz', + 'payload_size', 'resvd0', 'erase_bitmap', 'comp_bitmap', + ] + parts = { + 'tag': b'CBP_', + 'pbc_ver': struct.pack('> 8) & 0xff)), + 'pfm_ver_minor': struct.pack('> 8) & 0xff), + 'build_hash3': struct.pack('> 16) & 0xff), + 'resvd0': b'\xff'* 1, + 'pfm_len': '' + } + + # PFM should be 128bytes aligned, find the padding bytes + padding_bytes = 128 - (self.pfm_bytes % 128) + self.pfm_bytes += padding_bytes + parts['pfm_len'] = struct.pack(' + print('usage: {} '.format(sys.argv[0])) + return + + json_file = sys.argv[1] + update_file = sys.argv[2] + build_ver = sys.argv[3] + build_num = sys.argv[4] + build_hash = sys.argv[5] + + # function to generate BMC PFM, PBC header and BMC compressed image + pfr_bmc_image(json_file, update_file, build_ver, build_num, build_hash) + +if __name__ == '__main__': + main() diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/rk_prv.pem b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/rk_prv.pem new file mode 100644 index 000000000..9e8616795 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/rk_prv.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHVbq5CmT4Vr4Jb0eJK0+KhUxDOWy1kh9QYAClV5MH1GoAoGCCqGSM49 +AwEHoUQDQgAEZUL6ZcF0YN590Pq/bKPYjfa3F4E44XiKcqvS6+l2GfSdCLRhXWHw +iV803vFkTsZ1CfpzFdZGwfbwg7nvG5UpSQ== +-----END EC PRIVATE KEY----- diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/rk_pub.pem b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/rk_pub.pem new file mode 100644 index 000000000..117e08bae --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/rk_pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZUL6ZcF0YN590Pq/bKPYjfa3F4E4 +4XiKcqvS6+l2GfSdCLRhXWHwiV803vFkTsZ1CfpzFdZGwfbwg7nvG5UpSQ== +-----END PUBLIC KEY----- diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-pfr-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-pfr-manager_git.bb new file mode 100644 index 000000000..ebebe43bb --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-pfr-manager_git.bb @@ -0,0 +1,22 @@ +SUMMARY = "Intel PFR Manager Service" +DESCRIPTION = "Daemon to handle all PFR functionalities" + +PV = "1.0+git${SRCPV}" + +S = "${WORKDIR}/git/intel-pfr-manager" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e" + +SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh" +SRCREV = "4611d8dcba0c0dc92156bbafdb50607aaff122ab" + +inherit cmake systemd +SYSTEMD_SERVICE_${PN} = "xyz.openbmc_project.Intel.PFR.Manager.service" + +DEPENDS += " \ + sdbusplus \ + phosphor-logging \ + boost \ + i2c-tools \ + " diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/obmc-intel-pfr-image-native.bb b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/obmc-intel-pfr-image-native.bb new file mode 100644 index 000000000..ee2cc3934 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/obmc-intel-pfr-image-native.bb @@ -0,0 +1,38 @@ +SUMMARY = "Intel PFR manifest and signing key for development and testing" +DESCRIPTION = "Do not use this signing keys to sign CI and release images." + +PR = "r1" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658" + +inherit native + +PFR_KEY_NAME ?= "pfr-dev-key" +PFR_SIGN_UTIL ?= "blocksign" + +SRC_URI = " \ + file://pfr_image-manifest.json \ + file://pfr_image.py \ + file://blocksign \ + file://pfm_config.xml \ + file://bmc_config.xml \ + file://csk_prv.pem \ + file://csk_pub.pem \ + file://rk_pub.pem \ + file://rk_prv.pem \ + " + +do_install() { + bbplain "Copying the intel pfr image generation scripts and image signing keys" + + install -d ${STAGING_DIR}/intel-pfr-files + install -m 400 ${WORKDIR}/pfr_image-manifest.json ${STAGING_DIR}/intel-pfr-files + install -m 775 ${WORKDIR}/blocksign ${STAGING_DIR}/intel-pfr-files + install -m 400 ${WORKDIR}/pfm_config.xml ${STAGING_DIR}/intel-pfr-files + install -m 400 ${WORKDIR}/bmc_config.xml ${STAGING_DIR}/intel-pfr-files + install -m 775 ${WORKDIR}/pfr_image.py ${STAGING_DIR}/intel-pfr-files + install -m 400 ${WORKDIR}/csk_prv.pem ${STAGING_DIR}/intel-pfr-files/ + install -m 400 ${WORKDIR}/csk_pub.pem ${STAGING_DIR}/intel-pfr-files/ + install -m 400 ${WORKDIR}/rk_pub.pem ${STAGING_DIR}/intel-pfr-files/ + install -m 400 ${WORKDIR}/rk_prv.pem ${STAGING_DIR}/intel-pfr-files/ +} -- cgit v1.2.3