Files
OpenCellular/util/gen_touchpad_hash.c
Nicolas Boichat 82e0892fc3 update_fw: Store complete touchpad FW hash
This will be used by the updater to first check that the touchpad
FW on AP side matches the one for which we stored hashes on EC
side.

This guarantee that we do not accidentally try to flash an
incorrect FW, which would render the touchpad non-functional.

BRANCH=none
BUG=b:63993173
TEST=make TOUCHPAD_FW=SA459C-1211_ForGoogleHammer_3.0.bin \
          BOARD=hammer -j
TEST=./usb_updater2 -t
     includes output of
     sha256sum A459C-1211_ForGoogleHammer_3.0.bin

Change-Id: Id30ab2d7c7d7e2d0f25cc893f685d218c44c022e
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/641736
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
2017-09-15 10:50:27 -07:00

175 lines
3.6 KiB
C

/* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <err.h>
#include <getopt.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <openssl/sha.h>
#include "config.h"
static void print_hex(FILE *out, uint8_t *digest, int len, int last)
{
int i;
fputs("{ ", out);
for (i = 0; i < len; i++)
fprintf(out, "0x%02x, ", digest[i]);
fprintf(out, "}%c\n", last ? ';' : ',');
}
/* Output blank hashes */
static int hash_fw_blank(FILE *hashes)
{
uint8_t digest[SHA256_DIGEST_LENGTH] = { 0 };
int len;
fprintf(hashes, "const uint8_t touchpad_fw_hashes[%d][%d] = {\n",
CONFIG_TOUCHPAD_VIRTUAL_SIZE / CONFIG_UPDATE_PDU_SIZE,
SHA256_DIGEST_LENGTH);
for (len = 0; len < CONFIG_TOUCHPAD_VIRTUAL_SIZE;
len += CONFIG_UPDATE_PDU_SIZE) {
print_hex(hashes, digest, sizeof(digest), 0);
}
fputs("};\n", hashes);
fprintf(hashes, "const uint8_t touchpad_fw_full_hash[%d] =\n\t",
SHA256_DIGEST_LENGTH);
print_hex(hashes, digest, SHA256_DIGEST_LENGTH, 1);
return 0;
}
static int hash_fw(FILE *tp_fw, FILE *hashes)
{
uint8_t buffer[CONFIG_UPDATE_PDU_SIZE];
int len = 0;
int rb;
SHA256_CTX ctx;
SHA256_CTX ctx_all;
uint8_t digest[SHA256_DIGEST_LENGTH];
SHA256_Init(&ctx_all);
fprintf(hashes, "const uint8_t touchpad_fw_hashes[%d][%d] = {\n",
CONFIG_TOUCHPAD_VIRTUAL_SIZE / CONFIG_UPDATE_PDU_SIZE,
SHA256_DIGEST_LENGTH);
while (1) {
rb = fread(buffer, 1, sizeof(buffer), tp_fw);
len += rb;
if (rb == 0)
break;
/* Calculate hash for the block. */
SHA256_Init(&ctx);
SHA256_Update(&ctx, buffer, rb);
SHA256_Final(digest, &ctx);
SHA256_Update(&ctx_all, buffer, rb);
print_hex(hashes, digest, sizeof(digest), 0);
if (rb < sizeof(buffer))
break;
}
fputs("};\n", hashes);
SHA256_Final(digest, &ctx_all);
fprintf(hashes, "const uint8_t touchpad_fw_full_hash[%d] =\n\t",
SHA256_DIGEST_LENGTH);
print_hex(hashes, digest, SHA256_DIGEST_LENGTH, 1);
if (!feof(tp_fw) || ferror(tp_fw)) {
warn("Error reading input file");
return 1;
}
if (len != CONFIG_TOUCHPAD_VIRTUAL_SIZE) {
warnx("Incorrect TP FW size (%d vs %d)", len,
CONFIG_TOUCHPAD_VIRTUAL_SIZE);
return 1;
}
return 0;
}
int main(int argc, char **argv)
{
int nopt;
int ret;
const char *out = NULL;
char *tp_fw_name = NULL;
FILE *tp_fw = NULL;
FILE *hashes;
const char short_opt[] = "f:ho:";
const struct option long_opts[] = {
{ "firmware", 1, NULL, 'f' },
{ "help", 0, NULL, 'h' },
{ "out", 1, NULL, 'o' },
{ NULL }
};
const char usage[] = "USAGE: %s -f <touchpad FW> -o <output file>\n";
while ((nopt = getopt_long(argc, argv, short_opt,
long_opts, NULL)) != -1) {
switch (nopt) {
case 'f': /* -f or --firmware */
tp_fw_name = optarg;
break;
case 'h': /* -h or --help */
fprintf(stdout, usage, argv[0]);
return 0;
case 'o': /* -o or --out */
out = optarg;
break;
default: /* Invalid parameter. */
fprintf(stderr, usage, argv[0]);
return 1;
}
};
if (out == NULL)
return 1;
hashes = fopen(out, "we");
if (!hashes)
err(1, "Cannot open output file");
fputs("#include <stdint.h>\n\n", hashes);
if (tp_fw_name) {
tp_fw = fopen(tp_fw_name, "re");
if (!tp_fw) {
warn("Cannot open firmware");
ret = 1;
goto out;
}
ret = hash_fw(tp_fw, hashes);
fclose(tp_fw);
} else {
printf("No touchpad FW provided, outputting blank hashes.\n");
ret = hash_fw_blank(hashes);
}
out:
fclose(hashes);
/* In case of failure, remove output file. */
if (ret != 0)
unlink(out);
return ret;
}