/* 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; }
/* 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; }
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; }
static int vb1_make_keypair() { VbPrivateKey *privkey = 0; VbPublicKey *pubkey = 0; RSA *rsa_key = 0; uint8_t *keyb_data = 0; uint32_t keyb_size; enum vb2_signature_algorithm sig_alg; uint64_t vb1_algorithm; FILE *fp; int ret = 1; fp = fopen(infile, "rb"); if (!fp) { fprintf(stderr, "Unable to open %s\n", infile); goto done; } rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); if (!rsa_key) { fprintf(stderr, "Unable to read RSA key from %s\n", infile); goto done; } sig_alg = vb2_rsa_sig_alg(rsa_key); if (sig_alg == VB2_SIG_INVALID) { fprintf(stderr, "Unsupported sig algorithm in RSA key\n"); goto done; } /* combine the sig_alg with the hash_alg to get the vb1 algorithm */ vb1_algorithm = (sig_alg - VB2_SIG_RSA1024) * 3 + opt_hash_alg - VB2_HASH_SHA1; /* Create the private key */ privkey = (VbPrivateKey *)malloc(sizeof(VbPrivateKey)); if (!privkey) goto done; privkey->rsa_private_key = rsa_key; privkey->algorithm = vb1_algorithm; /* Write it out */ strcpy(outext, ".vbprivk"); if (0 != PrivateKeyWrite(outfile, privkey)) { fprintf(stderr, "unable to write private key\n"); goto done; } fprintf(stderr, "wrote %s\n", outfile); /* Create the public key */ ret = vb_keyb_from_rsa(rsa_key, &keyb_data, &keyb_size); if (ret) { fprintf(stderr, "couldn't extract the public key\n"); goto done; } pubkey = PublicKeyAlloc(keyb_size, vb1_algorithm, opt_version); if (!pubkey) goto done; memcpy(GetPublicKeyData(pubkey), keyb_data, keyb_size); /* Write it out */ strcpy(outext, ".vbpubk"); if (0 != PublicKeyWrite(outfile, pubkey)) { fprintf(stderr, "unable to write public key\n"); goto done; } fprintf(stderr, "wrote %s\n", outfile); ret = 0; done: free(privkey); free(pubkey); free(keyb_data); RSA_free(rsa_key); return ret; }