PSI-Rockin / Corgi3DS

An LLE dog-themed 3DS emulator
GNU General Public License v3.0
219 stars 20 forks source link

FIRM section verification fails under Linux #4

Closed profi200 closed 5 years ago

profi200 commented 5 years ago

In this post https://github.com/PSI-Rockin/Corgi3DS/issues/2#issuecomment-492749060 i already explained what happens. This seems to be an entirely different issue.

Msg: 6eff209c8f4af61f062413d602ca6b4da1eb5ab9b6f1a2ab226a711da2ccc27c74de1741143bf69058284caf444f92a45aafd5a068043323d48af1d0ec05564ebc79b55134e91a86c3788c97bc29d5a58a8a45255843b89122c7804542f72677c8da5eb7429baf18f7a8b02e8bb940fe990e9dc97edcf49ddb18092c28206e746753cc7c6e92362aa8d546b38d9e8d4311a6b1930da14897807e304b5e1ec0856eefd62ceaeef28b08bd80397a181560ae6fce39d09c39dc3ded8c870ab6abce2894940c0e9c4174f0131a0da0747c4a7a42c9ec3487f109e252b7a9b865ae477895e8d6a42a0717c40bccc7a735f33b1e3766ab0e4b5d681bab410734ab62b0
Exp: 10001
Mod: decfb6fc...
Result: 2d964f9e12652eb986ae5da2b55e654afb05a9d088adbd5a9b34d9406278fcaa6143f01b86b81a4e3ab047a8655f3e3befea4fd87037fa45187ce909d991ab5a839e54e23f51d628d4c90b9995205e77183f850b24bd75cf304193cb6f8e1d107ce74a0f9bf097464d043cd190cc6f0eb8e8c70eb99e0b91fb359820fae21d5b9175eb93eb0c55562f74534b27b219df7e67b5f9d300667aeb5003030305e9bb35bd25b7d6918ae7e969cc933185f070534cdd345881827c36c0f65692e741e6c8b93e2948d1d8a8b2648fe250e5a4ccf8f2137e94c39090bf51f4336aa1a2b8f4f2f881295179143b12cf11c1b8ed1533943beb191b792de265fa2226a2c

Working fine as you can see. The signature matches the one from here: http://www.sighax.com/ Bootrom error is the following:

BOOTROM 8046
ERRCODE: 00FB00FF
         DECFFFFF FFFFFFFF
         00000000 00000000

I tried replacing libgmp and the result is the same:

diff --git a/Corgi3DS.pro b/Corgi3DS.pro
index 1e9867a..bea4c6b 100644
--- a/Corgi3DS.pro
+++ b/Corgi3DS.pro
@@ -64,4 +64,4 @@ HEADERS += \

 INCLUDEPATH += /usr/local/include

-LIBS += -L/usr/local/lib -lgmpxx -lgmp
+LIBS += -L/usr/local/lib -lmbedcrypto
diff --git a/src/core/arm9/rsa.cpp b/src/core/arm9/rsa.cpp
index 26ee747..eeea5a7 100644
--- a/src/core/arm9/rsa.cpp
+++ b/src/core/arm9/rsa.cpp
@@ -216,67 +216,33 @@ void RSA::write32(uint32_t addr, uint32_t value)
     }
 }

