/* Copyright 2016 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 #include #include #include #include "2sha.h" #include "bdb.h" #include "bdb_api.h" #include "host.h" static f_extend extend = vb2_sha256_extend; static void help(void) { fprintf(stderr, "Usage: bdb_extend -b bdb_file -s bds_file " "[-d digest_file] [-m]\n" "\n" "Extends BDS based on a given BDB. When '-m' is given, a " "MVMAP2315's sha256_extend algorithm will be used. When " "digest_file is specified, the validity of the BDB key is " "checked and the secrets will be derived differently.\n"); } #define PACK32(str, x) \ { \ *(x) = ((uint32_t) *((str) + 3) ) \ | ((uint32_t) *((str) + 2) << 8) \ | ((uint32_t) *((str) + 1) << 16) \ | ((uint32_t) *((str) + 0) << 24); \ } /** * MVMAP2315's implementation of sha256 extend * * This performs incorrect but still cryptographically secure sha256 extension. * This is provided for test purpose only. * * See vb2_sha256_extend for details on arguments. */ static void mvmap2315_sha256_extend(const uint8_t *from, const uint8_t *by, uint8_t *to) { struct vb2_sha256_context dc; int i; vb2_sha256_init(&dc); for (i = 0; i < 8; i++) { PACK32(from, &dc.h[i]); from += 4; } vb2_sha256_update(&dc, by, VB2_SHA256_BLOCK_SIZE); vb2_sha256_finalize(&dc, to); } static void dump_secret(const uint8_t *secret, const char *label) { int i; printf("%s = {", label); for (i = 0; i < BDB_SECRET_SIZE; i++) { if (i % 8 == 0) printf("\n\t"); else printf(" "); printf("0x%02x,", secret[i]); } printf("\n}\n"); } static void dump_secrets(struct vba_context *ctx, const uint8_t *wsr) { dump_secret(ctx->secrets->bdb, "bdb"); dump_secret(ctx->secrets->boot_path, "boot_path"); dump_secret(ctx->secrets->boot_verified, "boot_verified"); dump_secret(ctx->secrets->nvm_wp, "nvm_wp"); dump_secret(ctx->secrets->nvm_rw, "nvm_rw"); dump_secret(wsr, "wsr"); } static int derive_secrets(struct vba_context *ctx, const uint8_t *bdb, uint8_t *wsr) { struct bdb_secrets secrets; memset(&secrets, 0, sizeof(secrets)); ctx->secrets = &secrets; if (vba_extend_secrets_ro(ctx, bdb, wsr, extend)) { fprintf(stderr, "ERROR: Failed to derive secrets\n"); return -1; } fprintf(stderr, "LOG: Secrets are derived as follows\n"); dump_secrets(ctx, wsr); return 0; } int main(int argc, char *argv[]) { struct vba_context ctx; uint8_t *bdb, *bds; uint8_t *key_digest = NULL; uint32_t bdb_size, bds_size, digest_size; const char *bdb_file = NULL; const char *digest_file = NULL; const char *bds_file = NULL; int rv; int opt; while ((opt = getopt(argc, argv, "b:d:hms:")) != -1) { switch(opt) { case 'b': bdb_file = optarg; break; case 'd': digest_file = optarg; break; case 'h': help(); return 0; case 'm': extend = mvmap2315_sha256_extend; break; case 's': bds_file = optarg; break; default: help(); return -1; } } if (!bdb_file || !bds_file) { fprintf(stderr, "ERROR: BDB and BDS aren't specified\n\n"); help(); return -1; } /* Read BDB */ bdb = read_file(bdb_file, &bdb_size); if (!bdb) { fprintf(stderr, "ERROR: Unable to read %s\n", bdb_file); return -1; } /* Read BDS */ bds = read_file(bds_file, &bds_size); if (!bds) { fprintf(stderr, "ERROR: Unable to read %s\n", bds_file); return -1; } if (bds_size != BDB_SECRET_SIZE) { fprintf(stderr, "ERROR: Invalid BDS size: %d\n", bds_size); return -1; } /* Read key digest if provided */ if (digest_file) { key_digest = read_file(digest_file, &digest_size); if (!key_digest) { fprintf(stderr, "ERROR: Unable to read %s\n", digest_file); return -1; } } /* Verify BDB and set a flag based on the result */ memset(&ctx, 0, sizeof(ctx)); rv = bdb_verify(bdb, bdb_size, key_digest); if (rv) { if (rv != BDB_GOOD_OTHER_THAN_KEY) { fprintf(stderr, "ERROR: BDB is invalid: %d\n", rv); return -1; } fprintf(stderr, "WARNING: BDB is valid but key digest doesn't match\n"); } else { ctx.flags |= VBA_CONTEXT_FLAG_BDB_KEY_EFUSED; fprintf(stderr, "BDB is successfully verified by eFused key\n"); } /* Derive secrets and dump the values */ return derive_secrets(&ctx, bdb, bds); }