mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 00:51:29 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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))) {
|
||||
|
||||
Reference in New Issue
Block a user