Skip to content

Commit

Permalink
Explorer update hash fix
Browse files Browse the repository at this point in the history
Need to adjust what image data to perform the SHA512 hash against. Also
verify this calculated hash value matches the value included in the
image fingerprint when building the PNOR header for this image.  Need to
also fix the byte order of scom register data when grabbing the current
Explorer hash.

From vendor:
At offset 0, is the Image fingerprint which is hash function
calculated from Byte 640(dec) till the end of the FW image.

Change-Id: Iae083ee7118b69794f41d54a6f52acbb42cd913b
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/93317
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Matthew Raybuck <matthew.raybuck@ibm.com>
Reviewed-by: Nicholas E Bofferding <bofferdn@us.ibm.com>
Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
  • Loading branch information
mderkse1 authored and dcrowell77 committed Mar 25, 2020
1 parent 7579887 commit e53402c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 16 deletions.
54 changes: 42 additions & 12 deletions src/build/buildpnor/pkgOcmbFw.pl
Expand Up @@ -6,7 +6,7 @@
#
# OpenPOWER HostBoot Project
#
# Contributors Listed Below - COPYRIGHT 2019
# Contributors Listed Below - COPYRIGHT 2019,2020
# [+] International Business Machines Corp.
#
#
Expand All @@ -30,6 +30,13 @@
# image or for verifying an existing OCMB firmware header of a pre-packaged
# OCMB firmware image.
#
# Unpackaged OCMB firmware image format:
# At offset 0, is the Image fingerprint which is a 64-byte hash
# calculated from Byte 640(dec) till the end of the FW image.
# The hash algorithm used is SHA-512.
# At offset 640(dec) is the 4 byte FW length field.
# FW binary image begins at offset 2048(dec).
#
# OCMB Firmware Header Format:
# 1. Magic number .. indicating this is OCMB firmware ('OCMBHDR'<null>).
# Can't ever change in presence or size. 8 bytes.
Expand Down Expand Up @@ -117,6 +124,7 @@
use constant HEADER_MIN_SIZE => 96;
use constant HEADER_BYTES_FOR_LENGTH_FIELD => 24;
use constant HEADER_SHA512_SIZE => 64;
use constant IMAGE_DATA_HEADER_SIZE => 640;

# supported tag values for tagged triplets
use constant TAG_SHA512 => 1;
Expand All @@ -135,6 +143,7 @@
my $g_timestamp = "";
my $g_verbose = 0;
my $g_help = 0;
my $g_skipVendorImageHashCheck = 0;

# Holds a variable number of tagged triplets <tagId><size><data>
my @g_taggedTriplets;
Expand Down Expand Up @@ -398,27 +407,39 @@ sub verifySHA512
}

my $firmwareImage;
my $imageSHA512;
#read in the rest of the file for the firmware image contents
{
local $/; #unset the field separator special variable
$firmwareImage = <$packagedDataFH>;

# grab the image SHA512 from header in image data
# See comments at top of the file for fw image layout
$imageSHA512 = substr $firmwareImage, 0, HEADER_SHA512_SIZE;

# skip past the header in the image data
$firmwareImage = substr $firmwareImage, IMAGE_DATA_HEADER_SIZE;
}

my $imageSHA512 = sha512($firmwareImage);
my $calcImageSHA512 = sha512($firmwareImage);

trace(1, "\nSHA512 hash from firmware image: ".unpack("H*", $imageSHA512));
trace(1, "\nCalculated SHA512 hash from firmware image: ".unpack("H*", $calcImageSHA512)."\n");

#Now, compare the two hash values
if($imageSHA512 eq $headerSHA512)
# Make sure the calculated hash matches the hash we found in the image
# as well as the hash we found in the header
if (!$g_skipVendorImageHashCheck &&
(($calcImageSHA512 ne $imageSHA512) ||
($calcImageSHA512 ne $headerSHA512) ))
{
trace(1, "\nHeader successfully validated against firmware image.");
traceErr("Calculated SHA512 hash from image data does not match value in firmware image and/or image header");
trace(1, "\nSHA512 hash in header data: ".unpack("H*", $headerSHA512));
trace(1, "\nSHA512 hash in image data: ".unpack("H*", $imageSHA512)."\n");
exit 2;
}
else
elsif($imageSHA512 eq $headerSHA512)
{
traceErr("Header SHA512 hash does not match firmware image!");
exit 1;
trace(1, "\nHeader successfully validated against firmware image.");
}

