-
Notifications
You must be signed in to change notification settings - Fork 137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mia: improve CIC detection algorithm #1296
Conversation
mia/medium/nintendo-64.cpp
Outdated
auto Nintendo64::ipl2checksum(u32 seed, array_view<u8> rom) -> u64 | ||
{ | ||
auto rotl = [](u32 value, u32 shift) -> u32 { | ||
return (value << shift) | (value >> (32 - shift)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shifting a u32 by 32 bits is UB. Same for rotr.
Might be good to move the rotate helpers to nall/bit.hpp. We can eventually just switch to the C++ standard library implementation when we move to C++20.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, but I don't want to move it to nall as I don't want to think now how to make that a template.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just some minor suggestions.
mia/medium/nintendo-64.cpp
Outdated
while (1) { | ||
loop++; | ||
dataLast = data; | ||
data = read(dataIndex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, array_view has a built-in helper for big endian reads.
data = rom.readm(4);
rom += 4;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, though readm
already advances the pointer
mia/medium/nintendo-64.cpp
Outdated
}; | ||
|
||
auto Nintendo64::ipl2checksum(u32 seed, array_view<u8> rom) -> u64 | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: brace style
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
mia/medium/nintendo-64.cpp
Outdated
for (auto &b : buf) b = state[0]; | ||
|
||
for (loop = 0; loop < 16; loop++) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: brace style
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Currently, we detect the CIC to emulate by calculating a CRC32 over IPL3 bootcode in ROM, and keeping a database of the known IPL3s. This works because right now there are only a handful of IPL3 variants (exactly one per CIC). In preparation for libdragon releasing an open source IPL3 that could evolve and be forked an unbounded number of times, we must stop keeping a database of IPL3s. This commit changes strategy: it simulates the IPL2 checksum hash over IPL3 (which is exactly what a real N64 does at boot) and verifies if the checksum matches that expected by any of the known CIC variants. This works because open source IPL3 variants must anyway have a checksum that collides with that of CICs (which must be obtained via a second preimage attack, bruteforced on GPUs), otherwise they would not work on real hardware nor on Ares itself (which correctly simulates the boot sequence and would refuse to boot an "unsigned" IPL3).
Currently, we detect the CIC to emulate by calculating a CRC32 over IPL3 bootcode in ROM, and keeping a database of the known IPL3s. This works because right now there are only a handful of IPL3 variants (exactly one per CIC).
In preparation for libdragon releasing an open source IPL3 that could evolve and be forked an unbounded number of times, we must stop keeping a database of IPL3s.
This commit changes strategy: it simulates the IPL2 checksum hash over IPL3 (which is exactly what a real N64 does at boot) and verifies if the checksum matches that expected by any of the known CIC variants. This works because open source IPL3 variants must anyway have a checksum that collides with that of CICs (which must be obtained via a second preimage attack, bruteforced on GPUs), otherwise they would not work on real hardware nor on Ares itself (which correctly simulates the boot sequence and would refuse to boot an "unsigned" IPL3).