char *FindKernelConfig(const char *infile, uint64_t kernel_body_load_address) { uint8_t* blob; size_t blob_size; uint8_t *config = NULL; char *newstr = NULL; blob = MMapFile(infile, &blob_size); if (!blob) { VbExError("Error reading input file\n"); return 0; } config = GetKernelConfig(blob, blob_size, kernel_body_load_address); if (!config) { VbExError("Error parsing input file\n"); munmap(blob, blob_size); return 0; } newstr = strndup((char *)config, CROS_CONFIG_SIZE); if (!newstr) VbExError("Can't allocate new string\n"); munmap(blob, blob_size); return newstr; }
VbPrivateKey* PrivateKeyRead(const char* filename) { VbPrivateKey *key; uint64_t filelen = 0; uint8_t *buffer; const unsigned char *start; buffer = ReadFile(filename, &filelen); if (!buffer) { VbExError("unable to read from file %s\n", filename); return 0; } key = (VbPrivateKey*)malloc(sizeof(VbPrivateKey)); if (!key) { VbExError("Unable to allocate VbPrivateKey\n"); free(buffer); return 0; } key->algorithm = *(typeof(key->algorithm) *)buffer; start = buffer + sizeof(key->algorithm); key->rsa_private_key = d2i_RSAPrivateKey(0, &start, filelen - sizeof(key->algorithm)); if (!key->rsa_private_key) { VbExError("Unable to parse RSA private key\n"); free(buffer); free(key); return 0; } free(buffer); return key; }
static void* MMapFile(const char* filename, size_t *size) { FILE* f; uint8_t* buf; long file_size = 0; f = fopen(filename, "rb"); if (!f) { VBDEBUG(("Unable to open file %s\n", filename)); return NULL; } fseek(f, 0, SEEK_END); file_size = ftell(f); rewind(f); if (file_size <= 0) { fclose(f); return NULL; } *size = (size_t) file_size; /* Uses a host primitive as this is not meant for firmware use. */ buf = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fileno(f), 0); if (buf == MAP_FAILED) { VbExError("Failed to mmap the file %s\n", filename); fclose(f); return NULL; } fclose(f); return buf; }
/* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */ static int Pack(const char *infile, const char *outfile, uint64_t algorithm, uint64_t version) { VbPublicKey* pubkey; VbPrivateKey* privkey; if (!infile || !outfile) { fprintf(stderr, "vbutil_key: Must specify --in and --out\n"); return 1; } if ((pubkey = PublicKeyReadKeyb(infile, algorithm, version))) { if (0 != PublicKeyWrite(outfile, pubkey)) { fprintf(stderr, "vbutil_key: Error writing key.\n"); return 1; } free(pubkey); return 0; } if ((privkey = PrivateKeyReadPem(infile, algorithm))) { if (0 != PrivateKeyWrite(outfile, privkey)) { fprintf(stderr, "vbutil_key: Error writing key.\n"); return 1; } free(privkey); return 0; } VbExError("Unable to parse either .keyb or .pem from %s\n", infile); return 1; }
void *VbExMalloc(size_t size) { void *ptr = cros_memalign_cache(size); if (!ptr) { VbExError("Internal malloc error."); } return ptr; }
VbError_t VbExBeep(uint32_t msec, uint32_t frequency) { #if defined(CONFIG_SYS_COREBOOT) if (frequency) enable_beep(frequency); else disable_beep(); if (msec > 0) { VbExSleepMs(msec); disable_beep(); } return VBERROR_SUCCESS; #elif defined CONFIG_SOUND int ret; VBDEBUG("About to beep for %d ms at %d Hz.\n", msec, frequency); if (!msec || !frequency) { if (msec) VbExSleepMs(msec); return VBERROR_NO_BACKGROUND_SOUND; } ret = sound_init(gd->fdt_blob); if (ret) { VbExError("Failed to initialize sound.\n"); return VBERROR_NO_SOUND; } ret = sound_play(msec, frequency); if (ret) { VbExError("Failed to play beep.\n"); return VBERROR_NO_SOUND; } return VBERROR_SUCCESS; #else /* TODO Implement it later. */ VbExSleepMs(msec); VBDEBUG("Beep!\n"); return VBERROR_NO_SOUND; #endif }
static uint8_t* GetKernelConfig(uint8_t* blob, size_t blob_size, uint64_t kernel_body_load_address) { VbKeyBlockHeader* key_block; VbKernelPreambleHeader* preamble; uint32_t now = 0; uint32_t offset = 0; /* Skip the key block */ key_block = (VbKeyBlockHeader*)blob; now += key_block->key_block_size; if (now + blob > blob + blob_size) { VbExError("key_block_size advances past the end of the blob\n"); return NULL; } /* Open up the preamble */ preamble = (VbKernelPreambleHeader*)(blob + now); now += preamble->preamble_size; if (now + blob > blob + blob_size) { VbExError("preamble_size advances past the end of the blob\n"); return NULL; } /* Read body_load_address from preamble if no kernel_body_load_address */ if (kernel_body_load_address == USE_PREAMBLE_LOAD_ADDR) kernel_body_load_address = preamble->body_load_address; /* The x86 kernels have a pointer to the kernel commandline in the zeropage * table, but that's irrelevant for ARM. Both types keep the config blob in * the same place, so just go find it. */ offset = preamble->bootloader_address - (kernel_body_load_address + CROS_PARAMS_SIZE + CROS_CONFIG_SIZE) + now; if (offset > blob_size) { VbExError("params are outside of the memory blob: %x\n", offset); return NULL; } return blob + offset; }
/* Write a private key to a file in .vbprivk format. */ int PrivateKeyWrite(const char* filename, const VbPrivateKey* key) { uint8_t *outbuf = 0; int buflen; FILE *f; buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf); if (buflen <= 0) { VbExError("Unable to write private key buffer\n"); return 1; } f = fopen(filename, "wb"); if (!f) { VbExError("Unable to open file %s\n", filename); free(outbuf); return 1; } if (1 != fwrite(&key->algorithm, sizeof(key->algorithm), 1, f)) { VbExError("Unable to write to file %s\n", filename); fclose(f); free(outbuf); unlink(filename); /* Delete any partial file */ } if (1 != fwrite(outbuf, buflen, 1, f)) { VbExError("Unable to write to file %s\n", filename); fclose(f); unlink(filename); /* Delete any partial file */ free(outbuf); } fclose(f); free(outbuf); return 0; }
/* Unpack a .vbpubk or .vbprivk */ static int Unpack(const char *infile, const char *outfile) { VbPublicKey* pubkey; VbPrivateKey* privkey; if (!infile) { fprintf(stderr, "Need file to unpack\n"); return 1; } if ((pubkey = PublicKeyRead(infile))) { printf("Public Key file: %s\n", infile); printf("Algorithm: %" PRIu64 " %s\n", pubkey->algorithm, (pubkey->algorithm < kNumAlgorithms ? algo_strings[pubkey->algorithm] : "(invalid)")); printf("Key Version: %" PRIu64 "\n", pubkey->key_version); printf("Key sha1sum: "); PrintPubKeySha1Sum(pubkey); printf("\n"); if (outfile) { if (0 != PublicKeyWrite(outfile, pubkey)) { fprintf(stderr, "vbutil_key: Error writing key copy.\n"); free(pubkey); return 1; } } free(pubkey); return 0; } if ((privkey = PrivateKeyRead(infile))) { printf("Private Key file: %s\n", infile); printf("Algorithm: %" PRIu64 " %s\n", privkey->algorithm, (privkey->algorithm < kNumAlgorithms ? algo_strings[privkey->algorithm] : "(invalid)")); if (outfile) { if (0 != PrivateKeyWrite(outfile, privkey)) { fprintf(stderr, "vbutil_key: Error writing key copy.\n"); free(privkey); return 1; } } free(privkey); return 0; } VbExError("Unable to parse either .vbpubk or vbprivk from %s\n", infile); return 1; }
int main(int argc, char** argv) { uint8_t disable, deactivated; TlclLibInit(); TPM_CHECK(TlclStartupIfNeeded()); TPM_CHECK(TlclSelfTestFull()); TPM_CHECK(TlclAssertPhysicalPresence()); TPM_CHECK(TlclGetFlags(&disable, &deactivated, NULL)); printf("disable is %d, deactivated is %d\n", disable, deactivated); TPM_CHECK(TlclSetEnable()); TPM_CHECK(TlclSetDeactivated(0)); TPM_CHECK(TlclGetFlags(&disable, &deactivated, NULL)); printf("disable is %d, deactivated is %d\n", disable, deactivated); if (disable == 1 || deactivated == 1) { VbExError("failed to enable or activate"); } printf("TEST SUCCEEDED\n"); return 0; }
static void setup_arch_unused_memory(memory_wipe_t *wipe, crossystem_data_t *cdata, VbCommonParams *cparams) { struct fdt_memory config, ramoops, lp0; if (cros_fdtdec_memory(gd->fdt_blob, "/memory", &config)) VbExError("FDT decode memory section error\n"); memory_wipe_add(wipe, config.start, config.end); #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) /* Exclude the TLB */ memory_wipe_sub(wipe, gd->tlb_addr, gd->tlb_addr + gd->tlb_size); #endif /* Excludes kcrashmem if in FDT */ if (cros_fdtdec_memory(gd->fdt_blob, "/ramoops", &ramoops)) VBDEBUG("RAMOOPS not contained within FDT\n"); else memory_wipe_sub(wipe, ramoops.start, ramoops.end); /* Excludes the LP0 vector; only applicable to tegra platforms */ if (cros_fdtdec_memory(gd->fdt_blob, "/lp0", &lp0)) VBDEBUG("LP0 not contained within FDT\n"); else memory_wipe_sub(wipe, lp0.start, lp0.end); #ifdef CONFIG_LCD { /* Excludes the frame buffer. */ int fb_size = lcd_fb_size(); memory_wipe_sub(wipe, (uintptr_t)gd->fb_base, (uintptr_t)gd->fb_base + fb_size); } #endif }
void *VbExMalloc(size_t size) { void *ptr; if (heap_current == NULL) { heap_current = &_heap[0]; heap_size = &_eheap[0] - &_heap[0]; VbExDebug("vboot heap: %p 0x%08x bytes\n", heap_current, heap_size); } if (heap_size < size) { VbExError("vboot heap request cannot be fulfilled. " "0x%08x available, 0x%08x requested\n", heap_size, size); } ptr = heap_current; heap_size -= size; heap_current += size; return ptr; }
/* Create a firmware .vblock */ static int Vblock(const char* outfile, const char* keyblock_file, const char* signprivate, uint64_t version, const char* fv_file, const char* kernelkey_file, uint32_t preamble_flags) { VbPrivateKey* signing_key; VbPublicKey* kernel_subkey; VbSignature* body_sig; VbFirmwarePreambleHeader* preamble; VbKeyBlockHeader* key_block; uint64_t key_block_size; uint8_t* fv_data; uint64_t fv_size; FILE* f; uint64_t i; if (!outfile) { VbExError("Must specify output filename\n"); return 1; } if (!keyblock_file || !signprivate || !kernelkey_file) { VbExError("Must specify all keys\n"); return 1; } if (!fv_file) { VbExError("Must specify firmware volume\n"); return 1; } /* Read the key block and keys */ key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size); if (!key_block) { VbExError("Error reading key block.\n"); return 1; } signing_key = PrivateKeyRead(signprivate); if (!signing_key) { VbExError("Error reading signing key.\n"); return 1; } kernel_subkey = PublicKeyRead(kernelkey_file); if (!kernel_subkey) { VbExError("Error reading kernel subkey.\n"); return 1; } /* Read and sign the firmware volume */ fv_data = ReadFile(fv_file, &fv_size); if (!fv_data) return 1; if (!fv_size) { VbExError("Empty firmware volume file\n"); return 1; } body_sig = CalculateSignature(fv_data, fv_size, signing_key); if (!body_sig) { VbExError("Error calculating body signature\n"); return 1; } free(fv_data); /* Create preamble */ preamble = CreateFirmwarePreamble(version, kernel_subkey, body_sig, signing_key, preamble_flags); if (!preamble) { VbExError("Error creating preamble.\n"); return 1; } /* Write the output file */ f = fopen(outfile, "wb"); if (!f) { VbExError("Can't open output file %s\n", outfile); return 1; } i = ((1 != fwrite(key_block, key_block_size, 1, f)) || (1 != fwrite(preamble, preamble->preamble_size, 1, f))); fclose(f); if (i) { VbExError("Can't write output file %s\n", outfile); unlink(outfile); return 1; } /* Success */ return 0; }
static int Verify(const char* infile, const char* signpubkey, const char* fv_file, const char* kernelkey_file) { VbKeyBlockHeader* key_block; VbFirmwarePreambleHeader* preamble; VbPublicKey* data_key; VbPublicKey* sign_key; VbPublicKey* kernel_subkey; RSAPublicKey* rsa; uint8_t* blob; uint64_t blob_size; uint8_t* fv_data; uint64_t fv_size; uint64_t now = 0; uint32_t flags; if (!infile || !signpubkey || !fv_file) { VbExError("Must specify filename, signpubkey, and fv\n"); return 1; } /* Read public signing key */ sign_key = PublicKeyRead(signpubkey); if (!sign_key) { VbExError("Error reading signpubkey.\n"); return 1; } /* Read blob */ blob = ReadFile(infile, &blob_size); if (!blob) { VbExError("Error reading input file\n"); return 1; } /* Read firmware volume */ fv_data = ReadFile(fv_file, &fv_size); if (!fv_data) { VbExError("Error reading firmware volume\n"); return 1; } /* Verify key block */ key_block = (VbKeyBlockHeader*)blob; if (0 != KeyBlockVerify(key_block, blob_size, sign_key, 0)) { VbExError("Error verifying key block.\n"); return 1; } free(sign_key); now += key_block->key_block_size; printf("Key block:\n"); data_key = &key_block->data_key; printf(" Size: %" PRIu64 "\n", key_block->key_block_size); printf(" Flags: %" PRIu64 " (ignored)\n", key_block->key_block_flags); printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, (data_key->algorithm < kNumAlgorithms ? algo_strings[data_key->algorithm] : "(invalid)")); printf(" Data key version: %" PRIu64 "\n", data_key->key_version); printf(" Data key sha1sum: "); PrintPubKeySha1Sum(data_key); printf("\n"); rsa = PublicKeyToRSA(&key_block->data_key); if (!rsa) { VbExError("Error parsing data key.\n"); return 1; } /* Verify preamble */ preamble = (VbFirmwarePreambleHeader*)(blob + now); if (0 != VerifyFirmwarePreamble(preamble, blob_size - now, rsa)) { VbExError("Error verifying preamble.\n"); return 1; } now += preamble->preamble_size; flags = VbGetFirmwarePreambleFlags(preamble); printf("Preamble:\n"); printf(" Size: %" PRIu64 "\n", preamble->preamble_size); printf(" Header version: %" PRIu32 ".%" PRIu32"\n", preamble->header_version_major, preamble->header_version_minor); printf(" Firmware version: %" PRIu64 "\n", preamble->firmware_version); kernel_subkey = &preamble->kernel_subkey; printf(" Kernel key algorithm: %" PRIu64 " %s\n", kernel_subkey->algorithm, (kernel_subkey->algorithm < kNumAlgorithms ? algo_strings[kernel_subkey->algorithm] : "(invalid)")); printf(" Kernel key version: %" PRIu64 "\n", kernel_subkey->key_version); printf(" Kernel key sha1sum: "); PrintPubKeySha1Sum(kernel_subkey); printf("\n"); printf(" Firmware body size: %" PRIu64 "\n", preamble->body_signature.data_size); printf(" Preamble flags: %" PRIu32 "\n", flags); /* TODO: verify body size same as signature size */ /* Verify body */ if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) { printf("Preamble requests USE_RO_NORMAL; skipping body verification.\n"); } else { if (0 != VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) { VbExError("Error verifying firmware body.\n"); return 1; } printf("Body verification succeeded.\n"); } if (kernelkey_file) { if (0 != PublicKeyWrite(kernelkey_file, kernel_subkey)) { fprintf(stderr, "vbutil_firmware: unable to write kernel subkey\n"); return 1; } } return 0; }
int main(int argc, char* argv[]) { char *infile = NULL; char *outfile = NULL; int mode = 0; int parse_error = 0; uint64_t version = 1; uint64_t algorithm = kNumAlgorithms; char* e; int i; char *progname = strrchr(argv[0], '/'); if (progname) progname++; else progname = argv[0]; while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { switch (i) { case '?': /* Unhandled option */ VbExError("Unknown option\n"); parse_error = 1; break; case OPT_INKEY: infile = optarg; break; case OPT_KEY_VERSION: version = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { VbExError("Invalid --version\n"); parse_error = 1; } break; case OPT_ALGORITHM: algorithm = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { VbExError("Invalid --algorithm\n"); parse_error = 1; } break; case OPT_MODE_PACK: mode = i; outfile = optarg; break; case OPT_MODE_UNPACK: mode = i; infile = optarg; break; case OPT_COPYTO: outfile = optarg; break; } } if (parse_error) return PrintHelp(progname); switch(mode) { case OPT_MODE_PACK: return Pack(infile, outfile, algorithm, version); case OPT_MODE_UNPACK: return Unpack(infile, outfile); default: printf("Must specify a mode.\n"); return PrintHelp(progname); } }