-void RSA::convert_to_bignum(uint8_t *src, mpz_t dest)
-{
-    mpz_t base, temp;
-
-    mpz_init(temp);
-    mpz_init_set_ui(dest, 0);
-    mpz_init_set_ui(base, 1);
-    for (int i = 0xFF; i >= 0; i--)
-    {
-        mpz_set_ui(temp, src[i]);
-        mpz_mul(temp, temp, base);
-        mpz_add(dest, dest, temp);
-        mpz_mul_ui(base, base, 256);
-    }
-}
-
 void RSA::do_rsa_op()
 {
-    mpz_t gmp_msg, gmp_b, gmp_e, gmp_m;
+    mbedtls_mpi mpi_b, mpi_e, mpi_m;

     RSA_KeySlot* key = &keys[RSA_CNT.keyslot];
-    mpz_inits(gmp_msg, NULL);
-    convert_to_bignum((uint8_t*)msg, gmp_b);
-    convert_to_bignum((uint8_t*)key->exp, gmp_e);
-    convert_to_bignum((uint8_t*)key->mod, gmp_m);
-
-    printf("Msg: %s\n", mpz_get_str(NULL, 16, gmp_b));
-    printf("Exp: %s\n", mpz_get_str(NULL, 16, gmp_e));
-    printf("Mod: %s\n", mpz_get_str(NULL, 16, gmp_m));
-
-    mpz_powm(gmp_msg, gmp_b, gmp_e, gmp_m);
-    printf("Result: %s\n", mpz_get_str(NULL, 16, gmp_msg));
-
-    convert_from_bignum(gmp_msg, msg);
+    mbedtls_mpi_init(&mpi_b);
+    mbedtls_mpi_init(&mpi_e);
+    mbedtls_mpi_init(&mpi_m);
+    mbedtls_mpi_read_binary(&mpi_b, msg, 0x100);
+    mbedtls_mpi_read_binary(&mpi_e, key->exp, 0x100);
+    mbedtls_mpi_read_binary(&mpi_m, key->mod, 0x100);
+
+    char tmpStr[0x100 * 2 + 1];
+    size_t olen;
+    mbedtls_mpi_write_string(&mpi_b, 16, tmpStr, 0x100 * 2 + 1, &olen);
+    printf("Msg: %s\n", tmpStr);
+    mbedtls_mpi_write_string(&mpi_e, 16, tmpStr, 0x100 * 2 + 1, &olen);
+    printf("Exp: %s\n", tmpStr);
+    mbedtls_mpi_write_string(&mpi_m, 16, tmpStr, 0x100 * 2 + 1, &olen);
+    printf("Mod: %s\n", tmpStr);
+
+    mbedtls_mpi mpi_msg;
+    mbedtls_mpi_init(&mpi_msg);
+    mbedtls_mpi_exp_mod(&mpi_msg, &mpi_b, &mpi_e, &mpi_m, nullptr);
+    mbedtls_mpi_write_string(&mpi_msg, 16, tmpStr, 0x100 * 2 + 1, &olen);
+    printf("Result: %s\n", tmpStr);
+
+    mbedtls_mpi_write_binary(&mpi_msg, msg, 0x100);
     int9->assert_irq(22);
 }
-
-void RSA::convert_from_bignum(mpz_t src, uint8_t* dest)
-{
-    std::string str = mpz_get_str(NULL, 16, src);
-
-    while (str.length() < 0x200)
-        str = '0' + str;
-
-    for (int i = 0; i < 0x100; i++)
-    {
-        uint8_t chr1 = str[(i * 2)];
-        uint8_t chr2 = str[(i * 2) + 1];
-
-        if (chr1 >= 'a')
-            chr1 = (chr1 - 'a') + 10;
-        else
-            chr1 -= '0';
-
-        if (chr2 >= 'a')
-            chr2 = (chr2 - 'a') + 10;
-        else
-            chr2 -= '0';
-
-        uint8_t byte = (chr1 << 4) | chr2;
-
-        dest[i] = byte;
-    }
-}
diff --git a/src/core/arm9/rsa.hpp b/src/core/arm9/rsa.hpp
index 2bac61c..9448eef 100644
--- a/src/core/arm9/rsa.hpp
+++ b/src/core/arm9/rsa.hpp
@@ -3,7 +3,7 @@
 #include <cstdint>
 #include <string>

-#include <gmp.h>
+#include <mbedtls/bignum.h>

 struct RSA_CNT_REG
 {
@@ -35,8 +35,6 @@ class RSA
         int msg_ctr;

         void do_rsa_op();
-        void convert_to_bignum(uint8_t* src, mpz_t dest);
-        void convert_from_bignum(mpz_t src, uint8_t* dest);
     public:
         RSA(Interrupt9* int9);
PSI-Rockin commented 5 years ago

This probably means our issue is not related to libgmp then. Can you produce a log of all the NAND reads it does? eMMC CMD18 is what's responsible for a read.

profi200 commented 5 years ago

From log.txt:

[EMMC] Read multiple blocks (start: $00000000 blocks: $00000001)
[EMMC] Read multiple blocks (start: $0B130000 blocks: $00000001)
[EMMC] Read multiple blocks (start: $0B530000 blocks: $00000001)
[EMMC] Read multiple blocks (start: $0B130000 blocks: $00000001)
[EMMC] Read multiple blocks (start: $0B130200 blocks: $0000005A)
[EMMC] Read multiple blocks (start: $0B130200 blocks: $0000005A)
[EMMC] Read multiple blocks (start: $0B130200 blocks: $0000005A)
[EMMC] Read multiple blocks (start: $0B530000 blocks: $00000001)
PSI-Rockin commented 5 years ago

So it reads the NCSH and FIRM section headers correctly (0x00000000, 0x0B130000). However, it fails when reading the first FIRM section (0x0B130200).

This means one of two things: either the AES decryption is messed up, or the SHA hash is messed up. I don't see why either would fail, so I need more logging.

Is there a easier real-time way to contact you? I have a Discord server for Corgi3DS - https://discord.gg/xFSDSeM or if that's not to your liking, we could also talk on IRC.

profi200 commented 5 years ago

I'm always on IRC. EFnet #3dsdev

PSI-Rockin commented 5 years ago

The latest commits fix two bugs that caused the FIRM to not boot, so I'm closing this issue.