Changes

6,489 bytes added ,  11:30, 28 July 2020
no edit summary
Line 12: Line 12:  
| 4
 
| 4
 
| RW
 
| RW
 +
|-
 +
| style="background: green" | Yes
 +
| [[#AES_MACEXTRABLKCNT|AES_MACBLKCNT]]
 +
| 0x10009004
 +
| 2
 +
| W
 
|-
 
|-
 
| style="background: green" | Yes
 
| style="background: green" | Yes
 
| [[#AES_BLKCNT|AES_BLKCNT]]
 
| [[#AES_BLKCNT|AES_BLKCNT]]
| 0x10009004
+
| 0x10009006
| 4
+
| 2
| W?
+
| W
 
|-
 
|-
 
| style="background: green" | Yes
 
| style="background: green" | Yes
Line 114: Line 120:  
| 11
 
| 11
 
| Flush read fifo (1=Clear read FIFO)
 
| Flush read fifo (1=Clear read FIFO)
 +
|-
 +
| 12-13
 +
| Write FIFO DMA size (0=16, 1=12, 2=8, 3=4 words)
 +
|-
 +
| 14-15
 +
| Read FIFO DMA size (0=4, 1=8, 2=12, 3=16 words)
 
|-
 
|-
 
| 18-16
 
| 18-16
Line 138: Line 150:  
| 25
 
| 25
 
| Input word order (1=Normal order, 0=Reversed order)
 
| Input word order (1=Normal order, 0=Reversed order)
|-
   
|-
 
|-
 
| 26
 
| 26
| Update keyslot (selects the keyslot specified by REG_AESKEYSEL when this bit is set)
+
| Update keyslot (selects the keyslot specified by AES_KEYSEL when this bit is set)
 
|-
 
|-
 
| 29-27
 
| 29-27
Line 153: Line 164:  
|}
 
|}
   −
When bit31 is clear, the AES engine will handle keyslot-selection when bit26 is set immediately. When bit31 is set, the AES engine won't handle bit26 immediately, instead the AES engine will automatically handle the already-set bit26 once bit31 clears(current AES operation finishes).
+
When bit31 is set, this register essentially becomes locked and doesn't change when written to. However if bit26 is "set", keyslot-selection is cued to be handled when bit31 is cleared.
    
Clearing bit31 while the AES engine is doing crypto will result in the AES engine stopping crypto, once it finishes processing the current block.
 
Clearing bit31 while the AES engine is doing crypto will result in the AES engine stopping crypto, once it finishes processing the current block.
 +
 +
Read/Write FIFO counts and the MAC status can never be set by writing to AES_CNT, they are read-only.
 +
 +
Changing the input word order triggers the key/keyX/keyY FIFOs to be flushed.
 +
 +
== AES_MACEXTRABLKCNT ==
 +
(CCM-MAC extra data length)>>4, i.e. the number of block of CCM-MAC extra data.
    
== AES_BLKCNT ==
 
== AES_BLKCNT ==
 +
(Data length)>>4, i.e. the number of blocks to process
 +
 +
== AES_WRFIFO/AES_RDFIFO ==
 +
The AES engine can accept up to 64 bytes of input data (16 32-bit words) and can hold up to 64 bytes of output data at a time (for a total of 128 bytes of buffered data). Bits 12-13 and 14-15 in AES_CNT configure the DMA request for the relevant FIFO (see above).
   −
{| class="wikitable" border="1"
+
The input data for the AES crypto operation is written to AES_WRFIFO, the output data is read from AES_RDFIFO.
!  Bit
  −
!  Description
  −
|-
  −
| 16-31
  −
| (Data length)>>4
  −
|}
     −
== AES_WRFIFO/AES_RDFIFO ==
+
Reading from AES_RDFIFO when there's no data available in the RDFIFO will result in reading the last word that was in the RDFIFO.
Up to 128 bytes of input data can be buffered.
     −
The input data for the AES crypto operation is written to REG_AESWRFIFO, the output data is read from REG_AESRDFIFO.
+
When triggering either RDFIFO or WRFIFO to be flushed, the AES Engine does not clear either buffer.
   −
Reading from REG_AESRDFIFO when there's no data available in the RDFIFO will result in reading the last word that was in the RDFIFO.
+
Word order and endianness can be changed between each read/write to these FIFOs. However changing the word order when writing to WRFIFO can cause the word to be written outside the current block, leaving uninitialized data in its place. Attempts to change endianness or word order are not honored when reading from RDFIFO when no more data is available.
    
== AES_KEYCNT ==
 
== AES_KEYCNT ==
Line 217: Line 232:     
== Endianness and word order ==
 
== Endianness and word order ==
When writing to the AES_CTR or AES_MAC register, the hardware will process the written data according to the current input endianness specified in AES_CNT. However, the current specified input word order will not be honored for this register, and always defaults to reversed word order. Therefore, for normal word order, the reversal must be carried out manually if required.
+
 
 +
=== AES_CNT.input_endianness ===
 +
 
 +
Swaps the bytes of 32-bit writes to AES_CTR, AES_WRFIFO, AES_KEY*FIFO according to specified endianness. AES_MAC?
 +
 
 +
=== AES_CNT.output_endianness ===
 +
 
 +
Swaps the bytes of 32-bit reads from AES_RDFIFO.
 +
 
 +
=== AES_CNT.input_word_order ===
 +
 
 +
If reversed, writes to AES_KEY*FIFO and AES_WRFIFO fill the FIFO backwards. For AES_WRFIFO, this means that every 16-byte block will have its words in the reverse order, but the order of these blocks remains the same. AES_CTR is unaffected by this field. AES_MAC?
 +
 
 +
=== AES_CNT.output_word_order ===
 +
 
 +
If reversed, reads from AES_RDFIFO will drain the FIFO backwards. This means that every 16-byte output block will have its words in the reverse order, but the order of these blocks remains the same.
 +
 
 +
== CCM mode pitfall ==
 +
Non-standard AES-CCM behaviour is observed on [[APT:Wrap|Wrap]]/[[APT:Unwrap|Unwrap]] function. According to [https://tools.ietf.org/html/rfc3610 RFC 3610], the first block B_0 for authentication should be generated from the message length and some other parameters. Using these function, it seems that the message length is aligned up to 16 when generating B_0. This makes the generated MAC not compliant with the standard when (inputsize-noncesize)%16!=0. It is very likely that this non-standard behaviour happens on the hardware level, but not confirmed yet.
    
== Keyslot ranges ==
 
== Keyslot ranges ==
Line 250: Line 283:  
| SSL cert key.
 
| SSL cert key.
 
| Same for all.
 
| Same for all.
| Same for all.
+
| Same for all, normalkeys-only.
| style="background: red" | No
+
| style="background: orange" | The keyXs are console-unique, however the normalkeys setup by Boot9 later during keyinit are not console-unique.
 
|-
 
|-
 
| 0x10-0x17
 
| 0x10-0x17
 
| -
 
| -
| Not set.
+
| Set for all except 0x11..0x13. Keydata is different for these.
| Not set.
+
| Normalkey, same for all except the last 4 are all different.
 
| -
 
| -
 
|-
 
|-
Line 262: Line 295:  
| Never used.
 
| Never used.
 
| Same for all.
 
| Same for all.
| Same for all.
+
| Same for all, normalkeys-only.
| style="background: green" | Yes
+
| style="background: orange" | The keyXs are console-unique, however the normalkeys setup by Boot9 later during keyinit are not console-unique.
 
|-
 
|-
 
| 0x1C-0x1F
 
| 0x1C-0x1F
 
| Never used.
 
| Never used.
 
| Same for all.
 
| Same for all.
| Same for all.
+
| Same for all, normalkeys-only.
| style="background: green" | Yes
+
| style="background: orange" | The keyXs are console-unique, however the normalkeys setup by Boot9 later during keyinit are not console-unique.
 
|-
 
|-
 
| 0x20-0x23
 
| 0x20-0x23
 
| Never used.
 
| Never used.
 
| Same for all.
 
| Same for all.
| Same for all.
+
| Same for all, normalkeys-only.
| style="background: orange" | Normalkey is not. keyX is. keyY unknown.
+
| style="background: orange" | The keyXs are console-unique, however the normalkeys setup by Boot9 later during keyinit are not console-unique.
 
|-
 
|-
 
| 0x24
 
| 0x24
 
| Never used.
 
| Never used.
 
| Individually set.
 
| Individually set.
| Individually set.
+
| Individually set, normalkey-only.
| style="background: orange" | Normalkey is not. keyX is. keyY unknown.
+
| style="background: orange" | The keyX is console-unique, however the normalkey setup by Boot9 later during keyinit is not console-unique.
 
|-
 
|-
 
| 0x25-0x27
 
| 0x25-0x27
 
| -
 
| -
 
| Not set.
 
| Not set.
| Not set.
+
| Same for all, normalkeys-only. Same keydata as keyslot 0x24.
| -
+
| style="background: red" | No
 
|-
 
|-
 
| 0x28-0x2B
 
| 0x28-0x2B
 
| Never used.
 
| Never used.
 
| Individually set.
 
| Individually set.
| Individually set.
+
| Individually set, normalkeys-only. Keyslot 0x28 has same normalkey as keyslot 0x24.
| style="background: orange" | Normalkey is not. keyX is. keyY unknown.
+
| style="background: orange" | The keyX is console-unique, however the normalkey setup by Boot9 later during keyinit is not console-unique.
 
|-
 
|-
 
| 0x2C-0x2F
 
| 0x2C-0x2F
 
| Various uniques.
 
| Various uniques.
 
| Same for all.
 
| Same for all.
| Same for all, probably.
+
| Same for all, normalkeys-only.
 
| style="background: red" | No
 
| style="background: red" | No
 
|-
 
|-
Line 304: Line 337:  
| Various uniques.
 
| Various uniques.
 
| Same for all.
 
| Same for all.
| Same for all, probably.
+
| Same for all, normalkeys-only.
 
| style="background: red" | No
 
| style="background: red" | No
 
|-
 
|-
Line 310: Line 343:  
| Various uniques.
 
| Various uniques.
 
| Same for all.
 
| Same for all.
| Same for all, probably.
+
| Same for all, normalkeys-only.
 
| style="background: red" | No
 
| style="background: red" | No
 
|-
 
|-
Line 316: Line 349:  
| Various uniques.
 
| Various uniques.
 
| Same for all.
 
| Same for all.
| Different for all.
+
| Same for all, normalkeys-only.
 
| style="background: red" | No
 
| style="background: red" | No
 
|-
 
|-
Line 322: Line 355:  
| Various uniques.
 
| Various uniques.
 
| Individually set.
 
| Individually set.
| Individually set.
+
| Individually set, normalkeys-only. Keyslot 0x3C has same normalkey as 0x38-0x3B.
 
| style="background: red" | No
 
| style="background: red" | No
 
|}
 
|}
Line 366: Line 399:  
|-
 
|-
 
| 0x0B
 
| 0x0B
| This is console-unique. This keyslot is used for the NAND [[Title_Database|dbs]] images AESMACs, and the [[Nand/private/movable.sed]] AESMAC(when used).
+
| This is console-unique. This keyslot is used for the NAND [[Title_Database|dbs]] images AES-CMACs, and the [[Nand/private/movable.sed]] AES-CMAC(when used).
 
| See above keyslot info.
 
| See above keyslot info.
 
| See above keyslot info.
 
| See above keyslot info.
Line 426: Line 459:  
|-
 
|-
 
| 0x19
 
| 0x19
| New3DS gamecard [[Savegames|savedata]] AES-MAC key.
+
| New3DS gamecard [[Savegames|savedata]] AES-CMAC key.
    
Equivalent of keyslot 0x33, used when a [[NCSD]] flag is set to a certain value (implemented with [[9.3.0-21|9.3.0-X]]).
 
Equivalent of keyslot 0x33, used when a [[NCSD]] flag is set to a certain value (implemented with [[9.3.0-21|9.3.0-X]]).
Line 451: Line 484:  
|-
 
|-
 
| 0x24
 
| 0x24
| AGB_FIRM savegame AES-MAC key.
+
| AGB_FIRM savegame AES-CMAC key.
 
| Bootrom.
 
| Bootrom.
 
| AGB/NATIVE_FIRM.
 
| AGB/NATIVE_FIRM.
Line 497: Line 530:  
|-
 
|-
 
| 0x30
 
| 0x30
| SD/NAND AES-MAC key.
+
| SD/NAND AES-CMAC key.
   −
This keyY is initialized via [[Nand/private/movable.sed|movable.sed]]. This is used for calculating the AESMACs under SD [[SD_Filesystem|/Nintendo 3DS/<ID0>/<ID1>/]] (except [[DSiWare_Exports]]) and [[Flash_Filesystem|NAND]] /data/.
+
This keyY is initialized via [[Nand/private/movable.sed|movable.sed]]. This is used for calculating the AES-CMACs under SD [[SD_Filesystem|/Nintendo 3DS/<ID0>/<ID1>/]] (except [[DSiWare_Exports]]) and [[Flash_Filesystem|NAND]] /data/.
 
| Bootrom.
 
| Bootrom.
 
| NATIVE_FIRM.
 
| NATIVE_FIRM.
Line 524: Line 557:  
|-
 
|-
 
| 0x33
 
| 0x33
| Gamecard [[Savegames|savedata]] AES-MAC.
+
| Gamecard [[Savegames|savedata]] AES-CMAC.
 
| Bootrom.
 
| Bootrom.
 
| NATIVE_FIRM.
 
| NATIVE_FIRM.
Line 542: Line 575:  
| Movable.sed key.
 
| Movable.sed key.
   −
This is the keyslot used for movable.sed encryption + AES-MAC with the import/export [[FSPXI:ImportIntegrityVerificationSeed|commands]].
+
This is the keyslot used for movable.sed encryption + AES-CBC MAC with the import/export [[FSPXI:ImportIntegrityVerificationSeed|commands]]. The keyYs used for crypto/CMAC are different, but both can be found in process9 rodata.
| Bootrom.
   
| Bootrom.
 
| Bootrom.
 +
| NATIVE_FIRM.
 
| -
 
| -
 
| Yes
 
| Yes
Line 585: Line 618:  
| DSiWare export key.
 
| DSiWare export key.
   −
This keyY is initialized via [[Nand/private/movable.sed|movable.sed]]. This is used for calculating the AESMACs for SD [[DSiWare_Exports]].
+
This keyY is initialized via [[Nand/private/movable.sed|movable.sed]]. This is used for calculating the AES-CMACs for SD [[DSiWare_Exports]].
 
| Bootrom.
 
| Bootrom.
 
| NATIVE_FIRM.
 
| NATIVE_FIRM.
Line 607: Line 640:  
| NATIVE_FIRM.
 
| NATIVE_FIRM.
 
| -
 
| -
 +
| Yes
 +
|-
 +
| 0x3F
 +
| Used for various internal Boot9 crypto operations, different keydata for each one. Used to decrypt the [[OTP_Registers|OTP]], the FIRM sections when [[Bootloader#Non-NAND_FIRM_boot|booting from non-NAND]], and when generating the console-unique keys.
 +
 +
The keydata for this keyslot is overwritten with other keydata before booting FIRM. This keyslot is not known to be used post-Boot9.
 +
| Bootrom.
 +
| Bootrom.
 +
| Bootrom.
 
| Yes
 
| Yes
 
|}
 
|}
    
=== Updating keydata ===
 
=== Updating keydata ===
The contents of the keyslot specified in REG_AESKEYCNT can be updated by consecutively writing four words to REG_AESKEYXFIFO (keyX), REG_AESKEYYFIFO(keyY), or REG_AESKEYFIFO (normalkey).
+
The contents of the keyslot specified in AES_KEYCNT can be updated by consecutively writing four words to AES_KEYXFIFO (keyX), AES_KEYYFIFO(keyY), or AES_KEYFIFO (normalkey).
   −
After writing to a keyslot, the keyslot must be selected again(write REG_AESKEYSEL + set REG_AESCNT bit26), even when writing to the same keyslot. Writing the last word to a key FIFO immediately after selecting a keyslot will not affect the keyslot keydata that gets used at that time, the new keydata will not get used until the keyslot gets selected again.
+
After writing to a keyslot, the keyslot must be selected again(write AES_KEYSEL + set AES_CNT bit26), even when writing to the same keyslot. Writing the last word to a key FIFO immediately after selecting a keyslot will not affect the keyslot keydata that gets used at that time, the new keydata will not get used until the keyslot gets selected again.
    
Writing to the key FIFOs with byte writes results in the AES engine converting the byte to a word for setting the key word, with this: word = (byteval) | (byteval<<8) | (byteval<<16) | (byteval<<24). The result is the same regardless of which FIFO register byte was written to.
 
Writing to the key FIFOs with byte writes results in the AES engine converting the byte to a word for setting the key word, with this: word = (byteval) | (byteval<<8) | (byteval<<16) | (byteval<<24). The result is the same regardless of which FIFO register byte was written to.
   −
The TWL keyslots 0x00-0x03 can be set directly by writing to the REG_AESKEY0-REG_AESKEY3 registers.
+
The TWL keyslots 0x00-0x03 can be set directly by writing to the AES_KEY0-AES_KEY3 registers.
   −
The key FIFOs can be written simultaneously. For example, executing the following 4 times will result in the keyX and keyY being set to all-zero(unknown for normalkey): memset(0x10009100, 0, 0x100);
+
The key FIFOs can be written simultaneously. For example, executing the following will result in the keyX and keyY being set to all-zero(unknown for normalkey): memset(0x10009100, 0, 0x100);
   −
Each key FIFO has a 0x10-byte tmp-buffer for storing the words written to that FIFO. Once the last word is written to a key FIFO, the filled tmp-buffer is then written to the key-data for the keyslot selected by REG_AESKEYCNT at the time the last word was written.
+
Each key FIFO has a 0x10-byte tmp-buffer for storing the words written to that FIFO. Once the last word is written to a key FIFO, the filled tmp-buffer is then written to the key-data for the keyslot selected by AES_KEYCNT at the time the last word was written.
    
=== Hardware key generator ===
 
=== Hardware key generator ===
Line 631: Line 673:  
! Mode
 
! Mode
 
! Formula
 
! Formula
! Secret Constant C
   
|-
 
|-
 
| 3DS
 
| 3DS
| NormalKey = (((KeyX ROL 2) XOR KeyY) + C) ROR 41
+
| NormalKey = (((KeyX ROL 2) XOR KeyY) + C1) ROR 41
| Not publicly disclosed.
   
|-
 
|-
 
| DSi
 
| DSi
| NormalKey = ((KeyX XOR KeyY) + C) ROL 42
+
| NormalKey = ((KeyX XOR KeyY) + C2) ROL 42
|
   
|}
 
|}
   Line 646: Line 685:  
=== FIRM-launch key clearing ===
 
=== FIRM-launch key clearing ===
 
Starting with [[9.0.0-20]] the Process9 FIRM-launch code now "clears" the following AES keyslots, with certain keydata by writing the normal-key: 0x15 and 0x18-0x20. These are the keyslots used by the New3DS [[FIRM]] arm9bin loader(minus keyslot 0x11), the New3DS Process9 does this too.
 
Starting with [[9.0.0-20]] the Process9 FIRM-launch code now "clears" the following AES keyslots, with certain keydata by writing the normal-key: 0x15 and 0x18-0x20. These are the keyslots used by the New3DS [[FIRM]] arm9bin loader(minus keyslot 0x11), the New3DS Process9 does this too.
 +
 +
=== AES key-init ===
 +
See [[Bootloader|here]] for how Boot9 initializes the AES keyslots.
 +
 +
For an issue with console-unique key-init, see [[OTP_Registers|here]].
 +
 +
Some of the Boot9 key-init appears to have a bug(?) when initializing a chunk of keyslots at once: normally it does <code>for(i=0; i<4; i++){... <setup_keyslot_keydata(keyslotbase+i, keydata)> ...}</code>, however in some cases it does that except with <code>(keyslotbase,</code> instead. This results in the keyslot specified by keyslotbase being initialized 4 times in a row, with the remaining 3 keyslots following keyslotbase being left uninitialized.
 +
 +
initialize_aeskeys() works as follows:
 +
* Validates input, calls panic() on failure. conunique_dataptr and bootrom_dataptr are both input parameters for initialize_aeskeys().
 +
* Calls crypto_initialize().
 +
* Then it ''basically'': copies 0x1C-bytes from conunique_dataptr to tmpbuf+0(sp+12), and copies data from bootrom_dataptr with size 0x40-0x1C to tmpbuf+0x1C(conunique_dataptr and bootrom_dataptr are updated afterwards).
 +
* The 0x40-byte tmpbuf is hashed with SHA256.
 +
* Keyslot 0x3F is then initialized using the above hash: keyX = first 0x10-bytes of the hash, keyY = last 0x10-bytes of the hash.
 +
* Then with each console-unique key-init code-block: IV is loaded from bootrom_dataptr(which is updated afterwards), then the 0x40-bytes from bootrom_dataptr is encrypted with AES-CBC. The output is then used as 4 keyXs for initializing keyslots. How bootrom_dataptr is updated if at all varies per code-block. Hashing similar to the code at the start of this function is also run(when the remaining size for conunique_dataptr is non-zero), but the output hash isn't used(this code is also slightly different for one code-block).
 +
* Once finished with that, the non-console-unique keyslots are initialized. This is done with keydata loaded directly from bootrom_dataptr.
 +
* The last initialized keyslot is 0x3F, via normalkey. The keydata for this is copied to 0xFFF00618. This is for restoring the keydata when non-NAND FIRM boot ''fails'', since those use keyslot 0x3F with other keydata.
 +
* Lastly it clears the 0x40-bytes at tmpbuf with the u32 loaded from bootrom_dataptr(the word following the above keyslot 0x3F keydata), then returns.
 +
 +
The keyslots are initialized with the same order of keyslots+keydata_type listed below:
 +
 +
Console-unique keydata, after the initialization for the key-generation keyslot(0x3F):
 +
  0x04..0x07 keyX
 +
  0x08..0x0B keyX
 +
  0x0C..0x0F keyX
 +
  0x10      keyX
 +
  0x14..0x17 keyX
 +
  0x18..0x1B keyX
 +
  0x1C..0x1F keyX
 +
  0x20..0x23 keyX
 +
  0x24      keyX
 +
  0x28..0x2B keyX
 +
 +
Common keydata:
 +
 +
  0x2C..0x2F keyX
 +
  0x30..0x33 keyX
 +
  0x34..0x37 keyX
 +
  0x38..0x3B keyX
 +
  0x3C..0x3F keyX
 +
  0x04..0x0B keyY
 +
  0x0C..0x0F normalkey
 +
  0x10..0x13 normalkey
 +
  0x14..0x17 normalkey
 +
  0x18..0x1B normalkey
 +
  0x1C..0x1F normalkey
 +
  0x20..0x23 normalkey
 +
  0x24..0x27 normalkey
 +
  0x28..0x2B normalkey
 +
  0x2C..0x2F normalkey
 +
  0x30..0x33 normalkey
 +
  0x34..0x37 normalkey
 +
  0x38..0x3B normalkey
 +
  0x3C..0x3F normalkey
48

edits