Title Database: Difference between revisions

From 3dbrew
Jump to navigation Jump to search
Idunoe (talk | contribs)
The tickets in ticket.db are not encrypted.
TimmSkiller (talk | contribs)
Restructure a bit to have a proper ToC
 
(14 intermediate revisions by 7 users not shown)
Line 4: Line 4:
* sdmc/Nintendo 3DS/<ID0>/<ID1>/dbs
* sdmc/Nintendo 3DS/<ID0>/<ID1>/dbs


ID0 is the first 0x10-bytes from a SHA256 [[nand/private/movable.sed|hash]]. The installation of [[SD Filesystem|SD Card]] titles was introduced in the [[2.0.0-2]] update and the SD dbs files are encrypted. These files are [[extdata]] images. The NAND extdata images are cleartext, however some of the images contain data encrypted with a console-unique keyslot.
ID0 is the first 0x10-bytes from a SHA256 [[nand/private/movable.sed|hash]]. The installation of [[SD Filesystem|SD Card]] titles was introduced in the [[2.0.0-2]] update and the SD dbs files are encrypted by [[SD Filesystem|the general SD filesystem encryption rule]]. These files are [[DISA and DIFF|DIFF containers]]. These DIFF files do not use external IVFC level 4, so all database data is duplicated in the container. In this page only the inner content of the container is described.


These files are only created on SD(via [[Application_Manager_Services|AM]]) if they don't exist when the [[eShop]] application is starting up, during network init etc(prior to showing the "system update required" dialog).
These files are only created on SD (via [[Application_Manager_Services|AM]]) if they don't exist when the [[eShop]] application is starting up, during network init etc (prior to showing the "system update required" dialog).


These files are stored under this directory:
These files are stored under this directory:
Line 14: Line 14:
!  Stored in CTR-NAND
!  Stored in CTR-NAND
!  Filename
!  Filename
!  [[Savegames#AES_MAC_header|CTR-9DB0]] ID
!  [[DISA and DIFF#CTR-9DB0|CTR-9DB0]] ID
!  Description
!  Description
|-
|-
Line 21: Line 21:
| ticket.db
| ticket.db
| 0x0
| 0x0
| This contains the installed tickets(NAND and SD).
| This contains the installed tickets (NAND and SD).
|-
|-
| No
| No
Line 33: Line 33:
| title.db
| title.db
| 0x2
| 0x2
| Title database, this contains entries for all installed titles (TWL & CTR) on the 3DS(Each database is responsible for titles installed on its medium).
| Title database, this contains entries for all installed titles (TWL & CTR) on the 3DS (Each database is responsible for titles installed on its medium).
|-
|-
| Yes
| Yes
Line 39: Line 39:
| import.db
| import.db
| 0x3
| 0x3
| This is an Import Database, it contains entries for titles(or versions of titles) not yet installed, ready for transferring to the title.db. (Automatic Update uses this, so completing the update takes seconds)
| This is an Import Database, it contains entries for titles (or versions of titles) not yet installed, ready for transferring to the title.db. (Automatic Update uses this, so completing the update takes seconds.)
|-
|-
| No
| No
Line 54: Line 54:
|}
|}


The SD dbs images use the same [[nand/private/movable.sed|keyslot]] as the other SD/NAND savedata images for the AES-MAC. The NAND dbs images for the AES-MAC use a console-unique keyslot where the keyX and keyY for it are initialized by bootrom.
The inner content of the container consists of a pre-header with size of 0x80 identifying the Database Type, followed by a BDRI container. The offsets in the BDRI header are usually relative to the offset to the start of the BDRI header (0x80 in the file)
 
The *.db [[extdata|Extdata]] images do not use a DATA partition, so there are two versions of the database in the image, an active and old version (the active one is defined by the DIFF header). These database files consist of a pre-header with size of 0x80 identifying the Database Type, followed by a BDRI container. The offsets in the BDRI header are usually relative to the offset to the start of the BDRI header (0x80 in the file)


== Pre Header ==
== Pre Header ==
Line 71: Line 69:
|-
|-
| 0x08
| 0x08
| 0x78
| 0x4
| Version (always 0)
|-
| 0xC
| 0x74
| Reserved
|}
 
For ticket.db, a different pre-header is used:
 
{| class="wikitable"
|-
! Start
! Length
! Description
|-
| 0x00
| 4
| Database Type "Magic" (see below)
|-
| 0x04
| 0x04
| Version (always 1)
|-
| 0x08
| 0x08
| Reserved
| Reserved
|}
|}
Line 81: Line 104:
! Database Type
! Database Type
! Magic
! Magic
|-
| CTR-NAND ticket.db
| TICK
|-
|-
| CTR-NAND import.db
| CTR-NAND import.db
Line 99: Line 125:
| SD Card title.db
| SD Card title.db
| TEMPTDB
| TEMPTDB
|-
| (unused, likely supposed to be SD card import.db)
| SDMCIDB
|}
|}


