mirror of
https://github.com/Scandal-UK/Incognito_RCM.git
synced 2024-11-22 20:06:42 +00:00
make decrypting work for unaligned blocks
This commit is contained in:
parent
76bfd54fd2
commit
5d6f606925
2 changed files with 171 additions and 111 deletions
|
@ -234,38 +234,38 @@ void dump_keys() {
|
||||||
se_aes_crypt_block_ecb(8, 0, master_key[6], master_key_source);
|
se_aes_crypt_block_ecb(8, 0, master_key[6], master_key_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_620) {
|
// if (pkg1_id->kb >= KB_FIRMWARE_VERSION_620) {
|
||||||
// derive all lower master keys in case keyblobs are bad
|
// // derive all lower master keys in case keyblobs are bad
|
||||||
if (_key_exists(master_key[pkg1_id->kb])) {
|
// if (_key_exists(master_key[pkg1_id->kb])) {
|
||||||
for (u32 i = pkg1_id->kb; i > 0; i--) {
|
// for (u32 i = pkg1_id->kb; i > 0; i--) {
|
||||||
se_aes_key_set(8, master_key[i], 0x10);
|
// se_aes_key_set(8, master_key[i], 0x10);
|
||||||
se_aes_crypt_block_ecb(8, 0, master_key[i-1], mkey_vectors[i]);
|
// se_aes_crypt_block_ecb(8, 0, master_key[i-1], mkey_vectors[i]);
|
||||||
}
|
// }
|
||||||
se_aes_key_set(8, master_key[0], 0x10);
|
// se_aes_key_set(8, master_key[0], 0x10);
|
||||||
se_aes_crypt_block_ecb(8, 0, temp_key, mkey_vectors[0]);
|
// se_aes_crypt_block_ecb(8, 0, temp_key, mkey_vectors[0]);
|
||||||
if (_key_exists(temp_key)) {
|
// if (_key_exists(temp_key)) {
|
||||||
EPRINTFARGS("Failed to derive master key. kb = %d", pkg1_id->kb);
|
// EPRINTFARGS("Failed to derive master key. kb = %d", pkg1_id->kb);
|
||||||
}
|
// }
|
||||||
} else if (_key_exists(master_key[KB_FIRMWARE_VERSION_MAX])) {
|
// } else if (_key_exists(master_key[KB_FIRMWARE_VERSION_MAX])) {
|
||||||
// handle sept version differences
|
// // handle sept version differences
|
||||||
for (u32 kb = KB_FIRMWARE_VERSION_MAX; kb >= KB_FIRMWARE_VERSION_620; kb--) {
|
// for (u32 kb = KB_FIRMWARE_VERSION_MAX; kb >= KB_FIRMWARE_VERSION_620; kb--) {
|
||||||
for (u32 i = kb; i > 0; i--) {
|
// for (u32 i = kb; i > 0; i--) {
|
||||||
se_aes_key_set(8, master_key[i], 0x10);
|
// se_aes_key_set(8, master_key[i], 0x10);
|
||||||
se_aes_crypt_block_ecb(8, 0, master_key[i-1], mkey_vectors[i]);
|
// se_aes_crypt_block_ecb(8, 0, master_key[i-1], mkey_vectors[i]);
|
||||||
}
|
// }
|
||||||
se_aes_key_set(8, master_key[0], 0x10);
|
// se_aes_key_set(8, master_key[0], 0x10);
|
||||||
se_aes_crypt_block_ecb(8, 0, temp_key, mkey_vectors[0]);
|
// se_aes_crypt_block_ecb(8, 0, temp_key, mkey_vectors[0]);
|
||||||
if (!_key_exists(temp_key)) {
|
// if (!_key_exists(temp_key)) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
memcpy(master_key[kb-1], master_key[kb], 0x10);
|
// memcpy(master_key[kb-1], master_key[kb], 0x10);
|
||||||
memcpy(master_key[kb], zeros, 0x10);
|
// memcpy(master_key[kb], zeros, 0x10);
|
||||||
}
|
// }
|
||||||
if (_key_exists(temp_key)) {
|
// if (_key_exists(temp_key)) {
|
||||||
EPRINTF("Failed to derive master key.");
|
// EPRINTF("Failed to derive master key.");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
u8 *keyblob_block = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
u8 *keyblob_block = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||||
u8 keyblob_mac[0x10] = {0};
|
u8 keyblob_mac[0x10] = {0};
|
||||||
|
@ -387,12 +387,16 @@ void dump_keys() {
|
||||||
gfx_hexdump(0, buffer, sizeof(buffer));
|
gfx_hexdump(0, buffer, sizeof(buffer));
|
||||||
//free(buffer);
|
//free(buffer);
|
||||||
|
|
||||||
verify();
|
// restore();
|
||||||
|
|
||||||
writeClientCertHash();
|
|
||||||
writeCal0Hash();
|
|
||||||
|
|
||||||
verify();
|
verify();
|
||||||
|
|
||||||
|
// writeClientCertHash();
|
||||||
|
// writeCal0Hash();
|
||||||
|
|
||||||
|
// verify();
|
||||||
|
|
||||||
|
// verify();
|
||||||
// free(tmp_copy);
|
// free(tmp_copy);
|
||||||
|
|
||||||
|
|
||||||
|
@ -686,30 +690,44 @@ bool writeData(u8 *buffer, u32 offset, u32 length)
|
||||||
|
|
||||||
bool writeHash(u32 hashOffset, u32 offset, u32 sz)
|
bool writeHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
{
|
{
|
||||||
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
|
||||||
|
|
||||||
SHA256_CTX ctx;
|
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||||
sha256_init(&ctx);
|
|
||||||
|
|
||||||
while (sz > NX_EMMC_BLOCKSIZE)
|
SHA256_CTX ctx;
|
||||||
{
|
sha256_init(&ctx);
|
||||||
|
|
||||||
readData(buffer, offset, NX_EMMC_BLOCKSIZE);
|
u32 newOffset = offset % NX_EMMC_BLOCKSIZE;
|
||||||
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
|
|
||||||
sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE);
|
|
||||||
|
|
||||||
sz -= NX_EMMC_BLOCKSIZE;
|
if (newOffset > 0 && newOffset + sz >= NX_EMMC_BLOCKSIZE)
|
||||||
offset += NX_EMMC_BLOCKSIZE;
|
{
|
||||||
}
|
u32 toRead = NX_EMMC_BLOCKSIZE - newOffset;
|
||||||
|
readData(buffer, offset, toRead);
|
||||||
|
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
|
||||||
|
sha256_update(&ctx, buffer, toRead);
|
||||||
|
|
||||||
if(sz > 0){
|
sz -= toRead;
|
||||||
|
offset += toRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (sz > NX_EMMC_BLOCKSIZE)
|
||||||
|
{
|
||||||
|
|
||||||
readData(buffer, offset, sz);
|
readData(buffer, offset, NX_EMMC_BLOCKSIZE);
|
||||||
sha256_update(&ctx, buffer, sz);
|
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
|
||||||
}
|
sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE);
|
||||||
u8 hash[0x20];
|
|
||||||
sha256_final(&ctx, hash);
|
sz -= NX_EMMC_BLOCKSIZE;
|
||||||
|
offset += NX_EMMC_BLOCKSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sz > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
readData(buffer, offset, sz);
|
||||||
|
sha256_update(&ctx, buffer, sz);
|
||||||
|
}
|
||||||
|
u8 hash[0x20];
|
||||||
|
sha256_final(&ctx, hash);
|
||||||
|
|
||||||
writeData(hash, hashOffset, 0x20);
|
writeData(hash, hashOffset, 0x20);
|
||||||
|
|
||||||
|
@ -720,63 +738,76 @@ bool writeHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
bool verifyHash(u32 hashOffset, u32 offset, u32 sz)
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
|
||||||
|
|
||||||
SHA256_CTX ctx;
|
|
||||||
sha256_init(&ctx);
|
|
||||||
|
|
||||||
while (sz > 64)
|
|
||||||
{
|
{
|
||||||
|
bool result = false;
|
||||||
|
u8 *buffer = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
readData(buffer, offset, 64);
|
SHA256_CTX ctx;
|
||||||
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
|
sha256_init(&ctx);
|
||||||
sha256_update(&ctx, buffer, 64);
|
|
||||||
|
|
||||||
sz -= 64;
|
u32 newOffset = offset % NX_EMMC_BLOCKSIZE;
|
||||||
offset += 64;
|
|
||||||
|
if (newOffset > 0 && newOffset + sz >= NX_EMMC_BLOCKSIZE)
|
||||||
|
{
|
||||||
|
u32 toRead = NX_EMMC_BLOCKSIZE - newOffset;
|
||||||
|
readData(buffer, offset, toRead);
|
||||||
|
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
|
||||||
|
sha256_update(&ctx, buffer, toRead);
|
||||||
|
|
||||||
|
sz -= toRead;
|
||||||
|
offset += toRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (sz > NX_EMMC_BLOCKSIZE)
|
||||||
|
{
|
||||||
|
|
||||||
|
readData(buffer, offset, NX_EMMC_BLOCKSIZE);
|
||||||
|
// gfx_hexdump(0, buffer + NX_EMMC_BLOCKSIZE - 8, 8);
|
||||||
|
sha256_update(&ctx, buffer, NX_EMMC_BLOCKSIZE);
|
||||||
|
|
||||||
|
sz -= NX_EMMC_BLOCKSIZE;
|
||||||
|
offset += NX_EMMC_BLOCKSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sz > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
readData(buffer, offset, sz);
|
||||||
|
sha256_update(&ctx, buffer, sz);
|
||||||
|
}
|
||||||
|
u8 hash1[0x20];
|
||||||
|
sha256_final(&ctx, hash1);
|
||||||
|
|
||||||
|
u8 hash2[0x20];
|
||||||
|
//se_calc_sha256(hash1, buffer, sz);
|
||||||
|
//sha256CalculateHash(hash1, buffer, sz);
|
||||||
|
|
||||||
|
readData(hash2, hashOffset, 0x20);
|
||||||
|
|
||||||
|
if (memcmp(hash1, hash2, 0x20))
|
||||||
|
{
|
||||||
|
EPRINTF("error: hash verification failed\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_hexdump(0, hash1, 0x20);
|
||||||
|
gfx_hexdump(0, hash2, 0x20);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sz > 0){
|
u32 certSize()
|
||||||
|
|
||||||
|
|
||||||
readData(buffer, offset, sz);
|
|
||||||
sha256_update(&ctx, buffer, sz);
|
|
||||||
}
|
|
||||||
u8 hash1[0x20];
|
|
||||||
sha256_final(&ctx, hash1);
|
|
||||||
|
|
||||||
u8 hash2[0x20];
|
|
||||||
//se_calc_sha256(hash1, buffer, sz);
|
|
||||||
//sha256CalculateHash(hash1, buffer, sz);
|
|
||||||
|
|
||||||
readData(hash2, hashOffset, 0x20);
|
|
||||||
|
|
||||||
if (memcmp(hash1, hash2, 0x20))
|
|
||||||
{
|
{
|
||||||
EPRINTF("error: hash verification failed\n");
|
u32 buffer;
|
||||||
}
|
readData((u8 *)&buffer, 0x0AD0, sizeof(buffer));
|
||||||
else
|
// EPRINTF("certSize");
|
||||||
{
|
// gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
|
||||||
result = true;
|
return buffer;
|
||||||
}
|
|
||||||
|
|
||||||
gfx_hexdump(0, hash1, 0x20);
|
|
||||||
gfx_hexdump(0, hash2, 0x20);
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 certSize()
|
|
||||||
{
|
|
||||||
u32 buffer;
|
|
||||||
readData((u8 *)&buffer, 0x0AD0, sizeof(buffer));
|
|
||||||
// EPRINTF("certSize");
|
|
||||||
// gfx_hexdump(0, (u8 *)&buffer, sizeof(buffer));
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 calibrationDataSize()
|
u32 calibrationDataSize()
|
||||||
|
@ -854,23 +885,51 @@ void backup(){
|
||||||
f_open(&fp, "sd:/prodinfoENC.bin", FA_CREATE_NEW | FA_WRITE);
|
f_open(&fp, "sd:/prodinfoENC.bin", FA_CREATE_NEW | FA_WRITE);
|
||||||
size = 0x3FBC00;
|
size = 0x3FBC00;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
while(size > NX_EMMC_BLOCKSIZE){
|
while(size > 0){
|
||||||
nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
|
nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
|
||||||
f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
f_write(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
||||||
offset ++;
|
offset ++;
|
||||||
size -= NX_EMMC_BLOCKSIZE;
|
size -= NX_EMMC_BLOCKSIZE;
|
||||||
}
|
}
|
||||||
if(size > 0){
|
// if(size > 0){
|
||||||
nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
|
// nx_emmc_part_read(&storage, prodinfo_part, offset, 1, bufferNX);
|
||||||
f_write(&fp, bufferNX, size, NULL);
|
// f_write(&fp, bufferNX, size, NULL);
|
||||||
}
|
// }
|
||||||
|
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
|
||||||
gfx_printf("\n%kBackup encrypted done!", 4);
|
gfx_printf("\n%kBackup encrypted done!", colors[4]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool restore(){
|
||||||
|
FIL fp;
|
||||||
|
if(f_open(&fp, "sd:/prodinfoENC.bin", FA_READ) != FR_OK){
|
||||||
|
gfx_printf("\n%Cannot open prodinfEnc.bin!", 4);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
u8 bufferNX[NX_EMMC_BLOCKSIZE];
|
||||||
|
|
||||||
|
u32 size = 0x3FBC00;
|
||||||
|
u32 offset = 0;
|
||||||
|
while(size > 0){
|
||||||
|
f_read(&fp, bufferNX, NX_EMMC_BLOCKSIZE, NULL);
|
||||||
|
nx_emmc_part_write(&storage, prodinfo_part, offset, 1, bufferNX);
|
||||||
|
offset ++;
|
||||||
|
size -= NX_EMMC_BLOCKSIZE;
|
||||||
|
}
|
||||||
|
// if(size > 0){
|
||||||
|
// f_read(&fp, bufferNX, size, NULL);
|
||||||
|
// nx_emmc_part_write(&storage, prodinfo_part, offset, 1, bufferNX);
|
||||||
|
// f_write(&fp, bufferNX, size, NULL);
|
||||||
|
// }
|
||||||
|
|
||||||
|
f_close(&fp);
|
||||||
|
|
||||||
|
gfx_printf("\n%Restore encrypted done!", 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// bool erase(u32 offset, u32 sz)
|
// bool erase(u32 offset, u32 sz)
|
||||||
// {
|
// {
|
||||||
// u8 zero = 0;
|
// u8 zero = 0;
|
||||||
|
|
|
@ -25,5 +25,6 @@ bool writeData(u8 *buffer, u32 offset, u32 length);
|
||||||
bool writeClientCertHash();
|
bool writeClientCertHash();
|
||||||
bool writeCal0Hash();
|
bool writeCal0Hash();
|
||||||
bool verify();
|
bool verify();
|
||||||
|
bool restore();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue