Implemented pipelined hash calculation in LoadFirmware()

Review URL: http://codereview.chromium.org/2802002
This commit is contained in:
Randall Spangler
2010-06-15 14:53:01 -07:00
parent dcab8fab94
commit 39ed88efe9
5 changed files with 80 additions and 9 deletions

View File

@@ -45,8 +45,8 @@ static void VerifyDataTest(const VbPublicKey* public_key,
const VbPrivateKey* private_key) {
const uint8_t test_data[] = "This is some test data to sign.";
VbSignature *sig;
RSAPublicKey *rsa;
VbSignature* sig;
RSAPublicKey* rsa;
sig = CalculateSignature(test_data, sizeof(test_data), private_key);
rsa = PublicKeyToRSA(public_key);
@@ -68,6 +68,32 @@ static void VerifyDataTest(const VbPublicKey* public_key,
}
static void VerifyDigestTest(const VbPublicKey* public_key,
const VbPrivateKey* private_key) {
const uint8_t test_data[] = "This is some other test data to sign.";
VbSignature* sig;
RSAPublicKey* rsa;
uint8_t* digest;
sig = CalculateSignature(test_data, sizeof(test_data), private_key);
rsa = PublicKeyToRSA(public_key);
digest = DigestBuf(test_data, sizeof(test_data), public_key->algorithm);
TEST_NEQ(sig && rsa && digest, 0, "VerifyData() prerequisites");
if (!sig || !rsa || !digest)
return;
TEST_EQ(VerifyDigest(digest, sig, rsa), 0, "VerifyDigest() ok");
GetSignatureData(sig)[0] ^= 0x5A;
TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() wrong sig");
RSAPublicKeyFree(rsa);
Free(sig);
Free(digest);
}
static void ReSignKernelPreamble(VbKernelPreambleHeader *h,
const VbPrivateKey *key) {
VbSignature *sig = CalculateSignature((const uint8_t*)h,
@@ -201,6 +227,7 @@ int main(int argc, char* argv[]) {
VerifyPublicKeyToRSA(public_key);
VerifyDataTest(public_key, private_key);
VerifyDigestTest(public_key, private_key);
VerifyKernelPreambleTest(public_key, private_key);
if (public_key)

View File

@@ -67,6 +67,12 @@ int VerifyData(const uint8_t* data, const VbSignature* sig,
const RSAPublicKey* key);
/* Verifies a secure hash digest from DigestBuf() or DigestFinal(),
* using [key]. */
int VerifyDigest(const uint8_t* digest, const VbSignature *sig,
const RSAPublicKey* key);
/* Checks the sanity of a key block of size [size] bytes, using public
* key [key]. If [key]==NULL, uses only the block checksum to verify
* the key block. Header fields are also checked for sanity. Does not

View File

@@ -122,6 +122,22 @@ int VerifyData(const uint8_t* data, const VbSignature *sig,
}
int VerifyDigest(const uint8_t* digest, const VbSignature *sig,
const RSAPublicKey* key) {
if (sig->sig_size != siglen_map[key->algorithm]) {
debug("Wrong signature size for algorithm.\n");
return 1;
}
if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest,
GetSignatureDataC(sig), key->algorithm))
return 1;
return 0;
}
int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size,
const VbPublicKey *key) {

View File

@@ -13,9 +13,23 @@
#include "utility.h"
#include "vboot_common.h"
/* Static variables for UpdateFirmwareBodyHash(). It's less than
* optimal to have static variables in a library, but in UEFI the
* caller is deep inside a different firmware stack and doesn't have a
* good way to pass the params struct back to us. */
static DigestContext ctx;
static uint64_t body_size_accum = 0;
static int inside_load_firmware = 0;
void UpdateFirmwareBodyHash2(uint8_t* data, uint64_t size) {
/* TODO: actually update the hash. */
if (!inside_load_firmware) {
debug("UpdateFirmwareBodyHash() called outside LoadFirmware()\n");
return;
}
DigestUpdate(&ctx, data, size);
body_size_accum += size;
}
@@ -56,6 +70,7 @@ int LoadFirmware2(LoadFirmwareParams* params) {
uint64_t key_version;
uint8_t* body_data;
uint64_t body_size;
uint8_t* body_digest;
/* Verify the key block */
if (0 == index) {
@@ -112,23 +127,29 @@ int LoadFirmware2(LoadFirmwareParams* params) {
continue;
/* Read the firmware data */
/* TODO: should set up hash for UpdateFirmwareBodyHash(). */
DigestInit(&ctx, data_key->algorithm);
body_size_accum = 0;
inside_load_firmware = 1;
body_data = GetFirmwareBody(index, &body_size);
if (!body_data || (body_size != preamble->body_signature.data_size)) {
inside_load_firmware = 0;
body_digest = DigestFinal(&ctx);
if (!body_data || (body_size != preamble->body_signature.data_size) ||
(body_size_accum != body_size)) {
RSAPublicKeyFree(data_key);
Free(body_digest);
continue;
}
/* Verify firmware data */
/* TODO: should use hash from UpdateFirmwareBodyHash() rather than
* recalculating it in VerifyData(). */
if (0 != VerifyData(body_data, &preamble->body_signature, data_key)) {
if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) {
RSAPublicKeyFree(data_key);
Free(body_digest);
continue;
}
/* Done with the data key, so can free it now */
/* Done with the digest and data key, so can free them now */
RSAPublicKeyFree(data_key);
Free(body_digest);
/* If we're still here, the firmware is valid. */
/* Save the first good firmware we find; that's the one we'll boot */

View File

@@ -79,6 +79,7 @@ int main(void)
VerifySignatureInside(0, 0, 0);
PublicKeyToRSA(0);
VerifyData(0, 0, 0);
VerifyDigest(0, 0, 0);
KeyBlockVerify(0, 0, 0);
VerifyFirmwarePreamble2(0, 0, 0);
VerifyKernelPreamble2(0, 0, 0);