3DSGuy / Project_CTR

428 stars 67 forks source link

[Question] [MakeROM] Where do the RSA keys come from? #138

Closed 0xb01u closed 1 year ago

0xb01u commented 1 year ago

I am interested on working with custom CIAs of GBA injections. After studying the theory from 3Dbrew and doing some manual experiments I came across some difficulties with the signing of the NCCHs. I decided to study the code for MakeROM to understand that process better. I understand the concepts behind RSA but I never worked with it on a real-use application. Basically, now I do not understand where the RSA keys used to sign everything come from and why do those specific keys work on the 3DS. I have found that, in the cases I have tested, the RSA modulus and RSA private key used are the ones defined as tpki_rsa in src/pki/test.h, and the RSA public key is defined in src/crypto.c. Are these three specific values arbitrary or have they any relation with the 3DS's system/hardware? I have only been able to find the (public) modulus inside the NCCHs I've been working with, how does the 3DS know what key to use to verify the signature / does it always use the specific (public) key specified earlier? 3Dbrew's documentation regarding that is somewhat lacking, and MakeROM is the tool universally used to create CIAs, so I didn't know where else to ask.

liamadvance commented 1 year ago

The RSA private key that are available in the makerom source code are only for test and development content, and not for production content. The production private key cannot be obtained, as it is stored in a hardware security module that we do not have access to. This means that you will not be able to sign content for production systems, and will instead need to use a custom firmware that patches out RSA signature validation, such as Luma3DS.

0xb01u commented 1 year ago

Thanks for the response!

[...] will instead need to use a custom firmware that patches out RSA signature validation, such as Luma3DS.

Hm, I kind of assumed that, (I mean, I assume everything homebrew related only works with CFW), but I didn't know to what extent this signing is CFW-specific. Nevertheless I am assuming Luma doesn't ignore signatures altogether, right? What would be the point of signing the CIAs in MakeROM, then? If I recall correctly, in my tests when I messed up the signature of the NCCHs, an error message was issued whenever I tried to open the corresponding application in my 3DS with CFW. That would mean that some type of signature check must be being performed, regardless of whether it is the vanilla check or another completely different. Unless I messed up somewhere else and didn't notice.

jakcron commented 1 year ago

The RSA public keys are located in the 3DS bootrom / process9 in most cases. There are two sets of RSA keys used by Nintendo 3DS depending on whether it is used for development, or a retail unit.

There are some keys that exist in a hierarchy

Other keys directly sign data

The RSA private keys are not stored on the consoles, so normally it would be impossible to know them, and therefore impossible to sign ROMs.

However some of the development RSA private keys have leaked via SDK/source leaks allowing MakeROM to be able to sign ROMs for development hardware.

Sadly the same is not true for production RSA keys.

MakeROM also has test keyset, used to test the signing functionality. This test key mode has since become the conventional mode to use to generate ROMs for 3DS units running custom firmware, since the signatures are not checked. The test key used in the test keyset is just a dummy key.

0xb01u commented 1 year ago

Hm, if signatures are not checked under custom firmware, then my problems must have come from somewhere else. (Nevertheless I have already moved past those using another different approach and I don't have any particular interest in going back and figuring out what it was.)

Thank you. All this information clears my doubts and now I understand better the way MakeROM and the 3DS work.