#define BL_CMD_GET 0x00 #define BL_CMD_READ_MEM 0x11 #define BL_CMD_WRITE_MEM 0x31 #define BL_CMD_ERASE 0x44 #define BL_CMD_GET_SIZES 0xEE /* our own command. reports: {u32 osSz, u32 sharedSz, u32 eeSz} all in big endian */ #define BL_CMD_UPDATE_FINISHED 0xEF /* our own command. attempts to verify the update -> ACK/NAK. MUST be called after upload to mark it as completed */
#define BL_ERROR 0xDEADBEAF /* returned in place of command in case of exchange errors */
// compute which flash block we are starting from for (i = 0; i < sector_cnt; i++) { if (dst >= mBlFlashTable[i].address &&
dst < (mBlFlashTable[i].address + mBlFlashTable[i].length)) { break;
}
}
// now loop through all the flash blocks and see if we have to do any // 0 -> 1 transitions of a bit. If so, return false // 1 -> 0 transitions of a bit do not require an erase
offset = (uint32_t)(dst - mBlFlashTable[i].address);
ptr = mBlFlashTable[i].address; while (j < length && i < sector_cnt) { if (offset == mBlFlashTable[i].length) {
i++;
offset = 0;
ptr = mBlFlashTable[i].address;
}
//all but first and last word of padding MUST have no zero bytes for (i = SHA2_HASH_WORDS + 1; i < RSA_WORDS - 1; i++) { if (!(uint8_t)(rsaResult[i] >> 0)) return NULL; if (!(uint8_t)(rsaResult[i] >> 8)) return NULL; if (!(uint8_t)(rsaResult[i] >> 16)) return NULL; if (!(uint8_t)(rsaResult[i] >> 24)) return NULL;
}
//first padding word must have all nonzero bytes except low byte if ((rsaResult[SHA2_HASH_WORDS] & 0xff) || !(rsaResult[SHA2_HASH_WORDS] & 0xff00) || !(rsaResult[SHA2_HASH_WORDS] & 0xff0000) || !(rsaResult[SHA2_HASH_WORDS] & 0xff000000)) return NULL;
//last padding word must have 0x0002 in top 16 bits and nonzero random bytes in lower bytes if ((rsaResult[RSA_WORDS - 1] >> 16) != 2) return NULL; if (!(rsaResult[RSA_WORDS - 1] & 0xff00) || !(rsaResult[RSA_WORDS - 1] & 0xff)) return NULL;
return rsaResult;
}
staticvoid blApplyVerifiedUpdate(conststruct OsUpdateHdr *os) //only called if an update has been found to exist and be valid, signed, etc!
{ //copy shared to code, and if successful, erase shared area if (blEraseTypedArea(BL_FLASH_KERNEL, BL_FLASH_KEY1, BL_FLASH_KEY2)) if (blProgramTypedArea(__code_start, (const uint8_t*)(os + 1), os->size, BL_FLASH_KERNEL, BL_FLASH_KEY1, BL_FLASH_KEY2))
(void)blExtApiEraseSharedArea(BL_FLASH_KEY1, BL_FLASH_KEY2);
}
// header does not fit or is not aligned if (addr < __shared_start || addr > (__shared_end - overhead) || ((uintptr_t)addr & 3)) return OS_UPDT_HDR_CHECK_FAILED;
// image does not fit if (hdr->size > (__shared_end - addr - overhead)) return OS_UPDT_HDR_CHECK_FAILED;
// OS magic does not match if (memcmp(hdr->magic, mOsUpdateMagic, sizeof(hdr->magic)) != 0) return OS_UPDT_HDR_CHECK_FAILED;
// we don't allow shortcuts on success path, but we want to fail quickly if (hdr->marker == OS_UPDT_MARKER_INVALID) return OS_UPDT_HDR_MARKER_INVALID;
// download did not finish if (hdr->marker == OS_UPDT_MARKER_INPROGRESS) return OS_UPDT_HDR_MARKER_INVALID;
//make sure the pub key is known for (i = 0, rsaKey = blExtApiGetRsaKeyInfo(&numRsaKeys); i < numRsaKeys; i++, rsaKey += RSA_WORDS) { if (memcmp(rsaKey, osSigPubkey, RSA_BYTES) == 0) break;
}
if (i == numRsaKeys) {
ret = OS_UPDT_UNKNOWN_PUBKEY; //signed with an unknown key -> fail goto fail;
}
//decode sig using pubkey do {
rsaResult = rsaPubOpIterative(&rsa, osSigHash, osSigPubkey, &rsaStateVar1, &rsaStateVar2, &rsaStep);
} while (rsaStep);
if (!rsaResult) { //decode fails -> invalid sig
ret = OS_UPDT_INVALID_SIGNATURE; goto fail;
}
//verify hash match if (memcmp(expectedHash, ourHash, SHA2_HASH_SIZE) != 0) { //hash does not match -> data tampered with
ret = OS_UPDT_INVALID_SIGNATURE_HASH; // same error; do not disclose nature of hash problem goto fail;
}
//it is valid
isValid = true;
ret = OS_UPDT_SUCCESS; if (start)
*start = hdr; if (size)
*size = hdr->size;
case BL_CMD_READ_MEM: if (!seenErase) //no reading till we erase the shared area (this way we do not leak encrypted apps' plaintexts) break;
//ACK the command
(void)blLoaderSendAck(true);
//get address for (i = 0; i < 4; i++) {
uint32_t byte = blLoaderRxByte();
checksum ^= byte;
addr = (addr << 8) + byte;
}
//reject addresses outside of our fake area or on invalid checksum if (blLoaderRxByte() != checksum || addr < BL_SHARED_AREA_FAKE_ADDR || addr - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start) break;
//ack the address
(void)blLoaderSendAck(true);
//get the length
len = blLoaderRxByte();
//reject invalid checksum if (blLoaderRxByte() != (uint8_t)~len || addr + len - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start) break;
len++;
//reject reads past the end of the shared area if (addr + len - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start) break;
//ack the length
(void)blLoaderSendAck(true);
//read the data & send it
blLoaderTxBytes(__shared_start + addr - BL_SHARED_AREA_FAKE_ADDR, len);
ack = true; break;
case BL_CMD_WRITE_MEM: if (!seenErase) //no writing till we erase the shared area (this way we do not purposefully modify encrypted apps' plaintexts in a nefarious fashion) break;
//ACK the command
(void)blLoaderSendAck(true);
//get address for (i = 0; i < 4; i++) {
uint32_t byte = blLoaderRxByte();
checksum ^= byte;
addr = (addr << 8) + byte;
}
//reject addresses outside of our fake area or on invalid checksum if (blLoaderRxByte() != checksum ||
addr < BL_SHARED_AREA_FAKE_ADDR ||
addr - BL_SHARED_AREA_FAKE_ADDR > __shared_end - __shared_start) break;
addr -= BL_SHARED_AREA_FAKE_ADDR; if (addr != nextAddr) break;
//ack the address
(void)blLoaderSendAck(true);
//get the length
checksum = len = blLoaderRxByte();
len++;
//get bytes for (i = 0; i < len; i++) {
uint32_t byte = blLoaderRxByte();
checksum ^= byte;
data[i] = byte;
}
//reject writes that takes out outside fo shared area or invalid checksums if (blLoaderRxByte() != checksum || addr + len > __shared_end - __shared_start) break;
//a write starting at zero must be big enough to contain a full OS update header if (!addr) { conststruct OsUpdateHdr *hdr = (conststruct OsUpdateHdr*)data;
//verify it is at least as big as the header if (len < sizeof(struct OsUpdateHdr)) break;
//check for magic for (i = 0; i < sizeof(hdr->magic) && hdr->magic[i] == mOsUpdateMagic[i]; i++);
//verify magic check passed & marker is properly set to inprogress if (i != sizeof(hdr->magic) || hdr->marker != OS_UPDT_MARKER_INPROGRESS) break;
expectedSize = sizeof(*hdr) + hdr->size + 2 * RSA_BYTES;
} if (addr + len > expectedSize) break;
//get address for (i = 0; i < 2; i++) {
uint32_t byte = blLoaderRxByte();
checksum ^= byte;
addr = (addr << 8) + byte;
}
//reject addresses that are not our magic address or on invalid checksum if (blLoaderRxByte() != checksum || addr != BL_SHARED_AREA_FAKE_ERASE_BLK) break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.