Skip to content

Instantly share code, notes, and snippets.

@cleverca22
Created April 5, 2022 23:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cleverca22/c2daffd51bb8c7eaed994ca75c72aa9e to your computer and use it in GitHub Desktop.
Save cleverca22/c2daffd51bb8c7eaed994ca75c72aa9e to your computer and use it in GitHub Desktop.
const fs = require("fs");
var crypto = require("crypto");
const full_bootcode = fs.readFileSync(process.argv[2]);
const footer = full_bootcode.slice(full_bootcode.length - 284);
const payload_size = footer.readUint32LE(0);
console.log("payload size:", payload_size);
if ((payload_size + 284) == full_bootcode.length) {
console.log("payload size is valid");
}
const key_index = footer.readUint32LE(4);
console.log("key index:", key_index);
const rsa_signature = footer.slice(8, 264);
console.log("rsa sig:", rsa_signature.toString("hex"));
// from both https://github.com/librerpi/rpi-open-firmware/commit/a65026a501d2e3e5b7c5397ad377b2acb27b795b and a discord convo with another person
// The type-00 blob is signed with RSA-SHA1 with PKCS#1 v1.5 padding (signature goes just before the HMAC and is covered by it). The public key is
// The RSA signature is interpreted as a 2048-bit big-endian integer, which is decrypted using the exponent value of 65537 and one of the 4 public key modulos and exporting the result again as a 2048-bit big-endian integer.
const pubkey_pem = fs.readFileSync(process.mainModule.path + "/pubkey.pem");
const pubkey = crypto.createPublicKey(pubkey_pem);
console.log(pubkey);
var verify = crypto.createVerify("RSA-SHA1");
verify.update(full_bootcode.slice(0, payload_size));
console.log(verify.verify(pubkey, rsa_signature));
const hmac_sig = footer.slice(264, 284);
console.log("hmac sig:", hmac_sig.toString("hex"));
var keys = require("./keys");
const hmac_payload = full_bootcode.slice(0, full_bootcode.length - 20);
// OTP values 19,20,21,22, in native byte order
// this converts them to a 16 byte blob, as it would have been in ram
var otp = Buffer.alloc(20,0);
for (var i=0; i<keys.otp.length; i++) {
otp.writeUInt32LE(keys.otp[i], i*4);
}
// found at addresss 0x600035a4 on my maskrom
// `dw -b 0x600100f0 20` also reveals it in sram
var salt = Buffer.from(keys.salt);
var key = Buffer.alloc(20, 0);
var key = Buffer.alloc(20, 0);
for (var i=0; i<key.length; i++) {
key[i] = salt[i] ^ otp[i];
}
var hmac = crypto.createHmac("sha1", key);
hmac.update(hmac_payload);
const actual_hmac_sig = hmac.digest();
console.log("expected hmac sig:", actual_hmac_sig.toString("hex"));
[nix-shell:~/apps/rpi/rpi-tools/signing-tool]$ node bootcode.js ~/apps/rpi/rpi-tools/eeprom/beta-pieeprom-2022-02-04/bootcode.bin
payload size: 47720
payload size is valid
key index: 0
rsa sig: 0e153f73059fd860195cb8be466aaf7892ebf29d4a68a64bf43a3ea3788bf64a4ac373ac0a88e0ad39f07d8e3caeeb70becb674f1dbb3b092367cebcc90cb06152c9c15a8195dcd9f11b94923a6cf2bd06ad0a84f81e3dfd7c59a0841cfa3396af7f331f79f9e711162511831f70b45fb317dba0d9122389611a248fba9e98c056b857ba68dfc551cf39a4d2d67e7d2a141f5779b647abb6a8006f6c376251811f145d1d9f1657363965264d6b4bc14e6bb3dcbe2510be6987be8c4db1095f7b101568bbb1001d584d05f8c2c4e49bd4ae4433e34747d5c529b1de43552dec08bbcdff6faff41d9d632d4b9400be1248d8cffdb520b3f5e1d27ae24b126e87e2
PublicKeyObject { [Symbol(kKeyType)]: 'public' }
false
hmac sig: 98071e6ab637d7138dad66533fd1ce93ee8ffd48
expected hmac sig: 98071e6ab637d7138dad66533fd1ce93ee8ffd48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment