How to Strip and Inject XCI (Nintendo Switch ROM) Certificates under Linux

Submitted by jbreland on Tue, 07/31/2018 - 22:02

Note: I previously posted this to Reddit, but posting here as well for permanence.  This post is of a technical nature and focuses on messing with dumped Nintendo Switch game cartridges, so for most people reading this site it'll be of little interest.  For anyone else interested in the subject, by all means continue reading...

This won't be of much use to people running Windows, but it may be helpful for fellow Linux users (and potentially OSX users as well). This will show to to strip a certificate out of a dumped XCI ROM, as well as restore it to return the ROM back to its original state. XCI Explorer provides an easier way to do this from within Windows, I just don't run Windows. :-)

So here is a Cave Story+ ROM that I dumped with gcdumptool:

$ md5sum Cave\ Story+.xci
a311902acb6813bf61f9cde9e0139913  Cave Story+.xci

If I try to verify the ROM (using a home-grown scripts that checks against no-intro DAT files), we'll see it doesn't match because the certificate field is stripped in the No-Intro dumps:

$ verify_game.sh -p xci Cave\ Story+.xci
Warning: No match found for XCI game 'Cave Story+.xci'

Using the following dd and printf commands I can strip the certificate and copy it to a separate file. Note that the checksum of the new XCI is different from the original and, this time, matches against No-Intro:

# First, backup the certificate to a separate file
$ dd bs=1 skip=28672 count=512 if=Cave\ Story+.xci >Cave\ Story+.cert
512+0 records in
512+0 records out
512 bytes copied, 0.0010961 s, 467 kB/s

$ ls -l Cave\ Story+.cert
-rw-r--r-- 1 user user 512 2018-07-30 19:01 Cave Story+.cert

# Next, strip the certificate from a copy of the ROM file
$ cp Cave\ Story+.xci test.xci
$ printf '\xff%.0s' {1..512} | dd bs=1 seek=28672 count=512 conv=notrunc of=test.xci
512+0 records in
512+0 records out
512 bytes copied, 0.00115365 s, 444 kB/s

$ md5sum Cave\ Story+.xci test.xci
a311902acb6813bf61f9cde9e0139913  Cave Story+.xci
af8ac186efd0fa1a02d0c63c40dd2fd4  test.xci

$ verify_game.sh test.xci
Verified XCI game: Cave Story+ (USA).xci

So far, so good. Now, let's say something happened to my original dump of Cave Story+ and I wanted to inject my certificate back into the stripped copy to re-create the original. The following dd command will write the certificate back to the ROM. Note that the test.xci file then has the same checksum as the original.

$ cat Cave\ Story+.cert | dd bs=1 seek=28672 count=512 conv=notrunc of=test.xci
512+0 records in
512+0 records out
512 bytes copied, 0.000806952 s, 634 kB/s

$ md5sum Cave\ Story+.xci test.xci
a311902acb6813bf61f9cde9e0139913  Cave Story+.xci
a311902acb6813bf61f9cde9e0139913  test.xci

Hope someone finds this helpful.