== BDRI ==
== BDRI ==


Information stored about titles in these Title Database files are stored in two parts in a BDRI partition. Firstly in a Title Entry Table, and secondly in a Title Info Table.
This is a variant of [[Inner FAT|FAT filesystem]]. It consists one "root" directory and multiple "files". Each "file" is one title info entry described below.
 
=== Title Info Entry ===
 
An entry contains information taken from both the application NCCH file(s) and TMD.


{| class="wikitable"
{| class="wikitable"
|-
|-
! Start
! Start !! Length !! Description
! Length
! Description
|-
|-
| 0x0
| 0x0 || 0x8 || u64, Title Size
| 4
| Database Magic ("BDRI")
|-
|-
| 0x4
| 0x8 || 0x4 || u32, Title Type from TMD (usually 0x40)
| 4
| Magic Number (0x30000)
|-
|-
| 0x8
| 0xC || 0x2 || u16, Title Version
| 8
| Unknown
|-
|-
| 0x10
| 0xE || 0x2 || u16, Content index for Download Play Child content
| 8
| File Size(including pre header), divided by the value at relative offset 0x18 (usually = 0x80)
|-
|-
| 0x18
| 0x10 || 0x2 || u16, Content index for Instruction Manual content
| 4
| Usually 0x80
|-
|-
| 0x1C
| 0x12 || 0x2 || u16, Content index for Old3DS update partition (even though this is unused because digital titles don't have update partitions)
| 4
| Reserved
|-
|-
| 0x20
| 0x14 || 0x4 || TMD file ID (the ID part in <code>{ID}.tmd</code> inside the title folder)
| 0x20
| Unknown/Constant
|-
|-
| 0x40
| 0x18 || 0x4 || CMD file ID (the ID part in <code>{ID}.cmd</code> inside the title folder)
| 0x18
| Unknown
|-
|-
| 0x58
| 0x1C || 0x4 || save file ID (the ID part in <code>{ID}.sav</code> inside the title/data folder)
| 8
| Relative Title Entry Table Offset
|-
|-
| 0x60
| 0x20 || 0x8 || u64, extdata ID (zero if title does not use extdata)
| 0x20
| Unknown
|}
 
== Title Entry Table ==
 
This contains 'Entries' for all the titles stored in the database. However this just appears to be an indexing table, the majority of title information is kept in a Title Info Table, which these index entries point to. Title Entries start immediately after the Title Entry Table Header. And there is no padding between entries.
 
=== Header ===
 
{| class="wikitable"
|-
|-
! Start
| 0x28 || 0x1 || bool, has public.sav (DSiWare only)
! Length
! Description
|-
|-
| 0x0
| 0x29 || 0x1 || bool, has private.sav (DSiWare only)
| 4
| Unknown/Magic? (usually = 0x2)
|-
|-
| 0x4
| 0x2A || 0x1 || bool, has banner.sav (DSiWare only)
| 4
| Unknown/Magic? (usually = 0x3)
|-
|-
| 0x8
| 0x2B || 0x1 || bool, requires moving public/private/banner.new to public/private/banner.sav (DSiWare only) (see [[AMPXI:WriteTWLSavedata]])
| 0x24
| Reserved
|-
|-
| 0x2C
| 0x2C || 0x1 || u8, CMD format version (see [[Titles#Data_Structure|Title Data Structure]])
| 4
| Number of used Title Entries
|-
|-
| 0x30
| 0x2D || 0x1 || bool, is user DSiWare title (as in, does not have system title bit set, see [[Title_list#TWL_(DSi)_Titles|TWL (DSi) Titles]] for more information)
| 0x50
| Reserved
|-
|-
| 0x80
| 0x2E || 0x2 || u16, New3DS update partition content index (even though this is unused because digital titles don't have update partitions)
| 4
| MAX Number of Title Entries
|-
|-
| 0x84
| 0x30 || 0x10 || Product code (first 12 bytes of raw .nds for DSiWare, which is the game title)
| 4
| Unknown
|-
|-
| 0x88
| 0x40 || 0x8 || u64, ordering number. Used in some code paths to find the "latest" added entry, but this value is never written and always 0.
| 0x20
| Reserved
|}
 
=== Title Entry Format ===
 
The entries are 0x2C bytes long.
 
{| class="wikitable"
|-
|-
! Start
| 0x48 || 0x1 || bool, is temporary (true for DLP child titles added into tmp_i/tmp_t.db)
! Length
! Description
|-
|-
| 0x0
| 0x49 || 0x1 || u8, [[Application_Manager_Services#ImportTitleContextState|ImportTitleContextState]]
| 4
| Unknown
|-
|-
| 0x4
| 0x4A || 0x1 || bool, overwrite (set when reinstalling an existing title)
| 4
| Active Flag. If this isn't = 0x1, then this entry slot is unused
|-
|-
| 0x8
| 0x4B || 0x1 || Reserved
| 0x8
| Title ID
|-
|-
| 0x10
| 0x4C || 0x4 || Content ID for content index 0, 0xFFFFFFFF if not applicable
| 4
| Title Entry Index
|-
|-
| 0x14
| 0x50 || 0x4 || u32, random value generated during title installation (See [[CTXT]])
| 4
| Relative Title Info Offset, divided by the value at offset 0x18 in this Title Entry (usually 0x80)
|-
|-
| 0x18
| 0x54 || 0x2C || Reserved
| 0x4
| Usually 0x80
|-
| 0x1c
| 4
| Reserved
|-
| 0x20
| 4
| Unknown, occasionally this value is the title's "Title ID lower"
|-
| 0x24
| 0x4
| Unknown
|-
| 0x28
| 0x4
| Unknown
|}
|}


* The actual Title Info offset is calculated by the following: Offset of BDRI Header + Relative Offset of Title Entry Table + Relative Title Info Offset
=== Ticket Info Entry ===
 
For ticket.db entries, there is a header indicates ticket count (as a Title ID can have more than one ticket installed). Then each entry contains the size, followed by the actual ticket data.
== Title Info Table ==
 
These consist of 0x80 byte long entries, pointed to by the title index entries. They contain information taken from both the application NCCH file(s) and TMD.


{| class="wikitable"
{| class="wikitable"
|+ Header
|-
|-
! Start
! Start
Line 261: Line 206:
|-
|-
| 0x0
| 0x0
| 8
| Title Size
|-
| 0x8
| 4
| 4
| Title Type(usually 0x40)
| Amount of tickets X
|-
| 0xC
| 4
| Title Version
|-
| 0x10
| 4
| Flags_0
|-
| 0x14
| 4
| TMD Content ID
|-
| 0x18
| 4
| CMD Content ID
|-
| 0x1c
| 4
| Flags_1
|-
| 0x20
| 4
| ExtdataID low (zero if title doesn't use Extdata)
|-
| 0x24
| 4
| Reserved
|-
| 0x28
| 8
| Flags_2
|-
| 0x30
| 0x10
| Product Code
|-
| 0x40
| 0x10
| Reserved
|-
|-
| 0x50
| 0x4
| 0x4
| Unknown
| X * (size of tickets + 4)
|-
| Ticket entries
| 0x54
| 0x2c
| Reserved
|}
|}
==== Flags_0 ====
{| class="wikitable"
{| class="wikitable"
|+ Ticket entry
|-
|-
! Index
! Start
! Length
! Description
! Description
|-
|-
| 0
| 0x0
| Electronic Manual
|-
| 1
| ?
|-
| 2
| ?
|-
| 3
| ?
|}
 
==== Flags_1 ====
 
{| class="wikitable"
|-
! Index
! Description
|-
| 0
| SD Save Data
|-
| 1
| ?
|-
| 2
| ?
|-
| 3
| ?
|}
 
==== Flags_2 ====
 
{| class="wikitable"
|-
! Index
! Description
|-
| 0
| DSiWare Related (Visibility on Home Menu/Export Flag?)
|-
| 1
| ?
|-
| 2
| ?
|-
| 3
| ?
|-
| 4
| 4
| Found with DSiWare Titles and titles with an 'Application' Title ID
| Ticket data size X (often 0x350 but some DLC tickets may be larger)
|-
|-
| 5
| 0x4
| DSiWare Related (Visibility on Home Menu/Export Flag?)
| X
|-
| [[Ticket|Ticket]] data
| 6
| ?
|-
| 7
| ?
|}
|}


Line 395: Line 235:
These NAND/SD /dbs images seem to be loaded by the ARM9 while NATIVE_FIRM is booting.
These NAND/SD /dbs images seem to be loaded by the ARM9 while NATIVE_FIRM is booting.


== Tools ==
Removing ticket.db from a New-3DS with signature checks disabled will not result in an unbootable system, however all icons except Slot-1 will disappear from Home. Applets can however still be used. Recovery can be accomplished via [[Hardware|hardmod]] or [[arm9loaderhax]] plus a known good backup of the file (or the whole partition or disk); Gamecard exploits were not tested, and Browserhax did not work.
 
[https://github.com/ps3hen/ctr_toolkit/tree/master/extdata_tool extdata_tool] - parsing cleartext .db extdata images

Latest revision as of 19:27, 27 May 2026

These files contain data relating to install/usage/management of installed 3DS titles. The database files are located at:

  • nand/dbs
  • sdmc/Nintendo 3DS/<ID0>/<ID1>/dbs

ID0 is the first 0x10-bytes from a SHA256 hash. The installation of SD Card titles was introduced in the 2.0.0-2 update and the SD dbs files are encrypted by the general SD filesystem encryption rule. These files are DIFF containers. These DIFF files do not use external IVFC level 4, so all database data is duplicated in the container. In this page only the inner content of the container is described.

These files are only created on SD (via AM) if they don't exist when the eShop application is starting up, during network init etc (prior to showing the "system update required" dialog).

These files are stored under this directory:

Stored on SD card Stored in CTR-NAND Filename CTR-9DB0 ID Description
No Yes ticket.db 0x0 This contains the installed tickets (NAND and SD).
No Yes certs.db 0x1 This contains the certificate chain used to verify TMDs and other certificates.
Yes Yes title.db 0x2 Title database, this contains entries for all installed titles (TWL & CTR) on the 3DS (Each database is responsible for titles installed on its medium).
Yes Yes import.db 0x3 This is an Import Database, it contains entries for titles (or versions of titles) not yet installed, ready for transferring to the title.db. (Automatic Update uses this, so completing the update takes seconds.)
No Yes tmp_t.db 0x4 This is the temporary Title database containing one entry for the currently installed Download Play Child.
No Yes tmp_i.db 0x5 Similar to import.db, except it's used in conjunction with tmp_t.db, for installing Download Play Children.

The inner content of the container consists of a pre-header with size of 0x80 identifying the Database Type, followed by a BDRI container. The offsets in the BDRI header are usually relative to the offset to the start of the BDRI header (0x80 in the file)

Pre Header

Start Length Description
0x00 8 Database Type "Magic" (see below)
0x08 0x4 Version (always 0)
0xC 0x74 Reserved

For ticket.db, a different pre-header is used:

Start Length Description
0x00 4 Database Type "Magic" (see below)
0x04 0x04 Version (always 1)
0x08 0x08 Reserved

Database Magic

Database Type Magic
CTR-NAND ticket.db TICK
CTR-NAND import.db NANDIDB
CTR-NAND title.db NANDTDB
CTR-NAND tmp_i.db TEMPIDB
CTR-NAND tmp_t.db TEMPIDB
SD Card import.db TEMPTDB
SD Card title.db TEMPTDB
(unused, likely supposed to be SD card import.db) SDMCIDB

BDRI

This is a variant of FAT filesystem. It consists one "root" directory and multiple "files". Each "file" is one title info entry described below.

Title Info Entry

An entry contains information taken from both the application NCCH file(s) and TMD.

Start Length Description
0x0 0x8 u64, Title Size
0x8 0x4 u32, Title Type from TMD (usually 0x40)
0xC 0x2 u16, Title Version
0xE 0x2 u16, Content index for Download Play Child content
0x10 0x2 u16, Content index for Instruction Manual content
0x12 0x2 u16, Content index for Old3DS update partition (even though this is unused because digital titles don't have update partitions)
0x14 0x4 TMD file ID (the ID part in {ID}.tmd inside the title folder)
0x18 0x4 CMD file ID (the ID part in {ID}.cmd inside the title folder)
0x1C 0x4 save file ID (the ID part in {ID}.sav inside the title/data folder)
0x20 0x8 u64, extdata ID (zero if title does not use extdata)
0x28 0x1 bool, has public.sav (DSiWare only)
0x29 0x1 bool, has private.sav (DSiWare only)
0x2A 0x1 bool, has banner.sav (DSiWare only)
0x2B 0x1 bool, requires moving public/private/banner.new to public/private/banner.sav (DSiWare only) (see AMPXI:WriteTWLSavedata)
0x2C 0x1 u8, CMD format version (see Title Data Structure)
0x2D 0x1 bool, is user DSiWare title (as in, does not have system title bit set, see TWL (DSi) Titles for more information)
0x2E 0x2 u16, New3DS update partition content index (even though this is unused because digital titles don't have update partitions)
0x30 0x10 Product code (first 12 bytes of raw .nds for DSiWare, which is the game title)
0x40 0x8 u64, ordering number. Used in some code paths to find the "latest" added entry, but this value is never written and always 0.
0x48 0x1 bool, is temporary (true for DLP child titles added into tmp_i/tmp_t.db)
0x49 0x1 u8, ImportTitleContextState
0x4A 0x1 bool, overwrite (set when reinstalling an existing title)
0x4B 0x1 Reserved
0x4C 0x4 Content ID for content index 0, 0xFFFFFFFF if not applicable
0x50 0x4 u32, random value generated during title installation (See CTXT)
0x54 0x2C Reserved

Ticket Info Entry

For ticket.db entries, there is a header indicates ticket count (as a Title ID can have more than one ticket installed). Then each entry contains the size, followed by the actual ticket data.

Header
Start Length Description
0x0 4 Amount of tickets X
0x4 X * (size of tickets + 4) Ticket entries
Ticket entry
Start Length Description
0x0 4 Ticket data size X (often 0x350 but some DLC tickets may be larger)
0x4 X Ticket data

NOTES:

It is important to note the database doesn't contain a hash of the .cmd. So if a user has more than one valid set of application data for a given .cmd Content ID they can be manually interchanged without issue. Though renaming a .cmd file to match the Content ID which the title.db is expecting will result in an error, as the CTR for the per-console encryption layer changes depending on the file path, and the MAC of the .cmd is probably generated with the .cmd Content ID in mind.

These NAND/SD /dbs images seem to be loaded by the ARM9 while NATIVE_FIRM is booting.

Removing ticket.db from a New-3DS with signature checks disabled will not result in an unbootable system, however all icons except Slot-1 will disappear from Home. Applets can however still be used. Recovery can be accomplished via hardmod or arm9loaderhax plus a known good backup of the file (or the whole partition or disk); Gamecard exploits were not tested, and Browserhax did not work.