exit 0;
}

Expand Down Expand Up @@ -465,6 +486,7 @@ sub usage
Usage:
$g_progName --verify
--packagedBin <packaged binary file name>
[--skipImageHashCheck]
[--verbose]
$g_progName --packagedBin <packaged binary file name>
--unpackagedBin <unpackaged binary file name>
Expand All @@ -477,6 +499,7 @@ sub usage
-h Print this help text
--verify Verify the SHA512 hash of a packaged binary file
--packagedBin <file> Name of packaged binary file
--skipImageHashCheck Skip checking match of SHA512 hash from vendor image
--unpackagedBin <file> Name of unpackaged binary file
--vendorVersion <string> Quoted vendor version string
--vendorUrl <string> Quoted vendor URL string
Expand All @@ -503,6 +526,7 @@ sub usage
"vendorVersion=s" => \$g_vendorVersion,
"vendorUrl=s" => \$g_vendorUrl,
"timestamp=s" => \$g_timestamp,
"skipImageHashCheck" => \$g_skipVendorImageHashCheck,
"verbose" => \$g_verbose,
"help" => \$g_help);

Expand All @@ -527,7 +551,7 @@ sub usage
# Check if we're just verifying an already packaged binary
if ($g_verify)
{
#this function does not return
#this function will exit the program and therefore does not return
verifySHA512();
}

Expand Down Expand Up @@ -556,8 +580,14 @@ sub usage
$unpackagedData = <UNPACKAGED_DATA>; #reads in entire file
}

# grab the image SHA512 from header in image data
my $imageSHA512 = substr $unpackagedData, 0, HEADER_SHA512_SIZE;

# skip past the header in the image data as that isn't part of the sha512 hash
my $firmwareImage = substr $unpackagedData, IMAGE_DATA_HEADER_SIZE;

# Generate sha512 hash of unpackaged file data
my $sha512_hash = sha512($unpackagedData);
my $sha512_hash = sha512($firmwareImage);

# Generate the sha512 tagged triplet and add it to our list of tagged triplets
push (@g_taggedTriplets, createTaggedTriplet(TAG_SHA512, $sha512_hash));
Expand Down
3 changes: 2 additions & 1 deletion src/build/mkrules/hbfw/img/makefile
Expand Up @@ -263,7 +263,8 @@ gen_default_images: ${GEN_DEFAULT_IMAGES_DEPS}
${PKG_OCMBFW_SCRIPT} --unpackagedBin ${UNPKGD_OCMBFW_IMG} --packagedBin ${OCMBFW_IMG} --timestamp "${DUMMY:!date!}" --vendorVersion "0.1" --vendorUrl "http://www.ibm.com"

# verify header sha512 hash value matches value calculated against image
${PKG_OCMBFW_SCRIPT} --verify --packagedBin ${OCMBFW_IMG}
# TODO RTC:195547 -- remove the skip when we have a good image packaged into the driver.
${PKG_OCMBFW_SCRIPT} --verify --packagedBin ${OCMBFW_IMG} --skipImageHashCheck
.endif

# Remove offset from start of Bootloader image for HBBL partition
Expand Down
8 changes: 5 additions & 3 deletions src/usr/isteps/expupd/expupd.C
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2019 */
/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -107,8 +107,10 @@ errlHndl_t getFlashedHash(TargetHandle_t i_target, sha512regs_t& o_regs)
// copy scom buffer into the unformatted uint8_t array.
// Even though the scom buffer is 8 bytes, only 4 bytes are read and
// copied into the least significant 4 bytes.
memcpy(&o_regs.unformatted[l_bytesCopied], l_scomPtr + sizeof(uint32_t),
sizeof(uint32_t));
uint32_t regValue;
memcpy(&regValue, l_scomPtr + sizeof(uint32_t), sizeof(uint32_t));
regValue = le32toh( regValue ); // need to reverse byte order
memcpy(&o_regs.unformatted[l_bytesCopied], &regValue, sizeof(regValue));
}

return l_err;
Expand Down

0 comments on commit e53402c

Please sign in to comment.