summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2015-11-05 10:51:41 -0800
committerchrome-bot <chrome-bot@chromium.org>2015-11-06 01:15:52 -0800
commite99775311728eb01e47d5c5d29156f13842ca721 (patch)
tree801d0a1713b230b16074f4df98299ecd24141de4 /util
parent6a5c36bd4a3a9a5e9a8a796ee26afdbd981c9d28 (diff)
downloadchrome-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.cc45
-rw-r--r--util/signer/common/image.h6
-rw-r--r--util/signer/common/signed_header.h10
-rw-r--r--util/signer/image.cc17
-rw-r--r--util/signer/publickey.cc19
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_);