Difference between revisions of "RSA Registers"

From 3dbrew
Jump to navigation Jump to search
(Created page with "== Registers == {| class="wikitable" border="1" ! NAME ! PHYSICAL ADDRESS ! WIDTH |- | REG_RSACNT | 0x1000B000 | 0x04 |- | REG_RSASLOT0 | 0x1000B100 | 0x10 |- | REG_RSASLOT1 |...")
 
 
(29 intermediate revisions by 7 users not shown)
Line 1: Line 1:
== Registers ==
+
= Overview =
 +
 
 +
The RSA module is essentially a hardware-accelerated modular exponentiation engine. It is specially optimized for RSA applications, so its behavior can be incoherent when RSA's invariants are broken.
 +
 
 +
=== Observed edge cases ===
 +
* if 2 divides mod, output == 0
 +
 
 +
= Registers =
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
NAME
+
Old3DS
PHYSICAL ADDRESS
+
Name
WIDTH
+
Address
 +
!  Width
 +
!  Used by
 
|-
 
|-
| REG_RSACNT
+
| style="background: green" | Yes
 +
| [[#RSA_CNT|RSA_CNT]]
 
| 0x1000B000
 
| 0x1000B000
 
| 0x04
 
| 0x04
 +
|
 +
|-
 +
| style="background: green" | Yes
 +
| RSA_?
 +
| 0x1000B0F0
 +
| 0x04
 +
|
 
|-
 
|-
| REG_RSASLOT0
+
| style="background: green" | Yes
 +
| [[#RSA_SLOT|RSA_SLOT]]0
 
| 0x1000B100
 
| 0x1000B100
 
| 0x10
 
| 0x10
 +
|
 
|-
 
|-
| REG_RSASLOT1
+
| style="background: green" | Yes
 +
| [[#RSA_SLOT|RSA_SLOT]]1
 
| 0x1000B110
 
| 0x1000B110
 
| 0x10
 
| 0x10
 +
|
 
|-
 
|-
| REG_RSASLOT2
+
| style="background: green" | Yes
 +
| [[#RSA_SLOT|RSA_SLOT]]2
 
| 0x1000B120
 
| 0x1000B120
 
| 0x10
 
| 0x10
 +
|
 
|-
 
|-
| REG_RSASLOT3
+
| style="background: green" | Yes
 +
| [[#RSA_SLOT|RSA_SLOT]]3
 
| 0x1000B130
 
| 0x1000B130
 
| 0x10
 
| 0x10
 +
|
 
|-
 
|-
| REG_RSAKEY
+
| style="background: green" | Yes
 +
| [[#RSA_EXPFIFO|RSA_EXPFIFO]]
 +
| 0x1000B200
 +
| 0x100 (can handle u32 writes to any aligned position in the FIFO)
 +
|
 +
|-
 +
| style="background: green" | Yes
 +
| [[#RSA_MOD|RSA_MOD]]
 
| 0x1000B400
 
| 0x1000B400
 
| 0x100
 
| 0x100
 +
|
 
|-
 
|-
| REG_RSAMSG
+
| style="background: green" | Yes
 +
| [[#RSA_TXT|RSA_TXT]]
 
| 0x1000B800
 
| 0x1000B800
 
| 0x100
 
| 0x100
|-
+
|
 
|}
 
|}
  
== REG_RSACNT ==
+
== RSA_CNT ==
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
!  Bit
 
!  Bit
Line 41: Line 75:
 
|-
 
|-
 
| 0
 
| 0
| Select keyslot, error?
+
| Start (1=Enable/Busy, 0=Idle)
 
|-
 
|-
 
| 1
 
| 1
| Keyslot select related?
+
| Interrupt enable (1=enable, 0=disable)
 
|-
 
|-
 
| 4-7
 
| 4-7
| Keyslot
+
| Keyslot (Bit6-7 don't actually affect the keyslot)
 
|-
 
|-
| 8-9
+
| 8
| Should be set to 0x3 before accessing REG_RSAMSG
+
| Endianness (1=Little endian, 0=Big endian). Affects RSA_EXPFIFO, RSA_MOD, and RSA_TXT.
 +
|-
 +
| 9
 +
| Word order (1=Normal order, 0=Reversed order). Affects RSA_MOD and RSA_TXT.
 
|}
 
|}
  
== REG_RSASLOT ==
+
== RSA_SLOT ==
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Start
+
Name
 +
!  Offset
 
!  Width
 
!  Width
!  Description
 
 
|-
 
|-
 +
| [[#RSA_SLOTCNT|RSA_SLOTCNT]]
 
| 0x0
 
| 0x0
 
| 0x4
 
| 0x4
| REG_RSASLOTCNT
 
 
|-
 
|-
 +
| [[#RSA_SLOTSIZE|RSA_SLOTSIZE]]
 
| 0x4
 
| 0x4
 
| 0x4
 
| 0x4
 +
|-
 
| ?
 
| ?
|-
 
 
| 0x8
 
| 0x8
 
| 0x4
 
| 0x4
 +
|-
 
| ?
 
| ?
|-
 
 
| 0xC
 
| 0xC
 
| 0x4
 
| 0x4
 +
|}
 +
 +
== RSA_SLOTCNT ==
 +
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0
 +
| Key status (1=Key has been set, 0=Key has not been set yet)
 +
|-
 +
| 1
 +
| Key write-protect, this bit is RW. (0 = no protection, 1 = protected)
 +
|-
 +
| 2
 +
| Key read-protect, this bit is RW. (0 = no protection, 1 = protected)
 +
|-
 +
| 30-3
 
| ?
 
| ?
 +
|-
 +
| 31
 +
| Key slot protect. Makes all other bits in this reg read-only until reset
 
|}
 
|}
  
== REG_RSAKEY ==
+
Before writing RSA_EXPFIFO/RSA_MOD, bit0 here should be cleared when bit31 is already clear. Otherwise, the ARM9 will hang when attempting to write to RSA_EXPFIFO.
The RSA public key for the selected keyslot can be written here. When writing the RSA key, the key is copied to 0x1000B500-RSA_bytesize, length RSA_bytesize. The engine determines the RSA byte-size by checking where the first word of the key was written. Normally the byte-size is 0x100, for RSA-2048.
+
 
 +
== RSA_SLOTSIZE ==
 +
This contains the RSA size for this slot, in words. Normally this is 0x40 for RSA-2048.
  
== REG_RSAMSG ==
+
== RSA_EXPFIFO ==
The RSA signature can be written here, and the data read from here is the message. The message padding must be checked by software. When writing the RSA signature, the signature is copied to 0x1000B900-RSA_bytesize, length RSA_bytesize. The engine determines the RSA byte-size by checking where the first word of the signature was written.
+
The 0x100-byte private or public exponent is written to this write-only FIFO.
 +
 
 +
== RSA_MOD ==
 +
The RSA key modulus for the selected keyslot can be written here. When writing the RSA modulus, the modulus must align with the end of the register area.
 +
 
 +
Writing to RSA_MOD does not change the exponent written with RSA_EXPFIFO.  An attack based on the [[wikipedia:Pohlig-Hellman algorithm|Pohlig-Hellman algorithm]] exists to "read" the contents of RSA_EXPFIFO as a result (see [[3DS System Flaws#Hardware|3DS System Flaws]]).
 +
 
 +
== RSA_TXT ==
 +
The RSA signature can be written here, and the data read from here is the message. When writing the RSA signature, the signature must be prepended with zeroes until it is a multiple of 8 bytes, and the end of the signature must align with the end of the register area.
 +
 
 +
The PKCS message padding must be manually checked by software, as hardware will only do raw RSA operations.
 +
 
 +
== Keyslots usage ==
 +
{| class="wikitable" border="1"
 +
!  Keyslot
 +
!  Description
 +
|-
 +
| 0
 +
| Arbitrary
 +
|-
 +
| 1
 +
| [[NCCH#CXI|CXI]] access desc (following the exheader)
 +
|-
 +
| 2-3
 +
| Initialized by the ARM9 bootrom, but not used by any of the [[FIRM]]s. It's unknown what the ARM9 bootrom uses these for, if anything.
 +
|}

Latest revision as of 01:34, 6 February 2021

Overview[edit]

The RSA module is essentially a hardware-accelerated modular exponentiation engine. It is specially optimized for RSA applications, so its behavior can be incoherent when RSA's invariants are broken.

Observed edge cases[edit]

  • if 2 divides mod, output == 0

Registers[edit]

Old3DS Name Address Width Used by
Yes RSA_CNT 0x1000B000 0x04
Yes RSA_? 0x1000B0F0 0x04
Yes RSA_SLOT0 0x1000B100 0x10
Yes RSA_SLOT1 0x1000B110 0x10
Yes RSA_SLOT2 0x1000B120 0x10
Yes RSA_SLOT3 0x1000B130 0x10
Yes RSA_EXPFIFO 0x1000B200 0x100 (can handle u32 writes to any aligned position in the FIFO)
Yes RSA_MOD 0x1000B400 0x100
Yes RSA_TXT 0x1000B800 0x100

RSA_CNT[edit]

Bit Description
0 Start (1=Enable/Busy, 0=Idle)
1 Interrupt enable (1=enable, 0=disable)
4-7 Keyslot (Bit6-7 don't actually affect the keyslot)
8 Endianness (1=Little endian, 0=Big endian). Affects RSA_EXPFIFO, RSA_MOD, and RSA_TXT.
9 Word order (1=Normal order, 0=Reversed order). Affects RSA_MOD and RSA_TXT.

RSA_SLOT[edit]

Name Offset Width
RSA_SLOTCNT 0x0 0x4
RSA_SLOTSIZE 0x4 0x4
? 0x8 0x4
? 0xC 0x4

RSA_SLOTCNT[edit]

Bits Description
0 Key status (1=Key has been set, 0=Key has not been set yet)
1 Key write-protect, this bit is RW. (0 = no protection, 1 = protected)
2 Key read-protect, this bit is RW. (0 = no protection, 1 = protected)
30-3 ?
31 Key slot protect. Makes all other bits in this reg read-only until reset

Before writing RSA_EXPFIFO/RSA_MOD, bit0 here should be cleared when bit31 is already clear. Otherwise, the ARM9 will hang when attempting to write to RSA_EXPFIFO.

RSA_SLOTSIZE[edit]

This contains the RSA size for this slot, in words. Normally this is 0x40 for RSA-2048.

RSA_EXPFIFO[edit]

The 0x100-byte private or public exponent is written to this write-only FIFO.

RSA_MOD[edit]

The RSA key modulus for the selected keyslot can be written here. When writing the RSA modulus, the modulus must align with the end of the register area.

Writing to RSA_MOD does not change the exponent written with RSA_EXPFIFO. An attack based on the Pohlig-Hellman algorithm exists to "read" the contents of RSA_EXPFIFO as a result (see 3DS System Flaws).

RSA_TXT[edit]

The RSA signature can be written here, and the data read from here is the message. When writing the RSA signature, the signature must be prepended with zeroes until it is a multiple of 8 bytes, and the end of the signature must align with the end of the register area.

The PKCS message padding must be manually checked by software, as hardware will only do raw RSA operations.

Keyslots usage[edit]

Keyslot Description
0 Arbitrary
1 CXI access desc (following the exheader)
2-3 Initialized by the ARM9 bootrom, but not used by any of the FIRMs. It's unknown what the ARM9 bootrom uses these for, if anything.