Add a kernel subkey signing algorithm key and algorithm fields to firmware preamble.

Review URL: http://codereview.chromium.org/2589001
This commit is contained in:
Gaurav Shah
2010-06-03 11:11:33 -07:00
parent 58efd70dc3
commit 9592919196
4 changed files with 82 additions and 32 deletions

View File

@@ -72,6 +72,12 @@ FirmwareImage* GenerateTestFirmwareImage(int algorithm,
/* Populate firmware and preamble with dummy data. */
image->firmware_version = firmware_version;
image->firmware_len = firmware_len;
/* Make the kernel subkey the same as the firmware signing key. */
image->kernel_subkey_sign_algorithm = algorithm;
image->kernel_subkey_sign_key = (uint8_t*) Malloc(
RSAProcessedKeySize(image->kernel_subkey_sign_algorithm));
Memcpy(image->kernel_subkey_sign_key, firmware_sign_key,
RSAProcessedKeySize(image->kernel_subkey_sign_algorithm));
image->preamble_signature = image->firmware_signature = NULL;
Memset(image->preamble, 'P', FIRMWARE_PREAMBLE_SIZE);
image->firmware_data = Malloc(image->firmware_len);

View File

@@ -36,6 +36,10 @@ typedef struct FirmwareImage {
/* Firmware Preamble. */
uint16_t firmware_version; /* Firmware Version# for preventing rollbacks.*/
uint64_t firmware_len; /* Length of the rest of the R/W firmware data. */
uint16_t kernel_subkey_sign_algorithm; /* Signature algorithm used for
* signing the kernel subkey. */
uint8_t* kernel_subkey_sign_key; /* Pre-processed public half of the kernel
* subkey signing key. */
uint8_t preamble[FIRMWARE_PREAMBLE_SIZE]; /* Remaining preamble data.*/
uint8_t* preamble_signature; /* Signature over the preamble. */
@@ -65,6 +69,10 @@ typedef struct FirmwareImage {
extern char* kVerifyFirmwareErrors[VERIFY_FIRMWARE_MAX];
/* Returns the length of the verified boot firmware preamble based on
* kernel subkey signing algorithm [algorithm]. */
uint64_t GetFirmwarePreambleLen(int algorithm);
/* Checks for the sanity of the firmware header pointed by [header_blob].
*
* On success, put signature algorithm in [algorithm], header length

View File

@@ -29,6 +29,15 @@ char* kVerifyFirmwareErrors[VERIFY_FIRMWARE_MAX] = {
"Firmware Version Rollback."
};
uint64_t GetFirmwarePreambleLen(int algorithm) {
return (FIELD_LEN(firmware_version) +
FIELD_LEN(firmware_len) +
FIELD_LEN(kernel_subkey_sign_algorithm) +
RSAProcessedKeySize(algorithm) +
FIELD_LEN(preamble));
}
int VerifyFirmwareHeader(const uint8_t* root_key_blob,
const uint8_t* header_blob,
int* algorithm,
@@ -89,22 +98,24 @@ int VerifyFirmwareHeader(const uint8_t* root_key_blob,
int VerifyFirmwarePreamble(RSAPublicKey* firmware_sign_key,
const uint8_t* preamble_blob,
int algorithm,
int firmware_sign_algorithm,
uint64_t* firmware_len) {
uint64_t len;
int preamble_len;
uint16_t firmware_version;
uint16_t kernel_subkey_sign_algorithm;
Memcpy(&firmware_version, preamble_blob, sizeof(firmware_version));
preamble_len = (FIELD_LEN(firmware_version) +
FIELD_LEN(firmware_len) +
FIELD_LEN(preamble));
Memcpy(&kernel_subkey_sign_algorithm,
preamble_blob + (FIELD_LEN(firmware_version) +
FIELD_LEN(firmware_len)),
FIELD_LEN(kernel_subkey_sign_algorithm));
preamble_len = GetFirmwarePreambleLen(kernel_subkey_sign_algorithm);
if (!RSAVerifyBinary_f(NULL, firmware_sign_key, /* Key to use */
preamble_blob, /* Data to verify */
preamble_len, /* Length of data */
preamble_blob + preamble_len, /* Expected Signature */
algorithm))
firmware_sign_algorithm))
return VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED;
Memcpy(&len, preamble_blob + FIELD_LEN(firmware_version),
@@ -117,19 +128,24 @@ int VerifyFirmwareData(RSAPublicKey* firmware_sign_key,
const uint8_t* preamble_start,
const uint8_t* firmware_data,
uint64_t firmware_len,
int algorithm) {
int signature_len = siglen_map[algorithm];
int preamble_len = (FIELD_LEN(firmware_version) +
FIELD_LEN(firmware_len) +
FIELD_LEN(preamble));;
int firmware_sign_algorithm) {
int signature_len = siglen_map[firmware_sign_algorithm];
int preamble_len;
uint16_t kernel_subkey_sign_algorithm;
uint8_t* digest = NULL;
const uint8_t* firmware_signature = NULL;
DigestContext ctx;
Memcpy(&kernel_subkey_sign_algorithm,
preamble_start + (FIELD_LEN(firmware_version) +
FIELD_LEN(firmware_len)),
FIELD_LEN(kernel_subkey_sign_algorithm));
preamble_len = GetFirmwarePreambleLen(kernel_subkey_sign_algorithm);
/* Since the firmware signature is over the preamble and the firmware data,
* which does not form a contiguous region of memory, we calculate the
* message digest ourselves. */
DigestInit(&ctx, algorithm);
DigestInit(&ctx, firmware_sign_algorithm);
DigestUpdate(&ctx, preamble_start, preamble_len);
DigestUpdate(&ctx, firmware_data, firmware_len);
digest = DigestFinal(&ctx);
@@ -139,7 +155,7 @@ int VerifyFirmwareData(RSAPublicKey* firmware_sign_key,
NULL, firmware_sign_key, /* Key to use. */
digest, /* Digest of the data to verify. */
firmware_signature, /* Expected Signature */
algorithm)) {
firmware_sign_algorithm)) {
Free(digest);
return VERIFY_FIRMWARE_SIGNATURE_FAILED;
}
@@ -151,7 +167,7 @@ int VerifyFirmware(const uint8_t* root_key_blob,
const uint8_t* verification_header_blob,
const uint8_t* firmware_blob) {
int error_code = 0;
int algorithm; /* Signing key algorithm. */
int firmware_sign_algorithm; /* Signing key algorithm. */
RSAPublicKey* firmware_sign_key = NULL;
int firmware_sign_key_len, signature_len, header_len;
uint64_t firmware_len;
@@ -172,25 +188,26 @@ int VerifyFirmware(const uint8_t* root_key_blob,
/* Only continue if header verification succeeds. */
if ((error_code = VerifyFirmwareHeader(root_key_blob, header_ptr,
&algorithm, &header_len))) {
&firmware_sign_algorithm,
&header_len))) {
debug("Couldn't verify Firmware header.\n");
return error_code; /* AKA jump to revovery. */
}
/* Parse signing key into RSAPublicKey structure since it is required multiple
* times. */
firmware_sign_key_len = RSAProcessedKeySize(algorithm);
firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_algorithm);
firmware_sign_key_ptr = header_ptr + (FIELD_LEN(header_len) +
FIELD_LEN(firmware_sign_algorithm) +
FIELD_LEN(firmware_key_version));
firmware_sign_key = RSAPublicKeyFromBuf(firmware_sign_key_ptr,
firmware_sign_key_len);
signature_len = siglen_map[algorithm];
signature_len = siglen_map[firmware_sign_algorithm];
/* Only continue if preamble verification succeeds. */
preamble_ptr = (header_ptr + header_len +
FIELD_LEN(firmware_key_signature));
if ((error_code = VerifyFirmwarePreamble(firmware_sign_key, preamble_ptr,
algorithm,
firmware_sign_algorithm,
&firmware_len))) {
RSAPublicKeyFree(firmware_sign_key);
debug("Couldn't verify Firmware preamble.\n");
@@ -200,7 +217,7 @@ int VerifyFirmware(const uint8_t* root_key_blob,
if ((error_code = VerifyFirmwareData(firmware_sign_key, preamble_ptr,
firmware_blob,
firmware_len,
algorithm))) {
firmware_sign_algorithm))) {
RSAPublicKeyFree(firmware_sign_key);
debug("Couldn't verify Firmware data.\n");
return error_code; /* AKA jump to recovery. */

View File

@@ -25,6 +25,7 @@ FirmwareImage* FirmwareImageNew(void) {
FirmwareImage* image = (FirmwareImage*) Malloc(sizeof(FirmwareImage));
if (image) {
image->firmware_sign_key = NULL;
image->kernel_subkey_sign_key = NULL;
image->preamble_signature = NULL;
image->firmware_signature = NULL;
image->firmware_data = NULL;
@@ -35,6 +36,7 @@ FirmwareImage* FirmwareImageNew(void) {
void FirmwareImageFree(FirmwareImage* image) {
if (image) {
Free(image->firmware_sign_key);
Free(image->kernel_subkey_sign_key);
Free(image->preamble_signature);
Free(image->firmware_signature);
Free(image->firmware_data);
@@ -116,6 +118,10 @@ FirmwareImage* ReadFirmwareImage(const char* input_file) {
/* Read the firmware preamble. */
StatefulMemcpy(&st,&image->firmware_version, FIELD_LEN(firmware_version));
StatefulMemcpy(&st, &image->firmware_len, FIELD_LEN(firmware_len));
StatefulMemcpy(&st, &image->kernel_subkey_sign_algorithm,
FIELD_LEN(kernel_subkey_sign_algorithm));
StatefulMemcpy(&st, image->kernel_subkey_sign_key,
RSAProcessedKeySize(image->kernel_subkey_sign_algorithm));
StatefulMemcpy(&st, image->preamble, FIELD_LEN(preamble));
/* Read firmware preamble signature. */
@@ -187,22 +193,24 @@ uint8_t* GetFirmwareHeaderBlob(const FirmwareImage* image) {
return header_blob;
}
int GetFirmwarePreambleLen(void) {
return (FIELD_LEN(firmware_version) + FIELD_LEN(firmware_len) +
FIELD_LEN(preamble));
}
uint8_t* GetFirmwarePreambleBlob(const FirmwareImage* image) {
uint8_t* preamble_blob = NULL;
MemcpyState st;
uint64_t preamble_len = GetFirmwarePreambleLen(
image->kernel_subkey_sign_algorithm);
preamble_blob = (uint8_t*) Malloc(GetFirmwarePreambleLen());
st.remaining_len = GetFirmwarePreambleLen();
preamble_blob = (uint8_t*) Malloc(preamble_len);
st.remaining_len = preamble_len;
st.remaining_buf = preamble_blob;
st.overrun = 0;
StatefulMemcpy_r(&st, &image->firmware_version, FIELD_LEN(firmware_version));
StatefulMemcpy_r(&st, &image->firmware_len, FIELD_LEN(firmware_len));
StatefulMemcpy_r(&st, &image->kernel_subkey_sign_algorithm,
FIELD_LEN(kernel_subkey_sign_algorithm));
StatefulMemcpy_r(&st, image->kernel_subkey_sign_key,
RSAProcessedKeySize(image->kernel_subkey_sign_algorithm));
StatefulMemcpy_r(&st, image->preamble, FIELD_LEN(preamble));
if (st.overrun || st.remaining_len != 0 ) { /* Underrun or Overrun. */
@@ -227,7 +235,7 @@ uint8_t* GetFirmwareBlob(const FirmwareImage* image, uint64_t* blob_len) {
*blob_len = (FIELD_LEN(magic) +
GetFirmwareHeaderLen(image) +
FIELD_LEN(firmware_key_signature) +
GetFirmwarePreambleLen() +
GetFirmwarePreambleLen(image->kernel_subkey_sign_algorithm) +
2 * firmware_signature_len +
image->firmware_len);
firmware_blob = (uint8_t*) Malloc(*blob_len);
@@ -242,7 +250,8 @@ uint8_t* GetFirmwareBlob(const FirmwareImage* image, uint64_t* blob_len) {
StatefulMemcpy_r(&st, header_blob, GetFirmwareHeaderLen(image));
StatefulMemcpy_r(&st, image->firmware_key_signature,
FIELD_LEN(firmware_key_signature));
StatefulMemcpy_r(&st, preamble_blob, GetFirmwarePreambleLen());
StatefulMemcpy_r(&st, preamble_blob,
GetFirmwarePreambleLen(image->kernel_subkey_sign_algorithm));
StatefulMemcpy_r(&st, image->preamble_signature, firmware_signature_len);
StatefulMemcpy_r(&st, image->firmware_signature, firmware_signature_len);
StatefulMemcpy_r(&st, image->firmware_data, image->firmware_len);
@@ -397,6 +406,10 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key,
FIELD_LEN(firmware_version));
DigestUpdate(&ctx, (uint8_t*) &image->firmware_len,
FIELD_LEN(firmware_len));
DigestUpdate(&ctx, (uint8_t*) &image->kernel_subkey_sign_algorithm,
FIELD_LEN(kernel_subkey_sign_algorithm));
DigestUpdate(&ctx, (uint8_t*) image->kernel_subkey_sign_key,
RSAProcessedKeySize(image->kernel_subkey_sign_algorithm));
DigestUpdate(&ctx, (uint8_t*) &image->preamble,
FIELD_LEN(preamble));
preamble_digest = DigestFinal(&ctx);
@@ -414,6 +427,10 @@ int VerifyFirmwareImage(const RSAPublicKey* root_key,
FIELD_LEN(firmware_version));
DigestUpdate(&firmware_ctx, (uint8_t*) &image->firmware_len,
FIELD_LEN(firmware_len));
DigestUpdate(&firmware_ctx, (uint8_t*) &image->kernel_subkey_sign_algorithm,
FIELD_LEN(kernel_subkey_sign_algorithm));
DigestUpdate(&firmware_ctx, (uint8_t*) image->kernel_subkey_sign_key,
RSAProcessedKeySize(image->kernel_subkey_sign_algorithm));
DigestUpdate(&firmware_ctx, (uint8_t*) &image->preamble,
FIELD_LEN(preamble));
DigestUpdate(&firmware_ctx, image->firmware_data, image->firmware_len);
@@ -464,12 +481,14 @@ int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file) {
uint8_t* firmware_signature = NULL;
uint8_t* firmware_buf = NULL;
int signature_len = siglen_map[image->firmware_sign_algorithm];
uint64_t preamble_len = GetFirmwarePreambleLen(
image->kernel_subkey_sign_algorithm);
preamble_blob = GetFirmwarePreambleBlob(image);
if (!preamble_blob)
return 0;
if (!(preamble_signature = SignatureBuf(preamble_blob,
GetFirmwarePreambleLen(),
preamble_len,
signing_key_file,
image->firmware_sign_algorithm))) {
Free(preamble_blob);
@@ -480,13 +499,13 @@ int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file) {
Free(preamble_signature);
/* Firmware signature must be calculated on preamble + firmware_data
* to avoid splicing attacks. */
firmware_buf = (uint8_t*) Malloc(GetFirmwarePreambleLen() +
firmware_buf = (uint8_t*) Malloc(preamble_len +
image->firmware_len);
Memcpy(firmware_buf, preamble_blob, GetFirmwarePreambleLen());
Memcpy(firmware_buf + GetFirmwarePreambleLen(), image->firmware_data,
Memcpy(firmware_buf, preamble_blob, preamble_len);
Memcpy(firmware_buf + preamble_len, image->firmware_data,
image->firmware_len);
if (!(firmware_signature = SignatureBuf(firmware_buf,
GetFirmwarePreambleLen() +
preamble_len +
image->firmware_len,
signing_key_file,
image->firmware_sign_algorithm))) {