diff options
author | Bill Richardson <wfrichar@chromium.org> | 2015-11-05 10:51:41 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2015-11-06 01:15:52 -0800 |
commit | e99775311728eb01e47d5c5d29156f13842ca721 (patch) | |
tree | 801d0a1713b230b16074f4df98299ecd24141de4 /util | |
parent | 6a5c36bd4a3a9a5e9a8a796ee26afdbd981c9d28 (diff) | |
download | chrome-ec-e99775311728eb01e47d5c5d29156f13842ca721.tar.gz |
Cr50: Update to the "final" FPGA image 20151104_041733@78962
In fact this provides support for three FPGA images:
20151104_011218 - full crypto, no USB
20151104_041733 - tiny crypto, full USB
20151104_065845 - full crypto, full USB (only for hard-to-get boards)
We can tell these FPGA images apart at run-time by looking at
some SWDP registers:
register crypto usb full
GREG32(SWDP, BUILD_TIME) 0x2bd2 0xa305 0x10135
GREG32(SWDP, FPGA_CONFIG) 0x1 0x2 0x3
This CL includes a run-time check for the USB features so that
it's safe to build the firmware with CONFIG_USB and run it on a
non-USB FPGA image.
Here are the differences I could find in the top-level image
header files:
All three FPGA images define different (apparently arbitrary)
default values for the PMU_PWRDN_SCRATCHn registers, but other
than that, the usb and full images differ only in the BUILD_TIME
and FPGA_CONFIG register values.
I'm not sure why, but function uart_init() in file
chip/g/polling_uart.c writes to one of the PMU_PWRDN_SCRATCHn
registers, but nothing seems to read it again.
The crypto image defines these values which don't appear in the
other images:
#define PINMUX_USB0_EXT_DM_PULLUP_EN_SEL 0x4f
#define PINMUX_USB0_EXT_DP_RPU1_ENB_SEL 0x50
#define PINMUX_USB0_EXT_DP_RPU2_ENB_SEL 0x51
#define PINMUX_USB0_EXT_FS_EDGE_SEL_SEL 0x52
#define PINMUX_USB0_EXT_RX_DMI_SEL 0x53
#define PINMUX_USB0_EXT_RX_DPI_SEL 0x54
#define PINMUX_USB0_EXT_RX_RCV_SEL 0x55
#define PINMUX_USB0_EXT_SUSPENDB_SEL 0x56
#define PINMUX_USB0_EXT_TX_DMO_SEL 0x57
#define PINMUX_USB0_EXT_TX_DPO_SEL 0x58
#define PINMUX_USB0_EXT_TX_OEB_SEL 0x59
#define PINMUX_USB0_EXT_DM_PULLUP_EN_SEL_OFFSET 0x230
#define PINMUX_USB0_EXT_DM_PULLUP_EN_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_DP_RPU1_ENB_SEL_OFFSET 0x234
#define PINMUX_USB0_EXT_DP_RPU1_ENB_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_DP_RPU2_ENB_SEL_OFFSET 0x238
#define PINMUX_USB0_EXT_DP_RPU2_ENB_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_FS_EDGE_SEL_SEL_OFFSET 0x23c
#define PINMUX_USB0_EXT_FS_EDGE_SEL_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_RX_DMI_SEL_OFFSET 0x240
#define PINMUX_USB0_EXT_RX_DMI_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_RX_DPI_SEL_OFFSET 0x244
#define PINMUX_USB0_EXT_RX_DPI_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_RX_RCV_SEL_OFFSET 0x248
#define PINMUX_USB0_EXT_RX_RCV_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_SUSPENDB_SEL_OFFSET 0x24c
#define PINMUX_USB0_EXT_SUSPENDB_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_TX_DMO_SEL_OFFSET 0x250
#define PINMUX_USB0_EXT_TX_DMO_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_TX_DPO_SEL_OFFSET 0x254
#define PINMUX_USB0_EXT_TX_DPO_SEL_DEFAULT 0x0
#define PINMUX_USB0_EXT_TX_OEB_SEL_OFFSET 0x258
#define PINMUX_USB0_EXT_TX_OEB_SEL_DEFAULT 0x0
The crypto image also differs in this:
#define PINMUX_VOLT0_TST_NEG_GLITCH_DET_SEL_OFFSET 0x25c
instead of this:
#define PINMUX_VOLT0_TST_NEG_GLITCH_DET_SEL_OFFSET 0x230
The rest of the differences between the crypto and usb versions
are in these values, which I don't think we care about. At least,
I can't find any place where they're used.
PINMUX_EXITEDGE0_DIOAn_OFFSET
PINMUX_EXITEDGE0_DIOBn_OFFSET
PINMUX_EXITEDGE0_DIOMn_OFFSET
PINMUX_EXITEDGE0_VIOn_OFFSET
PINMUX_EXITEDGE0_OFFSET
PINMUX_EXITEN0_DIOAn_OFFSET
PINMUX_EXITEN0_DIOBn_OFFSET
PINMUX_EXITEN0_DIOMn_OFFSET
PINMUX_EXITEN0_VIOn_OFFSET
PINMUX_EXITEN0_OFFSET
PINMUX_EXITINV0_DIOAn_OFFSET
PINMUX_EXITINV0_DIOBn_OFFSET
PINMUX_EXITINV0_DIOMn_OFFSET
PINMUX_EXITINV0_VIOn_OFFSET
PINMUX_EXITINV0_OFFSET
PINMUX_HOLD_OFFSET
PINMUX_SEL_COUNT
PINMUX_VOLT0_TST_NEG_GLITCH_DET_SEL
PINMUX_VOLT0_TST_POS_GLITCH_DET_SEL
PINMUX_VOLT0_TST_POS_GLITCH_DET_SEL_OFFSET
PINMUX_XO0_TESTBUSn_SEL
PINMUX_XO0_TESTBUSn_SEL_OFFSET
I used the header from the usb image to update chip/g/cr50_fpga_regdefs.h
BRANCH=none
BUG=chrome-os-partner:43791
CQ-DEPEND=CL:310978
TEST=make buildall
I also built a single Cr50 firmware and tried it on both the
crypto and usb FPGA images. Both worked as expected.
Change-Id: Ia8a064758f71f86771729437ae3e81226fd55789
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/311211
Diffstat (limited to 'util')
-rw-r--r-- | util/signer/codesigner.cc | 45 | ||||
-rw-r--r-- | util/signer/common/image.h | 6 | ||||
-rw-r--r-- | util/signer/common/signed_header.h | 10 | ||||
-rw-r--r-- | util/signer/image.cc | 17 | ||||
-rw-r--r-- | util/signer/publickey.cc | 19 |
5 files changed, 79 insertions, 18 deletions
diff --git a/util/signer/codesigner.cc b/util/signer/codesigner.cc index 7a6a323c74..547c829c8f 100644 --- a/util/signer/codesigner.cc +++ b/util/signer/codesigner.cc @@ -3,12 +3,14 @@ * found in the LICENSE file. */ #include <assert.h> +#include <fcntl.h> +#include <getopt.h> +#include <inttypes.h> #include <stddef.h> #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <inttypes.h> -#include <getopt.h> +#include <unistd.h> #include <common/image.h> #include <common/publickey.h> @@ -253,6 +255,9 @@ bool readJSON(const string& filename, GETVALUE("minor"); GETVALUE("applysec"); GETVALUE("config1"); + GETVALUE("err_response"); + GETVALUE("expect_response"); + GETVALUE("timestamp"); CHECKVALUE("tag"); const rapidjson::Document::ValueType& Tag = d["tag"]; @@ -275,6 +280,8 @@ string keyFilename; string xmlFilename; string jsonFilename; string outputFormat; +string signatureFilename; +string hashesFilename; void usage(int argc, char* argv[]) { fprintf(stderr, "Usage: %s options\n" @@ -284,6 +291,8 @@ void usage(int argc, char* argv[]) { "[--xml=$xml-filename] typically 'havenTop.xml'\n" "[--json=$json-filename] the signing manifest\n" "[--format=bin|hex] output file format, hex is default\n" + "[--signature=$sig-filename] replace signature with file content\n" + "[--hashes=$hashes-filename] destination file for intermediary hashes to be signed\n" "[--verbose]\n", argv[0]); } @@ -299,11 +308,13 @@ int getOptions(int argc, char* argv[]) { {"output", required_argument, NULL, 'o'}, {"verbose", no_argument, NULL, 'v'}, {"xml", required_argument, NULL, 'x'}, + {"signature", required_argument, NULL, 's'}, + {"hashes", required_argument, NULL, 'H'}, {0, 0, 0, 0} }; int c, option_index = 0; outputFormat.assign("hex"); - while ((c = getopt_long(argc, argv, "i:o:k:x:j:f:hv", + while ((c = getopt_long(argc, argv, "i:o:k:x:j:f:s:H:hv", long_options, &option_index)) != -1) { switch (c) { case 0: @@ -323,12 +334,18 @@ int getOptions(int argc, char* argv[]) { case 'x': xmlFilename.assign(optarg); break; + case 's': + signatureFilename.assign(optarg); + break; case 'j': jsonFilename.assign(optarg); break; case 'f': outputFormat.assign(optarg); break; + case 'H': + hashesFilename.assign(optarg); + break; case 'h': usage(argc, argv); return 1; @@ -401,6 +418,11 @@ int main(int argc, char* argv[]) { hdr.minor_ = values["minor"]; hdr.applysec_ = values["applysec"]; hdr.config1_ = values["config1"]; + hdr.err_response_ = values["err_response"]; + hdr.expect_response_ = values["expect_response"]; + if (values["timestamp"]) hdr.timestamp_ = values["timestamp"]; + + VERBOSE("timestamp: %ld\n", hdr.timestamp_); // Check keyId. if (values["keyid"] != hdr.keyid) { @@ -452,7 +474,7 @@ int main(int argc, char* argv[]) { } uint32_t idx = it->second; assert(idx < FUSE_MAX); - uint32_t mask = (1 << fuse_bits[x->first]) - 1; + uint32_t mask = (1ul << fuse_bits[x->first]) - 1; if ((x->second & mask) != x->second) { FATAL("specified fuse value too large\n"); } @@ -493,9 +515,22 @@ int main(int argc, char* argv[]) { } VERBOSE("\n"); + if (!signatureFilename.empty()) { + int fd = ::open(signatureFilename.c_str(), O_RDONLY); + if (fd > 0) { + int n = ::read(fd, hdr.signature, sizeof(hdr.signature)); + ::close(fd); + + if (n != sizeof(hdr.signature)) FATAL("cannot read from '%s'\n", signatureFilename.c_str()); + + VERBOSE("provided signature\n"); + } else { + FATAL("cannot open '%s'\n", signatureFilename.c_str()); + } + } // Sign image. - if (image.sign(key, &hdr, fuse_values, info_values)) { + if (image.sign(key, &hdr, fuse_values, info_values, hashesFilename)) { image.generate(outputFilename, outputFormat == "hex"); } else { FATAL("failed to sign\n"); diff --git a/util/signer/common/image.h b/util/signer/common/image.h index 1efe763d2d..ebf0c5d838 100644 --- a/util/signer/common/image.h +++ b/util/signer/common/image.h @@ -24,9 +24,11 @@ class Image { bool fromIntelHex(const std::string& filename, bool withSignature = true); bool fromElf(const std::string& filename); - bool sign(PublicKey& key, const SignedHeader* hdr, + bool sign(PublicKey& key, + const SignedHeader* hdr, const uint32_t fuses[], - const uint32_t info[]); + const uint32_t info[], + const std::string& hashesFilename); void generate(const std::string& outputFilename, bool hex_output) const; diff --git a/util/signer/common/signed_header.h b/util/signer/common/signed_header.h index dfb63010ad..98cc2c09a6 100644 --- a/util/signer/common/signed_header.h +++ b/util/signer/common/signed_header.h @@ -20,7 +20,7 @@ typedef struct SignedHeader { #ifdef __cplusplus SignedHeader() : magic(-1), image_size(0), epoch_(0x1337), major_(0), minor_(0xbabe), - p4cl_(0), applysec_(0), config1_(0) { + p4cl_(0), applysec_(0), config1_(0), err_response_(0), expect_response_(0) { memset(signature, 'S', sizeof(signature)); memset(tag, 'T', sizeof(tag)); memset(fusemap, 0, sizeof(fusemap)); @@ -58,9 +58,11 @@ typedef struct SignedHeader { uint32_t minor_; uint64_t timestamp_; // time of signing uint32_t p4cl_; - uint32_t applysec_; // bits per FUSE_FW_DEFINED_BROM_APPLYSEC - uint32_t config1_; // bits per FUSE_FW_DEFINED_BROM_CONFIG1 - uint32_t _pad[256 - 1 - 96 - 1 - 7 - 1 - 96 - 5*1 - 4 - 4 - 7*1 - 2 - 1]; + uint32_t applysec_; // bits to and with FUSE_FW_DEFINED_BROM_APPLYSEC + uint32_t config1_; // bits to mesh with FUSE_FW_DEFINED_BROM_CONFIG1 + uint32_t err_response_; // bits to or with FUSE_FW_DEFINED_BROM_ERR_RESPONSE + uint32_t expect_response_; // action to take when expectation is violated + uint32_t _pad[256 - 1 - 96 - 1 - 7 - 1 - 96 - 5*1 - 4 - 4 - 9*1 - 2 - 1]; uint32_t fuses_chk_; // top 32 bit of expected fuses hash uint32_t info_chk_; // top 32 bit of expected info hash } SignedHeader; diff --git a/util/signer/image.cc b/util/signer/image.cc index ffad1331b6..e82d3846ad 100644 --- a/util/signer/image.cc +++ b/util/signer/image.cc @@ -374,9 +374,11 @@ void Image::store(int adr, int v) { if (adr < low_) low_ = adr; } -bool Image::sign(PublicKey& key, const SignedHeader* input_hdr, +bool Image::sign(PublicKey& key, + const SignedHeader* input_hdr, const uint32_t fuses[FUSE_MAX], - const uint32_t info[INFO_MAX]) { + const uint32_t info[INFO_MAX], + const string& hashesFilename) { BIGNUM* sig = NULL; SignedHeader* hdr = (SignedHeader*)(&mem_[base_]); SHA256_CTX sha256; @@ -450,6 +452,17 @@ bool Image::sign(PublicKey& key, const SignedHeader* input_hdr, } VERBOSE("\n"); + if (!hashesFilename.empty()) { + // Write hashes to file for subsequent extraneous (re)signing. + int fd = open(hashesFilename.c_str(), O_CREAT|O_TRUNC|O_RDWR, 0600); + if (fd >= 0) { + write(fd, &hashes, sizeof(hashes)); + close(fd); + } + } + + sig = BN_bin2bn((uint8_t*)(hdr->signature), sizeof(hdr->signature), NULL); + result = key.sign(&hashes, sizeof(hashes), &sig); if (result != 1) { diff --git a/util/signer/publickey.cc b/util/signer/publickey.cc index b4bde6c6bf..4b977d123e 100644 --- a/util/signer/publickey.cc +++ b/util/signer/publickey.cc @@ -221,12 +221,21 @@ int PublicKey::sign(const void* msg, size_t msglen, BIGNUM** output) { sig = (uint8_t*)malloc(tmplen); if (publicOnly_) { - fprintf(stderr, "gnubby signing.."); fflush(stderr); - // TODO: 2k -> gnubby, 3k -> HSM? + if (nwords() == 64) { + // 2048 bit public key : gnubby + fprintf(stderr, "gnubby signing.."); fflush(stderr); - Gnubby gnubby; - result = gnubby.sign(ctx, sig, &siglen, key_); - fprintf(stderr, "Gnubby.sign: %d\n", result); + Gnubby gnubby; + result = gnubby.sign(ctx, sig, &siglen, key_); + fprintf(stderr, "Gnubby.sign: %d\n", result); + } else { + // other public key : best have signature prefilled + fprintf(stderr, "WARNING: public key size %lu; assuming preloaded signature\n", nwords()); + fprintf(stderr, " Likely you are trying to use the real rom key, try the -dev flavor\n"); + fflush(stderr); + siglen = BN_bn2bin(*output, sig); + result = 1; + } } else { VERBOSE("ossl signing.."); result = EVP_SignFinal(ctx, sig, &siglen, key_); |