Compare commits

..

No commits in common. "development-tip" and "v1.6.2" have entirely different histories.

56 changed files with 887 additions and 1094 deletions

View file

@ -1,10 +1,10 @@
name: Compile Project (Push/PR/Release) name: Compile Master Branch
on: on:
push: push:
branches: [ development-tip, stable ] branches: [ master ]
pull_request: pull_request:
branches: [ development-tip, stable ] branches: [ master ]
release: release:
types: [ created ] types: [ created ]
@ -20,25 +20,22 @@ jobs:
- dist: ubuntu_x86_64 - dist: ubuntu_x86_64
os: ubuntu-latest os: ubuntu-latest
arch: x86_64 arch: x86_64
bin_ext:
- dist: macos_x86_64 - dist: macos_x86_64
os: macos-latest os: macos-latest
arch: x86_64 arch: x86_64
bin_ext:
- dist: macos_arm64 - dist: macos_arm64
os: macos-latest os: macos-latest
arch: arm64 arch: arm64
bin_ext:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v1
- name: Clone submodules - name: Clone submodules
run: git submodule init && git submodule update run: git submodule init && git submodule update
- name: Compile ${{ matrix.prog }} - name: Compile ${{ matrix.prog }}
run: make PROJECT_PLATFORM_ARCH=${{ matrix.arch }} deps all run: make PROJECT_PLATFORM_ARCH=${{ matrix.arch }} deps all
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: ${{ matrix.prog }}-${{ matrix.dist }} name: ${{ matrix.prog }}-${{ matrix.dist }}
path: ./bin/${{ matrix.prog }}${{ matrix.bin_ext }} path: ./bin/${{ matrix.prog }}
build_visualstudio: build_visualstudio:
name: Compile ${{ matrix.prog }} for ${{ matrix.dist }} name: Compile ${{ matrix.prog }} for ${{ matrix.dist }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -52,22 +49,21 @@ jobs:
platform: x64 platform: x64
configuration: Release configuration: Release
build_path: x64\Release build_path: x64\Release
bin_ext: .exe
- dist: win_x86 - dist: win_x86
os: windows-latest os: windows-latest
platform: x86 platform: x86
configuration: Release configuration: Release
build_path: Release build_path: Release
bin_ext: .exe
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v1
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.3 uses: microsoft/setup-msbuild@v1.1
- name: Clone submodules - name: Clone submodules
run: git submodule init && git submodule update run: git submodule init && git submodule update
- name: Compile ${{ matrix.prog }} - name: Compile ${{ matrix.prog }}
run: msbuild .\build\visualstudio\${{ matrix.prog }}.sln /p:configuration=${{ matrix.configuration }} /p:platform=${{ matrix.platform }} run: msbuild .\build\visualstudio\${{ matrix.prog }}.sln /p:configuration=${{ matrix.configuration }} /p:platform=${{ matrix.platform }}
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: ${{ matrix.prog }}-${{ matrix.dist }} name: ${{ matrix.prog }}-${{ matrix.dist }}
path: .\build\visualstudio\${{ matrix.build_path }}\${{ matrix.prog }}${{ matrix.bin_ext }} path: .\build\visualstudio\${{ matrix.build_path }}\${{ matrix.prog }}.exe

33
.gitmodules vendored
View file

@ -1,15 +1,24 @@
[submodule "deps/libmbedtls"]
path = deps/libmbedtls
url = https://github.com/jakcron/libmbedtls.git
[submodule "deps/libfmt"]
path = deps/libfmt
url = https://github.com/jakcron/libfmt.git
[submodule "deps/libtoolchain"]
path = deps/libtoolchain
url = https://github.com/jakcron/libtoolchain.git
[submodule "deps/liblz4"] [submodule "deps/liblz4"]
path = deps/liblz4 path = deps/liblz4
url = https://github.com/jakcron/liblz4.git url = https://github.com/jakcron/liblz4.git
[submodule "deps/libpietendo"] [submodule "deps/libmbedtls"]
path = deps/libpietendo path = deps/libmbedtls
url = https://github.com/jakcron/libpietendo.git url = https://github.com/jakcron/libmbedtls
[submodule "deps/libtoolchain"]
path = deps/libtoolchain
url = https://github.com/jakcron/libtoolchain.git
[submodule "deps/libfmt"]
path = deps/libfmt
url = https://github.com/jakcron/libfmt.git
[submodule "deps/libnintendo-pki"]
path = deps/libnintendo-pki
url = https://github.com/jakcron/libnintendo-pki.git
[submodule "deps/libnintendo-es"]
path = deps/libnintendo-es
url = https://github.com/jakcron/libnintendo-es.git
[submodule "deps/libnintendo-hac"]
path = deps/libnintendo-hac
url = https://github.com/jakcron/libnintendo-hac.git
[submodule "deps/libnintendo-hac-hb"]
path = deps/libnintendo-hac-hb
url = https://github.com/jakcron/libnintendo-hac-hb.git

View file

@ -1,13 +1,4 @@
# Building # Building
## Git Submodules
This project makes use of git submodules to import dependencies into the source tree.
After cloning this repository using git, prior to building NSTool the dependencies need to be downloaded.
Run these two commands to initialise and download the dependencies:
```
git submodule init
git submodule update
```
## Linux (incl. Windows Subsystem for Linux) & MacOS - Makefile ## Linux (incl. Windows Subsystem for Linux) & MacOS - Makefile
### Requirements ### Requirements
* `make` * `make`

View file

@ -143,16 +143,6 @@ nstool -x /path/to/a/file.bin ./extract_dir/different_name.bin some_file.bin
* NSP * NSP
* XCI * XCI
## NCA Patches
Nintendo distributes game patches/updates in the style of a diff to keep file sizes down. This means extracting game patches requires the base version of the game to be able to process patch data. Typically this is only done for the Program NCA.
If `basegame_v0.nca` is the base Program NCA, and `gamepatch_v13219.nca` is the patch Program NCA, simply specify the base NCA using the base NCA option `--basenca` when processing the patch NCA.
```
nstool --basenca ./basegame_v0.nca -x ./patchdata gamepatch_v13219.nca
```
In the above example the patch NCA is being extracted to `./patchdata`
## Encrypted Files ## Encrypted Files
Some Nintendo Switch files are partially or completely encrypted. These require the user to supply the encryption keys to NSTool so that it can process them. Some Nintendo Switch files are partially or completely encrypted. These require the user to supply the encryption keys to NSTool so that it can process them.

View file

@ -203,18 +203,4 @@ nstool <32 char rightsid>.tik
##### Personalised Tickets ##### Personalised Tickets
If the ticket is personalised (encrypted with console unique RSA key), NSTool will not support it. You will need to use extract the title key with another tool and pass the encrypted title key directly with the `--titlekey` option. If the ticket is personalised (encrypted with console unique RSA key), NSTool will not support it. You will need to use extract the title key with another tool and pass the encrypted title key directly with the `--titlekey` option.
# Title Keys (title.keys) # Title
In order for NSTool to decrypt NCA files that use external content keys, the ticket or key data be provided to NSTool. For convience NSTool supports the hactool `title.keys` format. This file can store a dictionary of title keys, so that specifying a ticket or key data manually is not required, provided it is present in `title.keys`. This file must be present in: ___$HOME/.switch/___ .
## Format
* This file is in the format of (rights_id = title_key) pairs, each on their own line.
* There is no limit on the number of pairs.
* The `;` is the comment indicator. When parsing a file, it is treated as a new line character.
* The format is case insensitive
### Example
For example if rights id `010003000e1468000000000000000008` had a title key `8fa820b219781d331cca08968e6e5b52`, the row would look like this:
```
010003000e1468000000000000000008 = 8fa820b219781d331cca08968e6e5b52
```

View file

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 16
VisualStudioVersion = 17.2.32616.157 VisualStudioVersion = 16.0.31229.75
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nstool", "nstool\nstool.vcxproj", "{775EF5EB-CA49-4994-8AC4-47B4A5385266}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nstool", "nstool\nstool.vcxproj", "{775EF5EB-CA49-4994-8AC4-47B4A5385266}"
EndProject EndProject
@ -9,14 +9,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deps", "deps", "{05929EAE-4
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4", "..\..\deps\liblz4\build\visualstudio\liblz4\liblz4.vcxproj", "{E741ADED-7900-4E07-8DB0-D008C336C3FB}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4", "..\..\deps\liblz4\build\visualstudio\liblz4\liblz4.vcxproj", "{E741ADED-7900-4E07-8DB0-D008C336C3FB}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnintendo-es", "..\..\deps\libnintendo-es\build\visualstudio\libnintendo-es\libnintendo-es.vcxproj", "{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnintendo-hac", "..\..\deps\libnintendo-hac\build\visualstudio\libnintendo-hac\libnintendo-hac.vcxproj", "{8885C125-83FB-4F73-A93A-C712B1434D54}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnintendo-hac-hb", "..\..\deps\libnintendo-hac-hb\build\visualstudio\libnintendo-hac-hb\libnintendo-hac-hb.vcxproj", "{24D001B4-D439-4967-9371-DC3E0523EB19}"
ProjectSection(ProjectDependencies) = postProject
{8885C125-83FB-4F73-A93A-C712B1434D54} = {8885C125-83FB-4F73-A93A-C712B1434D54}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnintendo-pki", "..\..\deps\libnintendo-pki\build\visualstudio\libnintendo-pki\libnintendo-pki.vcxproj", "{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmbedtls", "..\..\deps\libmbedtls\build\visualstudio\libmbedtls\libmbedtls.vcxproj", "{7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmbedtls", "..\..\deps\libmbedtls\build\visualstudio\libmbedtls\libmbedtls.vcxproj", "{7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtoolchain", "..\..\deps\libtoolchain\build\visualstudio\libtoolchain\libtoolchain.vcxproj", "{E194E4B8-1482-40A2-901B-75D4387822E9}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtoolchain", "..\..\deps\libtoolchain\build\visualstudio\libtoolchain\libtoolchain.vcxproj", "{E194E4B8-1482-40A2-901B-75D4387822E9}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfmt", "..\..\deps\libfmt\build\visualstudio\libfmt\libfmt.vcxproj", "{F4B0540E-0AAE-4006-944B-356944EF61FA}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfmt", "..\..\deps\libfmt\build\visualstudio\libfmt\libfmt.vcxproj", "{F4B0540E-0AAE-4006-944B-356944EF61FA}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpietendo", "..\..\deps\libpietendo\build\visualstudio\libpietendo\libpietendo.vcxproj", "{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
@ -41,6 +50,38 @@ Global
{E741ADED-7900-4E07-8DB0-D008C336C3FB}.Release|x64.Build.0 = Release|x64 {E741ADED-7900-4E07-8DB0-D008C336C3FB}.Release|x64.Build.0 = Release|x64
{E741ADED-7900-4E07-8DB0-D008C336C3FB}.Release|x86.ActiveCfg = Release|Win32 {E741ADED-7900-4E07-8DB0-D008C336C3FB}.Release|x86.ActiveCfg = Release|Win32
{E741ADED-7900-4E07-8DB0-D008C336C3FB}.Release|x86.Build.0 = Release|Win32 {E741ADED-7900-4E07-8DB0-D008C336C3FB}.Release|x86.Build.0 = Release|Win32
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}.Debug|x64.ActiveCfg = Debug|x64
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}.Debug|x64.Build.0 = Debug|x64
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}.Debug|x86.ActiveCfg = Debug|Win32
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}.Debug|x86.Build.0 = Debug|Win32
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}.Release|x64.ActiveCfg = Release|x64
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}.Release|x64.Build.0 = Release|x64
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}.Release|x86.ActiveCfg = Release|Win32
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B}.Release|x86.Build.0 = Release|Win32
{8885C125-83FB-4F73-A93A-C712B1434D54}.Debug|x64.ActiveCfg = Debug|x64
{8885C125-83FB-4F73-A93A-C712B1434D54}.Debug|x64.Build.0 = Debug|x64
{8885C125-83FB-4F73-A93A-C712B1434D54}.Debug|x86.ActiveCfg = Debug|Win32
{8885C125-83FB-4F73-A93A-C712B1434D54}.Debug|x86.Build.0 = Debug|Win32
{8885C125-83FB-4F73-A93A-C712B1434D54}.Release|x64.ActiveCfg = Release|x64
{8885C125-83FB-4F73-A93A-C712B1434D54}.Release|x64.Build.0 = Release|x64
{8885C125-83FB-4F73-A93A-C712B1434D54}.Release|x86.ActiveCfg = Release|Win32
{8885C125-83FB-4F73-A93A-C712B1434D54}.Release|x86.Build.0 = Release|Win32
{24D001B4-D439-4967-9371-DC3E0523EB19}.Debug|x64.ActiveCfg = Debug|x64
{24D001B4-D439-4967-9371-DC3E0523EB19}.Debug|x64.Build.0 = Debug|x64
{24D001B4-D439-4967-9371-DC3E0523EB19}.Debug|x86.ActiveCfg = Debug|Win32
{24D001B4-D439-4967-9371-DC3E0523EB19}.Debug|x86.Build.0 = Debug|Win32
{24D001B4-D439-4967-9371-DC3E0523EB19}.Release|x64.ActiveCfg = Release|x64
{24D001B4-D439-4967-9371-DC3E0523EB19}.Release|x64.Build.0 = Release|x64
{24D001B4-D439-4967-9371-DC3E0523EB19}.Release|x86.ActiveCfg = Release|Win32
{24D001B4-D439-4967-9371-DC3E0523EB19}.Release|x86.Build.0 = Release|Win32
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}.Debug|x64.ActiveCfg = Debug|x64
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}.Debug|x64.Build.0 = Debug|x64
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}.Debug|x86.ActiveCfg = Debug|Win32
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}.Debug|x86.Build.0 = Debug|Win32
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}.Release|x64.ActiveCfg = Release|x64
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}.Release|x64.Build.0 = Release|x64
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}.Release|x86.ActiveCfg = Release|Win32
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF}.Release|x86.Build.0 = Release|Win32
{7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}.Debug|x64.ActiveCfg = Debug|x64 {7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}.Debug|x64.ActiveCfg = Debug|x64
{7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}.Debug|x64.Build.0 = Debug|x64 {7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}.Debug|x64.Build.0 = Debug|x64
{7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}.Debug|x86.ActiveCfg = Debug|Win32 {7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}.Debug|x86.ActiveCfg = Debug|Win32
@ -65,24 +106,19 @@ Global
{F4B0540E-0AAE-4006-944B-356944EF61FA}.Release|x64.Build.0 = Release|x64 {F4B0540E-0AAE-4006-944B-356944EF61FA}.Release|x64.Build.0 = Release|x64
{F4B0540E-0AAE-4006-944B-356944EF61FA}.Release|x86.ActiveCfg = Release|Win32 {F4B0540E-0AAE-4006-944B-356944EF61FA}.Release|x86.ActiveCfg = Release|Win32
{F4B0540E-0AAE-4006-944B-356944EF61FA}.Release|x86.Build.0 = Release|Win32 {F4B0540E-0AAE-4006-944B-356944EF61FA}.Release|x86.Build.0 = Release|Win32
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}.Debug|x64.ActiveCfg = Debug|x64
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}.Debug|x64.Build.0 = Debug|x64
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}.Debug|x86.ActiveCfg = Debug|Win32
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}.Debug|x86.Build.0 = Debug|Win32
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}.Release|x64.ActiveCfg = Release|x64
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}.Release|x64.Build.0 = Release|x64
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}.Release|x86.ActiveCfg = Release|Win32
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{E741ADED-7900-4E07-8DB0-D008C336C3FB} = {05929EAE-4471-4E8E-A6F3-793A81623D7F} {E741ADED-7900-4E07-8DB0-D008C336C3FB} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
{8616D6C9-C8DE-4C3F-AFC2-625636664C2B} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
{8885C125-83FB-4F73-A93A-C712B1434D54} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
{24D001B4-D439-4967-9371-DC3E0523EB19} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
{0BEF63A0-2801-4563-AB65-1E2FD881C3AF} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
{7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C} = {05929EAE-4471-4E8E-A6F3-793A81623D7F} {7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
{E194E4B8-1482-40A2-901B-75D4387822E9} = {05929EAE-4471-4E8E-A6F3-793A81623D7F} {E194E4B8-1482-40A2-901B-75D4387822E9} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
{F4B0540E-0AAE-4006-944B-356944EF61FA} = {05929EAE-4471-4E8E-A6F3-793A81623D7F} {F4B0540E-0AAE-4006-944B-356944EF61FA} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2} = {05929EAE-4471-4E8E-A6F3-793A81623D7F}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {ABDCFB40-D6B3-44A9-92B5-0D7AB38D9FB8} SolutionGuid = {ABDCFB40-D6B3-44A9-92B5-0D7AB38D9FB8}

View file

@ -76,7 +76,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libpietendo\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@ -86,7 +86,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libpietendo\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@ -98,7 +98,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libpietendo\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
@ -114,7 +114,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libpietendo\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
@ -129,15 +129,24 @@
<ProjectReference Include="$(SolutionDir)..\..\deps\liblz4\build\visualstudio\liblz4\liblz4.vcxproj"> <ProjectReference Include="$(SolutionDir)..\..\deps\liblz4\build\visualstudio\liblz4\liblz4.vcxproj">
<Project>{e741aded-7900-4e07-8db0-d008c336c3fb}</Project> <Project>{e741aded-7900-4e07-8db0-d008c336c3fb}</Project>
</ProjectReference> </ProjectReference>
<ProjectReference Include="$(SolutionDir)..\..\deps\libnintendo-es\build\visualstudio\libnintendo-es\libnintendo-es.vcxproj">
<Project>{8616d6c9-c8de-4c3f-afc2-625636664c2b}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)..\..\deps\libnintendo-hac-hb\build\visualstudio\libnintendo-hac-hb\libnintendo-hac-hb.vcxproj">
<Project>{24d001b4-d439-4967-9371-dc3e0523eb19}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)..\..\deps\libnintendo-hac\build\visualstudio\libnintendo-hac\libnintendo-hac.vcxproj">
<Project>{8885c125-83fb-4f73-a93a-c712b1434d54}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)..\..\deps\libnintendo-pki\build\visualstudio\libnintendo-pki\libnintendo-pki.vcxproj">
<Project>{0bef63a0-2801-4563-ab65-1e2fd881c3af}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)..\..\deps\libmbedtls\build\visualstudio\libmbedtls\libmbedtls.vcxproj"> <ProjectReference Include="$(SolutionDir)..\..\deps\libmbedtls\build\visualstudio\libmbedtls\libmbedtls.vcxproj">
<Project>{7a7c66f3-2b5b-4e23-85d8-2a74fedad92c}</Project> <Project>{7a7c66f3-2b5b-4e23-85d8-2a74fedad92c}</Project>
</ProjectReference> </ProjectReference>
<ProjectReference Include="$(SolutionDir)..\..\deps\libtoolchain\build\visualstudio\libtoolchain\libtoolchain.vcxproj"> <ProjectReference Include="$(SolutionDir)..\..\deps\libtoolchain\build\visualstudio\libtoolchain\libtoolchain.vcxproj">
<Project>{e194e4b8-1482-40a2-901b-75d4387822e9}</Project> <Project>{e194e4b8-1482-40a2-901b-75d4387822e9}</Project>
</ProjectReference> </ProjectReference>
<ProjectReference Include="$(SolutionDir)..\..\deps\libpietendo\build\visualstudio\libpietendo\libpietendo.vcxproj">
<Project>{5addd009-9d25-40be-b2a6-2f3ab4dcbbd2}</Project>
</ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\..\src\AssetProcess.h" /> <ClInclude Include="..\..\..\src\AssetProcess.h" />

2
deps/libfmt vendored

@ -1 +1 @@
Subproject commit b03b081e026ceb1226b45de926babe629d6c0688 Subproject commit 53d084cc0c6ea61bbb535a873299b0ae5ff9a05d

2
deps/liblz4 vendored

@ -1 +1 @@
Subproject commit 561775a11e00cbd21a45031c64068cb5e1242608 Subproject commit b40b46406e87a753328abfda3b53dfabd2408da2

2
deps/libmbedtls vendored

@ -1 +1 @@
Subproject commit 74346376dd035e9fbc161cdb80afc646b72fde86 Subproject commit e9e56bb773111f831af8dd36ad74de73b0c31aa2

1
deps/libnintendo-es vendored Submodule

@ -0,0 +1 @@
Subproject commit 984c7e6d80729eb59035932815c00e1ad614ef77

1
deps/libnintendo-hac vendored Submodule

@ -0,0 +1 @@
Subproject commit 19d38735ba4eb393faefefc3c923144628456857

1
deps/libnintendo-hac-hb vendored Submodule

@ -0,0 +1 @@
Subproject commit 0635b0c532f4ef152506775c930b3d45f575a14c

1
deps/libnintendo-pki vendored Submodule

@ -0,0 +1 @@
Subproject commit 87fdd1be853013a95116c107520078ece7869881

1
deps/libpietendo vendored

@ -1 +0,0 @@
Subproject commit 5d50d02f8f3b8918bdfbbb599b8c4c1628660d89

2
deps/libtoolchain vendored

@ -1 +1 @@
Subproject commit 578d170f5b294e4a9feb3cc2d504896e846f204e Subproject commit d7b48027a93ef69b9c6b0d78fe392abc0bce5e68

View file

@ -1,6 +1,6 @@
# C++/C Recursive Project Makefile # C++/C Recursive Project Makefile
# (c) Jack # (c) Jack
# Version 9 (20231231) # Version 6 (20211110)
# Project Name # Project Name
PROJECT_NAME = nstool PROJECT_NAME = nstool
@ -23,9 +23,16 @@ ifeq ($(ROOT_PROJECT_NAME),)
export ROOT_PROJECT_DEPENDENCY_PATH = $(ROOT_PROJECT_PATH)/deps export ROOT_PROJECT_DEPENDENCY_PATH = $(ROOT_PROJECT_PATH)/deps
endif endif
# Shared Library Definitions
PROJECT_SO_VER_MAJOR = 0
PROJECT_SO_VER_MINOR = 1
PROJECT_SO_VER_PATCH = 0
PROJECT_SONAME = $(PROJECT_NAME).so.$(PROJECT_SO_VER_MAJOR)
PROJECT_SO_FILENAME = $(PROJECT_SONAME).$(PROJECT_SO_VER_MINOR).$(PROJECT_SO_VER_PATCH)
# Project Dependencies # Project Dependencies
PROJECT_DEPEND = pietendo toolchain fmt lz4 mbedtls PROJECT_DEPEND = nintendo-hac-hb nintendo-hac nintendo-es nintendo-pki toolchain fmt lz4 mbedtls
PROJECT_DEPEND_LOCAL_DIR = libpietendo libtoolchain libfmt liblz4 libmbedtls PROJECT_DEPEND_LOCAL_DIR = libnintendo-hac-hb libnintendo-hac libnintendo-es libnintendo-pki libtoolchain libfmt liblz4 libmbedtls
# Generate compiler flags for including project include path # Generate compiler flags for including project include path
ifneq ($(PROJECT_INCLUDE_PATH),) ifneq ($(PROJECT_INCLUDE_PATH),)
@ -75,47 +82,45 @@ ifeq ($(PROJECT_PLATFORM), WIN32)
# Windows Flags/Libs # Windows Flags/Libs
CC = x86_64-w64-mingw32-gcc CC = x86_64-w64-mingw32-gcc
CXX = x86_64-w64-mingw32-g++ CXX = x86_64-w64-mingw32-g++
DEFINEFLAGS =
WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-but-set-variable WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-but-set-variable
ARCHFLAGS = ARCHFLAGS =
INC += INC +=
LIB += -static LIB += -static
ARFLAGS = cr ARFLAGS = cr -o
else ifeq ($(PROJECT_PLATFORM), GNU) else ifeq ($(PROJECT_PLATFORM), GNU)
# GNU/Linux Flags/Libs # GNU/Linux Flags/Libs
#CC = #CC =
#CXX = #CXX =
DEFINEFLAGS =
WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-but-set-variable WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-but-set-variable
ARCHFLAGS = ARCHFLAGS =
INC += INC +=
LIB += LIB +=
ARFLAGS = cr ARFLAGS = cr -o
else ifeq ($(PROJECT_PLATFORM), MACOS) else ifeq ($(PROJECT_PLATFORM), MACOS)
# MacOS Flags/Libs # MacOS Flags/Libs
#CC = #CC =
#CXX = #CXX =
DEFINEFLAGS =
WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-private-field WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-private-field
ARCHFLAGS = -arch $(PROJECT_PLATFORM_ARCH) ARCHFLAGS = -arch $(PROJECT_PLATFORM_ARCH)
INC += INC +=
LIB += LIB +=
ARFLAGS = rc ARFLAGS = rc
endif endif
# Compiler Flags # Compiler Flags
CXXFLAGS = -std=c++11 $(INC) $(DEFINEFLAGS) $(WARNFLAGS) $(ARCHFLAGS) -fPIC CXXFLAGS = -std=c++11 $(INC) $(WARNFLAGS) $(ARCHFLAGS) -fPIC
CFLAGS = -std=c11 $(INC) $(DEFINEFLAGS) $(WARNFLAGS) $(ARCHFLAGS) -fPIC CFLAGS = -std=c11 $(INC) $(WARNFLAGS) $(ARCHFLAGS) -fPIC
# Object Files # Object Files
SRC_OBJ = $(foreach dir,$(PROJECT_SRC_SUBDIRS),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(PROJECT_SRC_SUBDIRS),$(subst .cc,.o,$(wildcard $(dir)/*.cc))) $(foreach dir,$(PROJECT_SRC_SUBDIRS),$(subst .c,.o,$(wildcard $(dir)/*.c))) SRC_OBJ = $(foreach dir,$(PROJECT_SRC_SUBDIRS),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(PROJECT_SRC_SUBDIRS),$(subst .cc,.o,$(wildcard $(dir)/*.cc))) $(foreach dir,$(PROJECT_SRC_SUBDIRS),$(subst .c,.o,$(wildcard $(dir)/*.c)))
TESTSRC_OBJ = $(foreach dir,$(PROJECT_TESTSRC_SUBDIRS),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(PROJECT_TESTSRC_SUBDIRS),$(subst .cc,.o,$(wildcard $(dir)/*.cc))) $(foreach dir,$(PROJECT_TESTSRC_SUBDIRS),$(subst .c,.o,$(wildcard $(dir)/*.c))) TESTSRC_OBJ = $(foreach dir,$(PROJECT_TESTSRC_SUBDIRS),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(PROJECT_TESTSRC_SUBDIRS),$(subst .cc,.o,$(wildcard $(dir)/*.cc))) $(foreach dir,$(PROJECT_TESTSRC_SUBDIRS),$(subst .c,.o,$(wildcard $(dir)/*.c)))
# all is the default, user should specify what the default should do # all is the default, user should specify what the default should do
# - 'static_lib' for building source as a static library # - 'static_lib' for building static library
# - 'program' for building source as executable program # - 'shared_lib' for building shared library
# - 'program' for building the program
# - 'test_program' for building the test program # - 'test_program' for building the test program
# test_program can be used with program or static_lib, but program and static_lib cannot be used together # These can typically be used together however *_lib and program should not be used together
all: program all: program
clean: clean_object_files remove_binary_dir clean: clean_object_files remove_binary_dir
@ -153,6 +158,10 @@ static_lib: $(SRC_OBJ) create_binary_dir
@echo LINK $(PROJECT_BIN_PATH)/$(PROJECT_NAME).a @echo LINK $(PROJECT_BIN_PATH)/$(PROJECT_NAME).a
@ar $(ARFLAGS) "$(PROJECT_BIN_PATH)/$(PROJECT_NAME).a" $(SRC_OBJ) @ar $(ARFLAGS) "$(PROJECT_BIN_PATH)/$(PROJECT_NAME).a" $(SRC_OBJ)
shared_lib: $(SRC_OBJ) create_binary_dir
@echo LINK $(PROJECT_BIN_PATH)/$(PROJECT_SO_FILENAME)
@gcc -shared -Wl,-soname,$(PROJECT_SONAME) -o "$(PROJECT_BIN_PATH)/$(PROJECT_SO_FILENAME)" $(SRC_OBJ)
# Build Program # Build Program
program: $(SRC_OBJ) create_binary_dir program: $(SRC_OBJ) create_binary_dir
@echo LINK $(PROJECT_BIN_PATH)/$(PROJECT_NAME) @echo LINK $(PROJECT_BIN_PATH)/$(PROJECT_NAME)

View file

@ -64,12 +64,12 @@ void nstool::AssetProcess::importHeader()
throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions."); throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions.");
} }
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sAssetHeader))) if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sAssetHeader)))
{ {
throw tc::Exception(mModuleName, "Corrupt ASET: file too small"); throw tc::Exception(mModuleName, "Corrupt ASET: file too small");
} }
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sAssetHeader)); tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sAssetHeader));
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
@ -85,7 +85,10 @@ void nstool::AssetProcess::processSections()
if ((mHdr.getIconInfo().size + mHdr.getIconInfo().offset) > file_size) if ((mHdr.getIconInfo().size + mHdr.getIconInfo().offset) > file_size)
throw tc::Exception(mModuleName, "ASET geometry for icon beyond file size"); throw tc::Exception(mModuleName, "ASET geometry for icon beyond file size");
fmt::print("Saving {:s}...", mIconExtractPath.get().to_string()); std::string icon_extract_path_str;
tc::io::PathUtil::pathToUnixUTF8(mIconExtractPath.get(), icon_extract_path_str);
fmt::print("Saving {:s}...", icon_extract_path_str);
writeSubStreamToFile(mFile, mHdr.getIconInfo().offset, mHdr.getIconInfo().size, mIconExtractPath.get()); writeSubStreamToFile(mFile, mHdr.getIconInfo().offset, mHdr.getIconInfo().size, mIconExtractPath.get());
} }
@ -96,7 +99,6 @@ void nstool::AssetProcess::processSections()
if (mNacpExtractPath.isSet()) if (mNacpExtractPath.isSet())
{ {
fmt::print("Saving {:s}...", mNacpExtractPath.get().to_string());
writeSubStreamToFile(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size, mNacpExtractPath.get()); writeSubStreamToFile(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size, mNacpExtractPath.get());
} }

View file

@ -3,7 +3,7 @@
#include "NacpProcess.h" #include "NacpProcess.h"
#include "RomfsProcess.h" #include "RomfsProcess.h"
#include <pietendo/hac/AssetHeader.h> #include <nn/hac/AssetHeader.h>
namespace nstool { namespace nstool {
@ -33,7 +33,7 @@ private:
tc::Optional<tc::io::Path> mIconExtractPath; tc::Optional<tc::io::Path> mIconExtractPath;
tc::Optional<tc::io::Path> mNacpExtractPath; tc::Optional<tc::io::Path> mNacpExtractPath;
pie::hac::AssetHeader mHdr; nn::hac::AssetHeader mHdr;
NacpProcess mNacp; NacpProcess mNacp;
RomfsProcess mRomfs; RomfsProcess mRomfs;

View file

@ -1,6 +1,6 @@
#include "CnmtProcess.h" #include "CnmtProcess.h"
#include <pietendo/hac/ContentMetaUtil.h> #include <nn/hac/ContentMetaUtil.h>
nstool::CnmtProcess::CnmtProcess() : nstool::CnmtProcess::CnmtProcess() :
mModuleName("nstool::CnmtProcess"), mModuleName("nstool::CnmtProcess"),
@ -33,7 +33,7 @@ void nstool::CnmtProcess::setVerifyMode(bool verify)
mVerify = verify; mVerify = verify;
} }
const pie::hac::ContentMeta& nstool::CnmtProcess::getContentMeta() const const nn::hac::ContentMeta& nstool::CnmtProcess::getContentMeta() const
{ {
return mCnmt; return mCnmt;
} }
@ -67,11 +67,11 @@ void nstool::CnmtProcess::importCnmt()
void nstool::CnmtProcess::displayCnmt() void nstool::CnmtProcess::displayCnmt()
{ {
const pie::hac::sContentMetaHeader* cnmt_hdr = (const pie::hac::sContentMetaHeader*)mCnmt.getBytes().data(); const nn::hac::sContentMetaHeader* cnmt_hdr = (const nn::hac::sContentMetaHeader*)mCnmt.getBytes().data();
fmt::print("[ContentMeta]\n"); fmt::print("[ContentMeta]\n");
fmt::print(" TitleId: 0x{:016x}\n", mCnmt.getTitleId()); fmt::print(" TitleId: 0x{:016x}\n", mCnmt.getTitleId());
fmt::print(" Version: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getTitleVersion()), mCnmt.getTitleVersion()); fmt::print(" Version: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getTitleVersion()), mCnmt.getTitleVersion());
fmt::print(" Type: {:s} ({:d})\n", pie::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()), (uint32_t)mCnmt.getContentMetaType()); fmt::print(" Type: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()), (uint32_t)mCnmt.getContentMetaType());
fmt::print(" Attributes: 0x{:x}", *((byte_t*)&cnmt_hdr->attributes)); fmt::print(" Attributes: 0x{:x}", *((byte_t*)&cnmt_hdr->attributes));
if (mCnmt.getAttribute().size()) if (mCnmt.getAttribute().size())
{ {
@ -79,7 +79,7 @@ void nstool::CnmtProcess::displayCnmt()
for (auto itr = mCnmt.getAttribute().begin(); itr != mCnmt.getAttribute().end(); itr++) for (auto itr = mCnmt.getAttribute().begin(); itr != mCnmt.getAttribute().end(); itr++)
{ {
attribute_list.push_back(pie::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(pie::hac::cnmt::ContentMetaAttributeFlag(*itr))); attribute_list.push_back(nn::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(nn::hac::cnmt::ContentMetaAttributeFlag(*itr)));
} }
fmt::print(" ["); fmt::print(" [");
@ -95,28 +95,28 @@ void nstool::CnmtProcess::displayCnmt()
} }
fmt::print("\n"); fmt::print("\n");
fmt::print(" StorageId: {:s} ({:d})\n", pie::hac::ContentMetaUtil::getStorageIdAsString(mCnmt.getStorageId()), (uint32_t)mCnmt.getStorageId()); fmt::print(" StorageId: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getStorageIdAsString(mCnmt.getStorageId()), (uint32_t)mCnmt.getStorageId());
fmt::print(" ContentInstallType: {:s} ({:d})\n", pie::hac::ContentMetaUtil::getContentInstallTypeAsString(mCnmt.getContentInstallType()),(uint32_t)mCnmt.getContentInstallType()); fmt::print(" ContentInstallType: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getContentInstallTypeAsString(mCnmt.getContentInstallType()),(uint32_t)mCnmt.getContentInstallType());
fmt::print(" RequiredDownloadSystemVersion: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getRequiredDownloadSystemVersion()), mCnmt.getRequiredDownloadSystemVersion()); fmt::print(" RequiredDownloadSystemVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getRequiredDownloadSystemVersion()), mCnmt.getRequiredDownloadSystemVersion());
switch(mCnmt.getContentMetaType()) switch(mCnmt.getContentMetaType())
{ {
case (pie::hac::cnmt::ContentMetaType_Application): case (nn::hac::cnmt::ContentMetaType::Application):
fmt::print(" ApplicationExtendedHeader:\n"); fmt::print(" ApplicationExtendedHeader:\n");
fmt::print(" RequiredApplicationVersion: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion()), mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion()); fmt::print(" RequiredApplicationVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion()), mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion());
fmt::print(" RequiredSystemVersion: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()), mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()); fmt::print(" RequiredSystemVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()), mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion());
fmt::print(" PatchId: 0x{:016x}\n", mCnmt.getApplicationMetaExtendedHeader().getPatchId()); fmt::print(" PatchId: 0x{:016x}\n", mCnmt.getApplicationMetaExtendedHeader().getPatchId());
break; break;
case (pie::hac::cnmt::ContentMetaType_Patch): case (nn::hac::cnmt::ContentMetaType::Patch):
fmt::print(" PatchMetaExtendedHeader:\n"); fmt::print(" PatchMetaExtendedHeader:\n");
fmt::print(" RequiredSystemVersion: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()), mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()); fmt::print(" RequiredSystemVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()), mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion());
fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getPatchMetaExtendedHeader().getApplicationId()); fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getPatchMetaExtendedHeader().getApplicationId());
break; break;
case (pie::hac::cnmt::ContentMetaType_AddOnContent): case (nn::hac::cnmt::ContentMetaType::AddOnContent):
fmt::print(" AddOnContentMetaExtendedHeader:\n"); fmt::print(" AddOnContentMetaExtendedHeader:\n");
fmt::print(" RequiredApplicationVersion: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()), mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()); fmt::print(" RequiredApplicationVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()), mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion());
fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getAddOnContentMetaExtendedHeader().getApplicationId()); fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getAddOnContentMetaExtendedHeader().getApplicationId());
break; break;
case (pie::hac::cnmt::ContentMetaType_Delta): case (nn::hac::cnmt::ContentMetaType::Delta):
fmt::print(" DeltaMetaExtendedHeader:\n"); fmt::print(" DeltaMetaExtendedHeader:\n");
fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getDeltaMetaExtendedHeader().getApplicationId()); fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getDeltaMetaExtendedHeader().getApplicationId());
break; break;
@ -128,9 +128,9 @@ void nstool::CnmtProcess::displayCnmt()
fmt::print(" ContentInfo:\n"); fmt::print(" ContentInfo:\n");
for (size_t i = 0; i < mCnmt.getContentInfo().size(); i++) for (size_t i = 0; i < mCnmt.getContentInfo().size(); i++)
{ {
const pie::hac::ContentInfo& info = mCnmt.getContentInfo()[i]; const nn::hac::ContentInfo& info = mCnmt.getContentInfo()[i];
fmt::print(" {:d}\n", i); fmt::print(" {:d}\n", i);
fmt::print(" Type: {:s} ({:d})\n", pie::hac::ContentMetaUtil::getContentTypeAsString(info.getContentType()), (uint32_t)info.getContentType()); fmt::print(" Type: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getContentTypeAsString(info.getContentType()), (uint32_t)info.getContentType());
fmt::print(" Id: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(info.getContentId().data(), info.getContentId().size(), false, "")); fmt::print(" Id: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(info.getContentId().data(), info.getContentId().size(), false, ""));
fmt::print(" Size: 0x{:x}\n", info.getContentSize()); fmt::print(" Size: 0x{:x}\n", info.getContentSize());
fmt::print(" Hash: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(info.getContentHash().data(), info.getContentHash().size(), false, "")); fmt::print(" Hash: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(info.getContentHash().data(), info.getContentHash().size(), false, ""));
@ -143,19 +143,19 @@ void nstool::CnmtProcess::displayCnmt()
} }
// print extended data // print extended data
if (mCnmt.getContentMetaType() == pie::hac::cnmt::ContentMetaType_Patch && mCnmt.getPatchMetaExtendedHeader().getExtendedDataSize() != 0) if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::Patch && mCnmt.getPatchMetaExtendedHeader().getExtendedDataSize() != 0)
{ {
// this is stubbed as the raw output is for development purposes // this is stubbed as the raw output is for development purposes
//fmt::print(" PatchMetaExtendedData:\n"); //fmt::print(" PatchMetaExtendedData:\n");
//tc::cli::FormatUtil::formatBytesAsHxdHexString(mCnmt.getPatchMetaExtendedData().data(), mCnmt.getPatchMetaExtendedData().size()); //tc::cli::FormatUtil::formatBytesAsHxdHexString(mCnmt.getPatchMetaExtendedData().data(), mCnmt.getPatchMetaExtendedData().size());
} }
else if (mCnmt.getContentMetaType() == pie::hac::cnmt::ContentMetaType_Delta && mCnmt.getDeltaMetaExtendedHeader().getExtendedDataSize() != 0) else if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::Delta && mCnmt.getDeltaMetaExtendedHeader().getExtendedDataSize() != 0)
{ {
// this is stubbed as the raw output is for development purposes // this is stubbed as the raw output is for development purposes
//fmt::print(" DeltaMetaExtendedData:\n"); //fmt::print(" DeltaMetaExtendedData:\n");
//tc::cli::FormatUtil::formatBytesAsHxdHexString(mCnmt.getDeltaMetaExtendedData().data(), mCnmt.getDeltaMetaExtendedData().size()); //tc::cli::FormatUtil::formatBytesAsHxdHexString(mCnmt.getDeltaMetaExtendedData().data(), mCnmt.getDeltaMetaExtendedData().size());
} }
else if (mCnmt.getContentMetaType() == pie::hac::cnmt::ContentMetaType_SystemUpdate && mCnmt.getSystemUpdateMetaExtendedHeader().getExtendedDataSize() != 0) else if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::SystemUpdate && mCnmt.getSystemUpdateMetaExtendedHeader().getExtendedDataSize() != 0)
{ {
fmt::print(" SystemUpdateMetaExtendedData:\n"); fmt::print(" SystemUpdateMetaExtendedData:\n");
fmt::print(" FormatVersion: {:d}\n", mCnmt.getSystemUpdateMetaExtendedData().getFormatVersion()); fmt::print(" FormatVersion: {:d}\n", mCnmt.getSystemUpdateMetaExtendedData().getFormatVersion());
@ -180,12 +180,12 @@ void nstool::CnmtProcess::displayCnmt()
fmt::print(" Digest: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mCnmt.getDigest().data(), mCnmt.getDigest().size(), false, "")); fmt::print(" Digest: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mCnmt.getDigest().data(), mCnmt.getDigest().size(), false, ""));
} }
void nstool::CnmtProcess::displayContentMetaInfo(const pie::hac::ContentMetaInfo& content_meta_info, const std::string& prefix) void nstool::CnmtProcess::displayContentMetaInfo(const nn::hac::ContentMetaInfo& content_meta_info, const std::string& prefix)
{ {
const pie::hac::sContentMetaInfo* content_meta_info_raw = (const pie::hac::sContentMetaInfo*)content_meta_info.getBytes().data(); const nn::hac::sContentMetaInfo* content_meta_info_raw = (const nn::hac::sContentMetaInfo*)content_meta_info.getBytes().data();
fmt::print("{:s}Id: 0x{:016x}\n", prefix, content_meta_info.getTitleId()); fmt::print("{:s}Id: 0x{:016x}\n", prefix, content_meta_info.getTitleId());
fmt::print("{:s}Version: {:s} (v{:d})\n", prefix, pie::hac::ContentMetaUtil::getVersionAsString(content_meta_info.getTitleVersion()), content_meta_info.getTitleVersion()); fmt::print("{:s}Version: {:s} (v{:d})\n", prefix, nn::hac::ContentMetaUtil::getVersionAsString(content_meta_info.getTitleVersion()), content_meta_info.getTitleVersion());
fmt::print("{:s}Type: {:s} ({:d})\n", prefix, pie::hac::ContentMetaUtil::getContentMetaTypeAsString(content_meta_info.getContentMetaType()), (uint32_t)content_meta_info.getContentMetaType()); fmt::print("{:s}Type: {:s} ({:d})\n", prefix, nn::hac::ContentMetaUtil::getContentMetaTypeAsString(content_meta_info.getContentMetaType()), (uint32_t)content_meta_info.getContentMetaType());
fmt::print("{:s}Attributes: 0x{:x}", prefix, *((byte_t*)&content_meta_info_raw->attributes) ); fmt::print("{:s}Attributes: 0x{:x}", prefix, *((byte_t*)&content_meta_info_raw->attributes) );
if (content_meta_info.getAttribute().size()) if (content_meta_info.getAttribute().size())
{ {
@ -193,7 +193,7 @@ void nstool::CnmtProcess::displayContentMetaInfo(const pie::hac::ContentMetaInfo
for (auto itr = content_meta_info.getAttribute().begin(); itr != content_meta_info.getAttribute().end(); itr++) for (auto itr = content_meta_info.getAttribute().begin(); itr != content_meta_info.getAttribute().end(); itr++)
{ {
attribute_list.push_back(pie::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(pie::hac::cnmt::ContentMetaAttributeFlag(*itr))); attribute_list.push_back(nn::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(nn::hac::cnmt::ContentMetaAttributeFlag(*itr)));
} }
fmt::print(" ["); fmt::print(" [");
@ -210,11 +210,11 @@ void nstool::CnmtProcess::displayContentMetaInfo(const pie::hac::ContentMetaInfo
fmt::print("\n"); fmt::print("\n");
} }
void nstool::CnmtProcess::displayContentMetaInfoList(const std::vector<pie::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix) void nstool::CnmtProcess::displayContentMetaInfoList(const std::vector<nn::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix)
{ {
for (size_t i = 0; i < content_meta_info_list.size(); i++) for (size_t i = 0; i < content_meta_info_list.size(); i++)
{ {
const pie::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i]; const nn::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i];
fmt::print("{:s}{:d}\n", i); fmt::print("{:s}{:d}\n", i);
displayContentMetaInfo(info, prefix + " "); displayContentMetaInfo(info, prefix + " ");
} }

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "types.h" #include "types.h"
#include <pietendo/hac/ContentMeta.h> #include <nn/hac/ContentMeta.h>
namespace nstool { namespace nstool {
@ -16,7 +16,7 @@ public:
void setCliOutputMode(CliOutputMode type); void setCliOutputMode(CliOutputMode type);
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
const pie::hac::ContentMeta& getContentMeta() const; const nn::hac::ContentMeta& getContentMeta() const;
private: private:
std::string mModuleName; std::string mModuleName;
@ -24,13 +24,13 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
pie::hac::ContentMeta mCnmt; nn::hac::ContentMeta mCnmt;
void importCnmt(); void importCnmt();
void displayCnmt(); void displayCnmt();
void displayContentMetaInfo(const pie::hac::ContentMetaInfo& content_meta_info, const std::string& prefix); void displayContentMetaInfo(const nn::hac::ContentMetaInfo& content_meta_info, const std::string& prefix);
void displayContentMetaInfoList(const std::vector<pie::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix); void displayContentMetaInfoList(const std::vector<nn::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix);
}; };
} }

View file

@ -2,7 +2,7 @@
#include "PkiValidator.h" #include "PkiValidator.h"
#include "util.h" #include "util.h"
#include <pietendo/hac/es/SignUtils.h> #include <nn/pki/SignUtils.h>
nstool::EsCertProcess::EsCertProcess() : nstool::EsCertProcess::EsCertProcess() :
mModuleName("nstool::EsCertProcess"), mModuleName("nstool::EsCertProcess"),
@ -66,7 +66,7 @@ void nstool::EsCertProcess::importCerts()
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
pie::hac::es::SignedData<pie::hac::es::CertificateBody> cert; nn::pki::SignedData<nn::pki::CertificateBody> cert;
for (size_t f_pos = 0; f_pos < scratch.size(); f_pos += cert.getBytes().size()) for (size_t f_pos = 0; f_pos < scratch.size(); f_pos += cert.getBytes().size())
{ {
cert.fromBytes(scratch.data() + f_pos, scratch.size() - f_pos); cert.fromBytes(scratch.data() + f_pos, scratch.size() - f_pos);
@ -98,24 +98,24 @@ void nstool::EsCertProcess::displayCerts()
} }
} }
void nstool::EsCertProcess::displayCert(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert) void nstool::EsCertProcess::displayCert(const nn::pki::SignedData<nn::pki::CertificateBody>& cert)
{ {
fmt::print("[ES Certificate]\n"); fmt::print("[ES Certificate]\n");
fmt::print(" SignType {:s}", getSignTypeStr(cert.getSignature().getSignType())); fmt::print(" SignType {:s}", getSignTypeStr(cert.getSignature().getSignType()));
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
fmt::print(" (0x{:x}) ({:s})", (uint32_t)cert.getSignature().getSignType(), getEndiannessStr(cert.getSignature().isLittleEndian())); fmt::print(" (0x{:x}) ({:s})", cert.getSignature().getSignType(), getEndiannessStr(cert.getSignature().isLittleEndian()));
fmt::print("\n"); fmt::print("\n");
fmt::print(" Issuer: {:s}\n", cert.getBody().getIssuer()); fmt::print(" Issuer: {:s}\n", cert.getBody().getIssuer());
fmt::print(" Subject: {:s}\n", cert.getBody().getSubject()); fmt::print(" Subject: {:s}\n", cert.getBody().getSubject());
fmt::print(" PublicKeyType: {:s}", getPublicKeyTypeStr(cert.getBody().getPublicKeyType())); fmt::print(" PublicKeyType: {:s}", getPublicKeyTypeStr(cert.getBody().getPublicKeyType()));
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
fmt::print(" ({:d})", (uint32_t)cert.getBody().getPublicKeyType()); fmt::print(" ({:d})", cert.getBody().getPublicKeyType());
fmt::print("\n"); fmt::print("\n");
fmt::print(" CertID: 0x{:x}\n", cert.getBody().getCertId()); fmt::print(" CertID: 0x{:x}\n", cert.getBody().getCertId());
if (cert.getBody().getPublicKeyType() == pie::hac::es::cert::RSA4096) if (cert.getBody().getPublicKeyType() == nn::pki::cert::RSA4096)
{ {
fmt::print(" PublicKey:\n"); fmt::print(" PublicKey:\n");
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
@ -133,7 +133,7 @@ void nstool::EsCertProcess::displayCert(const pie::hac::es::SignedData<pie::hac:
fmt::print(" {:s}\n", getTruncatedBytesString(cert.getBody().getRsa4096PublicKey().e.data(), cert.getBody().getRsa4096PublicKey().e.size())); fmt::print(" {:s}\n", getTruncatedBytesString(cert.getBody().getRsa4096PublicKey().e.data(), cert.getBody().getRsa4096PublicKey().e.size()));
} }
} }
else if (cert.getBody().getPublicKeyType() == pie::hac::es::cert::RSA2048) else if (cert.getBody().getPublicKeyType() == nn::pki::cert::RSA2048)
{ {
fmt::print(" PublicKey:\n"); fmt::print(" PublicKey:\n");
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
@ -151,7 +151,7 @@ void nstool::EsCertProcess::displayCert(const pie::hac::es::SignedData<pie::hac:
fmt::print(" {:s}\n", getTruncatedBytesString(cert.getBody().getRsa2048PublicKey().e.data(), cert.getBody().getRsa2048PublicKey().e.size())); fmt::print(" {:s}\n", getTruncatedBytesString(cert.getBody().getRsa2048PublicKey().e.data(), cert.getBody().getRsa2048PublicKey().e.size()));
} }
} }
else if (cert.getBody().getPublicKeyType() == pie::hac::es::cert::ECDSA240) else if (cert.getBody().getPublicKeyType() == nn::pki::cert::ECDSA240)
{ {
fmt::print(" PublicKey:\n"); fmt::print(" PublicKey:\n");
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
@ -171,27 +171,27 @@ void nstool::EsCertProcess::displayCert(const pie::hac::es::SignedData<pie::hac:
} }
} }
std::string nstool::EsCertProcess::getSignTypeStr(pie::hac::es::sign::SignatureId type) const std::string nstool::EsCertProcess::getSignTypeStr(nn::pki::sign::SignatureId type) const
{ {
std::string str; std::string str;
switch (type) switch (type)
{ {
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA1): case (nn::pki::sign::SIGN_ID_RSA4096_SHA1):
str = "RSA4096-SHA1"; str = "RSA4096-SHA1";
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA1): case (nn::pki::sign::SIGN_ID_RSA2048_SHA1):
str = "RSA2048-SHA1"; str = "RSA2048-SHA1";
break; break;
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA1): case (nn::pki::sign::SIGN_ID_ECDSA240_SHA1):
str = "ECDSA240-SHA1"; str = "ECDSA240-SHA1";
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA256): case (nn::pki::sign::SIGN_ID_RSA4096_SHA256):
str = "RSA4096-SHA256"; str = "RSA4096-SHA256";
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA256): case (nn::pki::sign::SIGN_ID_RSA2048_SHA256):
str = "RSA2048-SHA256"; str = "RSA2048-SHA256";
break; break;
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA256): case (nn::pki::sign::SIGN_ID_ECDSA240_SHA256):
str = "ECDSA240-SHA256"; str = "ECDSA240-SHA256";
break; break;
default: default:
@ -206,18 +206,18 @@ std::string nstool::EsCertProcess::getEndiannessStr(bool isLittleEndian) const
return isLittleEndian ? "LittleEndian" : "BigEndian"; return isLittleEndian ? "LittleEndian" : "BigEndian";
} }
std::string nstool::EsCertProcess::getPublicKeyTypeStr(pie::hac::es::cert::PublicKeyType type) const std::string nstool::EsCertProcess::getPublicKeyTypeStr(nn::pki::cert::PublicKeyType type) const
{ {
std::string str; std::string str;
switch (type) switch (type)
{ {
case (pie::hac::es::cert::RSA4096): case (nn::pki::cert::RSA4096):
str = "RSA4096"; str = "RSA4096";
break; break;
case (pie::hac::es::cert::RSA2048): case (nn::pki::cert::RSA2048):
str = "RSA2048"; str = "RSA2048";
break; break;
case (pie::hac::es::cert::ECDSA240): case (nn::pki::cert::ECDSA240):
str = "ECDSA240"; str = "ECDSA240";
break; break;
default: default:

View file

@ -2,8 +2,8 @@
#include "types.h" #include "types.h"
#include "KeyBag.h" #include "KeyBag.h"
#include <pietendo/hac/es/SignedData.h> #include <nn/pki/SignedData.h>
#include <pietendo/hac/es/CertificateBody.h> #include <nn/pki/CertificateBody.h>
namespace nstool { namespace nstool {
@ -27,16 +27,16 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>> mCert; std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> mCert;
void importCerts(); void importCerts();
void validateCerts(); void validateCerts();
void displayCerts(); void displayCerts();
void displayCert(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert); void displayCert(const nn::pki::SignedData<nn::pki::CertificateBody>& cert);
std::string getSignTypeStr(pie::hac::es::sign::SignatureId type) const; std::string getSignTypeStr(nn::pki::sign::SignatureId type) const;
std::string getEndiannessStr(bool isLittleEndian) const; std::string getEndiannessStr(bool isLittleEndian) const;
std::string getPublicKeyTypeStr(pie::hac::es::cert::PublicKeyType type) const; std::string getPublicKeyTypeStr(nn::pki::cert::PublicKeyType type) const;
}; };
} }

View file

@ -1,7 +1,7 @@
#include "EsTikProcess.h" #include "EsTikProcess.h"
#include "PkiValidator.h" #include "PkiValidator.h"
#include <pietendo/hac/es/SignUtils.h> #include <nn/pki/SignUtils.h>
nstool::EsTikProcess::EsTikProcess() : nstool::EsTikProcess::EsTikProcess() :
mModuleName("nstool::EsTikProcess"), mModuleName("nstool::EsTikProcess"),
@ -32,7 +32,7 @@ void nstool::EsTikProcess::setKeyCfg(const KeyBag& keycfg)
mKeyCfg = keycfg; mKeyCfg = keycfg;
} }
void nstool::EsTikProcess::setCertificateChain(const std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>>& certs) void nstool::EsTikProcess::setCertificateChain(const std::vector<nn::pki::SignedData<nn::pki::CertificateBody>>& certs)
{ {
mCerts = certs; mCerts = certs;
} }
@ -78,15 +78,15 @@ void nstool::EsTikProcess::verifyTicket()
PkiValidator pki_validator; PkiValidator pki_validator;
tc::ByteData tik_hash; tc::ByteData tik_hash;
switch (pie::hac::es::sign::getHashAlgo(mTik.getSignature().getSignType())) switch (nn::pki::sign::getHashAlgo(mTik.getSignature().getSignType()))
{ {
case (pie::hac::es::sign::HASH_ALGO_SHA1): case (nn::pki::sign::HASH_ALGO_SHA1):
tik_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize); tik_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize);
tc::crypto::GenerateSha1Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size()); tc::crypto::GenerateSha1Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size());
break; break;
case (pie::hac::es::sign::HASH_ALGO_SHA256): case (nn::pki::sign::HASH_ALGO_SHA256):
tik_hash = tc::ByteData(tc::crypto::Sha2256Generator::kHashSize); tik_hash = tc::ByteData(tc::crypto::Sha256Generator::kHashSize);
tc::crypto::GenerateSha2256Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size()); tc::crypto::GenerateSha256Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size());
break; break;
} }
@ -104,24 +104,24 @@ void nstool::EsTikProcess::verifyTicket()
void nstool::EsTikProcess::displayTicket() void nstool::EsTikProcess::displayTicket()
{ {
const pie::hac::es::TicketBody_V2& body = mTik.getBody(); const nn::es::TicketBody_V2& body = mTik.getBody();
fmt::print("[ES Ticket]\n"); fmt::print("[ES Ticket]\n");
fmt::print(" SignType: {:s}", getSignTypeStr(mTik.getSignature().getSignType())); fmt::print(" SignType: {:s}", getSignTypeStr(mTik.getSignature().getSignType()));
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
fmt::print(" (0x{:x})", (uint32_t)mTik.getSignature().getSignType()); fmt::print(" (0x{:x})", mTik.getSignature().getSignType());
fmt::print("\n"); fmt::print("\n");
fmt::print(" Issuer: {:s}\n", body.getIssuer()); fmt::print(" Issuer: {:s}\n", body.getIssuer());
fmt::print(" Title Key:\n"); fmt::print(" Title Key:\n");
fmt::print(" EncMode: {:s}\n", getTitleKeyPersonalisationStr(body.getTitleKeyEncType())); fmt::print(" EncMode: {:s}\n", getTitleKeyPersonalisationStr(body.getTitleKeyEncType()));
fmt::print(" KeyGeneration: {:d}\n", (uint32_t)body.getCommonKeyId()); fmt::print(" KeyGeneration: {:d}\n", (uint32_t)body.getCommonKeyId());
if (body.getTitleKeyEncType() == pie::hac::es::ticket::RSA2048) if (body.getTitleKeyEncType() == nn::es::ticket::RSA2048)
{ {
fmt::print(" Data:\n"); fmt::print(" Data:\n");
fmt::print(" {:s}", tc::cli::FormatUtil::formatBytesAsStringWithLineLimit(body.getEncTitleKey(), 0x100, true, "", 0x10, 6, false)); fmt::print(" {:s}", tc::cli::FormatUtil::formatBytesAsStringWithLineLimit(body.getEncTitleKey(), 0x100, true, "", 0x10, 6, false));
} }
else if (body.getTitleKeyEncType() == pie::hac::es::ticket::AES128_CBC) else if (body.getTitleKeyEncType() == nn::es::ticket::AES128_CBC)
{ {
fmt::print(" Data:\n"); fmt::print(" Data:\n");
fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(body.getEncTitleKey(), 0x10, true, "")); fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(body.getEncTitleKey(), 0x10, true, ""));
@ -134,7 +134,7 @@ void nstool::EsTikProcess::displayTicket()
fmt::print(" License Type: {:s}\n", getLicenseTypeStr(body.getLicenseType())); fmt::print(" License Type: {:s}\n", getLicenseTypeStr(body.getLicenseType()));
if (body.getPropertyFlags().size() > 0 || mCliOutputMode.show_extended_info) if (body.getPropertyFlags().size() > 0 || mCliOutputMode.show_extended_info)
{ {
pie::hac::es::sTicketBody_v2* raw_body = (pie::hac::es::sTicketBody_v2*)body.getBytes().data(); nn::es::sTicketBody_v2* raw_body = (nn::es::sTicketBody_v2*)body.getBytes().data();
fmt::print(" PropertyMask: 0x{:04x}\n", ((tc::bn::le16<uint16_t>*)&raw_body->property_mask)->unwrap()); fmt::print(" PropertyMask: 0x{:04x}\n", ((tc::bn::le16<uint16_t>*)&raw_body->property_mask)->unwrap());
for (size_t i = 0; i < body.getPropertyFlags().size(); i++) for (size_t i = 0; i < body.getPropertyFlags().size(); i++)
{ {
@ -167,22 +167,22 @@ std::string nstool::EsTikProcess::getSignTypeStr(uint32_t type) const
std::string str; std::string str;
switch(type) switch(type)
{ {
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA1): case (nn::pki::sign::SIGN_ID_RSA4096_SHA1):
str = "RSA4096-SHA1"; str = "RSA4096-SHA1";
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA1): case (nn::pki::sign::SIGN_ID_RSA2048_SHA1):
str = "RSA2048-SHA1"; str = "RSA2048-SHA1";
break; break;
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA1): case (nn::pki::sign::SIGN_ID_ECDSA240_SHA1):
str = "ECDSA240-SHA1"; str = "ECDSA240-SHA1";
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA256): case (nn::pki::sign::SIGN_ID_RSA4096_SHA256):
str = "RSA4096-SHA256"; str = "RSA4096-SHA256";
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA256): case (nn::pki::sign::SIGN_ID_RSA2048_SHA256):
str = "RSA2048-SHA256"; str = "RSA2048-SHA256";
break; break;
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA256): case (nn::pki::sign::SIGN_ID_ECDSA240_SHA256):
str = "ECDSA240-SHA256"; str = "ECDSA240-SHA256";
break; break;
default: default:
@ -197,10 +197,10 @@ std::string nstool::EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) con
std::string str; std::string str;
switch(flag) switch(flag)
{ {
case (pie::hac::es::ticket::AES128_CBC): case (nn::es::ticket::AES128_CBC):
str = "Generic (AESCBC)"; str = "Generic (AESCBC)";
break; break;
case (pie::hac::es::ticket::RSA2048): case (nn::es::ticket::RSA2048):
str = "Personalised (RSA2048)"; str = "Personalised (RSA2048)";
break; break;
default: default:
@ -215,22 +215,22 @@ std::string nstool::EsTikProcess::getLicenseTypeStr(byte_t flag) const
std::string str; std::string str;
switch(flag) switch(flag)
{ {
case (pie::hac::es::ticket::LICENSE_PERMANENT): case (nn::es::ticket::LICENSE_PERMANENT):
str = "Permanent"; str = "Permanent";
break; break;
case (pie::hac::es::ticket::LICENSE_DEMO): case (nn::es::ticket::LICENSE_DEMO):
str = "Demo"; str = "Demo";
break; break;
case (pie::hac::es::ticket::LICENSE_TRIAL): case (nn::es::ticket::LICENSE_TRIAL):
str = "Trial"; str = "Trial";
break; break;
case (pie::hac::es::ticket::LICENSE_RENTAL): case (nn::es::ticket::LICENSE_RENTAL):
str = "Rental"; str = "Rental";
break; break;
case (pie::hac::es::ticket::LICENSE_SUBSCRIPTION): case (nn::es::ticket::LICENSE_SUBSCRIPTION):
str = "Subscription"; str = "Subscription";
break; break;
case (pie::hac::es::ticket::LICENSE_SERVICE): case (nn::es::ticket::LICENSE_SERVICE):
str = "Service"; str = "Service";
break; break;
default: default:
@ -245,22 +245,22 @@ std::string nstool::EsTikProcess::getPropertyFlagStr(byte_t flag) const
std::string str; std::string str;
switch(flag) switch(flag)
{ {
case (pie::hac::es::ticket::FLAG_PRE_INSTALL): case (nn::es::ticket::FLAG_PRE_INSTALL):
str = "PreInstall"; str = "PreInstall";
break; break;
case (pie::hac::es::ticket::FLAG_SHARED_TITLE): case (nn::es::ticket::FLAG_SHARED_TITLE):
str = "SharedTitle"; str = "SharedTitle";
break; break;
case (pie::hac::es::ticket::FLAG_ALLOW_ALL_CONTENT): case (nn::es::ticket::FLAG_ALLOW_ALL_CONTENT):
str = "AllContent"; str = "AllContent";
break; break;
case (pie::hac::es::ticket::FLAG_DEVICE_LINK_INDEPENDENT): case (nn::es::ticket::FLAG_DEVICE_LINK_INDEPENDENT):
str = "DeviceLinkIndependent"; str = "DeviceLinkIndependent";
break; break;
case (pie::hac::es::ticket::FLAG_VOLATILE): case (nn::es::ticket::FLAG_VOLATILE):
str = "Volatile"; str = "Volatile";
break; break;
case (pie::hac::es::ticket::FLAG_ELICENSE_REQUIRED): case (nn::es::ticket::FLAG_ELICENSE_REQUIRED):
str = "ELicenseRequired"; str = "ELicenseRequired";
break; break;
default: default:

View file

@ -2,9 +2,9 @@
#include "types.h" #include "types.h"
#include "KeyBag.h" #include "KeyBag.h"
#include <pietendo/hac/es/SignedData.h> #include <nn/pki/SignedData.h>
#include <pietendo/hac/es/CertificateBody.h> #include <nn/pki/CertificateBody.h>
#include <pietendo/hac/es/TicketBody_V2.h> #include <nn/es/TicketBody_V2.h>
namespace nstool { namespace nstool {
@ -17,7 +17,7 @@ public:
void setInputFile(const std::shared_ptr<tc::io::IStream>& file); void setInputFile(const std::shared_ptr<tc::io::IStream>& file);
void setKeyCfg(const KeyBag& keycfg); void setKeyCfg(const KeyBag& keycfg);
void setCertificateChain(const std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>>& certs); void setCertificateChain(const std::vector<nn::pki::SignedData<nn::pki::CertificateBody>>& certs);
void setCliOutputMode(CliOutputMode mode); void setCliOutputMode(CliOutputMode mode);
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
private: private:
@ -28,9 +28,9 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>> mCerts; std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> mCerts;
pie::hac::es::SignedData<pie::hac::es::TicketBody_V2> mTik; nn::pki::SignedData<nn::es::TicketBody_V2> mTik;
void importTicket(); void importTicket();
void verifyTicket(); void verifyTicket();

View file

@ -46,7 +46,7 @@ void nstool::FsProcess::process()
} }
} }
void nstool::FsProcess::setInputFileSystem(const std::shared_ptr<tc::io::IFileSystem>& input_fs) void nstool::FsProcess::setInputFileSystem(const std::shared_ptr<tc::io::IStorage>& input_fs)
{ {
mInputFs = input_fs; mInputFs = input_fs;
} }
@ -93,12 +93,15 @@ void nstool::FsProcess::extractFs()
for (auto itr = mExtractJobs.begin(); itr != mExtractJobs.end(); itr++) for (auto itr = mExtractJobs.begin(); itr != mExtractJobs.end(); itr++)
{ {
std::string path_str;
tc::io::PathUtil::pathToUnixUTF8(itr->virtual_path, path_str);
// check if root path (legacy case) // check if root path (legacy case)
if (itr->virtual_path == tc::io::Path("/")) if (itr->virtual_path == tc::io::Path("/"))
{ {
visitDir(tc::io::Path("/"), itr->extract_path, true, false); visitDir(tc::io::Path("/"), itr->extract_path, true, false);
//fmt::print("Root Dir Virtual Path: \"{:s}\"\n", itr->virtual_path.to_string()); //fmt::print("Root Dir Virtual Path: \"{:s}\"\n", path_str);
// root directory extract successful, continue to next job // root directory extract successful, continue to next job
continue; continue;
@ -109,10 +112,10 @@ void nstool::FsProcess::extractFs()
std::shared_ptr<tc::io::IStream> file_stream; std::shared_ptr<tc::io::IStream> file_stream;
mInputFs->openFile(itr->virtual_path, tc::io::FileMode::Open, tc::io::FileAccess::Read, file_stream); mInputFs->openFile(itr->virtual_path, tc::io::FileMode::Open, tc::io::FileAccess::Read, file_stream);
//fmt::print("Valid File Path: \"{:s}\"\n", itr->virtual_path.to_string()); //fmt::print("Valid File Path: \"{:s}\"\n", path_str);
// the output path for this file will depend on the user specified extract path // the output path for this file will depend on the user specified extract path
std::shared_ptr<tc::io::IFileSystem> local_fs = std::make_shared<tc::io::LocalFileSystem>(tc::io::LocalFileSystem()); std::shared_ptr<tc::io::IStorage> local_fs = std::make_shared<tc::io::LocalStorage>(tc::io::LocalStorage());
// case: the extract_path is a valid path to an existing directory // case: the extract_path is a valid path to an existing directory
// behaviour: extract the file, preserving the original filename, to the specified directory // behaviour: extract the file, preserving the original filename, to the specified directory
@ -124,7 +127,10 @@ void nstool::FsProcess::extractFs()
tc::io::Path file_extract_path = itr->extract_path + itr->virtual_path.back(); tc::io::Path file_extract_path = itr->extract_path + itr->virtual_path.back();
fmt::print("Saving {:s}...\n", file_extract_path.to_string()); std::string file_extract_path_str;
tc::io::PathUtil::pathToUnixUTF8(file_extract_path, file_extract_path_str);
fmt::print("Saving {:s}...\n", file_extract_path_str);
writeStreamToFile(file_stream, itr->extract_path + itr->virtual_path.back(), mDataCache); writeStreamToFile(file_stream, itr->extract_path + itr->virtual_path.back(), mDataCache);
@ -139,18 +145,24 @@ void nstool::FsProcess::extractFs()
// method: since this checks n-1 elements, it implies a path with more than one element, so that must be accounted for, as relative paths are valid and single element paths aren't always root // method: since this checks n-1 elements, it implies a path with more than one element, so that must be accounted for, as relative paths are valid and single element paths aren't always root
try { try {
std::string test_path_str;
// get path to parent directory // get path to parent directory
tc::io::Path parent_dir_path = itr->extract_path; tc::io::Path parent_dir_path = itr->extract_path;
// replace final path element with the current directory alias // replace final path element with the current directory alias
parent_dir_path.pop_back(); // remove filename parent_dir_path.pop_back(); // remove filename
parent_dir_path.push_back("."); // replace with the current dir name alias parent_dir_path.push_back("."); // replace with the current dir name alias
tc::io::PathUtil::pathToUnixUTF8(parent_dir_path, test_path_str);
// test parent directory exists // test parent directory exists
tc::io::sDirectoryListing dir_listing; tc::io::sDirectoryListing dir_listing;
local_fs->getDirectoryListing(parent_dir_path, dir_listing); local_fs->getDirectoryListing(parent_dir_path, dir_listing);
fmt::print("Saving {:s} as {:s}...\n", itr->virtual_path.to_string(), itr->extract_path.to_string()); std::string file_extract_path_str;
tc::io::PathUtil::pathToUnixUTF8(itr->extract_path, file_extract_path_str);
fmt::print("Saving {:s} as {:s}...\n", path_str, file_extract_path_str);
writeStreamToFile(file_stream, itr->extract_path, mDataCache); writeStreamToFile(file_stream, itr->extract_path, mDataCache);
@ -161,7 +173,9 @@ void nstool::FsProcess::extractFs()
// extract path could not be determined, inform the user and skip this job // extract path could not be determined, inform the user and skip this job
fmt::print("[WARNING] Extract path was invalid, and was skipped: {:s}\n", itr->extract_path.to_string()); std::string literal_extract_path_str;
tc::io::PathUtil::pathToUnixUTF8(itr->extract_path, literal_extract_path_str);
fmt::print("[WARNING] Extract path was invalid, and was skipped: {:s}\n", literal_extract_path_str);
continue; continue;
} catch (tc::io::FileNotFoundException&) { } catch (tc::io::FileNotFoundException&) {
// acceptable exception, just means file didn't exist // acceptable exception, just means file didn't exist
@ -172,9 +186,10 @@ void nstool::FsProcess::extractFs()
tc::io::sDirectoryListing dir_listing; tc::io::sDirectoryListing dir_listing;
mInputFs->getDirectoryListing(itr->virtual_path, dir_listing); mInputFs->getDirectoryListing(itr->virtual_path, dir_listing);
visitDir(itr->virtual_path, itr->extract_path, true, false); visitDir(itr->virtual_path, itr->extract_path, true, false);
//fmt::print("Valid Directory Path: \"{:s}\"\n", itr->virtual_path.to_string()); //fmt::print("Valid Directory Path: \"{:s}\"\n", path_str);
// directory extract successful, continue to next job // directory extract successful, continue to next job
continue; continue;
@ -183,14 +198,14 @@ void nstool::FsProcess::extractFs()
// acceptable exception, just means directory didn't exist // acceptable exception, just means directory didn't exist
} }
fmt::print("[WARNING] Failed to extract virtual path: \"{:s}\"\n", itr->virtual_path.to_string()); fmt::print("[WARNING] Failed to extract virtual path: \"{:s}\"\n", path_str);
} }
} }
void nstool::FsProcess::visitDir(const tc::io::Path& v_path, const tc::io::Path& l_path, bool extract_fs, bool print_fs) void nstool::FsProcess::visitDir(const tc::io::Path& v_path, const tc::io::Path& l_path, bool extract_fs, bool print_fs)
{ {
tc::io::LocalFileSystem local_fs; tc::io::LocalStorage local_fs;
// get listing for directory // get listing for directory
tc::io::sDirectoryListing info; tc::io::sDirectoryListing info;
@ -212,6 +227,7 @@ void nstool::FsProcess::visitDir(const tc::io::Path& v_path, const tc::io::Path&
// iterate thru child files // iterate thru child files
size_t cache_read_len; size_t cache_read_len;
tc::io::Path out_path; tc::io::Path out_path;
std::string out_path_str;
std::shared_ptr<tc::io::IStream> in_stream; std::shared_ptr<tc::io::IStream> in_stream;
std::shared_ptr<tc::io::IStream> out_stream; std::shared_ptr<tc::io::IStream> out_stream;
for (auto itr = info.file_list.begin(); itr != info.file_list.end(); itr++) for (auto itr = info.file_list.begin(); itr != info.file_list.end(); itr++)
@ -226,8 +242,9 @@ void nstool::FsProcess::visitDir(const tc::io::Path& v_path, const tc::io::Path&
{ {
// build out path // build out path
out_path = l_path + *itr; out_path = l_path + *itr;
tc::io::PathUtil::pathToUnixUTF8(out_path, out_path_str);
fmt::print("Saving {:s}...\n", out_path.to_string()); fmt::print("Saving {:s}...\n", out_path_str);
// begin export // begin export
mInputFs->openFile(v_path + *itr, tc::io::FileMode::Open, tc::io::FileAccess::Read, in_stream); mInputFs->openFile(v_path + *itr, tc::io::FileMode::Open, tc::io::FileAccess::Read, in_stream);

View file

@ -14,7 +14,7 @@ public:
void process(); void process();
void setInputFileSystem(const std::shared_ptr<tc::io::IFileSystem>& input_fs); void setInputFileSystem(const std::shared_ptr<tc::io::IStorage>& input_fs);
void setFsFormatName(const std::string& fs_format_name); void setFsFormatName(const std::string& fs_format_name);
void setFsProperties(const std::vector<std::string>& properties); void setFsProperties(const std::vector<std::string>& properties);
void setShowFsInfo(bool show_fs_info); void setShowFsInfo(bool show_fs_info);
@ -24,7 +24,7 @@ public:
private: private:
std::string mModuleLabel; std::string mModuleLabel;
std::shared_ptr<tc::io::IFileSystem> mInputFs; std::shared_ptr<tc::io::IStorage> mInputFs;
// fs info // fs info
tc::Optional<std::string> mFsFormatName; tc::Optional<std::string> mFsFormatName;

View file

@ -3,11 +3,11 @@
#include <tc/crypto.h> #include <tc/crypto.h>
#include <tc/io/IOUtil.h> #include <tc/io/IOUtil.h>
#include <pietendo/hac/GameCardUtil.h> #include <nn/hac/GameCardUtil.h>
#include <pietendo/hac/ContentMetaUtil.h> #include <nn/hac/ContentMetaUtil.h>
#include <pietendo/hac/ContentArchiveUtil.h> #include <nn/hac/ContentArchiveUtil.h>
#include <pietendo/hac/GameCardFsSnapshotGenerator.h> #include <nn/hac/GameCardFsMetaGenerator.h>
#include "FsProcess.h" #include "FsProcess.h"
@ -16,12 +16,10 @@ nstool::GameCardProcess::GameCardProcess() :
mFile(), mFile(),
mCliOutputMode(true, false, false, false), mCliOutputMode(true, false, false, false),
mVerify(false), mVerify(false),
mIsTrueSdkXci(false), mListFs(false),
mIsSdkXciEncrypted(false),
mGcHeaderOffset(0),
mProccessExtendedHeader(false), mProccessExtendedHeader(false),
mFileSystem(), mRootPfs(),
mFsProcess() mExtractJobs()
{ {
} }
@ -61,14 +59,14 @@ void nstool::GameCardProcess::setVerifyMode(bool verify)
mVerify = verify; mVerify = verify;
} }
void nstool::GameCardProcess::setShowFsTree(bool show_fs_tree)
{
mFsProcess.setShowFsTree(show_fs_tree);
}
void nstool::GameCardProcess::setExtractJobs(const std::vector<nstool::ExtractJob> extract_jobs) void nstool::GameCardProcess::setExtractJobs(const std::vector<nstool::ExtractJob> extract_jobs)
{ {
mFsProcess.setExtractJobs(extract_jobs); mExtractJobs = extract_jobs;
}
void nstool::GameCardProcess::setShowFsTree(bool show_fs_tree)
{
mListFs = show_fs_tree;
} }
void nstool::GameCardProcess::importHeader() void nstool::GameCardProcess::importHeader()
@ -83,25 +81,25 @@ void nstool::GameCardProcess::importHeader()
} }
// check stream is large enough for header // check stream is large enough for header
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sSdkGcHeader))) if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sSdkGcHeader)))
{ {
throw tc::Exception(mModuleName, "Corrupt GameCard Image: File too small."); throw tc::Exception(mModuleName, "Corrupt GameCard Image: File too small.");
} }
// allocate memory for header // allocate memory for header
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sSdkGcHeader)); tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sSdkGcHeader));
// read header region // read header region
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
// determine if this is a SDK XCI or a "Community" XCI // determine if this is a SDK XCI or a "Community" XCI
if (((pie::hac::sSdkGcHeader*)scratch.data())->signed_header.header.st_magic.unwrap() == pie::hac::gc::kGcHeaderStructMagic) if (((nn::hac::sSdkGcHeader*)scratch.data())->signed_header.header.st_magic.unwrap() == nn::hac::gc::kGcHeaderStructMagic)
{ {
mIsTrueSdkXci = true; mIsTrueSdkXci = true;
mGcHeaderOffset = sizeof(pie::hac::sGcKeyDataRegion); mGcHeaderOffset = sizeof(nn::hac::sGcKeyDataRegion);
} }
else if (((pie::hac::sGcHeader_Rsa2048Signed*)scratch.data())->header.st_magic.unwrap() == pie::hac::gc::kGcHeaderStructMagic) else if (((nn::hac::sGcHeader_Rsa2048Signed*)scratch.data())->header.st_magic.unwrap() == nn::hac::gc::kGcHeaderStructMagic)
{ {
mIsTrueSdkXci = false; mIsTrueSdkXci = false;
mGcHeaderOffset = 0; mGcHeaderOffset = 0;
@ -111,33 +109,33 @@ void nstool::GameCardProcess::importHeader()
throw tc::Exception(mModuleName, "Corrupt GameCard Image: Unexpected magic bytes."); throw tc::Exception(mModuleName, "Corrupt GameCard Image: Unexpected magic bytes.");
} }
pie::hac::sGcHeader_Rsa2048Signed* hdr_ptr = (pie::hac::sGcHeader_Rsa2048Signed*)(scratch.data() + mGcHeaderOffset); nn::hac::sGcHeader_Rsa2048Signed* hdr_ptr = (nn::hac::sGcHeader_Rsa2048Signed*)(scratch.data() + mGcHeaderOffset);
// generate hash of raw header // generate hash of raw header
tc::crypto::GenerateSha2256Hash(mHdrHash.data(), (byte_t*)&hdr_ptr->header, sizeof(pie::hac::sGcHeader)); tc::crypto::GenerateSha256Hash(mHdrHash.data(), (byte_t*)&hdr_ptr->header, sizeof(nn::hac::sGcHeader));
// save the signature // save the signature
memcpy(mHdrSignature.data(), hdr_ptr->signature.data(), mHdrSignature.size()); memcpy(mHdrSignature.data(), hdr_ptr->signature.data(), mHdrSignature.size());
// decrypt extended header // decrypt extended header
byte_t xci_header_key_index = hdr_ptr->header.key_flag & 0xf; byte_t xci_header_key_index = hdr_ptr->header.key_flag & 7;
if (mKeyCfg.xci_header_key.find(xci_header_key_index) != mKeyCfg.xci_header_key.end()) if (mKeyCfg.xci_header_key.find(xci_header_key_index) != mKeyCfg.xci_header_key.end())
{ {
pie::hac::GameCardUtil::decryptXciHeader(&hdr_ptr->header, mKeyCfg.xci_header_key[xci_header_key_index].data()); nn::hac::GameCardUtil::decryptXciHeader(&hdr_ptr->header, mKeyCfg.xci_header_key[xci_header_key_index].data());
mProccessExtendedHeader = true; mProccessExtendedHeader = true;
} }
// deserialise header // deserialise header
mHdr.fromBytes((byte_t*)&hdr_ptr->header, sizeof(pie::hac::sGcHeader)); mHdr.fromBytes((byte_t*)&hdr_ptr->header, sizeof(nn::hac::sGcHeader));
} }
void nstool::GameCardProcess::displayHeader() void nstool::GameCardProcess::displayHeader()
{ {
const pie::hac::sGcHeader* raw_hdr = (const pie::hac::sGcHeader*)mHdr.getBytes().data(); const nn::hac::sGcHeader* raw_hdr = (const nn::hac::sGcHeader*)mHdr.getBytes().data();
fmt::print("[GameCard/Header]\n"); fmt::print("[GameCard/Header]\n");
fmt::print(" CardHeaderVersion: {:d}\n", mHdr.getCardHeaderVersion()); fmt::print(" CardHeaderVersion: {:d}\n", mHdr.getCardHeaderVersion());
fmt::print(" RomSize: {:s}", pie::hac::GameCardUtil::getRomSizeAsString((pie::hac::gc::RomSize)mHdr.getRomSizeType())); fmt::print(" RomSize: {:s}", nn::hac::GameCardUtil::getRomSizeAsString((nn::hac::gc::RomSize)mHdr.getRomSizeType()));
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
fmt::print(" (0x{:x})", mHdr.getRomSizeType()); fmt::print(" (0x{:x})", mHdr.getRomSizeType());
fmt::print("\n"); fmt::print("\n");
@ -145,13 +143,13 @@ void nstool::GameCardProcess::displayHeader()
fmt::print(" Flags: 0x{:02x}\n", *((byte_t*)&raw_hdr->flags)); fmt::print(" Flags: 0x{:02x}\n", *((byte_t*)&raw_hdr->flags));
for (auto itr = mHdr.getFlags().begin(); itr != mHdr.getFlags().end(); itr++) for (auto itr = mHdr.getFlags().begin(); itr != mHdr.getFlags().end(); itr++)
{ {
fmt::print(" {:s}\n", pie::hac::GameCardUtil::getHeaderFlagsAsString((pie::hac::gc::HeaderFlags)*itr)); fmt::print(" {:s}\n", nn::hac::GameCardUtil::getHeaderFlagsAsString((nn::hac::gc::HeaderFlags)*itr));
} }
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
{ {
fmt::print(" KekIndex: {:s} ({:d})\n", pie::hac::GameCardUtil::getKekIndexAsString((pie::hac::gc::KekIndex)mHdr.getKekIndex()), mHdr.getKekIndex()); fmt::print(" KekIndex: {:s} ({:d})\n", nn::hac::GameCardUtil::getKekIndexAsString((nn::hac::gc::KekIndex)mHdr.getKekIndex()), mHdr.getKekIndex());
fmt::print(" TitleKeyDecIndex: {:d}\n", mHdr.getTitleKeyDecIndex()); fmt::print(" TitleKeyDecIndex: {:d}\n", mHdr.getTitleKeyDecIndex());
fmt::print(" InitialData:\n"); fmt::print(" InitialData:\n");
fmt::print(" Hash:\n"); fmt::print(" Hash:\n");
@ -169,22 +167,22 @@ void nstool::GameCardProcess::displayHeader()
{ {
fmt::print(" RomAreaStartPage: 0x{:x}", mHdr.getRomAreaStartPage()); fmt::print(" RomAreaStartPage: 0x{:x}", mHdr.getRomAreaStartPage());
if (mHdr.getRomAreaStartPage() != (uint32_t)(-1)) if (mHdr.getRomAreaStartPage() != (uint32_t)(-1))
fmt::print(" (0x{:x})", pie::hac::GameCardUtil::blockToAddr(mHdr.getRomAreaStartPage())); fmt::print(" (0x{:x})", nn::hac::GameCardUtil::blockToAddr(mHdr.getRomAreaStartPage()));
fmt::print("\n"); fmt::print("\n");
fmt::print(" BackupAreaStartPage: 0x{:x}", mHdr.getBackupAreaStartPage()); fmt::print(" BackupAreaStartPage: 0x{:x}", mHdr.getBackupAreaStartPage());
if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1)) if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1))
fmt::print(" (0x{:x})", pie::hac::GameCardUtil::blockToAddr(mHdr.getBackupAreaStartPage())); fmt::print(" (0x{:x})", nn::hac::GameCardUtil::blockToAddr(mHdr.getBackupAreaStartPage()));
fmt::print("\n"); fmt::print("\n");
fmt::print(" ValidDataEndPage: 0x{:x}", mHdr.getValidDataEndPage()); fmt::print(" ValidDataEndPage: 0x{:x}", mHdr.getValidDataEndPage());
if (mHdr.getValidDataEndPage() != (uint32_t)(-1)) if (mHdr.getValidDataEndPage() != (uint32_t)(-1))
fmt::print(" (0x{:x})", pie::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage())); fmt::print(" (0x{:x})", nn::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage()));
fmt::print("\n"); fmt::print("\n");
fmt::print(" LimArea: 0x{:x}", mHdr.getLimAreaPage()); fmt::print(" LimArea: 0x{:x}", mHdr.getLimAreaPage());
if (mHdr.getLimAreaPage() != (uint32_t)(-1)) if (mHdr.getLimAreaPage() != (uint32_t)(-1))
fmt::print(" (0x{:x})", pie::hac::GameCardUtil::blockToAddr(mHdr.getLimAreaPage())); fmt::print(" (0x{:x})", nn::hac::GameCardUtil::blockToAddr(mHdr.getLimAreaPage()));
fmt::print("\n"); fmt::print("\n");
fmt::print(" PartitionFs Header:\n"); fmt::print(" PartitionFs Header:\n");
@ -201,17 +199,17 @@ void nstool::GameCardProcess::displayHeader()
if (mProccessExtendedHeader) if (mProccessExtendedHeader)
{ {
fmt::print("[GameCard/ExtendedHeader]\n"); fmt::print("[GameCard/ExtendedHeader]\n");
fmt::print(" FwVersion: v{:d} ({:s})\n", mHdr.getFwVersion(), pie::hac::GameCardUtil::getCardFwVersionDescriptionAsString((pie::hac::gc::FwVersion)mHdr.getFwVersion())); fmt::print(" FwVersion: v{:d} ({:s})\n", mHdr.getFwVersion(), nn::hac::GameCardUtil::getCardFwVersionDescriptionAsString((nn::hac::gc::FwVersion)mHdr.getFwVersion()));
fmt::print(" AccCtrl1: 0x{:x}\n", mHdr.getAccCtrl1()); fmt::print(" AccCtrl1: 0x{:x}\n", mHdr.getAccCtrl1());
fmt::print(" CardClockRate: {:s}\n", pie::hac::GameCardUtil::getCardClockRateAsString((pie::hac::gc::CardClockRate)mHdr.getAccCtrl1())); fmt::print(" CardClockRate: {:s}\n", nn::hac::GameCardUtil::getCardClockRateAsString((nn::hac::gc::CardClockRate)mHdr.getAccCtrl1()));
fmt::print(" Wait1TimeRead: 0x{:x}\n", mHdr.getWait1TimeRead()); fmt::print(" Wait1TimeRead: 0x{:x}\n", mHdr.getWait1TimeRead());
fmt::print(" Wait2TimeRead: 0x{:x}\n", mHdr.getWait2TimeRead()); fmt::print(" Wait2TimeRead: 0x{:x}\n", mHdr.getWait2TimeRead());
fmt::print(" Wait1TimeWrite: 0x{:x}\n", mHdr.getWait1TimeWrite()); fmt::print(" Wait1TimeWrite: 0x{:x}\n", mHdr.getWait1TimeWrite());
fmt::print(" Wait2TimeWrite: 0x{:x}\n", mHdr.getWait2TimeWrite()); fmt::print(" Wait2TimeWrite: 0x{:x}\n", mHdr.getWait2TimeWrite());
fmt::print(" SdkAddon Version: {:s} (v{:d})\n", pie::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getFwMode()), mHdr.getFwMode()); fmt::print(" SdkAddon Version: {:s} (v{:d})\n", nn::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getFwMode()), mHdr.getFwMode());
fmt::print(" CompatibilityType: {:s} ({:d})\n", pie::hac::GameCardUtil::getCompatibilityTypeAsString((pie::hac::gc::CompatibilityType)mHdr.getCompatibilityType()), mHdr.getCompatibilityType()); fmt::print(" CompatibilityType: {:s} ({:d})\n", nn::hac::GameCardUtil::getCompatibilityTypeAsString((nn::hac::gc::CompatibilityType)mHdr.getCompatibilityType()), mHdr.getCompatibilityType());
fmt::print(" Update Partition Info:\n"); fmt::print(" Update Partition Info:\n");
fmt::print(" CUP Version: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mHdr.getUppVersion()), mHdr.getUppVersion()); fmt::print(" CUP Version: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mHdr.getUppVersion()), mHdr.getUppVersion());
fmt::print(" CUP TitleId: 0x{:016x}\n", mHdr.getUppId()); fmt::print(" CUP TitleId: 0x{:016x}\n", mHdr.getUppId());
fmt::print(" CUP Digest: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getUppHash().data(), mHdr.getUppHash().size(), true, "")); fmt::print(" CUP Digest: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getUppHash().data(), mHdr.getUppHash().size(), true, ""));
} }
@ -225,14 +223,14 @@ bool nstool::GameCardProcess::validateRegionOfFile(int64_t offset, int64_t len,
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
// update hash // update hash
tc::crypto::Sha2256Generator sha256_gen; tc::crypto::Sha256Generator sha256_gen;
sha256_gen.initialize(); sha256_gen.initialize();
sha256_gen.update(scratch.data(), scratch.size()); sha256_gen.update(scratch.data(), scratch.size());
if (use_salt) if (use_salt)
sha256_gen.update(&salt, sizeof(salt)); sha256_gen.update(&salt, sizeof(salt));
// calculate hash // calculate hash
pie::hac::detail::sha256_hash_t calc_hash; nn::hac::detail::sha256_hash_t calc_hash;
sha256_gen.getHash(calc_hash.data()); sha256_gen.getHash(calc_hash.data());
return memcmp(calc_hash.data(), test_hash, calc_hash.size()) == 0; return memcmp(calc_hash.data(), test_hash, calc_hash.size()) == 0;
@ -247,7 +245,7 @@ void nstool::GameCardProcess::validateXciSignature()
{ {
if (mKeyCfg.xci_header_sign_key.isSet()) if (mKeyCfg.xci_header_sign_key.isSet())
{ {
if (tc::crypto::VerifyRsa2048Pkcs1Sha2256(mHdrSignature.data(), mHdrHash.data(), mKeyCfg.xci_header_sign_key.get()) == false) if (tc::crypto::VerifyRsa2048Pkcs1Sha256(mHdrSignature.data(), mHdrHash.data(), mKeyCfg.xci_header_sign_key.get()) == false)
{ {
fmt::print("[WARNING] GameCard Header Signature: FAIL\n"); fmt::print("[WARNING] GameCard Header Signature: FAIL\n");
} }
@ -260,24 +258,29 @@ void nstool::GameCardProcess::validateXciSignature()
void nstool::GameCardProcess::processRootPfs() void nstool::GameCardProcess::processRootPfs()
{ {
if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().data(), mHdr.getCompatibilityType() != pie::hac::gc::CompatibilityType_Global, mHdr.getCompatibilityType()) == false) if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().data(), mHdr.getCompatibilityType() != nn::hac::gc::COMPAT_GLOBAL, mHdr.getCompatibilityType()) == false)
{ {
fmt::print("[WARNING] GameCard Root HFS0: FAIL (bad hash)\n"); fmt::print("[WARNING] GameCard Root HFS0: FAIL (bad hash)\n");
} }
std::shared_ptr<tc::io::IStream> gc_fs_raw = std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, mHdr.getPartitionFsAddress(), pie::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage()+1) - mHdr.getPartitionFsAddress())); std::shared_ptr<tc::io::IStream> gc_fs_raw = std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, mHdr.getPartitionFsAddress(), nn::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage()+1) - mHdr.getPartitionFsAddress()));
auto gc_vfs_snapshot = pie::hac::GameCardFsSnapshotGenerator(gc_fs_raw, mHdr.getPartitionFsSize(), mVerify ? pie::hac::GameCardFsSnapshotGenerator::ValidationMode_Warn : pie::hac::GameCardFsSnapshotGenerator::ValidationMode_None); auto gc_vfs_meta = nn::hac::GameCardFsMetaGenerator(gc_fs_raw, mHdr.getPartitionFsSize(), mVerify ? nn::hac::GameCardFsMetaGenerator::ValidationMode_Warn : nn::hac::GameCardFsMetaGenerator::ValidationMode_None);
mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(gc_vfs_snapshot) ); std::shared_ptr<tc::io::IStorage> gc_vfs = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(gc_vfs_meta) );
mFsProcess.setInputFileSystem(mFileSystem); FsProcess fs_proc;
mFsProcess.setFsFormatName("PartitionFs");
mFsProcess.setFsProperties({ fs_proc.setInputFileSystem(gc_vfs);
fs_proc.setFsFormatName("PartitionFs");
fs_proc.setFsProperties({
fmt::format("Type: Nested HFS0"), fmt::format("Type: Nested HFS0"),
fmt::format("DirNum: {:d}", gc_vfs_snapshot.dir_entries.empty() ? 0 : gc_vfs_snapshot.dir_entries.size() - 1), // -1 to not include root directory fmt::format("DirNum: {:d}", gc_vfs_meta.dir_entries.empty() ? 0 : gc_vfs_meta.dir_entries.size() - 1), // -1 to not include root directory
fmt::format("FileNum: {:d}", gc_vfs_snapshot.file_entries.size()) fmt::format("FileNum: {:d}", gc_vfs_meta.file_entries.size())
}); });
mFsProcess.setShowFsInfo(mCliOutputMode.show_basic_info); fs_proc.setShowFsInfo(mCliOutputMode.show_basic_info);
mFsProcess.setFsRootLabel(kXciMountPointName); fs_proc.setShowFsTree(mListFs);
mFsProcess.process(); fs_proc.setFsRootLabel(kXciMountPointName);
fs_proc.setExtractJobs(mExtractJobs);
fs_proc.process();
} }

View file

@ -3,7 +3,7 @@
#include "KeyBag.h" #include "KeyBag.h"
#include "PfsProcess.h" #include "PfsProcess.h"
#include <pietendo/hac/GameCardHeader.h> #include <nn/hac/GameCardHeader.h>
namespace nstool { namespace nstool {
@ -32,18 +32,18 @@ private:
KeyBag mKeyCfg; KeyBag mKeyCfg;
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
bool mListFs;
bool mIsTrueSdkXci; bool mIsTrueSdkXci;
bool mIsSdkXciEncrypted; bool mIsSdkXciEncrypted;
size_t mGcHeaderOffset; size_t mGcHeaderOffset;
bool mProccessExtendedHeader; bool mProccessExtendedHeader;
pie::hac::detail::rsa2048_signature_t mHdrSignature; nn::hac::detail::rsa2048_signature_t mHdrSignature;
pie::hac::detail::sha256_hash_t mHdrHash; nn::hac::detail::sha256_hash_t mHdrHash;
pie::hac::GameCardHeader mHdr; nn::hac::GameCardHeader mHdr;
// fs processing PfsProcess mRootPfs;
std::shared_ptr<tc::io::IFileSystem> mFileSystem; std::vector<nstool::ExtractJob> mExtractJobs;
FsProcess mFsProcess;
void importHeader(); void importHeader();
void displayHeader(); void displayHeader();

View file

@ -59,13 +59,13 @@ void nstool::IniProcess::importHeader()
} }
// check if file_size is smaller than INI header size // check if file_size is smaller than INI header size
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(pie::hac::sIniHeader)) if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sIniHeader))
{ {
throw tc::Exception(mModuleName, "Corrupt INI: file too small."); throw tc::Exception(mModuleName, "Corrupt INI: file too small.");
} }
// read ini // read ini
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sIniHeader)); tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sIniHeader));
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
@ -76,12 +76,12 @@ void nstool::IniProcess::importHeader()
void nstool::IniProcess::importKipList() void nstool::IniProcess::importKipList()
{ {
// kip pos info // kip pos info
int64_t kip_pos = tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sIniHeader)); int64_t kip_pos = tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sIniHeader));
int64_t kip_size = 0; int64_t kip_size = 0;
// tmp data to determine size // tmp data to determine size
pie::hac::sKipHeader hdr_raw; nn::hac::sKipHeader hdr_raw;
pie::hac::KernelInitialProcessHeader hdr; nn::hac::KernelInitialProcessHeader hdr;
for (size_t i = 0; i < mHdr.getKipNum(); i++) for (size_t i = 0; i < mHdr.getKipNum(); i++)
{ {
@ -121,11 +121,12 @@ void nstool::IniProcess::extractKipList()
tc::ByteData cache = tc::ByteData(kCacheSize); tc::ByteData cache = tc::ByteData(kCacheSize);
// make extract dir // make extract dir
tc::io::LocalFileSystem local_fs; tc::io::LocalStorage local_fs;
local_fs.createDirectory(mKipExtractPath.get()); local_fs.createDirectory(mKipExtractPath.get());
// out path for extracted KIP // out path for extracted KIP
tc::io::Path out_path; tc::io::Path out_path;
std::string out_path_str;
// extract KIPs // extract KIPs
for (auto itr = mKipList.begin(); itr != mKipList.end(); itr++) for (auto itr = mKipList.begin(); itr != mKipList.end(); itr++)
@ -133,15 +134,17 @@ void nstool::IniProcess::extractKipList()
out_path = mKipExtractPath.get(); out_path = mKipExtractPath.get();
out_path += fmt::format("{:s}.kip", itr->hdr.getName()); out_path += fmt::format("{:s}.kip", itr->hdr.getName());
tc::io::PathUtil::pathToUnixUTF8(out_path, out_path_str);
if (mCliOutputMode.show_basic_info) if (mCliOutputMode.show_basic_info)
fmt::print("Saving {:s}...\n", out_path.to_string()); fmt::print("Saving {:s}...\n", out_path_str);
writeStreamToFile(itr->stream, out_path, cache); writeStreamToFile(itr->stream, out_path, cache);
} }
} }
int64_t nstool::IniProcess::getKipSizeFromHeader(const pie::hac::KernelInitialProcessHeader& hdr) const int64_t nstool::IniProcess::getKipSizeFromHeader(const nn::hac::KernelInitialProcessHeader& hdr) const
{ {
// the order of elements in a KIP are sequential, there are no file offsets // the order of elements in a KIP are sequential, there are no file offsets
return int64_t(sizeof(pie::hac::sKipHeader)) + int64_t(hdr.getTextSegmentInfo().file_layout.size + hdr.getRoSegmentInfo().file_layout.size + hdr.getDataSegmentInfo().file_layout.size); return int64_t(sizeof(nn::hac::sKipHeader)) + int64_t(hdr.getTextSegmentInfo().file_layout.size + hdr.getRoSegmentInfo().file_layout.size + hdr.getDataSegmentInfo().file_layout.size);
} }

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "types.h" #include "types.h"
#include <pietendo/hac/IniHeader.h> #include <nn/hac/IniHeader.h>
#include <pietendo/hac/KernelInitialProcessHeader.h> #include <nn/hac/KernelInitialProcessHeader.h>
namespace nstool { namespace nstool {
@ -29,10 +29,10 @@ private:
tc::Optional<tc::io::Path> mKipExtractPath; tc::Optional<tc::io::Path> mKipExtractPath;
pie::hac::IniHeader mHdr; nn::hac::IniHeader mHdr;
struct InnerKipInfo struct InnerKipInfo
{ {
pie::hac::KernelInitialProcessHeader hdr; nn::hac::KernelInitialProcessHeader hdr;
std::shared_ptr<tc::io::IStream> stream; std::shared_ptr<tc::io::IStream> stream;
}; };
std::vector<InnerKipInfo> mKipList; std::vector<InnerKipInfo> mKipList;
@ -43,7 +43,7 @@ private:
void displayKipList(); void displayKipList();
void extractKipList(); void extractKipList();
int64_t getKipSizeFromHeader(const pie::hac::KernelInitialProcessHeader& hdr) const; int64_t getKipSizeFromHeader(const nn::hac::KernelInitialProcessHeader& hdr) const;
}; };
} }

View file

@ -3,33 +3,28 @@
#include "util.h" #include "util.h"
#include <tc/cli/FormatUtil.h> #include <tc/cli/FormatUtil.h>
#include <pietendo/hac/define/types.h> #include <nn/hac/define/types.h>
#include <pietendo/hac/define/gc.h> #include <nn/hac/define/gc.h>
#include <pietendo/hac/AesKeygen.h> #include <nn/hac/AesKeygen.h>
#include <pietendo/hac/es/SignUtils.h> #include <nn/pki/SignUtils.h>
#include <pietendo/hac/es/SignedData.h> #include <nn/pki/SignedData.h>
#include <pietendo/hac/es/CertificateBody.h> #include <nn/pki/CertificateBody.h>
#include <pietendo/hac/es/TicketBody_V2.h> #include <nn/es/TicketBody_V2.h>
nstool::KeyBagInitializer::KeyBagInitializer(bool isDev, const tc::Optional<tc::io::Path>& keyfile_path, const tc::Optional<tc::io::Path>& titlekeyfile_path, const std::vector<tc::io::Path>& tik_path_list, const tc::Optional<tc::io::Path>& cert_path) nstool::KeyBagInitializer::KeyBagInitializer(bool isDev, const tc::Optional<tc::io::Path>& keyfile_path, const tc::Optional<tc::io::Path>& tik_path, const tc::Optional<tc::io::Path>& cert_path)
{ {
if (keyfile_path.isSet()) if (keyfile_path.isSet())
{ {
importBaseKeyFile(keyfile_path.get(), isDev); importBaseKeyFile(keyfile_path.get(), isDev);
} }
if (titlekeyfile_path.isSet())
{
importTitleKeyFile(titlekeyfile_path.get());
}
if (cert_path.isSet()) if (cert_path.isSet())
{ {
importCertificateChain(cert_path.get()); importCertificateChain(cert_path.get());
} }
if (!tik_path_list.empty()) if (tik_path.isSet())
{ {
for (auto itr = tik_path_list.begin(); itr != tik_path_list.end(); itr++) importTicket(tik_path.get());
importTicket(*itr);
} }
// this will populate known keys if they aren't supplied by the user provided keyfiles. // this will populate known keys if they aren't supplied by the user provided keyfiles.
@ -357,7 +352,7 @@ void nstool::KeyBagInitializer::importBaseKeyFile(const tc::io::Path& keyfile_pa
} }
// xci header key (old label, prod/dev keys are actually a fake distinction, the are different key indexes available to both?, so select correct index when importing) // xci header key (old label, prod/dev keys are actually a fake distinction, the are different key indexes available to both?, so select correct index when importing)
//fmt::print("{:s}_{:s}\n", kXciHeaderBase[name_idx], kKeyStr); //fmt::print("{:s}_{:s}\n", kXciHeaderBase[name_idx], kKeyStr);
_SAVE_AES128KEY(fmt::format("{:s}_{:s}", kXciHeaderBase[name_idx], kKeyStr), xci_header_key[isDev ? pie::hac::gc::KekIndex_Dev : pie::hac::gc::KekIndex_Prod]); _SAVE_AES128KEY(fmt::format("{:s}_{:s}", kXciHeaderBase[name_idx], kKeyStr), xci_header_key[isDev ? nn::hac::gc::KEK_DEV : nn::hac::gc::KEK_PROD]);
// xci header sign key // xci header sign key
//fmt::print("{:s}_{:s}_{:s}\n", kXciHeaderBase[name_idx], kSignKey, kPrivateStr); //fmt::print("{:s}_{:s}_{:s}\n", kXciHeaderBase[name_idx], kSignKey, kPrivateStr);
@ -409,22 +404,22 @@ void nstool::KeyBagInitializer::importBaseKeyFile(const tc::io::Path& keyfile_pa
if (nca_header_key.isNull()) if (nca_header_key.isNull())
{ {
aes128_key_t nca_header_kek_tmp; aes128_key_t nca_header_kek_tmp;
pie::hac::AesKeygen::generateKey(nca_header_kek_tmp.data(), aes_kek_generation_source.get().data(), nca_header_kek_source.get().data(), aes_key_generation_source.get().data(), itr->second.data()); nn::hac::AesKeygen::generateKey(nca_header_kek_tmp.data(), aes_kek_generation_source.get().data(), nca_header_kek_source.get().data(), aes_key_generation_source.get().data(), itr->second.data());
aes128_xtskey_t nca_header_key_tmp; aes128_xtskey_t nca_header_key_tmp;
pie::hac::AesKeygen::generateKey(nca_header_key_tmp[0].data(), nca_header_key_source.get()[0].data(), nca_header_kek_tmp.data()); nn::hac::AesKeygen::generateKey(nca_header_key_tmp[0].data(), nca_header_key_source.get()[0].data(), nca_header_kek_tmp.data());
pie::hac::AesKeygen::generateKey(nca_header_key_tmp[1].data(), nca_header_key_source.get()[1].data(), nca_header_kek_tmp.data()); nn::hac::AesKeygen::generateKey(nca_header_key_tmp[1].data(), nca_header_key_source.get()[1].data(), nca_header_kek_tmp.data());
nca_header_key = nca_header_key_tmp; nca_header_key = nca_header_key_tmp;
} }
} }
for (size_t keak_idx = 0; keak_idx < pie::hac::nca::kKeyAreaEncryptionKeyNum; keak_idx++) for (size_t keak_idx = 0; keak_idx < nn::hac::nca::kKeyAreaEncryptionKeyNum; keak_idx++)
{ {
if (key_area_key_source[keak_idx].isSet() && nca_key_area_encryption_key[keak_idx].find(itr->first) == nca_key_area_encryption_key[keak_idx].end()) if (key_area_key_source[keak_idx].isSet() && nca_key_area_encryption_key[keak_idx].find(itr->first) != nca_key_area_encryption_key[keak_idx].end())
{ {
aes128_key_t nca_key_area_encryption_key_tmp; aes128_key_t nca_key_area_encryption_key_tmp;
pie::hac::AesKeygen::generateKey(nca_key_area_encryption_key_tmp.data(), aes_kek_generation_source.get().data(), key_area_key_source[keak_idx].get().data(), aes_key_generation_source.get().data(), itr->second.data()); nn::hac::AesKeygen::generateKey(nca_key_area_encryption_key_tmp.data(), aes_kek_generation_source.get().data(), key_area_key_source[keak_idx].get().data(), aes_key_generation_source.get().data(), itr->second.data());
nca_key_area_encryption_key[keak_idx][itr->first] = nca_key_area_encryption_key_tmp; nca_key_area_encryption_key[keak_idx][itr->first] = nca_key_area_encryption_key_tmp;
} }
} }
@ -432,13 +427,13 @@ void nstool::KeyBagInitializer::importBaseKeyFile(const tc::io::Path& keyfile_pa
if (ticket_titlekek_source.isSet() && etik_common_key.find(itr->first) == etik_common_key.end()) if (ticket_titlekek_source.isSet() && etik_common_key.find(itr->first) == etik_common_key.end())
{ {
aes128_key_t etik_common_key_tmp; aes128_key_t etik_common_key_tmp;
pie::hac::AesKeygen::generateKey(etik_common_key_tmp.data(), ticket_titlekek_source.get().data(), itr->second.data()); nn::hac::AesKeygen::generateKey(etik_common_key_tmp.data(), ticket_titlekek_source.get().data(), itr->second.data());
etik_common_key[itr->first] = etik_common_key_tmp; etik_common_key[itr->first] = etik_common_key_tmp;
} }
if (package2_key_source.isSet() && pkg2_key.find(itr->first) == pkg2_key.end()) if (package2_key_source.isSet() && pkg2_key.find(itr->first) == pkg2_key.end())
{ {
aes128_key_t pkg2_key_tmp; aes128_key_t pkg2_key_tmp;
pie::hac::AesKeygen::generateKey(pkg2_key_tmp.data(), package2_key_source.get().data(), itr->second.data()); nn::hac::AesKeygen::generateKey(pkg2_key_tmp.data(), package2_key_source.get().data(), itr->second.data());
pkg2_key[itr->first] = pkg2_key_tmp; pkg2_key[itr->first] = pkg2_key_tmp;
} }
} }
@ -446,58 +441,28 @@ void nstool::KeyBagInitializer::importBaseKeyFile(const tc::io::Path& keyfile_pa
// Save PKI Root Key // Save PKI Root Key
if (pki_root_sign_key.isSet()) if (pki_root_sign_key.isSet())
{ {
broadon_signer["Root"] = { tc::ByteData(), pie::hac::es::sign::SIGN_ALGO_RSA4096, pki_root_sign_key.get() }; broadon_signer["Root"] = { tc::ByteData(), nn::pki::sign::SIGN_ALGO_RSA4096, pki_root_sign_key.get() };
} }
} }
void nstool::KeyBagInitializer::importTitleKeyFile(const tc::io::Path& keyfile_path) void nstool::KeyBagInitializer::importTitleKeyFile(const tc::io::Path& keyfile_path)
{ {
std::shared_ptr<tc::io::FileStream> keyfile_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(keyfile_path, tc::io::FileMode::Open, tc::io::FileAccess::Read));
// import keyfile into a dictionary
std::map<std::string, std::string> keyfile_dict;
processResFile(keyfile_stream, keyfile_dict);
// process title keys
tc::ByteData tmp;
KeyBag::rights_id_t rights_id_tmp;
KeyBag::aes128_key_t title_key_tmp;
for (auto itr = keyfile_dict.begin(); itr != keyfile_dict.end(); itr++)
{
//fmt::print("RightsID[{:s}] = TitleKey[{:s}]\n", itr->first, itr->second);
// parse the rights id
tmp = tc::cli::FormatUtil::hexStringToBytes(itr->first);
if (tmp.size() != rights_id_tmp.size())
{
fmt::print("[nstool::KeyBagInitializer WARNING] RightsID: \"{}\" has incorrect length. Skipping...\n", itr->first);
continue;
}
memcpy(rights_id_tmp.data(), tmp.data(), rights_id_tmp.size());
// parse the title key
tmp = tc::cli::FormatUtil::hexStringToBytes(itr->second);
if (tmp.size() != title_key_tmp.size())
{
fmt::print("[nstool::KeyBagInitializer WARNING] TitleKey for \"{}\": \"{}\" has incorrect length. Skipping...\n", itr->first, itr->second);
continue;
}
memcpy(title_key_tmp.data(), tmp.data(), title_key_tmp.size());
// save to encrypted key dict
external_enc_content_keys[rights_id_tmp] = title_key_tmp;
}
} }
void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_path) void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_path)
{ {
// save file path string for error messages
std::string cert_path_str;
tc::io::PathUtil::pathToUnixUTF8(cert_path, cert_path_str);
// open cert file // open cert file
std::shared_ptr<tc::io::FileStream> certfile_stream; std::shared_ptr<tc::io::FileStream> certfile_stream;
try { try {
certfile_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(cert_path, tc::io::FileMode::Open, tc::io::FileAccess::Read)); certfile_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(cert_path, tc::io::FileMode::Open, tc::io::FileAccess::Read));
} }
catch (tc::io::FileNotFoundException& e) { catch (tc::io::FileNotFoundException& e) {
fmt::print("[WARNING] Failed to open certificate file \"{:s}\" ({:s}).\n", cert_path.to_string(), e.error()); fmt::print("[WARNING] Failed to open certificate file \"{:s}\" ({:s}).\n", cert_path_str, e.error());
return; return;
} }
@ -505,7 +470,7 @@ void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_
size_t cert_raw_size = tc::io::IOUtil::castInt64ToSize(certfile_stream->length()); size_t cert_raw_size = tc::io::IOUtil::castInt64ToSize(certfile_stream->length());
if (cert_raw_size > 0x10000) if (cert_raw_size > 0x10000)
{ {
fmt::print("[WARNING] Certificate file \"{:s}\" was too large.\n", cert_path.to_string()); fmt::print("[WARNING] Certificate file \"{:s}\" was too large.\n", cert_path_str);
return; return;
} }
@ -514,7 +479,7 @@ void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_
certfile_stream->seek(0, tc::io::SeekOrigin::Begin); certfile_stream->seek(0, tc::io::SeekOrigin::Begin);
certfile_stream->read(cert_raw.data(), cert_raw.size()); certfile_stream->read(cert_raw.data(), cert_raw.size());
pie::hac::es::SignedData<pie::hac::es::CertificateBody> cert; nn::pki::SignedData<nn::pki::CertificateBody> cert;
try { try {
for (size_t f_pos = 0; f_pos < cert_raw.size(); f_pos += cert.getBytes().size()) for (size_t f_pos = 0; f_pos < cert_raw.size(); f_pos += cert.getBytes().size())
{ {
@ -523,14 +488,14 @@ void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_
std::string cert_identity = fmt::format("{:s}-{:s}", cert.getBody().getIssuer(), cert.getBody().getSubject()); std::string cert_identity = fmt::format("{:s}-{:s}", cert.getBody().getIssuer(), cert.getBody().getSubject());
switch (cert.getBody().getPublicKeyType()) { switch (cert.getBody().getPublicKeyType()) {
case pie::hac::es::cert::PublicKeyType::RSA2048: case nn::pki::cert::PublicKeyType::RSA2048:
broadon_signer[cert_identity] = { cert.getBytes(), pie::hac::es::sign::SIGN_ALGO_RSA2048, cert.getBody().getRsa2048PublicKey() }; broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_RSA2048, cert.getBody().getRsa2048PublicKey() };
break; break;
case pie::hac::es::cert::PublicKeyType::RSA4096: case nn::pki::cert::PublicKeyType::RSA4096:
broadon_signer[cert_identity] = { cert.getBytes(), pie::hac::es::sign::SIGN_ALGO_RSA4096, cert.getBody().getRsa4096PublicKey() }; broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_RSA4096, cert.getBody().getRsa4096PublicKey() };
break; break;
case pie::hac::es::cert::PublicKeyType::ECDSA240: case nn::pki::cert::PublicKeyType::ECDSA240:
// broadon_signer[cert_identity] = { cert.getBytes(), pie::hac::es::sign::SIGN_ALGO_ECDSA240, cert.getBody().getRsa4096PublicKey() }; // broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_ECDSA240, cert.getBody().getRsa4096PublicKey() };
fmt::print("[WARNING] Certificate {:s} will not be imported. ecc233 public keys are not supported yet.\n", cert_identity); fmt::print("[WARNING] Certificate {:s} will not be imported. ecc233 public keys are not supported yet.\n", cert_identity);
break; break;
default: default:
@ -539,20 +504,24 @@ void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_
} }
} }
catch (tc::Exception& e) { catch (tc::Exception& e) {
fmt::print("[WARNING] Certificate file \"{:s}\" is corrupted ({:s}).\n", cert_path.to_string(), e.error()); fmt::print("[WARNING] Certificate file \"{:s}\" is corrupted ({:s}).\n", cert_path_str, e.error());
return; return;
} }
} }
void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path) void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
{ {
// save file path string for error messages
std::string tik_path_str;
tc::io::PathUtil::pathToUnixUTF8(tik_path, tik_path_str);
// open cert file // open cert file
std::shared_ptr<tc::io::FileStream> tik_stream; std::shared_ptr<tc::io::FileStream> tik_stream;
try { try {
tik_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(tik_path, tc::io::FileMode::Open, tc::io::FileAccess::Read)); tik_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(tik_path, tc::io::FileMode::Open, tc::io::FileAccess::Read));
} }
catch (tc::io::FileNotFoundException& e) { catch (tc::io::FileNotFoundException& e) {
fmt::print("[WARNING] Failed to open ticket \"{:s}\" ({:s}).\n", tik_path.to_string(), e.error()); fmt::print("[WARNING] Failed to open ticket \"{:s}\" ({:s}).\n", tik_path_str, e.error());
return; return;
} }
@ -560,7 +529,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
size_t tik_raw_size = tc::io::IOUtil::castInt64ToSize(tik_stream->length()); size_t tik_raw_size = tc::io::IOUtil::castInt64ToSize(tik_stream->length());
if (tik_raw_size > 0x10000) if (tik_raw_size > 0x10000)
{ {
fmt::print("[WARNING] Ticket \"{:s}\" was too large.\n", tik_path.to_string()); fmt::print("[WARNING] Ticket \"{:s}\" was too large.\n", tik_path_str);
return; return;
} }
@ -569,7 +538,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
tik_stream->seek(0, tc::io::SeekOrigin::Begin); tik_stream->seek(0, tc::io::SeekOrigin::Begin);
tik_stream->read(tik_raw.data(), tik_raw.size()); tik_stream->read(tik_raw.data(), tik_raw.size());
pie::hac::es::SignedData<pie::hac::es::TicketBody_V2> tik; nn::pki::SignedData<nn::es::TicketBody_V2> tik;
try { try {
// de serialise ticket // de serialise ticket
tik.fromBytes(tik_raw.data(), tik_raw.size()); tik.fromBytes(tik_raw.data(), tik_raw.size());
@ -579,7 +548,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
memcpy(rights_id.data(), tik.getBody().getRightsId(), rights_id.size()); memcpy(rights_id.data(), tik.getBody().getRightsId(), rights_id.size());
// check ticket is not personalised // check ticket is not personalised
if (tik.getBody().getTitleKeyEncType() != pie::hac::es::ticket::AES128_CBC) if (tik.getBody().getTitleKeyEncType() != nn::es::ticket::AES128_CBC)
{ {
fmt::print("[WARNING] Ticket \"{:s}\" will not be imported. Personalised tickets are not supported.\n", tc::cli::FormatUtil::formatBytesAsString(rights_id.data(), rights_id.size(), true, "")); fmt::print("[WARNING] Ticket \"{:s}\" will not be imported. Personalised tickets are not supported.\n", tc::cli::FormatUtil::formatBytesAsString(rights_id.data(), rights_id.size(), true, ""));
return; return;
@ -590,7 +559,10 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
memcpy(enc_title_key.data(), tik.getBody().getEncTitleKey(), enc_title_key.size()); memcpy(enc_title_key.data(), tik.getBody().getEncTitleKey(), enc_title_key.size());
// save the encrypted title key as the fallback enc content key incase the ticket was malformed and workarounds to decrypt it in isolation fail // save the encrypted title key as the fallback enc content key incase the ticket was malformed and workarounds to decrypt it in isolation fail
external_enc_content_keys[rights_id] = enc_title_key; if (fallback_enc_content_key.isNull())
{
fallback_enc_content_key = enc_title_key;
}
// determine key to decrypt title key // determine key to decrypt title key
byte_t common_key_index = tik.getBody().getCommonKeyId(); byte_t common_key_index = tik.getBody().getCommonKeyId();
@ -605,7 +577,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
} }
// convert key_generation // convert key_generation
common_key_index = pie::hac::AesKeygen::getMasterKeyRevisionFromKeyGeneration(common_key_index); common_key_index = nn::hac::AesKeygen::getMasterKeyRevisionFromKeyGeneration(common_key_index);
if (etik_common_key.find(common_key_index) == etik_common_key.end()) if (etik_common_key.find(common_key_index) == etik_common_key.end())
{ {
@ -617,19 +589,19 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
aes128_key_t dec_title_key; aes128_key_t dec_title_key;
tc::crypto::DecryptAes128Ecb(dec_title_key.data(), enc_title_key.data(), sizeof(aes128_key_t), etik_common_key[common_key_index].data(), sizeof(aes128_key_t)); tc::crypto::DecryptAes128Ecb(dec_title_key.data(), enc_title_key.data(), sizeof(aes128_key_t), etik_common_key[common_key_index].data(), sizeof(aes128_key_t));
// add to decrypted key dict // add to key dict
external_content_keys[rights_id] = dec_title_key; external_content_keys[rights_id] = dec_title_key;
} }
catch (tc::Exception& e) { catch (tc::Exception& e) {
fmt::print("[WARNING] Ticket \"{:s}\" is corrupted ({:s}).\n", tik_path.to_string(), e.error()); fmt::print("[WARNING] Ticket \"{:s}\" is corrupted ({:s}).\n", tik_path_str, e.error());
return; return;
} }
} }
void nstool::KeyBagInitializer::importKnownKeys(bool isDev) void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
{ {
static const pie::hac::detail::rsa2048_block_t kXciHeaderSignModulus = { static const nn::hac::detail::rsa2048_block_t kXciHeaderSignModulus = {
0x98, 0xC7, 0x26, 0xB6, 0x0D, 0x0A, 0x50, 0xA7, 0x39, 0x21, 0x0A, 0xE3, 0x2F, 0xE4, 0x3E, 0x2E, 0x98, 0xC7, 0x26, 0xB6, 0x0D, 0x0A, 0x50, 0xA7, 0x39, 0x21, 0x0A, 0xE3, 0x2F, 0xE4, 0x3E, 0x2E,
0x5B, 0xA2, 0x86, 0x75, 0xAA, 0x5C, 0xEE, 0x34, 0xF1, 0xA3, 0x3A, 0x7E, 0xBD, 0x90, 0x4E, 0xF7, 0x5B, 0xA2, 0x86, 0x75, 0xAA, 0x5C, 0xEE, 0x34, 0xF1, 0xA3, 0x3A, 0x7E, 0xBD, 0x90, 0x4E, 0xF7,
0x8D, 0xFA, 0x17, 0xAA, 0x6B, 0xC6, 0x36, 0x6D, 0x4C, 0x9A, 0x6D, 0x57, 0x2F, 0x80, 0xA2, 0xBC, 0x8D, 0xFA, 0x17, 0xAA, 0x6B, 0xC6, 0x36, 0x6D, 0x4C, 0x9A, 0x6D, 0x57, 0x2F, 0x80, 0xA2, 0xBC,
@ -648,7 +620,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
0x9A, 0xC1, 0xDD, 0x62, 0x86, 0x9C, 0x2E, 0xE1, 0x2D, 0x6F, 0x62, 0x67, 0x51, 0x08, 0x0E, 0xCF 0x9A, 0xC1, 0xDD, 0x62, 0x86, 0x9C, 0x2E, 0xE1, 0x2D, 0x6F, 0x62, 0x67, 0x51, 0x08, 0x0E, 0xCF
}; };
static const pie::hac::detail::rsa2048_block_t kXciCertSignModulus = { static const nn::hac::detail::rsa2048_block_t kXciCertSignModulus = {
0xCD, 0xF3, 0x2C, 0xB0, 0xF5, 0x14, 0x78, 0x34, 0xE5, 0x02, 0xD0, 0x29, 0x6A, 0xA5, 0xFD, 0x97, 0xCD, 0xF3, 0x2C, 0xB0, 0xF5, 0x14, 0x78, 0x34, 0xE5, 0x02, 0xD0, 0x29, 0x6A, 0xA5, 0xFD, 0x97,
0x6A, 0xE0, 0xB0, 0xBB, 0xB0, 0x3B, 0x1A, 0x80, 0xB7, 0xD7, 0x58, 0x92, 0x79, 0x84, 0xC0, 0x36, 0x6A, 0xE0, 0xB0, 0xBB, 0xB0, 0x3B, 0x1A, 0x80, 0xB7, 0xD7, 0x58, 0x92, 0x79, 0x84, 0xC0, 0x36,
0xB1, 0x55, 0x23, 0xD8, 0xA5, 0x60, 0x91, 0x26, 0x48, 0x1A, 0x80, 0x4A, 0xEA, 0x00, 0x98, 0x2A, 0xB1, 0x55, 0x23, 0xD8, 0xA5, 0x60, 0x91, 0x26, 0x48, 0x1A, 0x80, 0x4A, 0xEA, 0x00, 0x98, 0x2A,
@ -669,7 +641,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
/* Keydata for very early beta NCA0 archives' RSA-OAEP. */ /* Keydata for very early beta NCA0 archives' RSA-OAEP. */
/* /*
static const pie::hac::detail::rsa2048_block_t beta_nca0_modulus = { static const nn::hac::detail::rsa2048_block_t beta_nca0_modulus = {
0xAD, 0x58, 0xEE, 0x97, 0xF9, 0x47, 0x90, 0x7D, 0xF9, 0x29, 0x5F, 0x1F, 0x39, 0x68, 0xEE, 0x49, 0xAD, 0x58, 0xEE, 0x97, 0xF9, 0x47, 0x90, 0x7D, 0xF9, 0x29, 0x5F, 0x1F, 0x39, 0x68, 0xEE, 0x49,
0x4C, 0x1E, 0x8D, 0x84, 0x91, 0x31, 0x5D, 0xE5, 0x96, 0x27, 0xB2, 0xB3, 0x59, 0x7B, 0xDE, 0xFD, 0x4C, 0x1E, 0x8D, 0x84, 0x91, 0x31, 0x5D, 0xE5, 0x96, 0x27, 0xB2, 0xB3, 0x59, 0x7B, 0xDE, 0xFD,
0xB7, 0xEB, 0x40, 0xA1, 0xE7, 0xEB, 0xDC, 0x60, 0xD0, 0x3D, 0xC5, 0x50, 0x92, 0xAD, 0x3D, 0xC4, 0xB7, 0xEB, 0x40, 0xA1, 0xE7, 0xEB, 0xDC, 0x60, 0xD0, 0x3D, 0xC5, 0x50, 0x92, 0xAD, 0x3D, 0xC4,
@ -688,7 +660,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
0xB0, 0xB4, 0xD0, 0x17, 0xA1, 0x0F, 0x73, 0x98, 0x5A, 0xF6, 0xEE, 0xC0, 0x2F, 0x9E, 0xCE, 0xC5 0xB0, 0xB4, 0xD0, 0x17, 0xA1, 0x0F, 0x73, 0x98, 0x5A, 0xF6, 0xEE, 0xC0, 0x2F, 0x9E, 0xCE, 0xC5
}; };
static const pie::hac::detail::sha256_hash_t beta_nca0_label_hash = { static const nn::hac::detail::sha256_hash_t beta_nca0_label_hash = {
0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
}; };
@ -696,10 +668,10 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
struct sRsaKeyForGeneration { struct sRsaKeyForGeneration {
byte_t generation; byte_t generation;
pie::hac::detail::rsa2048_block_t modulus; nn::hac::detail::rsa2048_block_t modulus;
}; };
static const pie::hac::detail::rsa2048_block_t kProdPackage2HeaderModulus = { static const nn::hac::detail::rsa2048_block_t kProdPackage2HeaderModulus = {
0x8D, 0x13, 0xA7, 0x77, 0x6A, 0xE5, 0xDC, 0xC0, 0x3B, 0x25, 0xD0, 0x58, 0xE4, 0x20, 0x69, 0x59, 0x8D, 0x13, 0xA7, 0x77, 0x6A, 0xE5, 0xDC, 0xC0, 0x3B, 0x25, 0xD0, 0x58, 0xE4, 0x20, 0x69, 0x59,
0x55, 0x4B, 0xAB, 0x70, 0x40, 0x08, 0x28, 0x07, 0xA8, 0xA7, 0xFD, 0x0F, 0x31, 0x2E, 0x11, 0xFE, 0x55, 0x4B, 0xAB, 0x70, 0x40, 0x08, 0x28, 0x07, 0xA8, 0xA7, 0xFD, 0x0F, 0x31, 0x2E, 0x11, 0xFE,
0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5, 0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5,
@ -802,7 +774,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
}, },
}; };
static const pie::hac::detail::rsa2048_block_t kDevPackage2HeaderModulus = { static const nn::hac::detail::rsa2048_block_t kDevPackage2HeaderModulus = {
0xB3, 0x65, 0x54, 0xFB, 0x0A, 0xB0, 0x1E, 0x85, 0xA7, 0xF6, 0xCF, 0x91, 0x8E, 0xBA, 0x96, 0x99, 0xB3, 0x65, 0x54, 0xFB, 0x0A, 0xB0, 0x1E, 0x85, 0xA7, 0xF6, 0xCF, 0x91, 0x8E, 0xBA, 0x96, 0x99,
0x0D, 0x8B, 0x91, 0x69, 0x2A, 0xEE, 0x01, 0x20, 0x4F, 0x34, 0x5C, 0x2C, 0x4F, 0x4E, 0x37, 0xC7, 0x0D, 0x8B, 0x91, 0x69, 0x2A, 0xEE, 0x01, 0x20, 0x4F, 0x34, 0x5C, 0x2C, 0x4F, 0x4E, 0x37, 0xC7,
0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6, 0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6,
@ -908,7 +880,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
struct sBroadOnRsaKeyAndCert struct sBroadOnRsaKeyAndCert
{ {
std::string issuer; std::string issuer;
pie::hac::es::sign::SignatureAlgo key_type; nn::pki::sign::SignatureAlgo key_type;
tc::ByteData modulus; tc::ByteData modulus;
tc::ByteData certificate; tc::ByteData certificate;
}; };
@ -917,31 +889,31 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
{ {
{ {
"Root", "Root",
pie::hac::es::sign::SIGN_ALGO_RSA4096, nn::pki::sign::SIGN_ALGO_RSA4096,
tc::cli::FormatUtil::hexStringToBytes("F8246C58BAE7500301FBB7C2EBE0010571DA922378F0514EC0031DD0D21ED3D07EFC852069B5DE9BB951A8BC90A244926D379295AE9436AAA6A302510C7B1DEDD5FB20869D7F3016F6BE65D383A16DB3321B95351890B17002937EE193F57E99A2474E9D3824C7AEE38541F567E7518C7A0E38E7EBAF41191BCFF17B42A6B4EDE6CE8DE7318F7F5204B3990E226745AFD485B24493008B08C7F6B7E56B02B3E8FE0C9D859CB8B68223B8AB27EE5F6538078B2DB91E2A153E85818072A23B6DD93281054F6FB0F6F5AD283ECA0B7AF35455E03DA7B68326F3EC834AF314048AC6DF20D28508673CAB62A2C7BC131A533E0B66806B1C30664B372331BDC4B0CAD8D11EE7BBD9285548AAEC1F66E821B3C8A0476900C5E688E80CCE3C61D69CBBA137C6604F7A72DD8C7B3E3D51290DAA6A597B081F9D3633A3467A356109ACA7DD7D2E2FB2C1AEB8E20F4892D8B9F8B46F4E3C11F4F47D8B757DFEFEA3899C33595C5EFDEBCBABE8413E3A9A803C69356EB2B2AD5CC4C858455EF5F7B30644B47C64068CDF809F76025A2DB446E03D7CF62F34E702457B02A4CF5D9DD53CA53A7CA629788C67CA08BFECCA43A957AD16C94E1CD875CA107DCE7E0118F0DF6BFEE51DDBD991C26E60CD4858AA592C820075F29F526C917C6FE5403EA7D4A50CEC3B7384DE886E82D2EB4D4E42B5F2B149A81EA7CE7144DC2994CFC44E1F91CBD495"), tc::cli::FormatUtil::hexStringToBytes("F8246C58BAE7500301FBB7C2EBE0010571DA922378F0514EC0031DD0D21ED3D07EFC852069B5DE9BB951A8BC90A244926D379295AE9436AAA6A302510C7B1DEDD5FB20869D7F3016F6BE65D383A16DB3321B95351890B17002937EE193F57E99A2474E9D3824C7AEE38541F567E7518C7A0E38E7EBAF41191BCFF17B42A6B4EDE6CE8DE7318F7F5204B3990E226745AFD485B24493008B08C7F6B7E56B02B3E8FE0C9D859CB8B68223B8AB27EE5F6538078B2DB91E2A153E85818072A23B6DD93281054F6FB0F6F5AD283ECA0B7AF35455E03DA7B68326F3EC834AF314048AC6DF20D28508673CAB62A2C7BC131A533E0B66806B1C30664B372331BDC4B0CAD8D11EE7BBD9285548AAEC1F66E821B3C8A0476900C5E688E80CCE3C61D69CBBA137C6604F7A72DD8C7B3E3D51290DAA6A597B081F9D3633A3467A356109ACA7DD7D2E2FB2C1AEB8E20F4892D8B9F8B46F4E3C11F4F47D8B757DFEFEA3899C33595C5EFDEBCBABE8413E3A9A803C69356EB2B2AD5CC4C858455EF5F7B30644B47C64068CDF809F76025A2DB446E03D7CF62F34E702457B02A4CF5D9DD53CA53A7CA629788C67CA08BFECCA43A957AD16C94E1CD875CA107DCE7E0118F0DF6BFEE51DDBD991C26E60CD4858AA592C820075F29F526C917C6FE5403EA7D4A50CEC3B7384DE886E82D2EB4D4E42B5F2B149A81EA7CE7144DC2994CFC44E1F91CBD495"),
tc::ByteData() tc::ByteData()
}, },
{ {
"Root-CA00000003", "Root-CA00000003",
pie::hac::es::sign::SIGN_ALGO_RSA2048, nn::pki::sign::SIGN_ALGO_RSA2048,
tc::cli::FormatUtil::hexStringToBytes("B279C9E2EEE121C6EAF44FF639F88F078B4B77ED9F9560B0358281B50E55AB721115A177703C7A30FE3AE9EF1C60BC1D974676B23A68CC04B198525BC968F11DE2DB50E4D9E7F071E562DAE2092233E9D363F61DD7C19FF3A4A91E8F6553D471DD7B84B9F1B8CE7335F0F5540563A1EAB83963E09BE901011F99546361287020E9CC0DAB487F140D6626A1836D27111F2068DE4772149151CF69C61BA60EF9D949A0F71F5499F2D39AD28C7005348293C431FFBD33F6BCA60DC7195EA2BCC56D200BAF6D06D09C41DB8DE9C720154CA4832B69C08C69CD3B073A0063602F462D338061A5EA6C915CD5623579C3EB64CE44EF586D14BAAA8834019B3EEBEED379"), tc::cli::FormatUtil::hexStringToBytes("B279C9E2EEE121C6EAF44FF639F88F078B4B77ED9F9560B0358281B50E55AB721115A177703C7A30FE3AE9EF1C60BC1D974676B23A68CC04B198525BC968F11DE2DB50E4D9E7F071E562DAE2092233E9D363F61DD7C19FF3A4A91E8F6553D471DD7B84B9F1B8CE7335F0F5540563A1EAB83963E09BE901011F99546361287020E9CC0DAB487F140D6626A1836D27111F2068DE4772149151CF69C61BA60EF9D949A0F71F5499F2D39AD28C7005348293C431FFBD33F6BCA60DC7195EA2BCC56D200BAF6D06D09C41DB8DE9C720154CA4832B69C08C69CD3B073A0063602F462D338061A5EA6C915CD5623579C3EB64CE44EF586D14BAAA8834019B3EEBEED379"),
tc::cli::FormatUtil::hexStringToBytes("00010003704138EFBBBDA16A987DD901326D1C9459484C88A2861B91A312587AE70EF6237EC50E1032DC39DDE89A96A8E859D76A98A6E7E36A0CFE352CA893058234FF833FCB3B03811E9F0DC0D9A52F8045B4B2F9411B67A51C44B5EF8CE77BD6D56BA75734A1856DE6D4BED6D3A242C7C8791B3422375E5C779ABF072F7695EFA0F75BCB83789FC30E3FE4CC8392207840638949C7F688565F649B74D63D8D58FFADDA571E9554426B1318FC468983D4C8A5628B06B6FC5D507C13E7A18AC1511EB6D62EA5448F83501447A9AFB3ECC2903C9DD52F922AC9ACDBEF58C6021848D96E208732D3D1D9D9EA440D91621C7A99DB8843C59C1F2E2C7D9B577D512C166D6F7E1AAD4A774A37447E78FE2021E14A95D112A068ADA019F463C7A55685AABB6888B9246483D18B9C806F474918331782344A4B8531334B26303263D9D2EB4F4BB99602B352F6AE4046C69A5E7E8E4A18EF9BC0A2DED61310417012FD824CC116CFB7C4C1F7EC7177A17446CBDE96F3EDD88FCD052F0B888A45FDAF2B631354F40D16E5FA9C2C4EDA98E798D15E6046DC5363F3096B2C607A9D8DD55B1502A6AC7D3CC8D8C575998E7D796910C804C495235057E91ECD2637C9C1845151AC6B9A0490AE3EC6F47740A0DB0BA36D075956CEE7354EA3E9A4F2720B26550C7D394324BC0CB7E9317D8A8661F42191FF10B08256CE3FD25B745E5194906B4D61CB4C2E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001434130303030303030330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007BE8EF6CB279C9E2EEE121C6EAF44FF639F88F078B4B77ED9F9560B0358281B50E55AB721115A177703C7A30FE3AE9EF1C60BC1D974676B23A68CC04B198525BC968F11DE2DB50E4D9E7F071E562DAE2092233E9D363F61DD7C19FF3A4A91E8F6553D471DD7B84B9F1B8CE7335F0F5540563A1EAB83963E09BE901011F99546361287020E9CC0DAB487F140D6626A1836D27111F2068DE4772149151CF69C61BA60EF9D949A0F71F5499F2D39AD28C7005348293C431FFBD33F6BCA60DC7195EA2BCC56D200BAF6D06D09C41DB8DE9C720154CA4832B69C08C69CD3B073A0063602F462D338061A5EA6C915CD5623579C3EB64CE44EF586D14BAAA8834019B3EEBEED3790001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), tc::cli::FormatUtil::hexStringToBytes("00010003704138EFBBBDA16A987DD901326D1C9459484C88A2861B91A312587AE70EF6237EC50E1032DC39DDE89A96A8E859D76A98A6E7E36A0CFE352CA893058234FF833FCB3B03811E9F0DC0D9A52F8045B4B2F9411B67A51C44B5EF8CE77BD6D56BA75734A1856DE6D4BED6D3A242C7C8791B3422375E5C779ABF072F7695EFA0F75BCB83789FC30E3FE4CC8392207840638949C7F688565F649B74D63D8D58FFADDA571E9554426B1318FC468983D4C8A5628B06B6FC5D507C13E7A18AC1511EB6D62EA5448F83501447A9AFB3ECC2903C9DD52F922AC9ACDBEF58C6021848D96E208732D3D1D9D9EA440D91621C7A99DB8843C59C1F2E2C7D9B577D512C166D6F7E1AAD4A774A37447E78FE2021E14A95D112A068ADA019F463C7A55685AABB6888B9246483D18B9C806F474918331782344A4B8531334B26303263D9D2EB4F4BB99602B352F6AE4046C69A5E7E8E4A18EF9BC0A2DED61310417012FD824CC116CFB7C4C1F7EC7177A17446CBDE96F3EDD88FCD052F0B888A45FDAF2B631354F40D16E5FA9C2C4EDA98E798D15E6046DC5363F3096B2C607A9D8DD55B1502A6AC7D3CC8D8C575998E7D796910C804C495235057E91ECD2637C9C1845151AC6B9A0490AE3EC6F47740A0DB0BA36D075956CEE7354EA3E9A4F2720B26550C7D394324BC0CB7E9317D8A8661F42191FF10B08256CE3FD25B745E5194906B4D61CB4C2E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001434130303030303030330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007BE8EF6CB279C9E2EEE121C6EAF44FF639F88F078B4B77ED9F9560B0358281B50E55AB721115A177703C7A30FE3AE9EF1C60BC1D974676B23A68CC04B198525BC968F11DE2DB50E4D9E7F071E562DAE2092233E9D363F61DD7C19FF3A4A91E8F6553D471DD7B84B9F1B8CE7335F0F5540563A1EAB83963E09BE901011F99546361287020E9CC0DAB487F140D6626A1836D27111F2068DE4772149151CF69C61BA60EF9D949A0F71F5499F2D39AD28C7005348293C431FFBD33F6BCA60DC7195EA2BCC56D200BAF6D06D09C41DB8DE9C720154CA4832B69C08C69CD3B073A0063602F462D338061A5EA6C915CD5623579C3EB64CE44EF586D14BAAA8834019B3EEBEED3790001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
}, },
{ {
"Root-CA00000003-XS00000020", "Root-CA00000003-XS00000020",
pie::hac::es::sign::SIGN_ALGO_RSA2048, nn::pki::sign::SIGN_ALGO_RSA2048,
tc::cli::FormatUtil::hexStringToBytes("D21D3CE67C1069DA049D5E5310E76B907E18EEC80B337C4723E339573F4C664907DB2F0832D03DF5EA5F160A4AF24100D71AFAC2E3AE75AFA1228012A9A21616597DF71EAFCB65941470D1B40F5EF83A597E179FCB5B57C2EE17DA3BC3769864CB47856767229D67328141FC9AB1DF149E0C5C15AEB80BC58FC71BE18966642D68308B506934B8EF779F78E4DDF30A0DCF93FCAFBFA131A8839FD641949F47EE25CEECF814D55B0BE6E5677C1EFFEC6F29871EF29AA3ED9197B0D83852E050908031EF1ABBB5AFC8B3DD937A076FF6761AB362405C3F7D86A3B17A6170A659C16008950F7F5E06A5DE3E5998895EFA7DEEA060BE9575668F78AB1907B3BA1B7D"), tc::cli::FormatUtil::hexStringToBytes("D21D3CE67C1069DA049D5E5310E76B907E18EEC80B337C4723E339573F4C664907DB2F0832D03DF5EA5F160A4AF24100D71AFAC2E3AE75AFA1228012A9A21616597DF71EAFCB65941470D1B40F5EF83A597E179FCB5B57C2EE17DA3BC3769864CB47856767229D67328141FC9AB1DF149E0C5C15AEB80BC58FC71BE18966642D68308B506934B8EF779F78E4DDF30A0DCF93FCAFBFA131A8839FD641949F47EE25CEECF814D55B0BE6E5677C1EFFEC6F29871EF29AA3ED9197B0D83852E050908031EF1ABBB5AFC8B3DD937A076FF6761AB362405C3F7D86A3B17A6170A659C16008950F7F5E06A5DE3E5998895EFA7DEEA060BE9575668F78AB1907B3BA1B7D"),
tc::cli::FormatUtil::hexStringToBytes("00010004969FE8288DA6B9DD52C7BD63642A4A9AE5F053ECCB93613FDA37992087BD9199DA5E6797618D77098133FD5B05CD8288139E2E975CD2608003878CDAF020F51A0E5B7692780845561B31C61808E8A47C3462224D94F736E9A14E56ACBF71B7F11BBDEE38DDB846D6BD8F0AB4E4948C5434EAF9BF26529B7EB83671D3CE60A6D7A850DBE6801EC52A7B7A3E5A27BC675BA3C53377CFC372EBCE02062F59F37003AA23AE35D4880E0E4B69F982FB1BAC806C2F75BA29587F2815FD7783998C354D52B19E3FAD9FBEF444C48579288DB0978116AFC82CE54DACB9ED7E1BFD50938F22F85EECF3A4F426AE5FEB15B72F022FB36ECCE9314DAD131429BFC9675F58EE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D21D3CE67C1069DA049D5E5310E76B907E18EEC80B337C4723E339573F4C664907DB2F0832D03DF5EA5F160A4AF24100D71AFAC2E3AE75AFA1228012A9A21616597DF71EAFCB65941470D1B40F5EF83A597E179FCB5B57C2EE17DA3BC3769864CB47856767229D67328141FC9AB1DF149E0C5C15AEB80BC58FC71BE18966642D68308B506934B8EF779F78E4DDF30A0DCF93FCAFBFA131A8839FD641949F47EE25CEECF814D55B0BE6E5677C1EFFEC6F29871EF29AA3ED9197B0D83852E050908031EF1ABBB5AFC8B3DD937A076FF6761AB362405C3F7D86A3B17A6170A659C16008950F7F5E06A5DE3E5998895EFA7DEEA060BE9575668F78AB1907B3BA1B7D0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), tc::cli::FormatUtil::hexStringToBytes("00010004969FE8288DA6B9DD52C7BD63642A4A9AE5F053ECCB93613FDA37992087BD9199DA5E6797618D77098133FD5B05CD8288139E2E975CD2608003878CDAF020F51A0E5B7692780845561B31C61808E8A47C3462224D94F736E9A14E56ACBF71B7F11BBDEE38DDB846D6BD8F0AB4E4948C5434EAF9BF26529B7EB83671D3CE60A6D7A850DBE6801EC52A7B7A3E5A27BC675BA3C53377CFC372EBCE02062F59F37003AA23AE35D4880E0E4B69F982FB1BAC806C2F75BA29587F2815FD7783998C354D52B19E3FAD9FBEF444C48579288DB0978116AFC82CE54DACB9ED7E1BFD50938F22F85EECF3A4F426AE5FEB15B72F022FB36ECCE9314DAD131429BFC9675F58EE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D21D3CE67C1069DA049D5E5310E76B907E18EEC80B337C4723E339573F4C664907DB2F0832D03DF5EA5F160A4AF24100D71AFAC2E3AE75AFA1228012A9A21616597DF71EAFCB65941470D1B40F5EF83A597E179FCB5B57C2EE17DA3BC3769864CB47856767229D67328141FC9AB1DF149E0C5C15AEB80BC58FC71BE18966642D68308B506934B8EF779F78E4DDF30A0DCF93FCAFBFA131A8839FD641949F47EE25CEECF814D55B0BE6E5677C1EFFEC6F29871EF29AA3ED9197B0D83852E050908031EF1ABBB5AFC8B3DD937A076FF6761AB362405C3F7D86A3B17A6170A659C16008950F7F5E06A5DE3E5998895EFA7DEEA060BE9575668F78AB1907B3BA1B7D0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
}, },
{ {
"Root-CA00000003-XS00000022", "Root-CA00000003-XS00000022",
pie::hac::es::sign::SIGN_ALGO_RSA2048, nn::pki::sign::SIGN_ALGO_RSA2048,
tc::cli::FormatUtil::hexStringToBytes("E29775264ADC30C0FDE2DEFCFBBAC406A3B1C2ADDC2644C4C3E46DAD11E4F1ED7BC8B6E8CDBBE87E01020DF807520CE8A8F88BB53BE82CAFF4A1AF7FC5CD69EB34E24BEA74781203B611D09EBF56F82E3F21A494549F407FABA948545B34B64F487E1F27B031A83D337CE40496A3034AC6A2DB9E9353A1967EC7A07A4B3672B5B3F7934FF166D90EC131D8A75DC925ED629F8381A586589A82790489D4BF170F29F8E4BE50811ECBA9564D5517362D8DE777B01FC0A0AD8DED692CEAFD028A468CD6A6BF18A2767801AF8BB954EDB4DA3CED78337F3E9B6A1602B94752C85A53993678FDFA0300A4200CA752FA0D94E5A4B74B726FB61876146E49EC148508F5"), tc::cli::FormatUtil::hexStringToBytes("E29775264ADC30C0FDE2DEFCFBBAC406A3B1C2ADDC2644C4C3E46DAD11E4F1ED7BC8B6E8CDBBE87E01020DF807520CE8A8F88BB53BE82CAFF4A1AF7FC5CD69EB34E24BEA74781203B611D09EBF56F82E3F21A494549F407FABA948545B34B64F487E1F27B031A83D337CE40496A3034AC6A2DB9E9353A1967EC7A07A4B3672B5B3F7934FF166D90EC131D8A75DC925ED629F8381A586589A82790489D4BF170F29F8E4BE50811ECBA9564D5517362D8DE777B01FC0A0AD8DED692CEAFD028A468CD6A6BF18A2767801AF8BB954EDB4DA3CED78337F3E9B6A1602B94752C85A53993678FDFA0300A4200CA752FA0D94E5A4B74B726FB61876146E49EC148508F5"),
tc::cli::FormatUtil::hexStringToBytes("0001000458C7FFCDB0A1758925286C3C5029942683A8ED614A4E5C24EECE90548F99A0E59429C3D7D9CA37910CC1F5974E3AA2D7438627FBE456C9C830E5BF5B4440013CD41AA6F0AE02307E3EDEF3EDE0E6404A87234786FED37878F4BF4D964C2290C66AF167AC94869DC2F8378FA3FE0B764F776F9CE479B9E7A4EAE77FCA924B84035C9C06075F5F23BBF3A202AC1AF6A640C62BEEE4603925534783642663238A803D5FC87C5BEA58E09B0669CE9273509A87FACEDA94333FC6264D095708C18F9A50963F0E02A0771AEBC7174D4A89BE158C6CF407BD11658363E924F2808B15C7FE00267565CBD386E576540C906F9B2FFB3AFC64BA1198FA711A48F107E6A9AD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E29775264ADC30C0FDE2DEFCFBBAC406A3B1C2ADDC2644C4C3E46DAD11E4F1ED7BC8B6E8CDBBE87E01020DF807520CE8A8F88BB53BE82CAFF4A1AF7FC5CD69EB34E24BEA74781203B611D09EBF56F82E3F21A494549F407FABA948545B34B64F487E1F27B031A83D337CE40496A3034AC6A2DB9E9353A1967EC7A07A4B3672B5B3F7934FF166D90EC131D8A75DC925ED629F8381A586589A82790489D4BF170F29F8E4BE50811ECBA9564D5517362D8DE777B01FC0A0AD8DED692CEAFD028A468CD6A6BF18A2767801AF8BB954EDB4DA3CED78337F3E9B6A1602B94752C85A53993678FDFA0300A4200CA752FA0D94E5A4B74B726FB61876146E49EC148508F50001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), tc::cli::FormatUtil::hexStringToBytes("0001000458C7FFCDB0A1758925286C3C5029942683A8ED614A4E5C24EECE90548F99A0E59429C3D7D9CA37910CC1F5974E3AA2D7438627FBE456C9C830E5BF5B4440013CD41AA6F0AE02307E3EDEF3EDE0E6404A87234786FED37878F4BF4D964C2290C66AF167AC94869DC2F8378FA3FE0B764F776F9CE479B9E7A4EAE77FCA924B84035C9C06075F5F23BBF3A202AC1AF6A640C62BEEE4603925534783642663238A803D5FC87C5BEA58E09B0669CE9273509A87FACEDA94333FC6264D095708C18F9A50963F0E02A0771AEBC7174D4A89BE158C6CF407BD11658363E924F2808B15C7FE00267565CBD386E576540C906F9B2FFB3AFC64BA1198FA711A48F107E6A9AD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E29775264ADC30C0FDE2DEFCFBBAC406A3B1C2ADDC2644C4C3E46DAD11E4F1ED7BC8B6E8CDBBE87E01020DF807520CE8A8F88BB53BE82CAFF4A1AF7FC5CD69EB34E24BEA74781203B611D09EBF56F82E3F21A494549F407FABA948545B34B64F487E1F27B031A83D337CE40496A3034AC6A2DB9E9353A1967EC7A07A4B3672B5B3F7934FF166D90EC131D8A75DC925ED629F8381A586589A82790489D4BF170F29F8E4BE50811ECBA9564D5517362D8DE777B01FC0A0AD8DED692CEAFD028A468CD6A6BF18A2767801AF8BB954EDB4DA3CED78337F3E9B6A1602B94752C85A53993678FDFA0300A4200CA752FA0D94E5A4B74B726FB61876146E49EC148508F50001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
}, },
{ {
"Root-CA00000003-XS00000024", "Root-CA00000003-XS00000024",
pie::hac::es::sign::SIGN_ALGO_RSA2048, nn::pki::sign::SIGN_ALGO_RSA2048,
tc::cli::FormatUtil::hexStringToBytes("C694562BBDC74E83069876608EAD1EE7B1BC715036E9A6BDF58A6D22FD660ABD9CF360AA893D7746C92C5B9D20E480EAD1387786739956E060EBA79BD6ED7C06B2FCC6DBC1734ED12999AFEE5396FEE722FE3B96846D903F00A32671AC0CEDAAAB0C933C950304650A76152ED1B69547031793755599939B42F075CDF137F8C16D35870DE90D1BACBDB4B746F814AED0D3CB7F7C1B789A1FDF9947717B641BA972A6460D3258F5561CAA1D8E20085E8E3B9EBC92C9B6DCBB872A2AE02D74577F65EFA5AAFF29FD52EAA400D1408B2815C5C96CD2B54DF0F6708A755FB1DFA694A7794C4A0422F1BF8FAFE9E6870578133D50FD3D5356506CFCEC94EF79D6B639"), tc::cli::FormatUtil::hexStringToBytes("C694562BBDC74E83069876608EAD1EE7B1BC715036E9A6BDF58A6D22FD660ABD9CF360AA893D7746C92C5B9D20E480EAD1387786739956E060EBA79BD6ED7C06B2FCC6DBC1734ED12999AFEE5396FEE722FE3B96846D903F00A32671AC0CEDAAAB0C933C950304650A76152ED1B69547031793755599939B42F075CDF137F8C16D35870DE90D1BACBDB4B746F814AED0D3CB7F7C1B789A1FDF9947717B641BA972A6460D3258F5561CAA1D8E20085E8E3B9EBC92C9B6DCBB872A2AE02D74577F65EFA5AAFF29FD52EAA400D1408B2815C5C96CD2B54DF0F6708A755FB1DFA694A7794C4A0422F1BF8FAFE9E6870578133D50FD3D5356506CFCEC94EF79D6B639"),
tc::cli::FormatUtil::hexStringToBytes("000100046EEED0424FF97D659DA43F85DF01E0997BA1FD1593997145BDE95703AABBDB7EFDE315F8CFE8AEC0F710FFF002938AEF8CEF7EBF90F725B6AC4EDA66DCF85132435E974DDBBE8F8C725CD114CE38C83404DFC0123BB4137C676C5C86EB4E211B7C35A03AB0C7E7637F1BF2486FDF0A5CCE5B047483841B5EA6BDC09AE770951ACA79EFB5497C46750585CF6C3FE4159ACE1CDFAB1BA8C00AB2446B57383F2F063344052E48E1557BD60BF973B252AC5AB4F5A12323AFCC1B06718775F3EDA4DD580A47A04D8063844235DC35D21A4FDED5A44EA401519920B73D15C66FDDF9F8286CF9122795EB9D5EA95C6E51603F6E62AA1631549EBE9E272B4BC3AEBC0D89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C694562BBDC74E83069876608EAD1EE7B1BC715036E9A6BDF58A6D22FD660ABD9CF360AA893D7746C92C5B9D20E480EAD1387786739956E060EBA79BD6ED7C06B2FCC6DBC1734ED12999AFEE5396FEE722FE3B96846D903F00A32671AC0CEDAAAB0C933C950304650A76152ED1B69547031793755599939B42F075CDF137F8C16D35870DE90D1BACBDB4B746F814AED0D3CB7F7C1B789A1FDF9947717B641BA972A6460D3258F5561CAA1D8E20085E8E3B9EBC92C9B6DCBB872A2AE02D74577F65EFA5AAFF29FD52EAA400D1408B2815C5C96CD2B54DF0F6708A755FB1DFA694A7794C4A0422F1BF8FAFE9E6870578133D50FD3D5356506CFCEC94EF79D6B6390001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), tc::cli::FormatUtil::hexStringToBytes("000100046EEED0424FF97D659DA43F85DF01E0997BA1FD1593997145BDE95703AABBDB7EFDE315F8CFE8AEC0F710FFF002938AEF8CEF7EBF90F725B6AC4EDA66DCF85132435E974DDBBE8F8C725CD114CE38C83404DFC0123BB4137C676C5C86EB4E211B7C35A03AB0C7E7637F1BF2486FDF0A5CCE5B047483841B5EA6BDC09AE770951ACA79EFB5497C46750585CF6C3FE4159ACE1CDFAB1BA8C00AB2446B57383F2F063344052E48E1557BD60BF973B252AC5AB4F5A12323AFCC1B06718775F3EDA4DD580A47A04D8063844235DC35D21A4FDED5A44EA401519920B73D15C66FDDF9F8286CF9122795EB9D5EA95C6E51603F6E62AA1631549EBE9E272B4BC3AEBC0D89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C694562BBDC74E83069876608EAD1EE7B1BC715036E9A6BDF58A6D22FD660ABD9CF360AA893D7746C92C5B9D20E480EAD1387786739956E060EBA79BD6ED7C06B2FCC6DBC1734ED12999AFEE5396FEE722FE3B96846D903F00A32671AC0CEDAAAB0C933C950304650A76152ED1B69547031793755599939B42F075CDF137F8C16D35870DE90D1BACBDB4B746F814AED0D3CB7F7C1B789A1FDF9947717B641BA972A6460D3258F5561CAA1D8E20085E8E3B9EBC92C9B6DCBB872A2AE02D74577F65EFA5AAFF29FD52EAA400D1408B2815C5C96CD2B54DF0F6708A755FB1DFA694A7794C4A0422F1BF8FAFE9E6870578133D50FD3D5356506CFCEC94EF79D6B6390001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
} }
@ -951,31 +923,31 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
{ {
{ {
"Root", "Root",
pie::hac::es::sign::SIGN_ALGO_RSA4096, nn::pki::sign::SIGN_ALGO_RSA4096,
tc::cli::FormatUtil::hexStringToBytes("D01FE100D43556B24B56DAE971B5A5D384B93003BE1BBF28A2305B060645467D5B0251D2561A274F9E9F9CEC646150AB3D2AE3366866ACA4BAE81AE3D79AA6B04A8BCBA7E6FB648945EBDFDB85BA091FD7D114B5A3A780E3A22E6ECD87B5A4C6F910E4032208814B0CEEA1A17DF739695F617EF63528DB949637A056037F7B32413895C0A8F1982E1565E38EEDC22E590EE2677B8609F48C2E303FBC405CAC18042F822084E4936803DA7F41349248562B8EE12F78F803246330BC7BE7EE724AF458A472E7AB46A1A7C10C2F18FA07C3DDD89806A11C9CC130B247A33C8D47DE67F29E5577B11C43493D5BBA7634A7E4E71531B7DF5981FE24A114554CBD8F005CE1DB35085CCFC77806B6DE254068A26CB5492D4580438FE1E5A9ED75C5ED451DCE789439CCC3BA28A2312A1B8719EF0F73B713950C02591A7462A607F37C0AA7A18FA943A36D752A5F4192F0136100AA9CB41BBE14BEB1F9FC692FDFA09446DE5A9DDE2CA5F68C1C0C21429287CB2DAAA3D263752F73E09FAF4479D2817429F69800AFDE6B592DC19882BDF581CCABF2CB91029EF35C4CFDBBFF49C1FA1B2FE31DE7A560ECB47EBCFE32425B956F81B69917487E3B789151DB2E78B1FD2EBE7E626B3EA165B4FB00CCB751AF507329C4A3939EA6DD9C50A0E7386B0145796B41AF61F78555944F3BC22DC3BD0D00F8798A42B1AAA08320659AC7395AB4F329"), tc::cli::FormatUtil::hexStringToBytes("D01FE100D43556B24B56DAE971B5A5D384B93003BE1BBF28A2305B060645467D5B0251D2561A274F9E9F9CEC646150AB3D2AE3366866ACA4BAE81AE3D79AA6B04A8BCBA7E6FB648945EBDFDB85BA091FD7D114B5A3A780E3A22E6ECD87B5A4C6F910E4032208814B0CEEA1A17DF739695F617EF63528DB949637A056037F7B32413895C0A8F1982E1565E38EEDC22E590EE2677B8609F48C2E303FBC405CAC18042F822084E4936803DA7F41349248562B8EE12F78F803246330BC7BE7EE724AF458A472E7AB46A1A7C10C2F18FA07C3DDD89806A11C9CC130B247A33C8D47DE67F29E5577B11C43493D5BBA7634A7E4E71531B7DF5981FE24A114554CBD8F005CE1DB35085CCFC77806B6DE254068A26CB5492D4580438FE1E5A9ED75C5ED451DCE789439CCC3BA28A2312A1B8719EF0F73B713950C02591A7462A607F37C0AA7A18FA943A36D752A5F4192F0136100AA9CB41BBE14BEB1F9FC692FDFA09446DE5A9DDE2CA5F68C1C0C21429287CB2DAAA3D263752F73E09FAF4479D2817429F69800AFDE6B592DC19882BDF581CCABF2CB91029EF35C4CFDBBFF49C1FA1B2FE31DE7A560ECB47EBCFE32425B956F81B69917487E3B789151DB2E78B1FD2EBE7E626B3EA165B4FB00CCB751AF507329C4A3939EA6DD9C50A0E7386B0145796B41AF61F78555944F3BC22DC3BD0D00F8798A42B1AAA08320659AC7395AB4F329"),
tc::ByteData() tc::ByteData()
}, },
{ {
"Root-CA00000004", "Root-CA00000004",
pie::hac::es::sign::SIGN_ALGO_RSA2048, nn::pki::sign::SIGN_ALGO_RSA2048,
tc::cli::FormatUtil::hexStringToBytes("C9CC2DC4DF2930E4DF3F8C70A078948775AD5E9AA604C5B4D8EAFF2AA1D214676564EFCA28CC00154554A1A3EA1379E9E6CAACED1593FE88D89AC6B8ACCCAB6E207CEB7CCA29809E2980440662B7D4382A15DA43085745A9AAE59AA05BDB32F66869A2DD4295386C87ECDD3508A2CF60D01E23EC2FE698F470D6001549A2F06759131E534C7006057DEF1D18A83F0AC79CFE80FF5A91F2BED4A0837061190A0329902165403C9A908FB615739F3CE33BF1BAEA16C25BCED7963FACC9D24D9C0AD76FC020B2C4B84C10A741A2CC7D9BAC3AACCCA3529BAC316A9AA75D2A26C7D7D288CBA466C5FE5F454AE679744A90A15772DB3B0E47A49AF031D16DBEAB332B"), tc::cli::FormatUtil::hexStringToBytes("C9CC2DC4DF2930E4DF3F8C70A078948775AD5E9AA604C5B4D8EAFF2AA1D214676564EFCA28CC00154554A1A3EA1379E9E6CAACED1593FE88D89AC6B8ACCCAB6E207CEB7CCA29809E2980440662B7D4382A15DA43085745A9AAE59AA05BDB32F66869A2DD4295386C87ECDD3508A2CF60D01E23EC2FE698F470D6001549A2F06759131E534C7006057DEF1D18A83F0AC79CFE80FF5A91F2BED4A0837061190A0329902165403C9A908FB615739F3CE33BF1BAEA16C25BCED7963FACC9D24D9C0AD76FC020B2C4B84C10A741A2CC7D9BAC3AACCCA3529BAC316A9AA75D2A26C7D7D288CBA466C5FE5F454AE679744A90A15772DB3B0E47A49AF031D16DBEAB332B"),
tc::cli::FormatUtil::hexStringToBytes("000100031949429D1E58A62E7E8B56D1B76AE302FD8B97491F778745F75388C4DD0BEB1DF122FB9642151497764A53CF78151845E42CA8FDE486FD2A4F53F8A1BA008A7485FF73B3BF7E3C980729D0656B693219ADE835EB5FFFFCCB7CBB5E307FE0688B888EF2D2053FB7E791E985FD15EF10D79CCA88D6BB15E8E4714A98EE09BF7B8AF053232B6450E6D5FDFFC20A6D1EA6A23812E1014525D56D4082703B86986959A73CD1A14364D2C2DAEA96B095F76C46E4FF4155465E70EF1ED31053D97011E010CC93E7914013687FA3A802996D1E557B1CCC7A7E8F5865C1742E28E26DEF38A93AB5D82D43ECCCBF0BEF22E1FD57E2864333582FEDEABC012F986DDFC3E9447973470308455BDC57AA170B84427F73A29B48F6DA135F66C745C142A84AFB0E6A5EED85D7B9719936F8CE2B621F395F40DC03BEF8854C1117FF0C128641CC7843B97B4346DB226F6026ACB56C278B8E0EA79A2D65EF798E1078AD80ED4B9604D2F08B2CD64A23A3DB270833B402F80851F35BED3EE4577C6660FBF16D9413E09C917A49D42C6DA375BC27F0230DB98F8973AB027B522CD57EC03D25E8B3FC3494C97FB108FE18C68A4336E46C26B6F280D27E34BE287C3E4687BC9D776B76D928D1B6352EC0347D7294AA9360268D26F5F652064AF240D7D00C7C5EA3C32DE62D9B5C4B4CAB6FD7BD371D57C2166095910E4AD8E9ED181EF761936153892D77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081122A46C9CC2DC4DF2930E4DF3F8C70A078948775AD5E9AA604C5B4D8EAFF2AA1D214676564EFCA28CC00154554A1A3EA1379E9E6CAACED1593FE88D89AC6B8ACCCAB6E207CEB7CCA29809E2980440662B7D4382A15DA43085745A9AAE59AA05BDB32F66869A2DD4295386C87ECDD3508A2CF60D01E23EC2FE698F470D6001549A2F06759131E534C7006057DEF1D18A83F0AC79CFE80FF5A91F2BED4A0837061190A0329902165403C9A908FB615739F3CE33BF1BAEA16C25BCED7963FACC9D24D9C0AD76FC020B2C4B84C10A741A2CC7D9BAC3AACCCA3529BAC316A9AA75D2A26C7D7D288CBA466C5FE5F454AE679744A90A15772DB3B0E47A49AF031D16DBEAB332B0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), tc::cli::FormatUtil::hexStringToBytes("000100031949429D1E58A62E7E8B56D1B76AE302FD8B97491F778745F75388C4DD0BEB1DF122FB9642151497764A53CF78151845E42CA8FDE486FD2A4F53F8A1BA008A7485FF73B3BF7E3C980729D0656B693219ADE835EB5FFFFCCB7CBB5E307FE0688B888EF2D2053FB7E791E985FD15EF10D79CCA88D6BB15E8E4714A98EE09BF7B8AF053232B6450E6D5FDFFC20A6D1EA6A23812E1014525D56D4082703B86986959A73CD1A14364D2C2DAEA96B095F76C46E4FF4155465E70EF1ED31053D97011E010CC93E7914013687FA3A802996D1E557B1CCC7A7E8F5865C1742E28E26DEF38A93AB5D82D43ECCCBF0BEF22E1FD57E2864333582FEDEABC012F986DDFC3E9447973470308455BDC57AA170B84427F73A29B48F6DA135F66C745C142A84AFB0E6A5EED85D7B9719936F8CE2B621F395F40DC03BEF8854C1117FF0C128641CC7843B97B4346DB226F6026ACB56C278B8E0EA79A2D65EF798E1078AD80ED4B9604D2F08B2CD64A23A3DB270833B402F80851F35BED3EE4577C6660FBF16D9413E09C917A49D42C6DA375BC27F0230DB98F8973AB027B522CD57EC03D25E8B3FC3494C97FB108FE18C68A4336E46C26B6F280D27E34BE287C3E4687BC9D776B76D928D1B6352EC0347D7294AA9360268D26F5F652064AF240D7D00C7C5EA3C32DE62D9B5C4B4CAB6FD7BD371D57C2166095910E4AD8E9ED181EF761936153892D77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081122A46C9CC2DC4DF2930E4DF3F8C70A078948775AD5E9AA604C5B4D8EAFF2AA1D214676564EFCA28CC00154554A1A3EA1379E9E6CAACED1593FE88D89AC6B8ACCCAB6E207CEB7CCA29809E2980440662B7D4382A15DA43085745A9AAE59AA05BDB32F66869A2DD4295386C87ECDD3508A2CF60D01E23EC2FE698F470D6001549A2F06759131E534C7006057DEF1D18A83F0AC79CFE80FF5A91F2BED4A0837061190A0329902165403C9A908FB615739F3CE33BF1BAEA16C25BCED7963FACC9D24D9C0AD76FC020B2C4B84C10A741A2CC7D9BAC3AACCCA3529BAC316A9AA75D2A26C7D7D288CBA466C5FE5F454AE679744A90A15772DB3B0E47A49AF031D16DBEAB332B0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
}, },
{ {
"Root-CA00000004-XS00000020", "Root-CA00000004-XS00000020",
pie::hac::es::sign::SIGN_ALGO_RSA2048, nn::pki::sign::SIGN_ALGO_RSA2048,
tc::cli::FormatUtil::hexStringToBytes("BA278428765D879A7F215404C6EE4E0A0D3F66C33BC7F8A32FD898E52CB7B63443CED8B00527D89DEDC6BBF60AD1C5C9923021DD555F9BAD4BE0C0C406D3702915E5B34AC2D2ABE503C32A3A23B43834C9157B9A0AF2E4E9C03BEDE2B4C115F5353DFC66BD04A6C079970E38CBDD5A50A2B98FF2D765FCF83381E9E0E849C3573578378FF65951613E95F75EE8EF26183A40AAE4A76D7384EA478D2CDCE80FBA0321A6BF8D69983C3AA7AE5443B72BFE410BF1323CBD88C3560EA13D17D38A2E34041DE7AAF389DE4375225CA87EE349C760C7D99BE7E737C6261CC74E25AE46527AC9619F939057088D7435A6DE7B25AB82DD5410F2579CAEF1491A909D302B"), tc::cli::FormatUtil::hexStringToBytes("BA278428765D879A7F215404C6EE4E0A0D3F66C33BC7F8A32FD898E52CB7B63443CED8B00527D89DEDC6BBF60AD1C5C9923021DD555F9BAD4BE0C0C406D3702915E5B34AC2D2ABE503C32A3A23B43834C9157B9A0AF2E4E9C03BEDE2B4C115F5353DFC66BD04A6C079970E38CBDD5A50A2B98FF2D765FCF83381E9E0E849C3573578378FF65951613E95F75EE8EF26183A40AAE4A76D7384EA478D2CDCE80FBA0321A6BF8D69983C3AA7AE5443B72BFE410BF1323CBD88C3560EA13D17D38A2E34041DE7AAF389DE4375225CA87EE349C760C7D99BE7E737C6261CC74E25AE46527AC9619F939057088D7435A6DE7B25AB82DD5410F2579CAEF1491A909D302B"),
tc::cli::FormatUtil::hexStringToBytes("00010004603483F7F4EF3C863FF7B46821E9D83983EFB0BA29C45B10DFB2E8A268AE06084DFEB0B9680B6D40D6DF82CAE7D651E28F31364F5AB567DD9DCCFCBB5EFF8F1CEA92489C046E8BED2AF0D7F9CA0BD50F683633D681B08D1AF417D7B7F8762AD88E3AF0D1C45DAC5407B9D8F24F167AEDC7C5DBCF4E0E176EC341D4F9BA8ADFE749CF37F45688653886566A9045ED89AD353DD289E32631867BDFD7FC67738BDF0E1E858F3BF9DEE25B02206F0B7FFB61F866DA4D862D77DDBDA9668BB61CBDEFACB2583CE5C9FAB22FC90EF8EB06954743E5A32A37A3513C6C795BC8E0C65E2F170B435A8C447765381C4050427F88E9828E6E94144D28441C7F9C7F6D92FE5B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BA278428765D879A7F215404C6EE4E0A0D3F66C33BC7F8A32FD898E52CB7B63443CED8B00527D89DEDC6BBF60AD1C5C9923021DD555F9BAD4BE0C0C406D3702915E5B34AC2D2ABE503C32A3A23B43834C9157B9A0AF2E4E9C03BEDE2B4C115F5353DFC66BD04A6C079970E38CBDD5A50A2B98FF2D765FCF83381E9E0E849C3573578378FF65951613E95F75EE8EF26183A40AAE4A76D7384EA478D2CDCE80FBA0321A6BF8D69983C3AA7AE5443B72BFE410BF1323CBD88C3560EA13D17D38A2E34041DE7AAF389DE4375225CA87EE349C760C7D99BE7E737C6261CC74E25AE46527AC9619F939057088D7435A6DE7B25AB82DD5410F2579CAEF1491A909D302B0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), tc::cli::FormatUtil::hexStringToBytes("00010004603483F7F4EF3C863FF7B46821E9D83983EFB0BA29C45B10DFB2E8A268AE06084DFEB0B9680B6D40D6DF82CAE7D651E28F31364F5AB567DD9DCCFCBB5EFF8F1CEA92489C046E8BED2AF0D7F9CA0BD50F683633D681B08D1AF417D7B7F8762AD88E3AF0D1C45DAC5407B9D8F24F167AEDC7C5DBCF4E0E176EC341D4F9BA8ADFE749CF37F45688653886566A9045ED89AD353DD289E32631867BDFD7FC67738BDF0E1E858F3BF9DEE25B02206F0B7FFB61F866DA4D862D77DDBDA9668BB61CBDEFACB2583CE5C9FAB22FC90EF8EB06954743E5A32A37A3513C6C795BC8E0C65E2F170B435A8C447765381C4050427F88E9828E6E94144D28441C7F9C7F6D92FE5B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BA278428765D879A7F215404C6EE4E0A0D3F66C33BC7F8A32FD898E52CB7B63443CED8B00527D89DEDC6BBF60AD1C5C9923021DD555F9BAD4BE0C0C406D3702915E5B34AC2D2ABE503C32A3A23B43834C9157B9A0AF2E4E9C03BEDE2B4C115F5353DFC66BD04A6C079970E38CBDD5A50A2B98FF2D765FCF83381E9E0E849C3573578378FF65951613E95F75EE8EF26183A40AAE4A76D7384EA478D2CDCE80FBA0321A6BF8D69983C3AA7AE5443B72BFE410BF1323CBD88C3560EA13D17D38A2E34041DE7AAF389DE4375225CA87EE349C760C7D99BE7E737C6261CC74E25AE46527AC9619F939057088D7435A6DE7B25AB82DD5410F2579CAEF1491A909D302B0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
}, },
{ {
"Root-CA00000004-XS00000021", "Root-CA00000004-XS00000021",
pie::hac::es::sign::SIGN_ALGO_RSA2048, nn::pki::sign::SIGN_ALGO_RSA2048,
tc::cli::FormatUtil::hexStringToBytes("CA303087732E88FB2736A4644B6A84DF02393786EBE3DBE914F92224126AB3C38D7CA67322B7D3107B9AC0E00AED9AF13DEDDC62BCB8AC889A47B07196B45BC97AC5DD333CC63E872E30CDB52BD35E055FBA56C2521AFC8BBFC8B06390522E99699750B457C8647A42D6318BE5EAA192ADA35DA7023FC348215613141919821FD5599B93497893CA58E7A88C8D6E6E9EB0A57567BF8C12EB25241BB6082BED7A696658A58DDB66E7CC2562F2EA061E5373E6A5397BF6299F7EA9065B0047AA408F24A5D6F6E4050B99DA86831F663792E08D96F182400182D9BECB917AE315A238CA89741B6AEAF52E238590CDA60FC5B74DC638F9D6FCAF95D2CA7AE005A7B1"), tc::cli::FormatUtil::hexStringToBytes("CA303087732E88FB2736A4644B6A84DF02393786EBE3DBE914F92224126AB3C38D7CA67322B7D3107B9AC0E00AED9AF13DEDDC62BCB8AC889A47B07196B45BC97AC5DD333CC63E872E30CDB52BD35E055FBA56C2521AFC8BBFC8B06390522E99699750B457C8647A42D6318BE5EAA192ADA35DA7023FC348215613141919821FD5599B93497893CA58E7A88C8D6E6E9EB0A57567BF8C12EB25241BB6082BED7A696658A58DDB66E7CC2562F2EA061E5373E6A5397BF6299F7EA9065B0047AA408F24A5D6F6E4050B99DA86831F663792E08D96F182400182D9BECB917AE315A238CA89741B6AEAF52E238590CDA60FC5B74DC638F9D6FCAF95D2CA7AE005A7B1"),
tc::cli::FormatUtil::hexStringToBytes("000100041282394569ED63B5C4E54747B31E3B32C68B0EB90712E3C04662101CA77A551A0394CC36CB28E369DFBBB9FD78C9C503C3B1F184729C2B05B4D1691581A877AF82F8EC3D70E95B27F459039B65D8221D4864CCB282FF721EBDD6C46863F8C95591C1BF36D0AC118C0027FA3E2D434821A5FEF123C65F17885321F9A520C22B9EE6FC533EEF582706A95DD0CEABACE87B0169E136336E2E9CC0399637CE4CC77B6DA418671A277614F80A0A909569018F624DE0C5E1A67DB134C63F1FFE30BB64C201FDD8DAD42F4C88B247C1C6133CC554DE6B15684320D6AA1E09CB59EAD15F37140C9DD4BE69D87CC90DD8F733C946FBA6C576C70533601AF4E8294A3B5DD4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA303087732E88FB2736A4644B6A84DF02393786EBE3DBE914F92224126AB3C38D7CA67322B7D3107B9AC0E00AED9AF13DEDDC62BCB8AC889A47B07196B45BC97AC5DD333CC63E872E30CDB52BD35E055FBA56C2521AFC8BBFC8B06390522E99699750B457C8647A42D6318BE5EAA192ADA35DA7023FC348215613141919821FD5599B93497893CA58E7A88C8D6E6E9EB0A57567BF8C12EB25241BB6082BED7A696658A58DDB66E7CC2562F2EA061E5373E6A5397BF6299F7EA9065B0047AA408F24A5D6F6E4050B99DA86831F663792E08D96F182400182D9BECB917AE315A238CA89741B6AEAF52E238590CDA60FC5B74DC638F9D6FCAF95D2CA7AE005A7B10001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), tc::cli::FormatUtil::hexStringToBytes("000100041282394569ED63B5C4E54747B31E3B32C68B0EB90712E3C04662101CA77A551A0394CC36CB28E369DFBBB9FD78C9C503C3B1F184729C2B05B4D1691581A877AF82F8EC3D70E95B27F459039B65D8221D4864CCB282FF721EBDD6C46863F8C95591C1BF36D0AC118C0027FA3E2D434821A5FEF123C65F17885321F9A520C22B9EE6FC533EEF582706A95DD0CEABACE87B0169E136336E2E9CC0399637CE4CC77B6DA418671A277614F80A0A909569018F624DE0C5E1A67DB134C63F1FFE30BB64C201FDD8DAD42F4C88B247C1C6133CC554DE6B15684320D6AA1E09CB59EAD15F37140C9DD4BE69D87CC90DD8F733C946FBA6C576C70533601AF4E8294A3B5DD4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA303087732E88FB2736A4644B6A84DF02393786EBE3DBE914F92224126AB3C38D7CA67322B7D3107B9AC0E00AED9AF13DEDDC62BCB8AC889A47B07196B45BC97AC5DD333CC63E872E30CDB52BD35E055FBA56C2521AFC8BBFC8B06390522E99699750B457C8647A42D6318BE5EAA192ADA35DA7023FC348215613141919821FD5599B93497893CA58E7A88C8D6E6E9EB0A57567BF8C12EB25241BB6082BED7A696658A58DDB66E7CC2562F2EA061E5373E6A5397BF6299F7EA9065B0047AA408F24A5D6F6E4050B99DA86831F663792E08D96F182400182D9BECB917AE315A238CA89741B6AEAF52E238590CDA60FC5B74DC638F9D6FCAF95D2CA7AE005A7B10001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
}, },
{ {
"Root-CA00000004-XS00000024", "Root-CA00000004-XS00000024",
pie::hac::es::sign::SIGN_ALGO_RSA2048, nn::pki::sign::SIGN_ALGO_RSA2048,
tc::cli::FormatUtil::hexStringToBytes("E5E262EA591EEB885DE5A3CA451CE9E4FEA0E89DAA9BBCD9EC6C23E3FEFCE31BE7C7217DAC3E1F5A8331EF3F0C738E9310E765E71AAAB92C6E18D36071E7F93446E06E2581A28483AE9EB9C8217C1D68A21FD098E186C71B6A1E1E2626C80B69FFD562EAD515C77D616554F6B74B34DEEB0DE905F44631F56A6FF12B47AC0190578267559592FAB173146071ECFBB014951512E45299A21C0B8B3377E55DCD95625130E533877BF11157585D43DB00F61DFE77CFA44F5F29F44945DBF4214F37214921C16ED7D74455B2AE7C8CA15DFBD20A4D5E6501965B78C2C542727D7A91C071C56403738F07E858239CD150DB304BA5ACD8751145A9A91D3E97085AD217"), tc::cli::FormatUtil::hexStringToBytes("E5E262EA591EEB885DE5A3CA451CE9E4FEA0E89DAA9BBCD9EC6C23E3FEFCE31BE7C7217DAC3E1F5A8331EF3F0C738E9310E765E71AAAB92C6E18D36071E7F93446E06E2581A28483AE9EB9C8217C1D68A21FD098E186C71B6A1E1E2626C80B69FFD562EAD515C77D616554F6B74B34DEEB0DE905F44631F56A6FF12B47AC0190578267559592FAB173146071ECFBB014951512E45299A21C0B8B3377E55DCD95625130E533877BF11157585D43DB00F61DFE77CFA44F5F29F44945DBF4214F37214921C16ED7D74455B2AE7C8CA15DFBD20A4D5E6501965B78C2C542727D7A91C071C56403738F07E858239CD150DB304BA5ACD8751145A9A91D3E97085AD217"),
tc::cli::FormatUtil::hexStringToBytes("000100049EA82934BD64EDCED4D506BB68BF1F217BAD912BEF134B687C8E590F2A9355D8EDD9BE00D85735A83820F69978B3E2876FE07BBB7F356B25CDCC98EEEA17BFA9EF649769E921BFDA7867D0570D2F0A7A223E7ACD8D9AE1F304F8EEC6C96B11805436CF686FBD05969E4C0D19A63EF89DA00899222D2CF006776FF027118E96CB027114AABBA268CB1775022B25EAF045C9E4A328A55FF85CFFFFFEAEFB78F1CD184ED9042D23A06F0161E5FBADE92638A483A1A3680DC9994A03D02F1D76EB0EE793843D31CCC172A3993C7344B2C5E634F2B89C47F85FD8B74D21745AEBCFD55E32FC03F6BCD40421499261F8AB93AC8A07E6EF5436036283A3B86192890A78000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E5E262EA591EEB885DE5A3CA451CE9E4FEA0E89DAA9BBCD9EC6C23E3FEFCE31BE7C7217DAC3E1F5A8331EF3F0C738E9310E765E71AAAB92C6E18D36071E7F93446E06E2581A28483AE9EB9C8217C1D68A21FD098E186C71B6A1E1E2626C80B69FFD562EAD515C77D616554F6B74B34DEEB0DE905F44631F56A6FF12B47AC0190578267559592FAB173146071ECFBB014951512E45299A21C0B8B3377E55DCD95625130E533877BF11157585D43DB00F61DFE77CFA44F5F29F44945DBF4214F37214921C16ED7D74455B2AE7C8CA15DFBD20A4D5E6501965B78C2C542727D7A91C071C56403738F07E858239CD150DB304BA5ACD8751145A9A91D3E97085AD2170001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), tc::cli::FormatUtil::hexStringToBytes("000100049EA82934BD64EDCED4D506BB68BF1F217BAD912BEF134B687C8E590F2A9355D8EDD9BE00D85735A83820F69978B3E2876FE07BBB7F356B25CDCC98EEEA17BFA9EF649769E921BFDA7867D0570D2F0A7A223E7ACD8D9AE1F304F8EEC6C96B11805436CF686FBD05969E4C0D19A63EF89DA00899222D2CF006776FF027118E96CB027114AABBA268CB1775022B25EAF045C9E4A328A55FF85CFFFFFEAEFB78F1CD184ED9042D23A06F0161E5FBADE92638A483A1A3680DC9994A03D02F1D76EB0EE793843D31CCC172A3993C7344B2C5E634F2B89C47F85FD8B74D21745AEBCFD55E32FC03F6BCD40421499261F8AB93AC8A07E6EF5436036283A3B86192890A78000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E5E262EA591EEB885DE5A3CA451CE9E4FEA0E89DAA9BBCD9EC6C23E3FEFCE31BE7C7217DAC3E1F5A8331EF3F0C738E9310E765E71AAAB92C6E18D36071E7F93446E06E2581A28483AE9EB9C8217C1D68A21FD098E186C71B6A1E1E2626C80B69FFD562EAD515C77D616554F6B74B34DEEB0DE905F44631F56A6FF12B47AC0190578267559592FAB173146071ECFBB014951512E45299A21C0B8B3377E55DCD95625130E533877BF11157585D43DB00F61DFE77CFA44F5F29F44945DBF4214F37214921C16ED7D74455B2AE7C8CA15DFBD20A4D5E6501965B78C2C542727D7A91C071C56403738F07E858239CD150DB304BA5ACD8751145A9A91D3E97085AD2170001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
} }

View file

@ -5,22 +5,22 @@
#include <map> #include <map>
#include <tc/Optional.h> #include <tc/Optional.h>
#include <tc/io.h> #include <tc/io.h>
#include <pietendo/hac/es/SignUtils.h> #include <nn/pki/SignUtils.h>
#include <pietendo/hac/define/types.h> #include <nn/hac/define/types.h>
#include <pietendo/hac/define/nca.h> #include <nn/hac/define/nca.h>
namespace nstool { namespace nstool {
struct KeyBag struct KeyBag
{ {
using aes128_key_t = pie::hac::detail::aes128_key_t; using aes128_key_t = nn::hac::detail::aes128_key_t;
using aes128_xtskey_t = pie::hac::detail::aes128_xtskey_t; using aes128_xtskey_t = nn::hac::detail::aes128_xtskey_t;
using rsa_key_t = tc::crypto::RsaKey; using rsa_key_t = tc::crypto::RsaKey;
//using ecc_key_t = tc::crypto::EccKey; //using ecc_key_t = tc::crypto::EccKey;
using rights_id_t = pie::hac::detail::rights_id_t; using rights_id_t = nn::hac::detail::rights_id_t;
using key_generation_t = byte_t; using key_generation_t = byte_t;
using broadon_issuer_t = std::string; using broadon_issuer_t = std::string;
static const size_t kNcaKeakNum = pie::hac::nca::kKeyAreaEncryptionKeyNum; static const size_t kNcaKeakNum = nn::hac::nca::kKeyAreaEncryptionKeyNum;
// acid // acid
@ -39,7 +39,6 @@ struct KeyBag
// external content keys (nca<->ticket) // external content keys (nca<->ticket)
std::map<rights_id_t, aes128_key_t> external_content_keys; std::map<rights_id_t, aes128_key_t> external_content_keys;
std::map<rights_id_t, aes128_key_t> external_enc_content_keys; // encrypted content key list to be used when external_content_keys does not have the required content key (usually taken raw from ticket)
tc::Optional<aes128_key_t> fallback_enc_content_key; // encrypted content key to be used when external_content_keys does not have the required content key (usually taken raw from ticket) tc::Optional<aes128_key_t> fallback_enc_content_key; // encrypted content key to be used when external_content_keys does not have the required content key (usually taken raw from ticket)
tc::Optional<aes128_key_t> fallback_content_key; // content key to be used when external_content_keys does not have the required content key (usually already decrypted from ticket) tc::Optional<aes128_key_t> fallback_content_key; // content key to be used when external_content_keys does not have the required content key (usually already decrypted from ticket)
@ -61,7 +60,7 @@ struct KeyBag
{ {
tc::ByteData certificate; tc::ByteData certificate;
pie::hac::es::sign::SignatureAlgo key_type; nn::pki::sign::SignatureAlgo key_type;
rsa_key_t rsa_key; rsa_key_t rsa_key;
// ecc_key_t ecc_key; // ecc_key_t ecc_key;
}; };
@ -71,7 +70,7 @@ struct KeyBag
class KeyBagInitializer : public KeyBag class KeyBagInitializer : public KeyBag
{ {
public: public:
KeyBagInitializer(bool isDev, const tc::Optional<tc::io::Path>& keyfile_path, const tc::Optional<tc::io::Path>& titlekeyfile_path, const std::vector<tc::io::Path>& tik_path_list, const tc::Optional<tc::io::Path>& cert_path); KeyBagInitializer(bool isDev, const tc::Optional<tc::io::Path>& keyfile_path, const tc::Optional<tc::io::Path>& tik_path, const tc::Optional<tc::io::Path>& cert_path);
private: private:
KeyBagInitializer(); KeyBagInitializer();

View file

@ -1,6 +1,6 @@
#include "KipProcess.h" #include "KipProcess.h"
#include <pietendo/hac/KernelCapabilityUtil.h> #include <nn/hac/KernelCapabilityUtil.h>
#include <tc/NotImplementedException.h> #include <tc/NotImplementedException.h>
@ -50,13 +50,13 @@ void nstool::KipProcess::importHeader()
} }
// check if file_size is smaller than KIP header size // check if file_size is smaller than KIP header size
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(pie::hac::sKipHeader)) if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sKipHeader))
{ {
throw tc::Exception(mModuleName, "Corrupt KIP: file too small."); throw tc::Exception(mModuleName, "Corrupt KIP: file too small.");
} }
// read kip // read kip
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sKipHeader)); tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sKipHeader));
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
@ -189,12 +189,12 @@ void nstool::KipProcess::displayHeader()
} }
void nstool::KipProcess::displayKernelCap(const pie::hac::KernelCapabilityControl& kern) void nstool::KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
{ {
fmt::print("[Kernel Capabilities]\n"); fmt::print("[Kernel Capabilities]\n");
if (kern.getThreadInfo().isSet()) if (kern.getThreadInfo().isSet())
{ {
pie::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo(); nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo();
fmt::print(" Thread Priority:\n"); fmt::print(" Thread Priority:\n");
fmt::print(" Min: {:d}\n", threadInfo.getMinPriority()); fmt::print(" Min: {:d}\n", threadInfo.getMinPriority());
fmt::print(" Max: {:d}\n", threadInfo.getMaxPriority()); fmt::print(" Max: {:d}\n", threadInfo.getMaxPriority());
@ -211,7 +211,7 @@ void nstool::KipProcess::displayKernelCap(const pie::hac::KernelCapabilityContro
for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++) for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++)
{ {
if (syscall_ids.test(syscall_id)) if (syscall_ids.test(syscall_id))
syscall_names.push_back(pie::hac::KernelCapabilityUtil::getSystemCallIdAsString(pie::hac::kc::SystemCallId(syscall_id))); syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id)));
} }
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(syscall_names, 60, 4)); fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(syscall_names, 60, 4));
} }
@ -243,7 +243,7 @@ void nstool::KipProcess::displayKernelCap(const pie::hac::KernelCapabilityContro
} }
if (kern.getMiscParams().isSet()) if (kern.getMiscParams().isSet())
{ {
fmt::print(" ProgramType: {:s} ({:d})\n", pie::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), (uint32_t)kern.getMiscParams().getProgramType()); fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), kern.getMiscParams().getProgramType());
} }
if (kern.getKernelVersion().isSet()) if (kern.getKernelVersion().isSet())
{ {
@ -261,13 +261,13 @@ void nstool::KipProcess::displayKernelCap(const pie::hac::KernelCapabilityContro
for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++) for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++)
{ {
if (misc_flags.test(misc_flags_bit)) if (misc_flags.test(misc_flags_bit))
misc_flags_names.push_back(pie::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(pie::hac::kc::MiscFlagsBit(misc_flags_bit))); misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit)));
} }
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(misc_flags_names, 60, 4)); fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(misc_flags_names, 60, 4));
} }
} }
std::string nstool::KipProcess::formatMappingAsString(const pie::hac::MemoryMappingHandler::sMemoryMapping& map) const std::string nstool::KipProcess::formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const
{ {
return fmt::format("0x{:016x} - 0x{:016x} (perm={:s}) (type={:s})", ((uint64_t)map.addr << 12), (((uint64_t)(map.addr + map.size) << 12) - 1), pie::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), pie::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type)); return fmt::format("0x{:016x} - 0x{:016x} (perm={:s}) (type={:s})", ((uint64_t)map.addr << 12), (((uint64_t)(map.addr + map.size) << 12) - 1), nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), nn::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type));
} }

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "types.h" #include "types.h"
#include <pietendo/hac/KernelInitialProcessHeader.h> #include <nn/hac/KernelInitialProcessHeader.h>
namespace nstool { namespace nstool {
@ -22,16 +22,16 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
pie::hac::KernelInitialProcessHeader mHdr; nn::hac::KernelInitialProcessHeader mHdr;
tc::ByteData mTextBlob, mRoBlob, mDataBlob; tc::ByteData mTextBlob, mRoBlob, mDataBlob;
void importHeader(); void importHeader();
void importCodeSegments(); void importCodeSegments();
size_t decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity); size_t decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity);
void displayHeader(); void displayHeader();
void displayKernelCap(const pie::hac::KernelCapabilityControl& kern); void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
std::string formatMappingAsString(const pie::hac::MemoryMappingHandler::sMemoryMapping& map) const; std::string formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const;
}; };
} }

View file

@ -1,9 +1,9 @@
#include "MetaProcess.h" #include "MetaProcess.h"
#include <pietendo/hac/AccessControlInfoUtil.h> #include <nn/hac/AccessControlInfoUtil.h>
#include <pietendo/hac/FileSystemAccessUtil.h> #include <nn/hac/FileSystemAccessUtil.h>
#include <pietendo/hac/KernelCapabilityUtil.h> #include <nn/hac/KernelCapabilityUtil.h>
#include <pietendo/hac/MetaUtil.h> #include <nn/hac/MetaUtil.h>
nstool::MetaProcess::MetaProcess() : nstool::MetaProcess::MetaProcess() :
mModuleName("nstool::MetaProcess"), mModuleName("nstool::MetaProcess"),
@ -65,7 +65,7 @@ void nstool::MetaProcess::setVerifyMode(bool verify)
mVerify = verify; mVerify = verify;
} }
const pie::hac::Meta& nstool::MetaProcess::getMeta() const const nn::hac::Meta& nstool::MetaProcess::getMeta() const
{ {
return mMeta; return mMeta;
} }
@ -96,7 +96,7 @@ void nstool::MetaProcess::importMeta()
mMeta.fromBytes(scratch.data(), scratch.size()); mMeta.fromBytes(scratch.data(), scratch.size());
} }
void nstool::MetaProcess::validateAcidSignature(const pie::hac::AccessControlInfoDesc& acid, byte_t key_generation) void nstool::MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid, byte_t key_generation)
{ {
try { try {
if (mKeyCfg.acid_sign_key.find(key_generation) == mKeyCfg.acid_sign_key.end()) if (mKeyCfg.acid_sign_key.find(key_generation) == mKeyCfg.acid_sign_key.end())
@ -112,7 +112,7 @@ void nstool::MetaProcess::validateAcidSignature(const pie::hac::AccessControlInf
} }
void nstool::MetaProcess::validateAciFromAcid(const pie::hac::AccessControlInfo& aci, const pie::hac::AccessControlInfoDesc& acid) void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, const nn::hac::AccessControlInfoDesc& acid)
{ {
// check Program ID // check Program ID
if (acid.getProgramIdRestrict().min > 0 && aci.getProgramId() < acid.getProgramIdRestrict().min) if (acid.getProgramIdRestrict().min > 0 && aci.getProgramId() < acid.getProgramIdRestrict().min)
@ -137,7 +137,7 @@ void nstool::MetaProcess::validateAciFromAcid(const pie::hac::AccessControlInfo&
if (rightFound == false) if (rightFound == false)
{ {
fmt::print("[WARNING] ACI/FAC FsaRights: FAIL ({:s} not permitted)\n", pie::hac::FileSystemAccessUtil::getFsAccessFlagAsString(fs_access[i])); fmt::print("[WARNING] ACI/FAC FsaRights: FAIL ({:s} not permitted)\n", nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(fs_access[i]));
} }
} }
@ -157,9 +157,6 @@ void nstool::MetaProcess::validateAciFromAcid(const pie::hac::AccessControlInfo&
} }
} }
// See https://github.com/jakcron/nstool/issues/92
// Nintendo doesn't populate SaveDataOwnerIdList in ACID, so this field cannot be verified
#if 0
for (size_t i = 0; i < aci.getFileSystemAccessControl().getSaveDataOwnerIdList().size(); i++) for (size_t i = 0; i < aci.getFileSystemAccessControl().getSaveDataOwnerIdList().size(); i++)
{ {
bool rightFound = false; bool rightFound = false;
@ -172,10 +169,9 @@ void nstool::MetaProcess::validateAciFromAcid(const pie::hac::AccessControlInfo&
if (rightFound == false) if (rightFound == false)
{ {
fmt::print("[WARNING] ACI/FAC SaveDataOwnerId: FAIL (0x{:016x} ({:d}) not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id, (uint32_t)aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type); fmt::print("[WARNING] ACI/FAC SaveDataOwnerId: FAIL (0x{:016x} ({:d}) not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id, aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type);
} }
} }
#endif
// check SAC // check SAC
for (size_t i = 0; i < aci.getServiceAccessControl().getServiceList().size(); i++) for (size_t i = 0; i < aci.getServiceAccessControl().getServiceList().size(); i++)
@ -218,7 +214,7 @@ void nstool::MetaProcess::validateAciFromAcid(const pie::hac::AccessControlInfo&
{ {
if (syscall_ids.test(i) && desc_syscall_ids.test(i) == false) if (syscall_ids.test(i) && desc_syscall_ids.test(i) == false)
{ {
fmt::print("[WARNING] ACI/KC SystemCallList: FAIL ({:s} not permitted)\n", pie::hac::KernelCapabilityUtil::getSystemCallIdAsString(pie::hac::kc::SystemCallId(i))); fmt::print("[WARNING] ACI/KC SystemCallList: FAIL ({:s} not permitted)\n", nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(i)));
} }
} }
// check memory maps // check memory maps
@ -272,7 +268,7 @@ void nstool::MetaProcess::validateAciFromAcid(const pie::hac::AccessControlInfo&
// check misc params // check misc params
if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType()) if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType())
{ {
fmt::print("[WARNING] ACI/KC ProgramType: FAIL ({:d} not permitted)\n", (uint32_t)aci.getKernelCapabilities().getMiscParams().getProgramType()); fmt::print("[WARNING] ACI/KC ProgramType: FAIL ({:d} not permitted)\n", aci.getKernelCapabilities().getMiscParams().getProgramType());
} }
// check kernel version // check kernel version
uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor(); uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor();
@ -293,18 +289,18 @@ void nstool::MetaProcess::validateAciFromAcid(const pie::hac::AccessControlInfo&
{ {
if (misc_flags.test(i) && desc_misc_flags.test(i) == false) if (misc_flags.test(i) && desc_misc_flags.test(i) == false)
{ {
fmt::print("[WARNING] ACI/KC MiscFlag: FAIL ({:s} not permitted)\n", pie::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(pie::hac::kc::MiscFlagsBit(i))); fmt::print("[WARNING] ACI/KC MiscFlag: FAIL ({:s} not permitted)\n", nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(i)));
} }
} }
} }
void nstool::MetaProcess::displayMetaHeader(const pie::hac::Meta& hdr) void nstool::MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr)
{ {
fmt::print("[Meta Header]\n"); fmt::print("[Meta Header]\n");
fmt::print(" ACID KeyGeneration: {:d}\n", hdr.getAccessControlInfoDescKeyGeneration()); fmt::print(" ACID KeyGeneration: {:d}\n", hdr.getAccessControlInfoDescKeyGeneration());
fmt::print(" Flags:\n"); fmt::print(" Flags:\n");
fmt::print(" Is64BitInstruction: {}\n", hdr.getIs64BitInstructionFlag()); fmt::print(" Is64BitInstruction: {}\n", hdr.getIs64BitInstructionFlag());
fmt::print(" ProcessAddressSpace: {:s}\n", pie::hac::MetaUtil::getProcessAddressSpaceAsString(hdr.getProcessAddressSpace())); fmt::print(" ProcessAddressSpace: {:s}\n", nn::hac::MetaUtil::getProcessAddressSpaceAsString(hdr.getProcessAddressSpace()));
fmt::print(" OptimizeMemoryAllocation: {}\n", hdr.getOptimizeMemoryAllocationFlag()); fmt::print(" OptimizeMemoryAllocation: {}\n", hdr.getOptimizeMemoryAllocationFlag());
fmt::print(" SystemResourceSize: 0x{:x}\n", hdr.getSystemResourceSize()); fmt::print(" SystemResourceSize: 0x{:x}\n", hdr.getSystemResourceSize());
fmt::print(" Main Thread Params:\n"); fmt::print(" Main Thread Params:\n");
@ -320,25 +316,25 @@ void nstool::MetaProcess::displayMetaHeader(const pie::hac::Meta& hdr)
} }
} }
void nstool::MetaProcess::displayAciHdr(const pie::hac::AccessControlInfo& aci) void nstool::MetaProcess::displayAciHdr(const nn::hac::AccessControlInfo& aci)
{ {
fmt::print("[Access Control Info]\n"); fmt::print("[Access Control Info]\n");
fmt::print(" ProgramID: 0x{:016x}\n", aci.getProgramId()); fmt::print(" ProgramID: 0x{:016x}\n", aci.getProgramId());
} }
void nstool::MetaProcess::displayAciDescHdr(const pie::hac::AccessControlInfoDesc& acid) void nstool::MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc& acid)
{ {
fmt::print("[Access Control Info Desc]\n"); fmt::print("[Access Control Info Desc]\n");
fmt::print(" Flags: \n"); fmt::print(" Flags: \n");
fmt::print(" Production: {}\n", acid.getProductionFlag()); fmt::print(" Production: {}\n", acid.getProductionFlag());
fmt::print(" Unqualified Approval: {}\n", acid.getUnqualifiedApprovalFlag()); fmt::print(" Unqualified Approval: {}\n", acid.getUnqualifiedApprovalFlag());
fmt::print(" Memory Region: {:s} ({:d})\n", pie::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()), (uint32_t)acid.getMemoryRegion()); fmt::print(" Memory Region: {:s} ({:d})\n", nn::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()), acid.getMemoryRegion());
fmt::print(" ProgramID Restriction\n"); fmt::print(" ProgramID Restriction\n");
fmt::print(" Min: 0x{:016x}\n", acid.getProgramIdRestrict().min); fmt::print(" Min: 0x{:016x}\n", acid.getProgramIdRestrict().min);
fmt::print(" Max: 0x{:016x}\n", acid.getProgramIdRestrict().max); fmt::print(" Max: 0x{:016x}\n", acid.getProgramIdRestrict().max);
} }
void nstool::MetaProcess::displayFac(const pie::hac::FileSystemAccessControl& fac) void nstool::MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac)
{ {
fmt::print("[FS Access Control]\n"); fmt::print("[FS Access Control]\n");
fmt::print(" Format Version: {:d}\n", fac.getFormatVersion()); fmt::print(" Format Version: {:d}\n", fac.getFormatVersion());
@ -348,10 +344,10 @@ void nstool::MetaProcess::displayFac(const pie::hac::FileSystemAccessControl& fa
std::vector<std::string> fs_access_str_list; std::vector<std::string> fs_access_str_list;
for (auto itr = fac.getFsAccess().begin(); itr != fac.getFsAccess().end(); itr++) for (auto itr = fac.getFsAccess().begin(); itr != fac.getFsAccess().end(); itr++)
{ {
std::string flag_string = pie::hac::FileSystemAccessUtil::getFsAccessFlagAsString(pie::hac::fac::FsAccessFlag(*itr)); std::string flag_string = nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(*itr));
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
{ {
fs_access_str_list.push_back(fmt::format("{:s} (bit {:d})", flag_string, (uint32_t)*itr)); fs_access_str_list.push_back(fmt::format("{:s} (bit {:d})", flag_string, *itr));
} }
else else
{ {
@ -378,12 +374,12 @@ void nstool::MetaProcess::displayFac(const pie::hac::FileSystemAccessControl& fa
fmt::print(" Save Data Owner IDs:\n"); fmt::print(" Save Data Owner IDs:\n");
for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++) for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++)
{ {
fmt::print(" 0x{:016x} ({:s})\n", fac.getSaveDataOwnerIdList()[i].id, pie::hac::FileSystemAccessUtil::getSaveDataOwnerAccessModeAsString(fac.getSaveDataOwnerIdList()[i].access_type)); fmt::print(" 0x{:016x} ({:s})\n", fac.getSaveDataOwnerIdList()[i].id, nn::hac::FileSystemAccessUtil::getSaveDataOwnerAccessModeAsString(fac.getSaveDataOwnerIdList()[i].access_type));
} }
} }
} }
void nstool::MetaProcess::displaySac(const pie::hac::ServiceAccessControl& sac) void nstool::MetaProcess::displaySac(const nn::hac::ServiceAccessControl& sac)
{ {
fmt::print("[Service Access Control]\n"); fmt::print("[Service Access Control]\n");
fmt::print(" Service List:\n"); fmt::print(" Service List:\n");
@ -395,12 +391,12 @@ void nstool::MetaProcess::displaySac(const pie::hac::ServiceAccessControl& sac)
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(service_name_list, 60, 4)); fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(service_name_list, 60, 4));
} }
void nstool::MetaProcess::displayKernelCap(const pie::hac::KernelCapabilityControl& kern) void nstool::MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
{ {
fmt::print("[Kernel Capabilities]\n"); fmt::print("[Kernel Capabilities]\n");
if (kern.getThreadInfo().isSet()) if (kern.getThreadInfo().isSet())
{ {
pie::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo(); nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo();
fmt::print(" Thread Priority:\n"); fmt::print(" Thread Priority:\n");
fmt::print(" Min: {:d}\n", threadInfo.getMinPriority()); fmt::print(" Min: {:d}\n", threadInfo.getMinPriority());
fmt::print(" Max: {:d}\n", threadInfo.getMaxPriority()); fmt::print(" Max: {:d}\n", threadInfo.getMaxPriority());
@ -417,7 +413,7 @@ void nstool::MetaProcess::displayKernelCap(const pie::hac::KernelCapabilityContr
for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++) for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++)
{ {
if (syscall_ids.test(syscall_id)) if (syscall_ids.test(syscall_id))
syscall_names.push_back(pie::hac::KernelCapabilityUtil::getSystemCallIdAsString(pie::hac::kc::SystemCallId(syscall_id))); syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id)));
} }
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(syscall_names, 60, 4)); fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(syscall_names, 60, 4));
} }
@ -449,7 +445,7 @@ void nstool::MetaProcess::displayKernelCap(const pie::hac::KernelCapabilityContr
} }
if (kern.getMiscParams().isSet()) if (kern.getMiscParams().isSet())
{ {
fmt::print(" ProgramType: {:s} ({:d})\n", pie::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), (uint32_t)kern.getMiscParams().getProgramType()); fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), kern.getMiscParams().getProgramType());
} }
if (kern.getKernelVersion().isSet()) if (kern.getKernelVersion().isSet())
{ {
@ -467,13 +463,13 @@ void nstool::MetaProcess::displayKernelCap(const pie::hac::KernelCapabilityContr
for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++) for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++)
{ {
if (misc_flags.test(misc_flags_bit)) if (misc_flags.test(misc_flags_bit))
misc_flags_names.push_back(pie::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(pie::hac::kc::MiscFlagsBit(misc_flags_bit))); misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit)));
} }
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(misc_flags_names, 60, 4)); fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(misc_flags_names, 60, 4));
} }
} }
std::string nstool::MetaProcess::formatMappingAsString(const pie::hac::MemoryMappingHandler::sMemoryMapping& map) const std::string nstool::MetaProcess::formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const
{ {
return fmt::format("0x{:016x} - 0x{:016x} (perm={:s}) (type={:s})", ((uint64_t)map.addr << 12), (((uint64_t)(map.addr + map.size) << 12) - 1), pie::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), pie::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type)); return fmt::format("0x{:016x} - 0x{:016x} (perm={:s}) (type={:s})", ((uint64_t)map.addr << 12), (((uint64_t)(map.addr + map.size) << 12) - 1), nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), nn::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type));
} }

View file

@ -2,7 +2,7 @@
#include "types.h" #include "types.h"
#include "KeyBag.h" #include "KeyBag.h"
#include <pietendo/hac/Meta.h> #include <nn/hac/Meta.h>
namespace nstool { namespace nstool {
@ -18,7 +18,7 @@ public:
void setCliOutputMode(CliOutputMode type); void setCliOutputMode(CliOutputMode type);
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
const pie::hac::Meta& getMeta() const; const nn::hac::Meta& getMeta() const;
private: private:
std::string mModuleName; std::string mModuleName;
@ -28,21 +28,21 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
pie::hac::Meta mMeta; nn::hac::Meta mMeta;
void importMeta(); void importMeta();
void validateAcidSignature(const pie::hac::AccessControlInfoDesc& acid, byte_t key_generation); void validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid, byte_t key_generation);
void validateAciFromAcid(const pie::hac::AccessControlInfo& aci, const pie::hac::AccessControlInfoDesc& acid); void validateAciFromAcid(const nn::hac::AccessControlInfo& aci, const nn::hac::AccessControlInfoDesc& acid);
void displayMetaHeader(const pie::hac::Meta& hdr); void displayMetaHeader(const nn::hac::Meta& hdr);
void displayAciHdr(const pie::hac::AccessControlInfo& aci); void displayAciHdr(const nn::hac::AccessControlInfo& aci);
void displayAciDescHdr(const pie::hac::AccessControlInfoDesc& aci); void displayAciDescHdr(const nn::hac::AccessControlInfoDesc& aci);
void displayFac(const pie::hac::FileSystemAccessControl& fac); void displayFac(const nn::hac::FileSystemAccessControl& fac);
void displaySac(const pie::hac::ServiceAccessControl& sac); void displaySac(const nn::hac::ServiceAccessControl& sac);
void displayKernelCap(const pie::hac::KernelCapabilityControl& kern); void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
std::string formatMappingAsString(const pie::hac::MemoryMappingHandler::sMemoryMapping& map) const; std::string formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const;
}; };
} }

View file

@ -1,6 +1,6 @@
#include "NacpProcess.h" #include "NacpProcess.h"
#include <pietendo/hac/ApplicationControlPropertyUtil.h> #include <nn/hac/ApplicationControlPropertyUtil.h>
nstool::NacpProcess::NacpProcess() : nstool::NacpProcess::NacpProcess() :
mModuleName("nstool::NacpProcess"), mModuleName("nstool::NacpProcess"),
@ -33,7 +33,7 @@ void nstool::NacpProcess::setVerifyMode(bool verify)
mVerify = verify; mVerify = verify;
} }
const pie::hac::ApplicationControlProperty& nstool::NacpProcess::getApplicationControlProperty() const const nn::hac::ApplicationControlProperty& nstool::NacpProcess::getApplicationControlProperty() const
{ {
return mNacp; return mNacp;
} }
@ -51,7 +51,7 @@ void nstool::NacpProcess::importNacp()
// check if file_size does matches expected size // check if file_size does matches expected size
size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length()); size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
if (file_size != sizeof(pie::hac::sApplicationControlProperty)) if (file_size != sizeof(nn::hac::sApplicationControlProperty))
{ {
throw tc::Exception(mModuleName, "File was incorrect size."); throw tc::Exception(mModuleName, "File was incorrect size.");
} }
@ -74,7 +74,7 @@ void nstool::NacpProcess::displayNacp()
fmt::print(" Title:\n"); fmt::print(" Title:\n");
for (auto itr = mNacp.getTitle().begin(); itr != mNacp.getTitle().end(); itr++) for (auto itr = mNacp.getTitle().begin(); itr != mNacp.getTitle().end(); itr++)
{ {
fmt::print(" {:s}:\n", pie::hac::ApplicationControlPropertyUtil::getLanguageAsString(itr->language)); fmt::print(" {:s}:\n", nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(itr->language));
fmt::print(" Name: {:s}\n", itr->name); fmt::print(" Name: {:s}\n", itr->name);
fmt::print(" Publisher: {:s}\n", itr->publisher); fmt::print(" Publisher: {:s}\n", itr->publisher);
} }
@ -95,21 +95,21 @@ void nstool::NacpProcess::displayNacp()
} }
// StartupUserAccount // StartupUserAccount
if (mNacp.getStartupUserAccount() != pie::hac::nacp::StartupUserAccount_None || mCliOutputMode.show_extended_info) if (mNacp.getStartupUserAccount() != nn::hac::nacp::StartupUserAccount::None || mCliOutputMode.show_extended_info)
{ {
fmt::print(" StartupUserAccount: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getStartupUserAccountAsString(mNacp.getStartupUserAccount())); fmt::print(" StartupUserAccount: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getStartupUserAccountAsString(mNacp.getStartupUserAccount()));
} }
// UserAccountSwitchLock // UserAccountSwitchLock
if (mNacp.getUserAccountSwitchLock() != pie::hac::nacp::UserAccountSwitchLock_Disable || mCliOutputMode.show_extended_info) if (mNacp.getUserAccountSwitchLock() != nn::hac::nacp::UserAccountSwitchLock::Disable || mCliOutputMode.show_extended_info)
{ {
fmt::print(" UserAccountSwitchLock: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getUserAccountSwitchLockAsString(mNacp.getUserAccountSwitchLock())); fmt::print(" UserAccountSwitchLock: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getUserAccountSwitchLockAsString(mNacp.getUserAccountSwitchLock()));
} }
// AddOnContentRegistrationType // AddOnContentRegistrationType
if (mNacp.getAddOnContentRegistrationType() != pie::hac::nacp::AddOnContentRegistrationType_AllOnLaunch || mCliOutputMode.show_extended_info) if (mNacp.getAddOnContentRegistrationType() != nn::hac::nacp::AddOnContentRegistrationType::AllOnLaunch || mCliOutputMode.show_extended_info)
{ {
fmt::print(" AddOnContentRegistrationType: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getAddOnContentRegistrationTypeAsString(mNacp.getAddOnContentRegistrationType())); fmt::print(" AddOnContentRegistrationType: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getAddOnContentRegistrationTypeAsString(mNacp.getAddOnContentRegistrationType()));
} }
// Attribute // Attribute
@ -118,7 +118,7 @@ void nstool::NacpProcess::displayNacp()
fmt::print(" Attribute:\n"); fmt::print(" Attribute:\n");
for (auto itr = mNacp.getAttribute().begin(); itr != mNacp.getAttribute().end(); itr++) for (auto itr = mNacp.getAttribute().begin(); itr != mNacp.getAttribute().end(); itr++)
{ {
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getAttributeFlagAsString(*itr)); fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getAttributeFlagAsString(*itr));
} }
} }
else if (mCliOutputMode.show_extended_info) else if (mCliOutputMode.show_extended_info)
@ -132,7 +132,7 @@ void nstool::NacpProcess::displayNacp()
fmt::print(" SupportedLanguage:\n"); fmt::print(" SupportedLanguage:\n");
for (auto itr = mNacp.getSupportedLanguage().begin(); itr != mNacp.getSupportedLanguage().end(); itr++) for (auto itr = mNacp.getSupportedLanguage().begin(); itr != mNacp.getSupportedLanguage().end(); itr++)
{ {
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getLanguageAsString(*itr)); fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(*itr));
} }
} }
else if (mCliOutputMode.show_extended_info) else if (mCliOutputMode.show_extended_info)
@ -146,7 +146,7 @@ void nstool::NacpProcess::displayNacp()
fmt::print(" ParentalControl:\n"); fmt::print(" ParentalControl:\n");
for (auto itr = mNacp.getParentalControl().begin(); itr != mNacp.getParentalControl().end(); itr++) for (auto itr = mNacp.getParentalControl().begin(); itr != mNacp.getParentalControl().end(); itr++)
{ {
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getParentalControlFlagAsString(*itr)); fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getParentalControlFlagAsString(*itr));
} }
} }
else if (mCliOutputMode.show_extended_info) else if (mCliOutputMode.show_extended_info)
@ -155,27 +155,27 @@ void nstool::NacpProcess::displayNacp()
} }
// Screenshot // Screenshot
if (mNacp.getScreenshot() != pie::hac::nacp::Screenshot_Allow || mCliOutputMode.show_extended_info) if (mNacp.getScreenshot() != nn::hac::nacp::Screenshot::Allow || mCliOutputMode.show_extended_info)
{ {
fmt::print(" Screenshot: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getScreenshotAsString(mNacp.getScreenshot())); fmt::print(" Screenshot: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getScreenshotAsString(mNacp.getScreenshot()));
} }
// VideoCapture // VideoCapture
if (mNacp.getVideoCapture() != pie::hac::nacp::VideoCapture_Disable || mCliOutputMode.show_extended_info) if (mNacp.getVideoCapture() != nn::hac::nacp::VideoCapture::Disable || mCliOutputMode.show_extended_info)
{ {
fmt::print(" VideoCapture: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getVideoCaptureAsString(mNacp.getVideoCapture())); fmt::print(" VideoCapture: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getVideoCaptureAsString(mNacp.getVideoCapture()));
} }
// DataLossConfirmation // DataLossConfirmation
if (mNacp.getDataLossConfirmation() != pie::hac::nacp::DataLossConfirmation_None || mCliOutputMode.show_extended_info) if (mNacp.getDataLossConfirmation() != nn::hac::nacp::DataLossConfirmation::None || mCliOutputMode.show_extended_info)
{ {
fmt::print(" DataLossConfirmation: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getDataLossConfirmationAsString(mNacp.getDataLossConfirmation())); fmt::print(" DataLossConfirmation: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getDataLossConfirmationAsString(mNacp.getDataLossConfirmation()));
} }
// PlayLogPolicy // PlayLogPolicy
if (mNacp.getPlayLogPolicy() != pie::hac::nacp::PlayLogPolicy_All || mCliOutputMode.show_extended_info) if (mNacp.getPlayLogPolicy() != nn::hac::nacp::PlayLogPolicy::All || mCliOutputMode.show_extended_info)
{ {
fmt::print(" PlayLogPolicy: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getPlayLogPolicyAsString(mNacp.getPlayLogPolicy())); fmt::print(" PlayLogPolicy: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getPlayLogPolicyAsString(mNacp.getPlayLogPolicy()));
} }
// PresenceGroupId // PresenceGroupId
@ -191,7 +191,7 @@ void nstool::NacpProcess::displayNacp()
for (auto itr = mNacp.getRatingAge().begin(); itr != mNacp.getRatingAge().end(); itr++) for (auto itr = mNacp.getRatingAge().begin(); itr != mNacp.getRatingAge().end(); itr++)
{ {
fmt::print(" {:s}:\n", pie::hac::ApplicationControlPropertyUtil::getOrganisationAsString(itr->organisation)); fmt::print(" {:s}:\n", nn::hac::ApplicationControlPropertyUtil::getOrganisationAsString(itr->organisation));
fmt::print(" Age: {:d}\n", itr->age); fmt::print(" Age: {:d}\n", itr->age);
} }
} }
@ -225,31 +225,31 @@ void nstool::NacpProcess::displayNacp()
// UserAccountSaveDataSize // UserAccountSaveDataSize
if (mNacp.getUserAccountSaveDataSize().size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getUserAccountSaveDataSize().size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" UserAccountSaveDataSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().size)); fmt::print(" UserAccountSaveDataSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().size));
} }
// UserAccountSaveDataJournalSize // UserAccountSaveDataJournalSize
if (mNacp.getUserAccountSaveDataSize().journal_size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getUserAccountSaveDataSize().journal_size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" UserAccountSaveDataJournalSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().journal_size)); fmt::print(" UserAccountSaveDataJournalSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().journal_size));
} }
// DeviceSaveDataSize // DeviceSaveDataSize
if (mNacp.getDeviceSaveDataSize().size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getDeviceSaveDataSize().size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" DeviceSaveDataSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().size)); fmt::print(" DeviceSaveDataSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().size));
} }
// DeviceSaveDataJournalSize // DeviceSaveDataJournalSize
if (mNacp.getDeviceSaveDataSize().journal_size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getDeviceSaveDataSize().journal_size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" DeviceSaveDataJournalSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().journal_size)); fmt::print(" DeviceSaveDataJournalSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().journal_size));
} }
// BcatDeliveryCacheStorageSize // BcatDeliveryCacheStorageSize
if (mNacp.getBcatDeliveryCacheStorageSize() != 0 || mCliOutputMode.show_extended_info) if (mNacp.getBcatDeliveryCacheStorageSize() != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" BcatDeliveryCacheStorageSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getBcatDeliveryCacheStorageSize())); fmt::print(" BcatDeliveryCacheStorageSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getBcatDeliveryCacheStorageSize()));
} }
// ApplicationErrorCodeCategory // ApplicationErrorCodeCategory
@ -277,39 +277,39 @@ void nstool::NacpProcess::displayNacp()
} }
// LogoType // LogoType
//if (mNacp.getLogoType() != pie::hac::nacp::LogoType_Nintendo || mCliOutputMode.show_extended_info) //if (mNacp.getLogoType() != nn::hac::nacp::LogoType::Nintendo || mCliOutputMode.show_extended_info)
//{ //{
fmt::print(" LogoType: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getLogoTypeAsString(mNacp.getLogoType())); fmt::print(" LogoType: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getLogoTypeAsString(mNacp.getLogoType()));
//} //}
// LogoHandling // LogoHandling
if (mNacp.getLogoHandling() != pie::hac::nacp::LogoHandling_Auto || mCliOutputMode.show_extended_info) if (mNacp.getLogoHandling() != nn::hac::nacp::LogoHandling::Auto || mCliOutputMode.show_extended_info)
{ {
fmt::print(" LogoHandling: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getLogoHandlingAsString(mNacp.getLogoHandling())); fmt::print(" LogoHandling: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getLogoHandlingAsString(mNacp.getLogoHandling()));
} }
// RuntimeAddOnContentInstall // RuntimeAddOnContentInstall
if (mNacp.getRuntimeAddOnContentInstall() != pie::hac::nacp::RuntimeAddOnContentInstall_Deny || mCliOutputMode.show_extended_info) if (mNacp.getRuntimeAddOnContentInstall() != nn::hac::nacp::RuntimeAddOnContentInstall::Deny || mCliOutputMode.show_extended_info)
{ {
fmt::print(" RuntimeAddOnContentInstall: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getRuntimeAddOnContentInstallAsString(mNacp.getRuntimeAddOnContentInstall())); fmt::print(" RuntimeAddOnContentInstall: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getRuntimeAddOnContentInstallAsString(mNacp.getRuntimeAddOnContentInstall()));
} }
// RuntimeParameterDelivery // RuntimeParameterDelivery
if (mNacp.getRuntimeParameterDelivery() != pie::hac::nacp::RuntimeParameterDelivery_Always || mCliOutputMode.show_extended_info) if (mNacp.getRuntimeParameterDelivery() != nn::hac::nacp::RuntimeParameterDelivery::Always || mCliOutputMode.show_extended_info)
{ {
fmt::print(" RuntimeParameterDelivery: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getRuntimeParameterDeliveryAsString(mNacp.getRuntimeParameterDelivery())); fmt::print(" RuntimeParameterDelivery: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getRuntimeParameterDeliveryAsString(mNacp.getRuntimeParameterDelivery()));
} }
// CrashReport // CrashReport
if (mNacp.getCrashReport() != pie::hac::nacp::CrashReport_Deny || mCliOutputMode.show_extended_info) if (mNacp.getCrashReport() != nn::hac::nacp::CrashReport::Deny || mCliOutputMode.show_extended_info)
{ {
fmt::print(" CrashReport: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getCrashReportAsString(mNacp.getCrashReport())); fmt::print(" CrashReport: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getCrashReportAsString(mNacp.getCrashReport()));
} }
// Hdcp // Hdcp
if (mNacp.getHdcp() != pie::hac::nacp::Hdcp_None || mCliOutputMode.show_extended_info) if (mNacp.getHdcp() != nn::hac::nacp::Hdcp::None || mCliOutputMode.show_extended_info)
{ {
fmt::print(" Hdcp: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getHdcpAsString(mNacp.getHdcp())); fmt::print(" Hdcp: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getHdcpAsString(mNacp.getHdcp()));
} }
// SeedForPsuedoDeviceId // SeedForPsuedoDeviceId
@ -334,7 +334,7 @@ void nstool::NacpProcess::displayNacp()
fmt::print(" StartupUserAccountOption:\n"); fmt::print(" StartupUserAccountOption:\n");
for (auto itr = mNacp.getStartupUserAccountOption().begin(); itr != mNacp.getStartupUserAccountOption().end(); itr++) for (auto itr = mNacp.getStartupUserAccountOption().begin(); itr != mNacp.getStartupUserAccountOption().end(); itr++)
{ {
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getStartupUserAccountOptionFlagAsString(*itr)); fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getStartupUserAccountOptionFlagAsString(*itr));
} }
} }
else if (mCliOutputMode.show_extended_info) else if (mCliOutputMode.show_extended_info)
@ -345,49 +345,49 @@ void nstool::NacpProcess::displayNacp()
// UserAccountSaveDataSizeMax // UserAccountSaveDataSizeMax
if (mNacp.getUserAccountSaveDataMax().size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getUserAccountSaveDataMax().size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" UserAccountSaveDataSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().size)); fmt::print(" UserAccountSaveDataSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().size));
} }
// UserAccountSaveDataJournalSizeMax // UserAccountSaveDataJournalSizeMax
if (mNacp.getUserAccountSaveDataMax().journal_size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getUserAccountSaveDataMax().journal_size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" UserAccountSaveDataJournalSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().journal_size)); fmt::print(" UserAccountSaveDataJournalSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().journal_size));
} }
// DeviceSaveDataSizeMax // DeviceSaveDataSizeMax
if (mNacp.getDeviceSaveDataMax().size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getDeviceSaveDataMax().size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" DeviceSaveDataSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().size)); fmt::print(" DeviceSaveDataSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().size));
} }
// DeviceSaveDataJournalSizeMax // DeviceSaveDataJournalSizeMax
if (mNacp.getDeviceSaveDataMax().journal_size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getDeviceSaveDataMax().journal_size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" DeviceSaveDataJournalSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().journal_size)); fmt::print(" DeviceSaveDataJournalSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().journal_size));
} }
// TemporaryStorageSize // TemporaryStorageSize
if (mNacp.getTemporaryStorageSize() != 0 || mCliOutputMode.show_extended_info) if (mNacp.getTemporaryStorageSize() != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" TemporaryStorageSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getTemporaryStorageSize())); fmt::print(" TemporaryStorageSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getTemporaryStorageSize()));
} }
// CacheStorageSize // CacheStorageSize
if (mNacp.getCacheStorageSize().size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getCacheStorageSize().size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" CacheStorageSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().size)); fmt::print(" CacheStorageSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().size));
} }
// CacheStorageJournalSize // CacheStorageJournalSize
if (mNacp.getCacheStorageSize().journal_size != 0 || mCliOutputMode.show_extended_info) if (mNacp.getCacheStorageSize().journal_size != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" CacheStorageJournalSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().journal_size)); fmt::print(" CacheStorageJournalSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().journal_size));
} }
// CacheStorageDataAndJournalSizeMax // CacheStorageDataAndJournalSizeMax
if (mNacp.getCacheStorageDataAndJournalSizeMax() != 0 || mCliOutputMode.show_extended_info) if (mNacp.getCacheStorageDataAndJournalSizeMax() != 0 || mCliOutputMode.show_extended_info)
{ {
fmt::print(" CacheStorageDataAndJournalSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageDataAndJournalSizeMax())); fmt::print(" CacheStorageDataAndJournalSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageDataAndJournalSizeMax()));
} }
// CacheStorageIndexMax // CacheStorageIndexMax
@ -411,9 +411,9 @@ void nstool::NacpProcess::displayNacp()
} }
// PlayLogQueryCapability // PlayLogQueryCapability
if (mNacp.getPlayLogQueryCapability() != pie::hac::nacp::PlayLogQueryCapability_None || mCliOutputMode.show_extended_info) if (mNacp.getPlayLogQueryCapability() != nn::hac::nacp::PlayLogQueryCapability::None || mCliOutputMode.show_extended_info)
{ {
fmt::print(" PlayLogQueryCapability: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getPlayLogQueryCapabilityAsString(mNacp.getPlayLogQueryCapability())); fmt::print(" PlayLogQueryCapability: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getPlayLogQueryCapabilityAsString(mNacp.getPlayLogQueryCapability()));
} }
// Repair // Repair
@ -422,7 +422,7 @@ void nstool::NacpProcess::displayNacp()
fmt::print(" Repair:\n"); fmt::print(" Repair:\n");
for (auto itr = mNacp.getRepair().begin(); itr != mNacp.getRepair().end(); itr++) for (auto itr = mNacp.getRepair().begin(); itr != mNacp.getRepair().end(); itr++)
{ {
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getRepairFlagAsString(*itr)); fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getRepairFlagAsString(*itr));
} }
} }
else if (mCliOutputMode.show_extended_info) else if (mCliOutputMode.show_extended_info)
@ -442,7 +442,7 @@ void nstool::NacpProcess::displayNacp()
fmt::print(" RequiredNetworkServiceLicenseOnLaunch:\n"); fmt::print(" RequiredNetworkServiceLicenseOnLaunch:\n");
for (auto itr = mNacp.getRequiredNetworkServiceLicenseOnLaunch().begin(); itr != mNacp.getRequiredNetworkServiceLicenseOnLaunch().end(); itr++) for (auto itr = mNacp.getRequiredNetworkServiceLicenseOnLaunch().begin(); itr != mNacp.getRequiredNetworkServiceLicenseOnLaunch().end(); itr++)
{ {
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getRequiredNetworkServiceLicenseOnLaunchFlagAsString(*itr)); fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getRequiredNetworkServiceLicenseOnLaunchFlagAsString(*itr));
} }
} }
else if (mCliOutputMode.show_extended_info) else if (mCliOutputMode.show_extended_info)
@ -468,7 +468,7 @@ void nstool::NacpProcess::displayNacp()
if (detect_config.countReceivableGroupConfig() > 0) if (detect_config.countReceivableGroupConfig() > 0)
{ {
fmt::print(" ReceivableGroupConfig:\n"); fmt::print(" ReceivableGroupConfig:\n");
for (size_t i = 0; i < pie::hac::nacp::kReceivableGroupConfigurationCount; i++) for (size_t i = 0; i < nn::hac::nacp::kReceivableGroupConfigurationCount; i++)
{ {
if (detect_config.receivable_data_configuration[i].isNull()) if (detect_config.receivable_data_configuration[i].isNull())
continue; continue;
@ -496,21 +496,21 @@ void nstool::NacpProcess::displayNacp()
} }
// PlayReportPermission // PlayReportPermission
if (mNacp.getPlayReportPermission() != pie::hac::nacp::PlayReportPermission_None || mCliOutputMode.show_extended_info) if (mNacp.getPlayReportPermission() != nn::hac::nacp::PlayReportPermission::None || mCliOutputMode.show_extended_info)
{ {
fmt::print(" PlayReportPermission: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getPlayReportPermissionAsString(mNacp.getPlayReportPermission())); fmt::print(" PlayReportPermission: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getPlayReportPermissionAsString(mNacp.getPlayReportPermission()));
} }
// CrashScreenshotForProd // CrashScreenshotForProd
if (mNacp.getCrashScreenshotForProd() != pie::hac::nacp::CrashScreenshotForProd_Deny || mCliOutputMode.show_extended_info) if (mNacp.getCrashScreenshotForProd() != nn::hac::nacp::CrashScreenshotForProd::Deny || mCliOutputMode.show_extended_info)
{ {
fmt::print(" CrashScreenshotForProd: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getCrashScreenshotForProdAsString(mNacp.getCrashScreenshotForProd())); fmt::print(" CrashScreenshotForProd: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getCrashScreenshotForProdAsString(mNacp.getCrashScreenshotForProd()));
} }
// CrashScreenshotForDev // CrashScreenshotForDev
if (mNacp.getCrashScreenshotForDev() != pie::hac::nacp::CrashScreenshotForDev_Deny || mCliOutputMode.show_extended_info) if (mNacp.getCrashScreenshotForDev() != nn::hac::nacp::CrashScreenshotForDev::Deny || mCliOutputMode.show_extended_info)
{ {
fmt::print(" CrashScreenshotForDev: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getCrashScreenshotForDevAsString(mNacp.getCrashScreenshotForDev())); fmt::print(" CrashScreenshotForDev: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getCrashScreenshotForDevAsString(mNacp.getCrashScreenshotForDev()));
} }
// AccessibleLaunchRequiredVersion // AccessibleLaunchRequiredVersion

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "types.h" #include "types.h"
#include <pietendo/hac/ApplicationControlProperty.h> #include <nn/hac/ApplicationControlProperty.h>
namespace nstool { namespace nstool {
@ -16,7 +16,7 @@ public:
void setCliOutputMode(CliOutputMode type); void setCliOutputMode(CliOutputMode type);
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
const pie::hac::ApplicationControlProperty& getApplicationControlProperty() const; const nn::hac::ApplicationControlProperty& getApplicationControlProperty() const;
private: private:
std::string mModuleName; std::string mModuleName;
@ -25,7 +25,7 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
pie::hac::ApplicationControlProperty mNacp; nn::hac::ApplicationControlProperty mNacp;
void importNacp(); void importNacp();
void displayNacp(); void displayNacp();

View file

@ -2,14 +2,15 @@
#include "MetaProcess.h" #include "MetaProcess.h"
#include "util.h" #include "util.h"
#include <pietendo/hac/ContentArchiveUtil.h> #include <tc/crypto/detail/BlockUtilImpl.h>
#include <pietendo/hac/AesKeygen.h>
#include <pietendo/hac/HierarchicalSha256Stream.h> #include <nn/hac/ContentArchiveUtil.h>
#include <pietendo/hac/HierarchicalIntegrityStream.h> #include <nn/hac/AesKeygen.h>
#include <pietendo/hac/BKTREncryptedStream.h> #include <nn/hac/HierarchicalSha256Stream.h>
#include <pietendo/hac/PartitionFsSnapshotGenerator.h> #include <nn/hac/HierarchicalIntegrityStream.h>
#include <pietendo/hac/RomFsSnapshotGenerator.h> #include <nn/hac/PartitionFsMetaGenerator.h>
#include <pietendo/hac/CombinedFsSnapshotGenerator.h> #include <nn/hac/RomFsMetaGenerator.h>
#include <nn/hac/CombinedFsMetaGenerator.h>
nstool::NcaProcess::NcaProcess() : nstool::NcaProcess::NcaProcess() :
mModuleName("nstool::NcaProcess"), mModuleName("nstool::NcaProcess"),
@ -49,11 +50,6 @@ void nstool::NcaProcess::setInputFile(const std::shared_ptr<tc::io::IStream>& fi
mFile = file; mFile = file;
} }
void nstool::NcaProcess::setBaseNcaPath(const tc::Optional<tc::io::Path>& nca_path)
{
mBaseNcaPath = nca_path;
}
void nstool::NcaProcess::setKeyCfg(const KeyBag& keycfg) void nstool::NcaProcess::setKeyCfg(const KeyBag& keycfg)
{ {
mKeyCfg = keycfg; mKeyCfg = keycfg;
@ -84,7 +80,7 @@ void nstool::NcaProcess::setExtractJobs(const std::vector<nstool::ExtractJob>& e
mFsProcess.setExtractJobs(extract_jobs); mFsProcess.setExtractJobs(extract_jobs);
} }
const std::shared_ptr<tc::io::IFileSystem>& nstool::NcaProcess::getFileSystem() const const std::shared_ptr<tc::io::IStorage>& nstool::NcaProcess::getFileSystem() const
{ {
return mFileSystem; return mFileSystem;
} }
@ -101,25 +97,25 @@ void nstool::NcaProcess::importHeader()
} }
// read header block // read header block
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sContentArchiveHeaderBlock))) if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sContentArchiveHeaderBlock)))
{ {
throw tc::Exception(mModuleName, "Corrupt NCA: File too small."); throw tc::Exception(mModuleName, "Corrupt NCA: File too small.");
} }
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read((byte_t*)(&mHdrBlock), sizeof(pie::hac::sContentArchiveHeaderBlock)); mFile->read((byte_t*)(&mHdrBlock), sizeof(nn::hac::sContentArchiveHeaderBlock));
// decrypt header block // decrypt header block
if (mKeyCfg.nca_header_key.isNull()) if (mKeyCfg.nca_header_key.isNull())
{ {
throw tc::Exception(mModuleName, "Failed to decrypt NCA header. (nca_header_key could not be loaded)"); throw tc::Exception(mModuleName, "Failed to decrypt NCA header. (nca_header_key could not be loaded)");
} }
pie::hac::ContentArchiveUtil::decryptContentArchiveHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyCfg.nca_header_key.get()); nn::hac::ContentArchiveUtil::decryptContentArchiveHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyCfg.nca_header_key.get());
// generate header hash // generate header hash
tc::crypto::GenerateSha2256Hash(mHdrHash.data(), (byte_t*)&mHdrBlock.header, sizeof(pie::hac::sContentArchiveHeader)); tc::crypto::GenerateSha256Hash(mHdrHash.data(), (byte_t*)&mHdrBlock.header, sizeof(nn::hac::sContentArchiveHeader));
// proccess main header // proccess main header
mHdr.fromBytes((byte_t*)&mHdrBlock.header, sizeof(pie::hac::sContentArchiveHeader)); mHdr.fromBytes((byte_t*)&mHdrBlock.header, sizeof(nn::hac::sContentArchiveHeader));
} }
void nstool::NcaProcess::generateNcaBodyEncryptionKeys() void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
@ -129,7 +125,7 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
memset(zero_aesctr_key.data(), 0, zero_aesctr_key.size()); memset(zero_aesctr_key.data(), 0, zero_aesctr_key.size());
// get key data from header // get key data from header
byte_t masterkey_rev = pie::hac::AesKeygen::getMasterKeyRevisionFromKeyGeneration(mHdr.getKeyGeneration()); byte_t masterkey_rev = nn::hac::AesKeygen::getMasterKeyRevisionFromKeyGeneration(mHdr.getKeyGeneration());
byte_t keak_index = mHdr.getKeyAreaEncryptionKeyIndex(); byte_t keak_index = mHdr.getKeyAreaEncryptionKeyIndex();
// process key area // process key area
@ -145,13 +141,13 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
if (i < 4 && mKeyCfg.nca_key_area_encryption_key[keak_index].find(masterkey_rev) != mKeyCfg.nca_key_area_encryption_key[keak_index].end()) if (i < 4 && mKeyCfg.nca_key_area_encryption_key[keak_index].find(masterkey_rev) != mKeyCfg.nca_key_area_encryption_key[keak_index].end())
{ {
kak.decrypted = true; kak.decrypted = true;
pie::hac::AesKeygen::generateKey(kak.dec.data(), kak.enc.data(), mKeyCfg.nca_key_area_encryption_key[keak_index][masterkey_rev].data()); nn::hac::AesKeygen::generateKey(kak.dec.data(), kak.enc.data(), mKeyCfg.nca_key_area_encryption_key[keak_index][masterkey_rev].data());
} }
// key[KeyBankIndex_AesCtrHw] // key[KEY_AESCTR_HW]
else if (i == pie::hac::nca::KeyBankIndex_AesCtrHw && mKeyCfg.nca_key_area_encryption_key_hw[keak_index].find(masterkey_rev) != mKeyCfg.nca_key_area_encryption_key_hw[keak_index].end()) else if (i == nn::hac::nca::KEY_AESCTR_HW && mKeyCfg.nca_key_area_encryption_key_hw[keak_index].find(masterkey_rev) != mKeyCfg.nca_key_area_encryption_key_hw[keak_index].end())
{ {
kak.decrypted = true; kak.decrypted = true;
pie::hac::AesKeygen::generateKey(kak.dec.data(), kak.enc.data(), mKeyCfg.nca_key_area_encryption_key_hw[keak_index][masterkey_rev].data()); nn::hac::AesKeygen::generateKey(kak.dec.data(), kak.enc.data(), mKeyCfg.nca_key_area_encryption_key_hw[keak_index][masterkey_rev].data());
} }
else else
{ {
@ -162,7 +158,7 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
} }
// clear content key // clear content key
mContentKey.aes_ctr = tc::Optional<pie::hac::detail::aes128_key_t>(); mContentKey.aes_ctr = tc::Optional<nn::hac::detail::aes128_key_t>();
// if this has a rights id, the key needs to be sourced from a ticket // if this has a rights id, the key needs to be sourced from a ticket
if (mHdr.hasRightsId() == true) if (mHdr.hasRightsId() == true)
@ -176,21 +172,12 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
{ {
mContentKey.aes_ctr = mKeyCfg.fallback_content_key.get(); mContentKey.aes_ctr = mKeyCfg.fallback_content_key.get();
} }
else if (mKeyCfg.external_enc_content_keys.find(mHdr.getRightsId()) != mKeyCfg.external_enc_content_keys.end())
{
tmp_key = mKeyCfg.external_enc_content_keys[mHdr.getRightsId()];
if (mKeyCfg.etik_common_key.find(masterkey_rev) != mKeyCfg.etik_common_key.end())
{
pie::hac::AesKeygen::generateKey(tmp_key.data(), tmp_key.data(), mKeyCfg.etik_common_key[masterkey_rev].data());
mContentKey.aes_ctr = tmp_key;
}
}
else if (mKeyCfg.fallback_enc_content_key.isSet()) else if (mKeyCfg.fallback_enc_content_key.isSet())
{ {
tmp_key = mKeyCfg.fallback_enc_content_key.get(); tmp_key = mKeyCfg.fallback_enc_content_key.get();
if (mKeyCfg.etik_common_key.find(masterkey_rev) != mKeyCfg.etik_common_key.end()) if (mKeyCfg.etik_common_key.find(masterkey_rev) != mKeyCfg.etik_common_key.end())
{ {
pie::hac::AesKeygen::generateKey(tmp_key.data(), tmp_key.data(), mKeyCfg.etik_common_key[masterkey_rev].data()); nn::hac::AesKeygen::generateKey(tmp_key.data(), tmp_key.data(), mKeyCfg.etik_common_key[masterkey_rev].data());
mContentKey.aes_ctr = tmp_key; mContentKey.aes_ctr = tmp_key;
} }
} }
@ -200,7 +187,7 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
{ {
for (size_t i = 0; i < mContentKey.kak_list.size(); i++) for (size_t i = 0; i < mContentKey.kak_list.size(); i++)
{ {
if (mContentKey.kak_list[i].index == pie::hac::nca::KeyBankIndex_AesCtr && mContentKey.kak_list[i].decrypted) if (mContentKey.kak_list[i].index == nn::hac::nca::KEY_AESCTR && mContentKey.kak_list[i].decrypted)
{ {
mContentKey.aes_ctr = mContentKey.kak_list[i].dec; mContentKey.aes_ctr = mContentKey.kak_list[i].dec;
} }
@ -226,72 +213,44 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
} }
} }
nstool::NcaProcess nstool::NcaProcess::readBaseNCA()
{
// open base nca stream
if (mBaseNcaPath.isNull())
{
throw tc::Exception(mModuleName, "Base NCA not supplied. Necessary for update NCA.");
}
std::shared_ptr<tc::io::IStream> base_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(mBaseNcaPath.get(), tc::io::FileMode::Open, tc::io::FileAccess::Read));
// process base nca with output suppressed
NcaProcess obj;
nstool::CliOutputMode cliOutput;
cliOutput.show_basic_info = false;
cliOutput.show_extended_info = false;
cliOutput.show_keydata = false;
cliOutput.show_layout = false;
obj.setCliOutputMode(cliOutput);
obj.setVerifyMode(true);
obj.setKeyCfg(mKeyCfg);
obj.setInputFile(base_stream);
obj.process();
// return processed base nca
return obj;
}
void nstool::NcaProcess::generatePartitionConfiguration() void nstool::NcaProcess::generatePartitionConfiguration()
{ {
for (size_t i = 0; i < mHdr.getPartitionEntryList().size(); i++) for (size_t i = 0; i < mHdr.getPartitionEntryList().size(); i++)
{ {
// get reference to relevant structures // get reference to relevant structures
const pie::hac::ContentArchiveHeader::sPartitionEntry& partition = mHdr.getPartitionEntryList()[i]; const nn::hac::ContentArchiveHeader::sPartitionEntry& partition = mHdr.getPartitionEntryList()[i];
pie::hac::sContentArchiveFsHeader& fs_header = mHdrBlock.fs_header[partition.header_index]; nn::hac::sContentArchiveFsHeader& fs_header = mHdrBlock.fs_header[partition.header_index];
// output structure // output structure
sPartitionInfo& info = mPartitions[partition.header_index]; sPartitionInfo& info = mPartitions[partition.header_index];
// validate header hash // validate header hash
pie::hac::detail::sha256_hash_t fs_header_hash; nn::hac::detail::sha256_hash_t fs_header_hash;
tc::crypto::GenerateSha2256Hash(fs_header_hash.data(), (const byte_t*)&mHdrBlock.fs_header[partition.header_index], sizeof(pie::hac::sContentArchiveFsHeader)); tc::crypto::GenerateSha256Hash(fs_header_hash.data(), (const byte_t*)&mHdrBlock.fs_header[partition.header_index], sizeof(nn::hac::sContentArchiveFsHeader));
if (fs_header_hash != partition.fs_header_hash) if (fs_header_hash != partition.fs_header_hash)
{ {
throw tc::Exception(mModuleName, fmt::format("NCA FS Header [{:d}] Hash: FAIL", partition.header_index)); throw tc::Exception(mModuleName, fmt::format("NCA FS Header [{:d}] Hash: FAIL", partition.header_index));
} }
if (fs_header.version.unwrap() != pie::hac::nca::kDefaultFsHeaderVersion) if (fs_header.version.unwrap() != nn::hac::nca::kDefaultFsHeaderVersion)
{ {
throw tc::Exception(mModuleName, fmt::format("NCA FS Header [{:d}] Version({:d}): UNSUPPORTED", partition.header_index, fs_header.version.unwrap())); throw tc::Exception(mModuleName, fmt::format("NCA FS Header [{:d}] Version({:d}): UNSUPPORTED", partition.header_index, fs_header.version.unwrap()));
} }
// setup AES-CTR // setup AES-CTR
pie::hac::ContentArchiveUtil::getNcaPartitionAesCtr(&fs_header, info.aes_ctr.data()); nn::hac::ContentArchiveUtil::getNcaPartitionAesCtr(&fs_header, info.aes_ctr.data());
// save partition configinfo // save partition configinfo
info.offset = partition.offset; info.offset = partition.offset;
info.size = partition.size; info.size = partition.size;
info.format_type = (pie::hac::nca::FormatType)fs_header.format_type; info.format_type = (nn::hac::nca::FormatType)fs_header.format_type;
info.hash_type = (pie::hac::nca::HashType)fs_header.hash_type; info.hash_type = (nn::hac::nca::HashType)fs_header.hash_type;
info.enc_type = (pie::hac::nca::EncryptionType)fs_header.encryption_type; info.enc_type = (nn::hac::nca::EncryptionType)fs_header.encryption_type;
info.metadata_hash_type = (pie::hac::nca::MetaDataHashType)fs_header.meta_data_hash_type; if (info.hash_type == nn::hac::nca::HashType::HierarchicalSha256)
if (info.hash_type == pie::hac::nca::HashType_HierarchicalSha256)
{ {
info.hierarchicalsha256_hdr.fromBytes(fs_header.hash_info.data(), fs_header.hash_info.size()); info.hierarchicalsha256_hdr.fromBytes(fs_header.hash_info.data(), fs_header.hash_info.size());
} }
else if (info.hash_type == pie::hac::nca::HashType_HierarchicalIntegrity) else if (info.hash_type == nn::hac::nca::HashType::HierarchicalIntegrity)
{ {
info.hierarchicalintegrity_hdr.fromBytes(fs_header.hash_info.data(), fs_header.hash_info.size()); info.hierarchicalintegrity_hdr.fromBytes(fs_header.hash_info.data(), fs_header.hash_info.size());
} }
@ -307,106 +266,68 @@ void nstool::NcaProcess::generatePartitionConfiguration()
else else
{ {
// create raw partition // create raw partition
info.raw_reader = std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, info.offset, info.size)); info.reader = std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, info.offset, info.size));
// handle encryption if required reader based on encryption type // handle encryption if required reader based on encryption type
if (info.enc_type == pie::hac::nca::EncryptionType_None) if (info.enc_type == nn::hac::nca::EncryptionType::None)
{ {
// no encryption so do nothing // no encryption so do nothing
info.decrypt_reader = info.raw_reader; //info.reader = info.reader;
} }
else if (info.enc_type == pie::hac::nca::EncryptionType_AesCtr) else if (info.enc_type == nn::hac::nca::EncryptionType::AesCtr)
{ {
if (mContentKey.aes_ctr.isNull()) if (mContentKey.aes_ctr.isNull())
throw tc::Exception(mModuleName, "AES-CTR Key was not determined"); throw tc::Exception(mModuleName, "AES-CTR Key was not determined");
// get partition key // get partition key
pie::hac::detail::aes128_key_t partition_key = mContentKey.aes_ctr.get(); nn::hac::detail::aes128_key_t partition_key = mContentKey.aes_ctr.get();
// get partition counter // get partition counter
pie::hac::detail::aes_iv_t partition_ctr = info.aes_ctr; nn::hac::detail::aes_iv_t partition_ctr = info.aes_ctr;
tc::crypto::IncrementCounterAes128Ctr(partition_ctr.data(), info.offset >> 4); tc::crypto::detail::incr_counter<16>(partition_ctr.data(), info.offset>>4);
// create decryption stream // create decryption stream
info.decrypt_reader = std::make_shared<tc::crypto::Aes128CtrEncryptedStream>(tc::crypto::Aes128CtrEncryptedStream(info.raw_reader, partition_key, partition_ctr)); info.reader = std::make_shared<tc::crypto::Aes128CtrEncryptedStream>(tc::crypto::Aes128CtrEncryptedStream(info.reader, partition_key, partition_ctr));
} }
else if (info.enc_type == pie::hac::nca::EncryptionType_AesCtrEx) else if (info.enc_type == nn::hac::nca::EncryptionType::AesXts || info.enc_type == nn::hac::nca::EncryptionType::AesCtrEx)
{ {
if (mContentKey.aes_ctr.isNull()) throw tc::Exception(mModuleName, fmt::format("EncryptionType({:s}): UNSUPPORTED", nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type)));
throw tc::Exception(mModuleName, "AES-CTR Key was not determined");
// get partition key
pie::hac::detail::aes128_key_t partition_key = mContentKey.aes_ctr.get();
// get partition counter
pie::hac::detail::aes_iv_t partition_ctr = info.aes_ctr;
tc::crypto::IncrementCounterAes128Ctr(partition_ctr.data(), info.offset >> 4);
// TODO see if AesCtrEx encryption can just be for creating the transparent decryption, with IndirectStorage IStream construction being done after decryption but before hash layer processing
// this might be relevant when processing compressed or sparse storage
NcaProcess nca_base = readBaseNCA();
if (nca_base.mHdr.getProgramId() != mHdr.getProgramId())
{
throw tc::Exception(mModuleName, "Invalid base nca. ProgramID diferent.");
}
std::shared_ptr<tc::io::IStream> base_reader;
for (auto& partition_base : nca_base.mPartitions)
{
if (partition_base.format_type == pie::hac::nca::FormatType::FormatType_RomFs && partition_base.raw_reader != nullptr)
{
base_reader = partition_base.decrypt_reader;
}
}
if (base_reader == nullptr)
{
throw tc::Exception(mModuleName, "Cannot determine RomFs from base nca.");
}
// create decryption stream
info.decrypt_reader = std::make_shared<pie::hac::BKTREncryptedStream>(pie::hac::BKTREncryptedStream(info.raw_reader, partition_key, partition_ctr, fs_header.patch_info, base_reader));
}
else if (info.enc_type == pie::hac::nca::EncryptionType_AesXts)
{
throw tc::Exception(mModuleName, fmt::format("EncryptionType({:s}): UNSUPPORTED", pie::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type)));
} }
else else
{ {
throw tc::Exception(mModuleName, fmt::format("EncryptionType({:s}): UNKNOWN", pie::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type))); throw tc::Exception(mModuleName, fmt::format("EncryptionType({:s}): UNKNOWN", nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type)));
} }
} }
// filter out unrecognised hash types, and hash based readers // filter out unrecognised hash types, and hash based readers
switch (info.hash_type) switch (info.hash_type)
{ {
case (pie::hac::nca::HashType_None): case (nn::hac::nca::HashType::None):
// no hash layer, do nothing
info.reader = info.decrypt_reader;
break; break;
case (pie::hac::nca::HashType_HierarchicalSha256): case (nn::hac::nca::HashType::HierarchicalSha256):
info.reader = std::make_shared<pie::hac::HierarchicalSha256Stream>(pie::hac::HierarchicalSha256Stream(info.decrypt_reader, info.hierarchicalsha256_hdr)); info.reader = std::make_shared<nn::hac::HierarchicalSha256Stream>(nn::hac::HierarchicalSha256Stream(info.reader, info.hierarchicalsha256_hdr));
break; break;
case (pie::hac::nca::HashType_HierarchicalIntegrity): case (nn::hac::nca::HashType::HierarchicalIntegrity):
info.reader = std::make_shared<pie::hac::HierarchicalIntegrityStream>(pie::hac::HierarchicalIntegrityStream(info.decrypt_reader, info.hierarchicalintegrity_hdr)); info.reader = std::make_shared<nn::hac::HierarchicalIntegrityStream>(nn::hac::HierarchicalIntegrityStream(info.reader, info.hierarchicalintegrity_hdr));
break; break;
default: default:
throw tc::Exception(mModuleName, fmt::format("HashType({:s}): UNKNOWN", pie::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type))); throw tc::Exception(mModuleName, fmt::format("HashType({:s}): UNKNOWN", nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type)));
} }
// filter out unrecognised format types // filter out unrecognised format types
switch (info.format_type) switch (info.format_type)
{ {
case (pie::hac::nca::FormatType_PartitionFs): case (nn::hac::nca::FormatType::PartitionFs):
info.fs_snapshot = pie::hac::PartitionFsSnapshotGenerator(info.reader); info.fs_meta = nn::hac::PartitionFsMetaGenerator(info.reader);
info.fs_reader = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(info.fs_snapshot)); info.fs_reader = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(info.fs_meta));
break; break;
case (pie::hac::nca::FormatType_RomFs): case (nn::hac::nca::FormatType::RomFs):
info.fs_snapshot = pie::hac::RomFsSnapshotGenerator(info.reader); info.fs_meta = nn::hac::RomFsMetaGenerator(info.reader);
info.fs_reader = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(info.fs_snapshot)); info.fs_reader = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(info.fs_meta));
break; break;
default: default:
throw tc::Exception(mModuleName, fmt::format("FormatType({:s}): UNKNOWN", pie::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type))); throw tc::Exception(mModuleName, fmt::format("FormatType({:s}): UNKNOWN", nn::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type)));
} }
} }
catch (const tc::Exception& e) catch (const tc::Exception& e)
@ -421,7 +342,7 @@ void nstool::NcaProcess::validateNcaSignatures()
// validate signature[0] // validate signature[0]
if (mKeyCfg.nca_header_sign0_key.find(mHdr.getSignatureKeyGeneration()) != mKeyCfg.nca_header_sign0_key.end()) if (mKeyCfg.nca_header_sign0_key.find(mHdr.getSignatureKeyGeneration()) != mKeyCfg.nca_header_sign0_key.end())
{ {
if (tc::crypto::VerifyRsa2048PssSha2256(mHdrBlock.signature_main.data(), mHdrHash.data(), mKeyCfg.nca_header_sign0_key[mHdr.getSignatureKeyGeneration()]) == false) if (tc::crypto::VerifyRsa2048PssSha256(mHdrBlock.signature_main.data(), mHdrHash.data(), mKeyCfg.nca_header_sign0_key[mHdr.getSignatureKeyGeneration()]) == false)
{ {
fmt::print("[WARNING] NCA Header Main Signature: FAIL\n"); fmt::print("[WARNING] NCA Header Main Signature: FAIL\n");
} }
@ -433,16 +354,16 @@ void nstool::NcaProcess::validateNcaSignatures()
// validate signature[1] // validate signature[1]
if (mHdr.getContentType() == pie::hac::nca::ContentType_Program) if (mHdr.getContentType() == nn::hac::nca::ContentType::Program)
{ {
try { try {
if (mPartitions[pie::hac::nca::ProgramContentPartitionIndex_Code].format_type == pie::hac::nca::FormatType_PartitionFs) if (mPartitions[nn::hac::nca::PARTITION_CODE].format_type == nn::hac::nca::FormatType::PartitionFs)
{ {
if (mPartitions[pie::hac::nca::ProgramContentPartitionIndex_Code].fs_reader != nullptr) if (mPartitions[nn::hac::nca::PARTITION_CODE].fs_reader != nullptr)
{ {
std::shared_ptr<tc::io::IStream> npdm_file; std::shared_ptr<tc::io::IStream> npdm_file;
try { try {
mPartitions[pie::hac::nca::ProgramContentPartitionIndex_Code].fs_reader->openFile(tc::io::Path(kNpdmExefsPath), tc::io::FileMode::Open, tc::io::FileAccess::Read, npdm_file); mPartitions[nn::hac::nca::PARTITION_CODE].fs_reader->openFile(tc::io::Path(kNpdmExefsPath), tc::io::FileMode::Open, tc::io::FileAccess::Read, npdm_file);
} }
catch (tc::io::FileNotFoundException&) { catch (tc::io::FileNotFoundException&) {
throw tc::Exception(fmt::format("\"{:s}\" not present in ExeFs", kNpdmExefsPath)); throw tc::Exception(fmt::format("\"{:s}\" not present in ExeFs", kNpdmExefsPath));
@ -455,7 +376,7 @@ void nstool::NcaProcess::validateNcaSignatures()
npdm.setCliOutputMode(CliOutputMode(false, false, false, false)); npdm.setCliOutputMode(CliOutputMode(false, false, false, false));
npdm.process(); npdm.process();
if (tc::crypto::VerifyRsa2048PssSha2256(mHdrBlock.signature_acid.data(), mHdrHash.data(), npdm.getMeta().getAccessControlInfoDesc().getContentArchiveHeaderSignature2Key()) == false) if (tc::crypto::VerifyRsa2048PssSha256(mHdrBlock.signature_acid.data(), mHdrHash.data(), npdm.getMeta().getAccessControlInfoDesc().getContentArchiveHeaderSignature2Key()) == false)
{ {
throw tc::Exception("Bad signature"); throw tc::Exception("Bad signature");
} }
@ -479,16 +400,16 @@ void nstool::NcaProcess::validateNcaSignatures()
void nstool::NcaProcess::displayHeader() void nstool::NcaProcess::displayHeader()
{ {
fmt::print("[NCA Header]\n"); fmt::print("[NCA Header]\n");
fmt::print(" Format Type: {:s}\n", pie::hac::ContentArchiveUtil::getFormatHeaderVersionAsString((pie::hac::nca::HeaderFormatVersion)mHdr.getFormatVersion())); fmt::print(" Format Type: {:s}\n", nn::hac::ContentArchiveUtil::getFormatHeaderVersionAsString((nn::hac::nca::HeaderFormatVersion)mHdr.getFormatVersion()));
fmt::print(" Dist. Type: {:s}\n", pie::hac::ContentArchiveUtil::getDistributionTypeAsString(mHdr.getDistributionType())); fmt::print(" Dist. Type: {:s}\n", nn::hac::ContentArchiveUtil::getDistributionTypeAsString(mHdr.getDistributionType()));
fmt::print(" Content Type: {:s}\n", pie::hac::ContentArchiveUtil::getContentTypeAsString(mHdr.getContentType())); fmt::print(" Content Type: {:s}\n", nn::hac::ContentArchiveUtil::getContentTypeAsString(mHdr.getContentType()));
fmt::print(" Key Generation: {:d}\n", mHdr.getKeyGeneration()); fmt::print(" Key Generation: {:d}\n", mHdr.getKeyGeneration());
fmt::print(" Sig. Generation: {:d}\n", mHdr.getSignatureKeyGeneration()); fmt::print(" Sig. Generation: {:d}\n", mHdr.getSignatureKeyGeneration());
fmt::print(" Kaek Index: {:s} ({:d})\n", pie::hac::ContentArchiveUtil::getKeyAreaEncryptionKeyIndexAsString((pie::hac::nca::KeyAreaEncryptionKeyIndex)mHdr.getKeyAreaEncryptionKeyIndex()), mHdr.getKeyAreaEncryptionKeyIndex()); fmt::print(" Kaek Index: {:s} ({:d})\n", nn::hac::ContentArchiveUtil::getKeyAreaEncryptionKeyIndexAsString((nn::hac::nca::KeyAreaEncryptionKeyIndex)mHdr.getKeyAreaEncryptionKeyIndex()), mHdr.getKeyAreaEncryptionKeyIndex());
fmt::print(" Size: 0x{:x}\n", mHdr.getContentSize()); fmt::print(" Size: 0x{:x}\n", mHdr.getContentSize());
fmt::print(" ProgID: 0x{:016x}\n", mHdr.getProgramId()); fmt::print(" ProgID: 0x{:016x}\n", mHdr.getProgramId());
fmt::print(" Content Index: {:d}\n", mHdr.getContentIndex()); fmt::print(" Content Index: {:d}\n", mHdr.getContentIndex());
fmt::print(" SdkAddon Ver.: {:s} (v{:d})\n", pie::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getSdkAddonVersion()), mHdr.getSdkAddonVersion()); fmt::print(" SdkAddon Ver.: {:s} (v{:d})\n", nn::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getSdkAddonVersion()), mHdr.getSdkAddonVersion());
if (mHdr.hasRightsId()) if (mHdr.hasRightsId())
{ {
fmt::print(" RightsId: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getRightsId().data(), mHdr.getRightsId().size(), true, "")); fmt::print(" RightsId: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getRightsId().data(), mHdr.getRightsId().size(), true, ""));
@ -497,18 +418,22 @@ void nstool::NcaProcess::displayHeader()
if (mContentKey.kak_list.size() > 0 && mCliOutputMode.show_keydata) if (mContentKey.kak_list.size() > 0 && mCliOutputMode.show_keydata)
{ {
fmt::print(" Key Area:\n"); fmt::print(" Key Area:\n");
fmt::print(" <--------------------------------------------------------------------------->\n"); fmt::print(" <--------------------------------------------------------------------------------------------------------->\n");
fmt::print(" | IDX | ENCRYPTED KEY | DECRYPTED KEY |\n"); fmt::print(" | IDX | ENCRYPTED KEY | DECRYPTED KEY |\n");
fmt::print(" |-----|----------------------------------|----------------------------------|\n"); fmt::print(" |-----|-------------------------------------------------|-------------------------------------------------|\n");
for (size_t i = 0; i < mContentKey.kak_list.size(); i++) for (size_t i = 0; i < mContentKey.kak_list.size(); i++)
{ {
std::string enc_key = tc::cli::FormatUtil::formatBytesAsString(mContentKey.kak_list[i].enc.data(), mContentKey.kak_list[i].enc.size(), true, ""); fmt::print(" | {:3d} | {:s} | ", mContentKey.kak_list[i].index, tc::cli::FormatUtil::formatBytesAsString(mContentKey.kak_list[i].enc.data(), mContentKey.kak_list[i].enc.size(), true, ""));
std::string dec_key = mContentKey.kak_list[i].decrypted ? tc::cli::FormatUtil::formatBytesAsString(mContentKey.kak_list[i].dec.data(), mContentKey.kak_list[i].dec.size(), true, "") : "<unable to decrypt>";
fmt::print(" | {:3d} | {:32s} | {:32s} |\n", mContentKey.kak_list[i].index, enc_key, dec_key); if (mContentKey.kak_list[i].decrypted)
fmt::print("{:s}", tc::cli::FormatUtil::formatBytesAsString(mContentKey.kak_list[i].dec.data(), mContentKey.kak_list[i].dec.size(), true, ""));
else
fmt::print("<unable to decrypt> ");
fmt::print(" |\n");
} }
fmt::print(" <--------------------------------------------------------------------------->\n"); fmt::print(" <--------------------------------------------------------------------------------------------------------->\n");
} }
if (mCliOutputMode.show_layout) if (mCliOutputMode.show_layout)
@ -523,18 +448,18 @@ void nstool::NcaProcess::displayHeader()
fmt::print(" {:d}:\n", index); fmt::print(" {:d}:\n", index);
fmt::print(" Offset: 0x{:x}\n", info.offset); fmt::print(" Offset: 0x{:x}\n", info.offset);
fmt::print(" Size: 0x{:x}\n", info.size); fmt::print(" Size: 0x{:x}\n", info.size);
fmt::print(" Format Type: {:s}\n", pie::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type)); fmt::print(" Format Type: {:s}\n", nn::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type));
fmt::print(" Hash Type: {:s}\n", pie::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type)); fmt::print(" Hash Type: {:s}\n", nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type));
fmt::print(" Enc. Type: {:s}\n", pie::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type)); fmt::print(" Enc. Type: {:s}\n", nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type));
if (info.enc_type == pie::hac::nca::EncryptionType_AesCtr) if (info.enc_type == nn::hac::nca::EncryptionType::AesCtr)
{ {
pie::hac::detail::aes_iv_t aes_ctr; nn::hac::detail::aes_iv_t aes_ctr;
memcpy(aes_ctr.data(), info.aes_ctr.data(), aes_ctr.size()); memcpy(aes_ctr.data(), info.aes_ctr.data(), aes_ctr.size());
tc::crypto::IncrementCounterAes128Ctr(aes_ctr.data(), info.offset>>4); tc::crypto::detail::incr_counter<16>(aes_ctr.data(), info.offset>>4);
fmt::print(" AesCtr Counter:\n"); fmt::print(" AesCtr Counter:\n");
fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(aes_ctr.data(), aes_ctr.size(), true, "")); fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(aes_ctr.data(), aes_ctr.size(), true, ""));
} }
if (info.hash_type == pie::hac::nca::HashType_HierarchicalIntegrity) if (info.hash_type == nn::hac::nca::HashType::HierarchicalIntegrity)
{ {
auto hash_hdr = info.hierarchicalintegrity_hdr; auto hash_hdr = info.hierarchicalintegrity_hdr;
fmt::print(" HierarchicalIntegrity Header:\n"); fmt::print(" HierarchicalIntegrity Header:\n");
@ -559,7 +484,7 @@ void nstool::NcaProcess::displayHeader()
fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(hash_hdr.getMasterHashList()[j].data()+0x10, 0x10, true, "")); fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(hash_hdr.getMasterHashList()[j].data()+0x10, 0x10, true, ""));
} }
} }
else if (info.hash_type == pie::hac::nca::HashType_HierarchicalSha256) else if (info.hash_type == nn::hac::nca::HashType::HierarchicalSha256)
{ {
auto hash_hdr = info.hierarchicalsha256_hdr; auto hash_hdr = info.hierarchicalsha256_hdr;
fmt::print(" HierarchicalSha256 Header:\n"); fmt::print(" HierarchicalSha256 Header:\n");
@ -588,7 +513,7 @@ void nstool::NcaProcess::displayHeader()
void nstool::NcaProcess::processPartitions() void nstool::NcaProcess::processPartitions()
{ {
std::vector<pie::hac::CombinedFsSnapshotGenerator::MountPointInfo> mount_points; std::vector<nn::hac::CombinedFsMetaGenerator::MountPointInfo> mount_points;
for (size_t i = 0; i < mHdr.getPartitionEntryList().size(); i++) for (size_t i = 0; i < mHdr.getPartitionEntryList().size(); i++)
{ {
@ -609,9 +534,9 @@ void nstool::NcaProcess::processPartitions()
std::string mount_point_name; std::string mount_point_name;
/* /*
if (mHdr.getContentType() == pie::hac::nca::ContentType_Program) if (mHdr.getContentType() == nn::hac::nca::ContentType::Program)
{ {
mount_point_name = pie::hac::ContentArchiveUtil::getProgramContentParititionIndexAsString((pie::hac::nca::ProgramContentPartitionIndex)index); mount_point_name = nn::hac::ContentArchiveUtil::getProgramContentParititionIndexAsString((nn::hac::nca::ProgramContentPartitionIndex)index);
} }
else else
*/ */
@ -619,12 +544,12 @@ void nstool::NcaProcess::processPartitions()
mount_point_name = fmt::format("{:d}", index); mount_point_name = fmt::format("{:d}", index);
} }
mount_points.push_back( { mount_point_name, partition.fs_snapshot } ); mount_points.push_back( { mount_point_name, partition.fs_meta } );
} }
tc::io::VirtualFileSystem::FileSystemSnapshot fs_snapshot = pie::hac::CombinedFsSnapshotGenerator(mount_points); tc::io::VirtualFileSystem::FileSystemMeta fs_meta = nn::hac::CombinedFsMetaGenerator(mount_points);
std::shared_ptr<tc::io::IFileSystem> nca_fs = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(fs_snapshot)); std::shared_ptr<tc::io::IStorage> nca_fs = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(fs_meta));
mFsProcess.setInputFileSystem(nca_fs); mFsProcess.setInputFileSystem(nca_fs);
mFsProcess.setFsFormatName("ContentArchive"); mFsProcess.setFsFormatName("ContentArchive");
@ -632,28 +557,28 @@ void nstool::NcaProcess::processPartitions()
mFsProcess.process(); mFsProcess.process();
} }
std::string nstool::NcaProcess::getContentTypeForMountStr(pie::hac::nca::ContentType cont_type) const std::string nstool::NcaProcess::getContentTypeForMountStr(nn::hac::nca::ContentType cont_type) const
{ {
std::string str; std::string str;
switch (cont_type) switch (cont_type)
{ {
case (pie::hac::nca::ContentType_Program): case (nn::hac::nca::ContentType::Program):
str = "program"; str = "program";
break; break;
case (pie::hac::nca::ContentType_Meta): case (nn::hac::nca::ContentType::Meta):
str = "meta"; str = "meta";
break; break;
case (pie::hac::nca::ContentType_Control): case (nn::hac::nca::ContentType::Control):
str = "control"; str = "control";
break; break;
case (pie::hac::nca::ContentType_Manual): case (nn::hac::nca::ContentType::Manual):
str = "manual"; str = "manual";
break; break;
case (pie::hac::nca::ContentType_Data): case (nn::hac::nca::ContentType::Data):
str = "data"; str = "data";
break; break;
case (pie::hac::nca::ContentType_PublicData): case (nn::hac::nca::ContentType::PublicData):
str = "publicdata"; str = "publicdata";
break; break;
default: default:

View file

@ -3,9 +3,9 @@
#include "KeyBag.h" #include "KeyBag.h"
#include "FsProcess.h" #include "FsProcess.h"
#include <pietendo/hac/ContentArchiveHeader.h> #include <nn/hac/ContentArchiveHeader.h>
#include <pietendo/hac/HierarchicalIntegrityHeader.h> #include <nn/hac/HierarchicalIntegrityHeader.h>
#include <pietendo/hac/HierarchicalSha256Header.h> #include <nn/hac/HierarchicalSha256Header.h>
namespace nstool { namespace nstool {
@ -21,8 +21,6 @@ public:
void setKeyCfg(const KeyBag& keycfg); void setKeyCfg(const KeyBag& keycfg);
void setCliOutputMode(CliOutputMode type); void setCliOutputMode(CliOutputMode type);
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
void setBaseNcaPath(const tc::Optional<tc::io::Path>& nca_path);
// fs specific // fs specific
void setShowFsTree(bool show_fs_tree); void setShowFsTree(bool show_fs_tree);
@ -30,7 +28,7 @@ public:
void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs); void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);
// post process() get FS out // post process() get FS out
const std::shared_ptr<tc::io::IFileSystem>& getFileSystem() const; const std::shared_ptr<tc::io::IStorage>& getFileSystem() const;
private: private:
const std::string kNpdmExefsPath = "/main.npdm"; const std::string kNpdmExefsPath = "/main.npdm";
@ -41,16 +39,15 @@ private:
KeyBag mKeyCfg; KeyBag mKeyCfg;
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
tc::Optional<tc::io::Path> mBaseNcaPath;
// fs processing // fs processing
std::shared_ptr<tc::io::IFileSystem> mFileSystem; std::shared_ptr<tc::io::IStorage> mFileSystem;
FsProcess mFsProcess; FsProcess mFsProcess;
// nca data // nca data
pie::hac::sContentArchiveHeaderBlock mHdrBlock; nn::hac::sContentArchiveHeaderBlock mHdrBlock;
pie::hac::detail::sha256_hash_t mHdrHash; nn::hac::detail::sha256_hash_t mHdrHash;
pie::hac::ContentArchiveHeader mHdr; nn::hac::ContentArchiveHeader mHdr;
// crypto // crypto
struct sKeys struct sKeys
@ -85,7 +82,7 @@ private:
}; };
std::vector<sKeyAreaKey> kak_list; std::vector<sKeyAreaKey> kak_list;
tc::Optional<pie::hac::detail::aes128_key_t> aes_ctr; tc::Optional<nn::hac::detail::aes128_key_t> aes_ctr;
} mContentKey; } mContentKey;
struct SparseInfo struct SparseInfo
@ -96,33 +93,30 @@ private:
// raw partition data // raw partition data
struct sPartitionInfo struct sPartitionInfo
{ {
std::shared_ptr<tc::io::IStream> raw_reader; // raw unprocessed partition stream std::shared_ptr<tc::io::IStream> reader;
std::shared_ptr<tc::io::IStream> decrypt_reader; // partition stream with transparent decryption tc::io::VirtualFileSystem::FileSystemMeta fs_meta;
std::shared_ptr<tc::io::IStream> reader; // partition stream with transparent decryption & hash layer processing std::shared_ptr<tc::io::IStorage> fs_reader;
tc::io::VirtualFileSystem::FileSystemSnapshot fs_snapshot;
std::shared_ptr<tc::io::IFileSystem> fs_reader;
std::string fail_reason; std::string fail_reason;
int64_t offset; int64_t offset;
int64_t size; int64_t size;
// meta data // meta data
pie::hac::nca::FormatType format_type; nn::hac::nca::FormatType format_type;
pie::hac::nca::HashType hash_type; nn::hac::nca::HashType hash_type;
pie::hac::nca::EncryptionType enc_type; nn::hac::nca::EncryptionType enc_type;
pie::hac::nca::MetaDataHashType metadata_hash_type;
// hash meta data // hash meta data
pie::hac::HierarchicalIntegrityHeader hierarchicalintegrity_hdr; nn::hac::HierarchicalIntegrityHeader hierarchicalintegrity_hdr;
pie::hac::HierarchicalSha256Header hierarchicalsha256_hdr; nn::hac::HierarchicalSha256Header hierarchicalsha256_hdr;
// crypto metadata // crypto metadata
pie::hac::detail::aes_iv_t aes_ctr; nn::hac::detail::aes_iv_t aes_ctr;
// sparse metadata // sparse metadata
SparseInfo sparse_info; SparseInfo sparse_info;
}; };
std::array<sPartitionInfo, pie::hac::nca::kPartitionNum> mPartitions; std::array<sPartitionInfo, nn::hac::nca::kPartitionNum> mPartitions;
void importHeader(); void importHeader();
void generateNcaBodyEncryptionKeys(); void generateNcaBodyEncryptionKeys();
@ -131,9 +125,7 @@ private:
void displayHeader(); void displayHeader();
void processPartitions(); void processPartitions();
NcaProcess readBaseNCA(); std::string getContentTypeForMountStr(nn::hac::nca::ContentType cont_type) const;
std::string getContentTypeForMountStr(pie::hac::nca::ContentType cont_type) const;
}; };
} }

View file

@ -1,5 +1,7 @@
#include "NroProcess.h" #include "NroProcess.h"
#include <nn/hac/define/nro-hb.h>
nstool::NroProcess::NroProcess() : nstool::NroProcess::NroProcess() :
mModuleName("nstool::NroProcess"), mModuleName("nstool::NroProcess"),
mFile(), mFile(),
@ -89,13 +91,13 @@ void nstool::NroProcess::importHeader()
} }
// check if file_size is smaller than NRO header size // check if file_size is smaller than NRO header size
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(pie::hac::sNroHeader)) if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sNroHeader))
{ {
throw tc::Exception(mModuleName, "Corrupt NRO: file too small."); throw tc::Exception(mModuleName, "Corrupt NRO: file too small.");
} }
// read nro // read nro
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sNroHeader)); tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sNroHeader));
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
@ -103,10 +105,10 @@ void nstool::NroProcess::importHeader()
mHdr.fromBytes(scratch.data(), scratch.size()); mHdr.fromBytes(scratch.data(), scratch.size());
// setup homebrew extension // setup homebrew extension
pie::hac::sNroHeader* raw_hdr = (pie::hac::sNroHeader*)scratch.data(); nn::hac::sNroHeader* raw_hdr = (nn::hac::sNroHeader*)scratch.data();
int64_t file_size = mFile->length(); int64_t file_size = mFile->length();
if (((tc::bn::le64<uint64_t>*)raw_hdr->reserved_0.data())->unwrap() == pie::hac::nro::kNroHomebrewStructMagic && file_size > int64_t(mHdr.getNroSize())) if (((tc::bn::le64<uint64_t>*)raw_hdr->reserved_0.data())->unwrap() == nn::hac::nro::kNroHomebrewStructMagic && file_size > int64_t(mHdr.getNroSize()))
{ {
mIsHomebrewNro = true; mIsHomebrewNro = true;
mAssetProc.setInputFile(std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, int64_t(mHdr.getNroSize()), file_size - int64_t(mHdr.getNroSize())))); mAssetProc.setInputFile(std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, int64_t(mHdr.getNroSize()), file_size - int64_t(mHdr.getNroSize()))));

View file

@ -3,7 +3,7 @@
#include "RoMetadataProcess.h" #include "RoMetadataProcess.h"
#include "AssetProcess.h" #include "AssetProcess.h"
#include <pietendo/hac/NroHeader.h> #include <nn/hac/NroHeader.h>
namespace nstool { namespace nstool {
@ -36,7 +36,7 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
pie::hac::NroHeader mHdr; nn::hac::NroHeader mHdr;
tc::ByteData mTextBlob, mRoBlob, mDataBlob; tc::ByteData mTextBlob, mRoBlob, mDataBlob;
nstool::RoMetadataProcess mRoMeta; nstool::RoMetadataProcess mRoMeta;
bool mIsHomebrewNro; bool mIsHomebrewNro;

View file

@ -71,13 +71,13 @@ void nstool::NsoProcess::importHeader()
// check if file_size is smaller than NSO header size // check if file_size is smaller than NSO header size
size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length()); size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
if (file_size < sizeof(pie::hac::sNsoHeader)) if (file_size < sizeof(nn::hac::sNsoHeader))
{ {
throw tc::Exception(mModuleName, "Corrupt NSO: file too small."); throw tc::Exception(mModuleName, "Corrupt NSO: file too small.");
} }
// read nso // read nso
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sNsoHeader)); tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sNsoHeader));
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
@ -88,7 +88,7 @@ void nstool::NsoProcess::importHeader()
void nstool::NsoProcess::importCodeSegments() void nstool::NsoProcess::importCodeSegments()
{ {
tc::ByteData scratch; tc::ByteData scratch;
pie::hac::detail::sha256_hash_t calc_hash; nn::hac::detail::sha256_hash_t calc_hash;
// process text segment // process text segment
if (mHdr.getTextSegmentInfo().is_compressed) if (mHdr.getTextSegmentInfo().is_compressed)
@ -116,7 +116,7 @@ void nstool::NsoProcess::importCodeSegments()
} }
if (mHdr.getTextSegmentInfo().is_hashed) if (mHdr.getTextSegmentInfo().is_hashed)
{ {
tc::crypto::GenerateSha2256Hash(calc_hash.data(), mTextBlob.data(), mTextBlob.size()); tc::crypto::GenerateSha256Hash(calc_hash.data(), mTextBlob.data(), mTextBlob.size());
if (calc_hash != mHdr.getTextSegmentInfo().hash) if (calc_hash != mHdr.getTextSegmentInfo().hash)
{ {
throw tc::Exception(mModuleName, "NSO text segment failed SHA256 verification"); throw tc::Exception(mModuleName, "NSO text segment failed SHA256 verification");
@ -149,7 +149,7 @@ void nstool::NsoProcess::importCodeSegments()
} }
if (mHdr.getRoSegmentInfo().is_hashed) if (mHdr.getRoSegmentInfo().is_hashed)
{ {
tc::crypto::GenerateSha2256Hash(calc_hash.data(), mRoBlob.data(), mRoBlob.size()); tc::crypto::GenerateSha256Hash(calc_hash.data(), mRoBlob.data(), mRoBlob.size());
if (calc_hash != mHdr.getRoSegmentInfo().hash) if (calc_hash != mHdr.getRoSegmentInfo().hash)
{ {
throw tc::Exception(mModuleName, "NSO ro segment failed SHA256 verification"); throw tc::Exception(mModuleName, "NSO ro segment failed SHA256 verification");
@ -182,7 +182,7 @@ void nstool::NsoProcess::importCodeSegments()
} }
if (mHdr.getDataSegmentInfo().is_hashed) if (mHdr.getDataSegmentInfo().is_hashed)
{ {
tc::crypto::GenerateSha2256Hash(calc_hash.data(), mDataBlob.data(), mDataBlob.size()); tc::crypto::GenerateSha256Hash(calc_hash.data(), mDataBlob.data(), mDataBlob.size());
if (calc_hash != mHdr.getDataSegmentInfo().hash) if (calc_hash != mHdr.getDataSegmentInfo().hash)
{ {
throw tc::Exception(mModuleName, "NSO data segment failed SHA256 verification"); throw tc::Exception(mModuleName, "NSO data segment failed SHA256 verification");

View file

@ -2,8 +2,8 @@
#include "types.h" #include "types.h"
#include "RoMetadataProcess.h" #include "RoMetadataProcess.h"
#include <pietendo/hac/define/meta.h> #include <nn/hac/define/meta.h>
#include <pietendo/hac/NsoHeader.h> #include <nn/hac/NsoHeader.h>
namespace nstool { namespace nstool {
@ -33,7 +33,7 @@ private:
bool mListApi; bool mListApi;
bool mListSymbols; bool mListSymbols;
pie::hac::NsoHeader mHdr; nn::hac::NsoHeader mHdr;
tc::ByteData mTextBlob, mRoBlob, mDataBlob; tc::ByteData mTextBlob, mRoBlob, mDataBlob;
nstool::RoMetadataProcess mRoMeta; nstool::RoMetadataProcess mRoMeta;

View file

@ -1,11 +1,11 @@
#include "PfsProcess.h" #include "PfsProcess.h"
#include "util.h" #include "util.h"
#include <pietendo/hac/PartitionFsUtil.h> #include <nn/hac/PartitionFsUtil.h>
#include <tc/io/LocalFileSystem.h> #include <tc/io/LocalStorage.h>
#include <tc/io/VirtualFileSystem.h> #include <tc/io/VirtualFileSystem.h>
#include <pietendo/hac/PartitionFsSnapshotGenerator.h> #include <nn/hac/PartitionFsMetaGenerator.h>
nstool::PfsProcess::PfsProcess() : nstool::PfsProcess::PfsProcess() :
@ -34,21 +34,21 @@ void nstool::PfsProcess::process()
tc::ByteData scratch; tc::ByteData scratch;
// read base header to determine complete header size // read base header to determine complete header size
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sPfsHeader))) if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sPfsHeader)))
{ {
throw tc::Exception(mModuleName, "Corrupt PartitionFs: File too small"); throw tc::Exception(mModuleName, "Corrupt PartitionFs: File too small");
} }
scratch = tc::ByteData(sizeof(pie::hac::sPfsHeader)); scratch = tc::ByteData(sizeof(nn::hac::sPfsHeader));
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size()); mFile->read(scratch.data(), scratch.size());
if (validateHeaderMagic(((pie::hac::sPfsHeader*)scratch.data())) == false) if (validateHeaderMagic(((nn::hac::sPfsHeader*)scratch.data())) == false)
{ {
throw tc::Exception(mModuleName, "Corrupt PartitionFs: Header had incorrect struct magic."); throw tc::Exception(mModuleName, "Corrupt PartitionFs: Header had incorrect struct magic.");
} }
// read complete size header // read complete size header
size_t pfsHeaderSize = determineHeaderSize(((pie::hac::sPfsHeader*)scratch.data())); size_t pfsHeaderSize = determineHeaderSize(((nn::hac::sPfsHeader*)scratch.data()));
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(pfsHeaderSize)) if (mFile->length() < tc::io::IOUtil::castSizeToInt64(pfsHeaderSize))
{ {
throw tc::Exception(mModuleName, "Corrupt PartitionFs: File too small"); throw tc::Exception(mModuleName, "Corrupt PartitionFs: File too small");
@ -62,12 +62,12 @@ void nstool::PfsProcess::process()
mPfs.fromBytes(scratch.data(), scratch.size()); mPfs.fromBytes(scratch.data(), scratch.size());
// create virtual filesystem // create virtual filesystem
mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(pie::hac::PartitionFsSnapshotGenerator(mFile, mVerify ? pie::hac::PartitionFsSnapshotGenerator::ValidationMode_Warn : pie::hac::PartitionFsSnapshotGenerator::ValidationMode_None))); mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(nn::hac::PartitionFsMetaGenerator(mFile, mVerify ? nn::hac::PartitionFsMetaGenerator::ValidationMode_Warn : nn::hac::PartitionFsMetaGenerator::ValidationMode_None)));
mFsProcess.setInputFileSystem(mFileSystem); mFsProcess.setInputFileSystem(mFileSystem);
// set properties for FsProcess // set properties for FsProcess
mFsProcess.setFsProperties({ mFsProcess.setFsProperties({
fmt::format("Type: {:s}", pie::hac::PartitionFsUtil::getFsTypeAsString(mPfs.getFsType())), fmt::format("Type: {:s}", nn::hac::PartitionFsUtil::getFsTypeAsString(mPfs.getFsType())),
fmt::format("FileNum: {:d}", mPfs.getFileList().size()) fmt::format("FileNum: {:d}", mPfs.getFileList().size())
}); });
@ -105,28 +105,28 @@ void nstool::PfsProcess::setExtractJobs(const std::vector<nstool::ExtractJob>& e
mFsProcess.setExtractJobs(extract_jobs); mFsProcess.setExtractJobs(extract_jobs);
} }
const pie::hac::PartitionFsHeader& nstool::PfsProcess::getPfsHeader() const const nn::hac::PartitionFsHeader& nstool::PfsProcess::getPfsHeader() const
{ {
return mPfs; return mPfs;
} }
const std::shared_ptr<tc::io::IFileSystem>& nstool::PfsProcess::getFileSystem() const const std::shared_ptr<tc::io::IStorage>& nstool::PfsProcess::getFileSystem() const
{ {
return mFileSystem; return mFileSystem;
} }
size_t nstool::PfsProcess::determineHeaderSize(const pie::hac::sPfsHeader* hdr) size_t nstool::PfsProcess::determineHeaderSize(const nn::hac::sPfsHeader* hdr)
{ {
size_t fileEntrySize = 0; size_t fileEntrySize = 0;
if (hdr->st_magic.unwrap() == pie::hac::pfs::kPfsStructMagic) if (hdr->st_magic.unwrap() == nn::hac::pfs::kPfsStructMagic)
fileEntrySize = sizeof(pie::hac::sPfsFile); fileEntrySize = sizeof(nn::hac::sPfsFile);
else else
fileEntrySize = sizeof(pie::hac::sHashedPfsFile); fileEntrySize = sizeof(nn::hac::sHashedPfsFile);
return sizeof(pie::hac::sPfsHeader) + hdr->file_num.unwrap() * fileEntrySize + hdr->name_table_size.unwrap(); return sizeof(nn::hac::sPfsHeader) + hdr->file_num.unwrap() * fileEntrySize + hdr->name_table_size.unwrap();
} }
bool nstool::PfsProcess::validateHeaderMagic(const pie::hac::sPfsHeader* hdr) bool nstool::PfsProcess::validateHeaderMagic(const nn::hac::sPfsHeader* hdr)
{ {
return hdr->st_magic.unwrap() == pie::hac::pfs::kPfsStructMagic || hdr->st_magic.unwrap() == pie::hac::pfs::kHashedPfsStructMagic; return hdr->st_magic.unwrap() == nn::hac::pfs::kPfsStructMagic || hdr->st_magic.unwrap() == nn::hac::pfs::kHashedPfsStructMagic;
} }

View file

@ -2,7 +2,7 @@
#include "types.h" #include "types.h"
#include "FsProcess.h" #include "FsProcess.h"
#include <pietendo/hac/PartitionFsHeader.h> #include <nn/hac/PartitionFsHeader.h>
namespace nstool { namespace nstool {
@ -24,8 +24,8 @@ public:
void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs); void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);
// post process() get PFS/FS out // post process() get PFS/FS out
const pie::hac::PartitionFsHeader& getPfsHeader() const; const nn::hac::PartitionFsHeader& getPfsHeader() const;
const std::shared_ptr<tc::io::IFileSystem>& getFileSystem() const; const std::shared_ptr<tc::io::IStorage>& getFileSystem() const;
private: private:
static const size_t kCacheSize = 0x10000; static const size_t kCacheSize = 0x10000;
@ -36,13 +36,13 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
pie::hac::PartitionFsHeader mPfs; nn::hac::PartitionFsHeader mPfs;
std::shared_ptr<tc::io::IFileSystem> mFileSystem; std::shared_ptr<tc::io::IStorage> mFileSystem;
FsProcess mFsProcess; FsProcess mFsProcess;
size_t determineHeaderSize(const pie::hac::sPfsHeader* hdr); size_t determineHeaderSize(const nn::hac::sPfsHeader* hdr);
bool validateHeaderMagic(const pie::hac::sPfsHeader* hdr); bool validateHeaderMagic(const nn::hac::sPfsHeader* hdr);
}; };
} }

View file

@ -1,8 +1,8 @@
#include "PkiValidator.h" #include "PkiValidator.h"
#include <tc/crypto.h> #include <tc/crypto.h>
#include <pietendo/hac/define/types.h> #include <nn/hac/define/types.h>
#include <pietendo/hac/es/SignUtils.h> #include <nn/pki/SignUtils.h>
nstool::PkiValidator::PkiValidator() : nstool::PkiValidator::PkiValidator() :
mModuleName("nstool::PkiValidator") mModuleName("nstool::PkiValidator")
@ -13,7 +13,7 @@ nstool::PkiValidator::PkiValidator() :
void nstool::PkiValidator::setKeyCfg(const KeyBag& keycfg) void nstool::PkiValidator::setKeyCfg(const KeyBag& keycfg)
{ {
// save a copy of the certificate bank // save a copy of the certificate bank
std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>> old_certs = mCertificateBank; std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> old_certs = mCertificateBank;
// clear the certificate bank // clear the certificate bank
mCertificateBank.clear(); mCertificateBank.clear();
@ -28,7 +28,7 @@ void nstool::PkiValidator::setKeyCfg(const KeyBag& keycfg)
} }
} }
void nstool::PkiValidator::addCertificates(const std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>>& certs) void nstool::PkiValidator::addCertificates(const std::vector<nn::pki::SignedData<nn::pki::CertificateBody>>& certs)
{ {
for (size_t i = 0; i < certs.size(); i++) for (size_t i = 0; i < certs.size(); i++)
{ {
@ -36,10 +36,11 @@ void nstool::PkiValidator::addCertificates(const std::vector<pie::hac::es::Signe
} }
} }
void nstool::PkiValidator::addCertificate(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert) void nstool::PkiValidator::addCertificate(const nn::pki::SignedData<nn::pki::CertificateBody>& cert)
{ {
std::string cert_ident; std::string cert_ident;
pie::hac::es::sign::HashAlgo cert_hash_algo; nn::pki::sign::SignatureAlgo cert_sign_algo;
nn::pki::sign::HashAlgo cert_hash_algo;
tc::ByteData cert_hash; tc::ByteData cert_hash;
try try
@ -51,19 +52,20 @@ void nstool::PkiValidator::addCertificate(const pie::hac::es::SignedData<pie::ha
throw tc::Exception(mModuleName, "Certificate already exists"); throw tc::Exception(mModuleName, "Certificate already exists");
} }
cert_hash_algo = pie::hac::es::sign::getHashAlgo(cert.getSignature().getSignType()); cert_sign_algo = nn::pki::sign::getSignatureAlgo(cert.getSignature().getSignType());
cert_hash_algo = nn::pki::sign::getHashAlgo(cert.getSignature().getSignType());
// get cert hash // get cert hash
switch (cert_hash_algo) switch (cert_hash_algo)
{ {
case (pie::hac::es::sign::HASH_ALGO_SHA1): case (nn::pki::sign::HASH_ALGO_SHA1):
cert_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize); cert_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize);
tc::crypto::GenerateSha1Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size()); tc::crypto::GenerateSha1Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size());
break; break;
case (pie::hac::es::sign::HASH_ALGO_SHA256): case (nn::pki::sign::HASH_ALGO_SHA256):
cert_hash = tc::ByteData(tc::crypto::Sha2256Generator::kHashSize); cert_hash = tc::ByteData(tc::crypto::Sha256Generator::kHashSize);
tc::crypto::GenerateSha2256Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size()); tc::crypto::GenerateSha256Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size());
break; break;
default: default:
throw tc::Exception(mModuleName, "Unrecognised hash type"); throw tc::Exception(mModuleName, "Unrecognised hash type");
@ -84,9 +86,9 @@ void nstool::PkiValidator::clearCertificates()
mCertificateBank.clear(); mCertificateBank.clear();
} }
void nstool::PkiValidator::validateSignature(const std::string& issuer, pie::hac::es::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const
{ {
pie::hac::es::sign::SignatureAlgo sign_algo = pie::hac::es::sign::getSignatureAlgo(signature_id); nn::pki::sign::SignatureAlgo sign_algo = nn::pki::sign::getSignatureAlgo(signature_id);
// validate signature // validate signature
bool sig_valid = false; bool sig_valid = false;
@ -110,7 +112,7 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, pie::hac
throw tc::Exception(mModuleName, fmt::format("Public key for issuer \"{:s}\" cannot verify this signature.", issuer)); throw tc::Exception(mModuleName, fmt::format("Public key for issuer \"{:s}\" cannot verify this signature.", issuer));
} }
if (sign_algo == pie::hac::es::sign::SIGN_ALGO_ECDSA240) if (sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
{ {
throw tc::Exception(mModuleName, "ECDSA signatures are not supported"); throw tc::Exception(mModuleName, "ECDSA signatures are not supported");
} }
@ -120,18 +122,18 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, pie::hac
else else
{ {
// try to find issuer cert // try to find issuer cert
const pie::hac::es::CertificateBody& issuer_cert = getCert(issuer).getBody(); const nn::pki::CertificateBody& issuer_cert = getCert(issuer).getBody();
pie::hac::es::cert::PublicKeyType issuer_pubk_type = issuer_cert.getPublicKeyType(); nn::pki::cert::PublicKeyType issuer_pubk_type = issuer_cert.getPublicKeyType();
if (issuer_pubk_type == pie::hac::es::cert::RSA4096 && sign_algo == pie::hac::es::sign::SIGN_ALGO_RSA4096) if (issuer_pubk_type == nn::pki::cert::RSA4096 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096)
{ {
rsa_key = issuer_cert.getRsa4096PublicKey(); rsa_key = issuer_cert.getRsa4096PublicKey();
} }
else if (issuer_pubk_type == pie::hac::es::cert::RSA2048 && sign_algo == pie::hac::es::sign::SIGN_ALGO_RSA2048) else if (issuer_pubk_type == nn::pki::cert::RSA2048 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048)
{ {
rsa_key = issuer_cert.getRsa2048PublicKey(); rsa_key = issuer_cert.getRsa2048PublicKey();
} }
else if (issuer_pubk_type == pie::hac::es::cert::ECDSA240 && sign_algo == pie::hac::es::sign::SIGN_ALGO_ECDSA240) else if (issuer_pubk_type == nn::pki::cert::ECDSA240 && sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
{ {
// ecc_key = issuer_cert.getEcdsa240PublicKey(); // ecc_key = issuer_cert.getEcdsa240PublicKey();
throw tc::Exception(mModuleName, "ECDSA signatures are not supported"); throw tc::Exception(mModuleName, "ECDSA signatures are not supported");
@ -144,22 +146,22 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, pie::hac
// verify signature // verify signature
switch (signature_id) { switch (signature_id) {
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA1): case (nn::pki::sign::SIGN_ID_RSA4096_SHA1):
sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha1(signature.data(), hash.data(), rsa_key); sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha1(signature.data(), hash.data(), rsa_key);
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA1): case (nn::pki::sign::SIGN_ID_RSA2048_SHA1):
sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha1(signature.data(), hash.data(), rsa_key); sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha1(signature.data(), hash.data(), rsa_key);
break; break;
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA1): case (nn::pki::sign::SIGN_ID_ECDSA240_SHA1):
sig_valid = false; sig_valid = false;
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA256): case (nn::pki::sign::SIGN_ID_RSA4096_SHA256):
sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha2256(signature.data(), hash.data(), rsa_key); sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha256(signature.data(), hash.data(), rsa_key);
break; break;
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA256): case (nn::pki::sign::SIGN_ID_RSA2048_SHA256):
sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha2256(signature.data(), hash.data(), rsa_key); sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha256(signature.data(), hash.data(), rsa_key);
break; break;
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA256): case (nn::pki::sign::SIGN_ID_ECDSA240_SHA256):
sig_valid = false; sig_valid = false;
break; break;
} }
@ -172,14 +174,14 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, pie::hac
} }
void nstool::PkiValidator::makeCertIdent(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert, std::string& ident) const void nstool::PkiValidator::makeCertIdent(const nn::pki::SignedData<nn::pki::CertificateBody>& cert, std::string& ident) const
{ {
makeCertIdent(cert.getBody().getIssuer(), cert.getBody().getSubject(), ident); makeCertIdent(cert.getBody().getIssuer(), cert.getBody().getSubject(), ident);
} }
void nstool::PkiValidator::makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const void nstool::PkiValidator::makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const
{ {
ident = issuer + pie::hac::es::sign::kIdentDelimiter + subject; ident = issuer + nn::pki::sign::kIdentDelimiter + subject;
ident = ident.substr(0, std::min<size_t>(ident.length(),64)); ident = ident.substr(0, std::min<size_t>(ident.length(),64));
} }
@ -200,7 +202,7 @@ bool nstool::PkiValidator::doesCertExist(const std::string& ident) const
return exists; return exists;
} }
const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& nstool::PkiValidator::getCert(const std::string& ident) const const nn::pki::SignedData<nn::pki::CertificateBody>& nstool::PkiValidator::getCert(const std::string& ident) const
{ {
std::string full_cert_name; std::string full_cert_name;
for (size_t i = 0; i < mCertificateBank.size(); i++) for (size_t i = 0; i < mCertificateBank.size(); i++)

View file

@ -2,8 +2,8 @@
#include "types.h" #include "types.h"
#include "KeyBag.h" #include "KeyBag.h"
#include <pietendo/hac/es/SignedData.h> #include <nn/pki/SignedData.h>
#include <pietendo/hac/es/CertificateBody.h> #include <nn/pki/CertificateBody.h>
namespace nstool { namespace nstool {
@ -13,22 +13,22 @@ public:
PkiValidator(); PkiValidator();
void setKeyCfg(const KeyBag& keycfg); void setKeyCfg(const KeyBag& keycfg);
void addCertificates(const std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>>& certs); void addCertificates(const std::vector<nn::pki::SignedData<nn::pki::CertificateBody>>& certs);
void addCertificate(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert); void addCertificate(const nn::pki::SignedData<nn::pki::CertificateBody>& cert);
void clearCertificates(); void clearCertificates();
void validateSignature(const std::string& issuer, pie::hac::es::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const; void validateSignature(const std::string& issuer, nn::pki::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const;
private: private:
std::string mModuleName; std::string mModuleName;
KeyBag mKeyCfg; KeyBag mKeyCfg;
std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>> mCertificateBank; std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> mCertificateBank;
void makeCertIdent(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert, std::string& ident) const; void makeCertIdent(const nn::pki::SignedData<nn::pki::CertificateBody>& cert, std::string& ident) const;
void makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const; void makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const;
bool doesCertExist(const std::string& ident) const; bool doesCertExist(const std::string& ident) const;
const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& getCert(const std::string& ident) const; const nn::pki::SignedData<nn::pki::CertificateBody>& getCert(const std::string& ident) const;
}; };
} }

View file

@ -3,7 +3,7 @@
#include "SdkApiString.h" #include "SdkApiString.h"
#include "ElfSymbolParser.h" #include "ElfSymbolParser.h"
#include <pietendo/hac/define/meta.h> #include <nn/hac/define/meta.h>
namespace nstool { namespace nstool {

View file

@ -2,7 +2,7 @@
#include "util.h" #include "util.h"
#include <tc/io/VirtualFileSystem.h> #include <tc/io/VirtualFileSystem.h>
#include <pietendo/hac/RomFsSnapshotGenerator.h> #include <nn/hac/RomFsMetaGenerator.h>
nstool::RomfsProcess::RomfsProcess() : nstool::RomfsProcess::RomfsProcess() :
@ -20,7 +20,6 @@ nstool::RomfsProcess::RomfsProcess() :
void nstool::RomfsProcess::process() void nstool::RomfsProcess::process()
{ {
// state checks
if (mFile == nullptr) if (mFile == nullptr)
{ {
throw tc::Exception(mModuleName, "No file reader set."); throw tc::Exception(mModuleName, "No file reader set.");
@ -30,62 +29,38 @@ void nstool::RomfsProcess::process()
throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions."); throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions.");
} }
tc::ByteData scratch;
// read base header to determine complete header size // read base header to determine complete header size
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sRomfsHeader))) if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sRomfsHeader)))
{ {
throw tc::Exception(mModuleName, "Corrupt RomFs: File too small"); throw tc::Exception(mModuleName, "Corrupt RomFs: File too small");
} }
mFile->seek(0, tc::io::SeekOrigin::Begin); mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read((byte_t*)&mRomfsHeader, sizeof(mRomfsHeader)); mFile->read((byte_t*)&mRomfsHeader, sizeof(mRomfsHeader));
if (mRomfsHeader.header_size.unwrap() != sizeof(pie::hac::sRomfsHeader) || if (mRomfsHeader.header_size.unwrap() != sizeof(nn::hac::sRomfsHeader) ||
mRomfsHeader.dir_entry.offset.unwrap() != (mRomfsHeader.dir_hash_bucket.offset.unwrap() + mRomfsHeader.dir_hash_bucket.size.unwrap()) || mRomfsHeader.dir_entry.offset.unwrap() != (mRomfsHeader.dir_hash_bucket.offset.unwrap() + mRomfsHeader.dir_hash_bucket.size.unwrap()) ||
mRomfsHeader.data_offset.unwrap() != align<int64_t>(mRomfsHeader.header_size.unwrap(), pie::hac::romfs::kRomfsHeaderAlign)) mRomfsHeader.data_offset.unwrap() != align<int64_t>(mRomfsHeader.header_size.unwrap(), nn::hac::romfs::kRomfsHeaderAlign))
{ {
throw tc::ArgumentOutOfRangeException(mModuleName, "Corrupt RomFs: RomFsHeader is corrupted."); throw tc::ArgumentOutOfRangeException(mModuleName, "Corrupt RomFs: RomFsHeader is corrupted.");
} }
/*
fmt::print("RomFsHeader:\n");
fmt::print(" > header_size = 0x{:04x}\n", mRomfsHeader.header_size.unwrap());
fmt::print(" > dir_hash_bucket\n");
fmt::print(" > offset = 0x{:04x}\n", mRomfsHeader.dir_hash_bucket.offset.unwrap());
fmt::print(" > size = 0x{:04x}\n", mRomfsHeader.dir_hash_bucket.size.unwrap());
fmt::print(" > dir_entry\n");
fmt::print(" > offset = 0x{:04x}\n", mRomfsHeader.dir_entry.offset.unwrap());
fmt::print(" > size = 0x{:04x}\n", mRomfsHeader.dir_entry.size.unwrap());
fmt::print(" > file_hash_bucket\n");
fmt::print(" > offset = 0x{:04x}\n", mRomfsHeader.file_hash_bucket.offset.unwrap())
fmt::print(" > size = 0x{:04x}\n", mRomfsHeader.file_hash_bucket.size.unwrap());
fmt::print(" > file_entry\n");
fmt::print(" > offset = 0x{:04x}\n", mRomfsHeader.file_entry.offset.unwrap());
fmt::print(" > size = 0x{:04x}\n", mRomfsHeader.file_entry.size.unwrap());
fmt::print(" > data_offset = 0x{:04x}\n", mRomfsHeader.data_offset.unwrap());
*/
// get dir entry ptr // get dir entry ptr
tc::ByteData dir_entry_table = tc::ByteData(); tc::ByteData dir_entry_table = tc::ByteData(tc::io::IOUtil::castInt64ToSize(mRomfsHeader.dir_entry.size.unwrap()));
if (mRomfsHeader.dir_entry.size.unwrap() > 0) mFile->seek(mRomfsHeader.dir_entry.offset.unwrap(), tc::io::SeekOrigin::Begin);
{ mFile->read(dir_entry_table.data(), dir_entry_table.size());
dir_entry_table = tc::ByteData(tc::io::IOUtil::castInt64ToSize(mRomfsHeader.dir_entry.size.unwrap()));
mFile->seek(mRomfsHeader.dir_entry.offset.unwrap(), tc::io::SeekOrigin::Begin);
mFile->read(dir_entry_table.data(), dir_entry_table.size());
}
// get file entry ptr // get file entry ptr
tc::ByteData file_entry_table = tc::ByteData(); tc::ByteData file_entry_table = tc::ByteData(tc::io::IOUtil::castInt64ToSize(mRomfsHeader.file_entry.size.unwrap()));
if (mRomfsHeader.file_entry.size.unwrap() > 0) mFile->seek(mRomfsHeader.file_entry.offset.unwrap(), tc::io::SeekOrigin::Begin);
{ mFile->read(file_entry_table.data(), file_entry_table.size());
file_entry_table = tc::ByteData(tc::io::IOUtil::castInt64ToSize(mRomfsHeader.file_entry.size.unwrap()));
mFile->seek(mRomfsHeader.file_entry.offset.unwrap(), tc::io::SeekOrigin::Begin);
mFile->read(file_entry_table.data(), file_entry_table.size());
}
// count dir num // count dir num
mDirNum = 0; mDirNum = 0;
for (uint32_t v_addr = 0; size_t(v_addr) < dir_entry_table.size();) for (uint32_t v_addr = 0; size_t(v_addr) < dir_entry_table.size();)
{ {
uint32_t total_size = sizeof(pie::hac::sRomfsDirEntry) + align<uint32_t>(((pie::hac::sRomfsDirEntry*)(dir_entry_table.data() + v_addr))->name_size.unwrap(), 4); uint32_t total_size = sizeof(nn::hac::sRomfsDirEntry) + align<uint32_t>(((nn::hac::sRomfsDirEntry*)(dir_entry_table.data() + v_addr))->name_size.unwrap(), 4);
// don't count root directory // don't count root directory
if (v_addr != 0) if (v_addr != 0)
@ -100,7 +75,7 @@ void nstool::RomfsProcess::process()
mFileNum = 0; mFileNum = 0;
for (uint32_t v_addr = 0; size_t(v_addr) < file_entry_table.size();) for (uint32_t v_addr = 0; size_t(v_addr) < file_entry_table.size();)
{ {
uint32_t total_size = sizeof(pie::hac::sRomfsFileEntry) + align<uint32_t>(((pie::hac::sRomfsFileEntry*)(file_entry_table.data() + v_addr))->name_size.unwrap(), 4); uint32_t total_size = sizeof(nn::hac::sRomfsFileEntry) + align<uint32_t>(((nn::hac::sRomfsFileEntry*)(file_entry_table.data() + v_addr))->name_size.unwrap(), 4);
mFileNum += 1; mFileNum += 1;
@ -108,7 +83,7 @@ void nstool::RomfsProcess::process()
} }
// create virtual filesystem // create virtual filesystem
mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(pie::hac::RomFsSnapshotGenerator(mFile))); mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(nn::hac::RomFsMetaGenerator(mFile)));
mFsProcess.setInputFileSystem(mFileSystem); mFsProcess.setInputFileSystem(mFileSystem);
// set properties for FsProcess // set properties for FsProcess

View file

@ -2,7 +2,7 @@
#include "types.h" #include "types.h"
#include "FsProcess.h" #include "FsProcess.h"
#include <pietendo/hac/define/romfs.h> #include <nn/hac/define/romfs.h>
namespace nstool { namespace nstool {
@ -31,11 +31,11 @@ private:
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
pie::hac::sRomfsHeader mRomfsHeader; nn::hac::sRomfsHeader mRomfsHeader;
size_t mDirNum; size_t mDirNum;
size_t mFileNum; size_t mFileNum;
std::shared_ptr<tc::io::IFileSystem> mFileSystem; std::shared_ptr<tc::io::IStorage> mFileSystem;
FsProcess mFsProcess; FsProcess mFsProcess;
}; };

View file

@ -9,24 +9,27 @@
#include <tc/io/FileStream.h> #include <tc/io/FileStream.h>
#include <tc/io/StreamSource.h> #include <tc/io/StreamSource.h>
#include <pietendo/hac/ContentArchiveUtil.h>
#include <pietendo/hac/AesKeygen.h>
#include <pietendo/hac/define/gc.h> #include <nn/hac/ContentArchiveUtil.h>
#include <pietendo/hac/define/pfs.h> #include <nn/hac/AesKeygen.h>
#include <pietendo/hac/define/nca.h> #include <nn/hac/define/gc.h>
#include <pietendo/hac/define/meta.h> #include <nn/hac/define/pfs.h>
#include <pietendo/hac/define/romfs.h> #include <nn/hac/define/nca.h>
#include <pietendo/hac/define/cnmt.h> #include <nn/hac/define/meta.h>
#include <pietendo/hac/define/nacp.h> #include <nn/hac/define/romfs.h>
#include <pietendo/hac/define/nso.h> #include <nn/hac/define/cnmt.h>
#include <pietendo/hac/define/nro.h> #include <nn/hac/define/nacp.h>
#include <pietendo/hac/define/ini.h> #include <nn/hac/define/nso.h>
#include <pietendo/hac/define/kip.h> #include <nn/hac/define/nro.h>
#include <pietendo/hac/define/aset.h> #include <nn/hac/define/ini.h>
#include <pietendo/hac/es/SignedData.h> #include <nn/hac/define/kip.h>
#include <pietendo/hac/es/CertificateBody.h> #include <nn/hac/define/aset.h>
#include <pietendo/hac/es/SignUtils.h> #include <nn/pki/SignedData.h>
#include <pietendo/hac/es/TicketBody_V2.h> #include <nn/pki/CertificateBody.h>
#include <nn/pki/SignUtils.h>
#include <nn/es/TicketBody_V2.h>
class UnkOptionHandler : public tc::cli::OptionParser::IOptionHandler class UnkOptionHandler : public tc::cli::OptionParser::IOptionHandler
{ {
@ -39,11 +42,6 @@ public:
throw tc::InvalidOperationException("getOptionStrings() not defined for UnkOptionHandler."); throw tc::InvalidOperationException("getOptionStrings() not defined for UnkOptionHandler.");
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
throw tc::InvalidOperationException("getOptionRegexPatterns() not defined for UnkOptionHandler.");
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
throw tc::Exception(mModuleLabel, "Unrecognized option: \"" + option + "\""); throw tc::Exception(mModuleLabel, "Unrecognized option: \"" + option + "\"");
@ -57,8 +55,7 @@ class DeprecatedOptionHandler : public tc::cli::OptionParser::IOptionHandler
public: public:
DeprecatedOptionHandler(const std::string& warn_message, const std::vector<std::string>& opts) : DeprecatedOptionHandler(const std::string& warn_message, const std::vector<std::string>& opts) :
mWarnMessage(warn_message), mWarnMessage(warn_message),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -66,11 +63,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
fmt::print("[WARNING] Option \"{}\" is deprecated.{}{}\n", option, (mWarnMessage.empty() ? "" : " "), mWarnMessage); fmt::print("[WARNING] Option \"{}\" is deprecated.{}{}\n", option, (mWarnMessage.empty() ? "" : " "), mWarnMessage);
@ -78,7 +70,6 @@ public:
private: private:
std::string mWarnMessage; std::string mWarnMessage;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -86,8 +77,7 @@ class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler
public: public:
FlagOptionHandler(bool& flag, const std::vector<std::string>& opts) : FlagOptionHandler(bool& flag, const std::vector<std::string>& opts) :
mFlag(flag), mFlag(flag),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -95,11 +85,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 0) if (params.size() != 0)
@ -112,7 +97,6 @@ public:
private: private:
bool& mFlag; bool& mFlag;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHandler class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -120,8 +104,7 @@ class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHand
public: public:
SingleParamStringOptionHandler(tc::Optional<std::string>& param, const std::vector<std::string>& opts) : SingleParamStringOptionHandler(tc::Optional<std::string>& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -129,11 +112,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -146,7 +124,6 @@ public:
private: private:
tc::Optional<std::string>& mParam; tc::Optional<std::string>& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandler class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -154,8 +131,7 @@ class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandle
public: public:
SingleParamPathOptionHandler(tc::Optional<tc::io::Path>& param, const std::vector<std::string>& opts) : SingleParamPathOptionHandler(tc::Optional<tc::io::Path>& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -163,11 +139,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -180,7 +151,6 @@ public:
private: private:
tc::Optional<tc::io::Path>& mParam; tc::Optional<tc::io::Path>& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandler class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -188,8 +158,7 @@ class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandl
public: public:
SingleParamSizetOptionHandler(size_t& param, const std::vector<std::string>& opts) : SingleParamSizetOptionHandler(size_t& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -197,11 +166,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -214,7 +178,6 @@ public:
private: private:
size_t& mParam; size_t& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class SingleParamAesKeyOptionHandler : public tc::cli::OptionParser::IOptionHandler class SingleParamAesKeyOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -222,8 +185,7 @@ class SingleParamAesKeyOptionHandler : public tc::cli::OptionParser::IOptionHand
public: public:
SingleParamAesKeyOptionHandler(tc::Optional<nstool::KeyBag::aes128_key_t>& param, const std::vector<std::string>& opts) : SingleParamAesKeyOptionHandler(tc::Optional<nstool::KeyBag::aes128_key_t>& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -231,11 +193,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -257,41 +214,6 @@ public:
private: private:
tc::Optional<nstool::KeyBag::aes128_key_t>& mParam; tc::Optional<nstool::KeyBag::aes128_key_t>& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
};
class SingleParamPathArrayOptionHandler : public tc::cli::OptionParser::IOptionHandler
{
public:
SingleParamPathArrayOptionHandler(std::vector<tc::io::Path>& param, const std::vector<std::string>& opts) :
mParam(param),
mOptStrings(opts),
mOptRegex()
{}
const std::vector<std::string>& getOptionStrings() const
{
return mOptStrings;
}
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params)
{
if (params.size() != 1)
{
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires a parameter.", option));
}
mParam.push_back(params[0]);
}
private:
std::vector<tc::io::Path>& mParam;
std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -299,8 +221,7 @@ class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
public: public:
FileTypeOptionHandler(nstool::Settings::FileType& param, const std::vector<std::string>& opts) : FileTypeOptionHandler(nstool::Settings::FileType& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -308,11 +229,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -394,7 +310,6 @@ public:
private: private:
nstool::Settings::FileType& mParam; nstool::Settings::FileType& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class InstructionTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler class InstructionTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -402,8 +317,7 @@ class InstructionTypeOptionHandler : public tc::cli::OptionParser::IOptionHandle
public: public:
InstructionTypeOptionHandler(bool& param, const std::vector<std::string>& opts) : InstructionTypeOptionHandler(bool& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -411,11 +325,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -439,7 +348,6 @@ public:
private: private:
bool& mParam; bool& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class ExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandler class ExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -447,8 +355,7 @@ class ExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandle
public: public:
ExtractDataPathOptionHandler(std::vector<nstool::ExtractJob>& jobs, const std::vector<std::string>& opts) : ExtractDataPathOptionHandler(std::vector<nstool::ExtractJob>& jobs, const std::vector<std::string>& opts) :
mJobs(jobs), mJobs(jobs),
mOptStrings(opts), mOptStrings(opts)
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -456,11 +363,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() == 1) if (params.size() == 1)
@ -479,7 +381,6 @@ public:
private: private:
std::vector<nstool::ExtractJob>& mJobs; std::vector<nstool::ExtractJob>& mJobs;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class CustomExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandler class CustomExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -488,7 +389,6 @@ public:
CustomExtractDataPathOptionHandler(std::vector<nstool::ExtractJob>& jobs, const std::vector<std::string>& opts, const tc::io::Path& custom_path) : CustomExtractDataPathOptionHandler(std::vector<nstool::ExtractJob>& jobs, const std::vector<std::string>& opts, const tc::io::Path& custom_path) :
mJobs(jobs), mJobs(jobs),
mOptStrings(opts), mOptStrings(opts),
mOptRegex(),
mCustomPath(custom_path) mCustomPath(custom_path)
{} {}
@ -497,11 +397,6 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -509,6 +404,9 @@ public:
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires a parameter.", option)); throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires a parameter.", option));
} }
std::string custom_path_str;
tc::io::PathUtil::pathToUnixUTF8(mCustomPath, custom_path_str);
fmt::print("[WARNING] \"{:s} {:s}\" is deprecated. ", option, params[0]); fmt::print("[WARNING] \"{:s} {:s}\" is deprecated. ", option, params[0]);
// if custom path is root path, use the shortened version of -x // if custom path is root path, use the shortened version of -x
if (mCustomPath == tc::io::Path("/")) if (mCustomPath == tc::io::Path("/"))
@ -517,7 +415,7 @@ public:
} }
else else
{ {
fmt::print("Consider using \"-x {:s} {:s}\" instead.\n", mCustomPath.to_string(), params[0]); fmt::print("Consider using \"-x {:s} {:s}\" instead.\n", custom_path_str, params[0]);
} }
@ -526,7 +424,6 @@ public:
private: private:
std::vector<nstool::ExtractJob>& mJobs; std::vector<nstool::ExtractJob>& mJobs;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
tc::io::Path mCustomPath; tc::io::Path mCustomPath;
}; };
@ -538,7 +435,7 @@ nstool::SettingsInitializer::SettingsInitializer(const std::vector<std::string>&
mVerbose(false), mVerbose(false),
mNcaEncryptedContentKey(), mNcaEncryptedContentKey(),
mNcaContentKey(), mNcaContentKey(),
mTikPathList(), mTikPath(),
mCertPath() mCertPath()
{ {
// parse input arguments // parse input arguments
@ -566,16 +463,29 @@ nstool::SettingsInitializer::SettingsInitializer(const std::vector<std::string>&
// locate key file, if not specfied // locate key file, if not specfied
if (mKeysetPath.isNull()) if (mKeysetPath.isNull())
{ {
loadKeyFile(mKeysetPath, opt.is_dev ? "dev.keys" : "prod.keys", "Maybe specify it with \"-k <path>\"?\n"); std::string home_path_str;
} if (tc::os::getEnvVar("HOME", home_path_str) || tc::os::getEnvVar("USERPROFILE", home_path_str))
// locate title key file, if not specfied {
if (mTitleKeysetPath.isNull()) tc::io::Path keyfile_path = tc::io::Path(home_path_str);
{ keyfile_path.push_back(".switch");
loadKeyFile(mTitleKeysetPath, "title.keys", ""); keyfile_path.push_back(opt.is_dev ? "dev.keys" : "prod.keys");
try {
tc::io::FileStream test = tc::io::FileStream(keyfile_path, tc::io::FileMode::Open, tc::io::FileAccess::Read);
mKeysetPath = keyfile_path;
}
catch (tc::io::FileNotFoundException&) {
fmt::print("[WARNING] Failed to load \"{}\" keyfile. Maybe specify it with \"-k <path>\"?\n", opt.is_dev ? "dev.keys" : "prod.keys");
}
}
else {
fmt::print("[WARNING] Failed to located \"{}\" keyfile. Maybe specify it with \"-k <path>\"?\n", opt.is_dev ? "dev.keys" : "prod.keys");
}
} }
// generate keybag // generate keybag
opt.keybag = KeyBagInitializer(opt.is_dev, mKeysetPath, mTitleKeysetPath, mTikPathList, mCertPath); opt.keybag = KeyBagInitializer(opt.is_dev, mKeysetPath, mTikPath, mCertPath);
opt.keybag.fallback_enc_content_key = mNcaEncryptedContentKey; opt.keybag.fallback_enc_content_key = mNcaEncryptedContentKey;
opt.keybag.fallback_content_key = mNcaContentKey; opt.keybag.fallback_content_key = mNcaContentKey;
@ -639,10 +549,9 @@ void nstool::SettingsInitializer::parse_args(const std::vector<std::string>& arg
// get user-provided keydata // get user-provided keydata
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mKeysetPath, {"-k", "--keyset"}))); opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mKeysetPath, {"-k", "--keyset"})));
//opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mTitleKeysetPath, {"--titlekeyset"})));
opts.registerOptionHandler(std::shared_ptr<SingleParamAesKeyOptionHandler>(new SingleParamAesKeyOptionHandler(mNcaEncryptedContentKey, {"--titlekey"}))); opts.registerOptionHandler(std::shared_ptr<SingleParamAesKeyOptionHandler>(new SingleParamAesKeyOptionHandler(mNcaEncryptedContentKey, {"--titlekey"})));
opts.registerOptionHandler(std::shared_ptr<SingleParamAesKeyOptionHandler>(new SingleParamAesKeyOptionHandler(mNcaContentKey, {"--contentkey", "--bodykey"}))); opts.registerOptionHandler(std::shared_ptr<SingleParamAesKeyOptionHandler>(new SingleParamAesKeyOptionHandler(mNcaContentKey, {"--contentkey", "--bodykey"})));
opts.registerOptionHandler(std::shared_ptr<SingleParamPathArrayOptionHandler>(new SingleParamPathArrayOptionHandler(mTikPathList, {"--tik"}))); opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mTikPath, {"--tik"})));
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mCertPath, {"--cert"}))); opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mCertPath, {"--cert"})));
// code options // code options
@ -667,8 +576,6 @@ void nstool::SettingsInitializer::parse_args(const std::vector<std::string>& arg
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--part2" }, tc::io::Path("/2/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--part2" }, tc::io::Path("/2/"))));
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--part3" }, tc::io::Path("/3/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--part3" }, tc::io::Path("/3/"))));
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(nca.base_nca_path, { "--basenca" })));
// kip options // kip options
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(kip.extract_path, { "--kipdir" }))); opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(kip.extract_path, { "--kipdir" })));
@ -683,7 +590,9 @@ void nstool::SettingsInitializer::parse_args(const std::vector<std::string>& arg
void nstool::SettingsInitializer::determine_filetype() void nstool::SettingsInitializer::determine_filetype()
{ {
//fmt::print("infile path = \"{}\"\n", infile.path.get().to_string()); //std::string infile_path_str;
//tc::io::PathUtil::pathToUnixUTF8(infile.path.get(), infile_path_str);
//fmt::print("infile path = \"{}\"\n", infile_path_str);
auto file = tc::io::StreamSource(std::make_shared<tc::io::FileStream>(tc::io::FileStream(infile.path.get(), tc::io::FileMode::Open, tc::io::FileAccess::Read))); auto file = tc::io::StreamSource(std::make_shared<tc::io::FileStream>(tc::io::FileStream(infile.path.get(), tc::io::FileMode::Open, tc::io::FileAccess::Read)));
@ -695,69 +604,69 @@ void nstool::SettingsInitializer::determine_filetype()
// do easy tests // do easy tests
// detect "scene" XCI // detect "scene" XCI
if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sGcHeader_Rsa2048Signed)) if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sGcHeader_Rsa2048Signed))
&& _TYPE_PTR(pie::hac::sGcHeader_Rsa2048Signed)->header.st_magic.unwrap() == pie::hac::gc::kGcHeaderStructMagic) && _TYPE_PTR(nn::hac::sGcHeader_Rsa2048Signed)->header.st_magic.unwrap() == nn::hac::gc::kGcHeaderStructMagic)
{ {
infile.filetype = FILE_TYPE_GAMECARD; infile.filetype = FILE_TYPE_GAMECARD;
} }
// detect "SDK" XCI // detect "SDK" XCI
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sSdkGcHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sSdkGcHeader))
&& _TYPE_PTR(pie::hac::sSdkGcHeader)->signed_header.header.st_magic.unwrap() == pie::hac::gc::kGcHeaderStructMagic) && _TYPE_PTR(nn::hac::sSdkGcHeader)->signed_header.header.st_magic.unwrap() == nn::hac::gc::kGcHeaderStructMagic)
{ {
infile.filetype = FILE_TYPE_GAMECARD; infile.filetype = FILE_TYPE_GAMECARD;
} }
// detect PFS0 // detect PFS0
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sPfsHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sPfsHeader))
&& _TYPE_PTR(pie::hac::sPfsHeader)->st_magic.unwrap() == pie::hac::pfs::kPfsStructMagic) && _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.unwrap() == nn::hac::pfs::kPfsStructMagic)
{ {
infile.filetype = FILE_TYPE_PARTITIONFS; infile.filetype = FILE_TYPE_PARTITIONFS;
} }
// detect HFS0 // detect HFS0
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sPfsHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sPfsHeader))
&& _TYPE_PTR(pie::hac::sPfsHeader)->st_magic.unwrap() == pie::hac::pfs::kHashedPfsStructMagic) && _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.unwrap() == nn::hac::pfs::kHashedPfsStructMagic)
{ {
infile.filetype = FILE_TYPE_PARTITIONFS; infile.filetype = FILE_TYPE_PARTITIONFS;
} }
// detect ROMFS // detect ROMFS
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sRomfsHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sRomfsHeader))
&& _TYPE_PTR(pie::hac::sRomfsHeader)->header_size.unwrap() == sizeof(pie::hac::sRomfsHeader) && _TYPE_PTR(nn::hac::sRomfsHeader)->header_size.unwrap() == sizeof(nn::hac::sRomfsHeader)
&& _TYPE_PTR(pie::hac::sRomfsHeader)->dir_entry.offset.unwrap() == (_TYPE_PTR(pie::hac::sRomfsHeader)->dir_hash_bucket.offset.unwrap() + _TYPE_PTR(pie::hac::sRomfsHeader)->dir_hash_bucket.size.unwrap())) && _TYPE_PTR(nn::hac::sRomfsHeader)->dir_entry.offset.unwrap() == (_TYPE_PTR(nn::hac::sRomfsHeader)->dir_hash_bucket.offset.unwrap() + _TYPE_PTR(nn::hac::sRomfsHeader)->dir_hash_bucket.size.unwrap()))
{ {
infile.filetype = FILE_TYPE_ROMFS; infile.filetype = FILE_TYPE_ROMFS;
} }
// detect NPDM // detect NPDM
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sMetaHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sMetaHeader))
&& _TYPE_PTR(pie::hac::sMetaHeader)->st_magic.unwrap() == pie::hac::meta::kMetaStructMagic) && _TYPE_PTR(nn::hac::sMetaHeader)->st_magic.unwrap() == nn::hac::meta::kMetaStructMagic)
{ {
infile.filetype = FILE_TYPE_META; infile.filetype = FILE_TYPE_META;
} }
// detect NSO // detect NSO
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sNsoHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sNsoHeader))
&& _TYPE_PTR(pie::hac::sNsoHeader)->st_magic.unwrap() == pie::hac::nso::kNsoStructMagic) && _TYPE_PTR(nn::hac::sNsoHeader)->st_magic.unwrap() == nn::hac::nso::kNsoStructMagic)
{ {
infile.filetype = FILE_TYPE_NSO; infile.filetype = FILE_TYPE_NSO;
} }
// detect NRO // detect NRO
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sNroHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sNroHeader))
&& _TYPE_PTR(pie::hac::sNroHeader)->st_magic.unwrap() == pie::hac::nro::kNroStructMagic) && _TYPE_PTR(nn::hac::sNroHeader)->st_magic.unwrap() == nn::hac::nro::kNroStructMagic)
{ {
infile.filetype = FILE_TYPE_NRO; infile.filetype = FILE_TYPE_NRO;
} }
// detect INI // detect INI
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sIniHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sIniHeader))
&& _TYPE_PTR(pie::hac::sIniHeader)->st_magic.unwrap() == pie::hac::ini::kIniStructMagic) && _TYPE_PTR(nn::hac::sIniHeader)->st_magic.unwrap() == nn::hac::ini::kIniStructMagic)
{ {
infile.filetype = FILE_TYPE_INI; infile.filetype = FILE_TYPE_INI;
} }
// detect KIP // detect KIP
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sKipHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sKipHeader))
&& _TYPE_PTR(pie::hac::sKipHeader)->st_magic.unwrap() == pie::hac::kip::kKipStructMagic) && _TYPE_PTR(nn::hac::sKipHeader)->st_magic.unwrap() == nn::hac::kip::kKipStructMagic)
{ {
infile.filetype = FILE_TYPE_KIP; infile.filetype = FILE_TYPE_KIP;
} }
// detect HB ASET // detect HB ASET
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sAssetHeader)) else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sAssetHeader))
&& _TYPE_PTR(pie::hac::sAssetHeader)->st_magic.unwrap() == pie::hac::aset::kAssetStructMagic) && _TYPE_PTR(nn::hac::sAssetHeader)->st_magic.unwrap() == nn::hac::aset::kAssetStructMagic)
{ {
infile.filetype = FILE_TYPE_KIP; infile.filetype = FILE_TYPE_KIP;
} }
@ -820,7 +729,7 @@ void nstool::SettingsInitializer::usage_text() const
fmt::print(" --normal Extract \"normal\" partition to directory. (Alias for \"-x /normal <out path>\")\n"); fmt::print(" --normal Extract \"normal\" partition to directory. (Alias for \"-x /normal <out path>\")\n");
fmt::print(" --secure Extract \"secure\" partition to directory. (Alias for \"-x /secure <out path>\")\n"); fmt::print(" --secure Extract \"secure\" partition to directory. (Alias for \"-x /secure <out path>\")\n");
fmt::print("\n NCA (Nintendo Content Archive)\n"); fmt::print("\n NCA (Nintendo Content Archive)\n");
fmt::print(" {:s} [--fstree] [-x [<virtual path>] <out path>] [--bodykey <key> --titlekey <key> -tik <tik path> --basenca <.nca file>] <.nca file>\n", BIN_NAME); fmt::print(" {:s} [--fstree] [-x [<virtual path>] <out path>] [--bodykey <key> --titlekey <key> -tik <tik path>] <.nca file>\n", BIN_NAME);
fmt::print(" --fstree Print filesystem tree.\n"); fmt::print(" --fstree Print filesystem tree.\n");
fmt::print(" -x, --extract Extract a file or directory to local filesystem.\n"); fmt::print(" -x, --extract Extract a file or directory to local filesystem.\n");
fmt::print(" --titlekey Specify (encrypted) title key extracted from ticket.\n"); fmt::print(" --titlekey Specify (encrypted) title key extracted from ticket.\n");
@ -831,7 +740,6 @@ void nstool::SettingsInitializer::usage_text() const
fmt::print(" --part1 Extract partition \"1\" to directory. (Alias for \"-x /1 <out path>\")\n"); fmt::print(" --part1 Extract partition \"1\" to directory. (Alias for \"-x /1 <out path>\")\n");
fmt::print(" --part2 Extract partition \"2\" to directory. (Alias for \"-x /2 <out path>\")\n"); fmt::print(" --part2 Extract partition \"2\" to directory. (Alias for \"-x /2 <out path>\")\n");
fmt::print(" --part3 Extract partition \"3\" to directory. (Alias for \"-x /3 <out path>\")\n"); fmt::print(" --part3 Extract partition \"3\" to directory. (Alias for \"-x /3 <out path>\")\n");
fmt::print(" --basenca Specify base NCA file for update NCA files.\n");
fmt::print("\n NSO (Nintendo Shared Object), NRO (Nintendo Relocatable Object)\n"); fmt::print("\n NSO (Nintendo Shared Object), NRO (Nintendo Relocatable Object)\n");
fmt::print(" {:s} [--listapi --listsym] [--insttype <inst. type>] <file>\n", BIN_NAME); fmt::print(" {:s} [--listapi --listsym] [--insttype <inst. type>] <file>\n", BIN_NAME);
fmt::print(" --listapi Print SDK API List.\n"); fmt::print(" --listapi Print SDK API List.\n");
@ -928,24 +836,24 @@ void nstool::SettingsInitializer::dump_keys() const
fmt::print(" {:s}:\n", itr->first); fmt::print(" {:s}:\n", itr->first);
fmt::print(" SignType: "); fmt::print(" SignType: ");
switch(itr->second.key_type) { switch(itr->second.key_type) {
case pie::hac::es::sign::SIGN_ALGO_RSA2048: case nn::pki::sign::SIGN_ALGO_RSA2048:
fmt::print("RSA-2048\n"); fmt::print("RSA-2048\n");
break; break;
case pie::hac::es::sign::SIGN_ALGO_RSA4096: case nn::pki::sign::SIGN_ALGO_RSA4096:
fmt::print("RSA-4096\n"); fmt::print("RSA-4096\n");
break; break;
case pie::hac::es::sign::SIGN_ALGO_ECDSA240: case nn::pki::sign::SIGN_ALGO_ECDSA240:
fmt::print("ECDSA-240\n"); fmt::print("ECDSA-240\n");
break; break;
default: default:
fmt::print("Unknown\n"); fmt::print("Unknown\n");
} }
switch(itr->second.key_type) { switch(itr->second.key_type) {
case pie::hac::es::sign::SIGN_ALGO_RSA2048: case nn::pki::sign::SIGN_ALGO_RSA2048:
case pie::hac::es::sign::SIGN_ALGO_RSA4096: case nn::pki::sign::SIGN_ALGO_RSA4096:
dump_rsa_key(itr->second.rsa_key, "RsaKey", 6, opt.cli_output_mode.show_extended_info); dump_rsa_key(itr->second.rsa_key, "RsaKey", 6, opt.cli_output_mode.show_extended_info);
break; break;
case pie::hac::es::sign::SIGN_ALGO_ECDSA240: case nn::pki::sign::SIGN_ALGO_ECDSA240:
default: default:
break; break;
} }
@ -989,34 +897,10 @@ void nstool::SettingsInitializer::dump_rsa_key(const KeyBag::rsa_key_t& key, con
} }
} }
void nstool::SettingsInitializer::loadKeyFile(tc::Optional<tc::io::Path>& keyfile_path, const std::string& keyfile_name, const std::string& cli_hint)
{
std::string home_path_str;
if (tc::os::getEnvVar("HOME", home_path_str) || tc::os::getEnvVar("USERPROFILE", home_path_str))
{
tc::io::Path tmp_path = tc::io::Path(home_path_str);
tmp_path.push_back(".switch");
tmp_path.push_back(keyfile_name);
try {
tc::io::FileStream test = tc::io::FileStream(tmp_path, tc::io::FileMode::Open, tc::io::FileAccess::Read);
keyfile_path = tmp_path;
}
catch (tc::io::FileNotFoundException&) {
fmt::print("[WARNING] Failed to load \"{}\" keyfile.{}\n", keyfile_name, cli_hint);
}
}
else {
fmt::print("[WARNING] Failed to locate \"{}\" keyfile.{}\n", keyfile_name, cli_hint);
}
}
bool nstool::SettingsInitializer::determineValidNcaFromSample(const tc::ByteData& sample) const bool nstool::SettingsInitializer::determineValidNcaFromSample(const tc::ByteData& sample) const
{ {
if (sample.size() < pie::hac::nca::kHeaderSize) if (sample.size() < nn::hac::nca::kHeaderSize)
{ {
return false; return false;
} }
@ -1027,26 +911,26 @@ bool nstool::SettingsInitializer::determineValidNcaFromSample(const tc::ByteData
return false; return false;
} }
pie::hac::detail::aes128_xtskey_t key = opt.keybag.nca_header_key.get(); nn::hac::detail::aes128_xtskey_t key = opt.keybag.nca_header_key.get();
//fmt::print("NCA header key: {} {}\n", tc::cli::FormatUtil::formatBytesAsString(opt.keybag.nca_header_key.get()[0].data(), opt.keybag.nca_header_key.get()[0].size(), true, ""), tc::cli::FormatUtil::formatBytesAsString(opt.keybag.nca_header_key.get()[1].data(), opt.keybag.nca_header_key.get()[1].size(), true, "")); //fmt::print("NCA header key: {} {}\n", tc::cli::FormatUtil::formatBytesAsString(opt.keybag.nca_header_key.get()[0].data(), opt.keybag.nca_header_key.get()[0].size(), true, ""), tc::cli::FormatUtil::formatBytesAsString(opt.keybag.nca_header_key.get()[1].data(), opt.keybag.nca_header_key.get()[1].size(), true, ""));
// init aes-xts // init aes-xts
tc::crypto::Aes128XtsEncryptor enc; tc::crypto::Aes128XtsEncryptor enc;
enc.initialize(key[0].data(), key[0].size(), key[1].data(), key[1].size(), pie::hac::nca::kSectorSize, false); enc.initialize(key[0].data(), key[0].size(), key[1].data(), key[1].size(), nn::hac::nca::kSectorSize, false);
// decrypt main header // decrypt main header
byte_t raw_hdr[pie::hac::nca::kSectorSize]; byte_t raw_hdr[nn::hac::nca::kSectorSize];
enc.decrypt(raw_hdr, sample.data() + pie::hac::ContentArchiveUtil::sectorToOffset(1), pie::hac::nca::kSectorSize, 1); enc.decrypt(raw_hdr, sample.data() + nn::hac::ContentArchiveUtil::sectorToOffset(1), nn::hac::nca::kSectorSize, 1);
pie::hac::sContentArchiveHeader* hdr = (pie::hac::sContentArchiveHeader*)(raw_hdr); nn::hac::sContentArchiveHeader* hdr = (nn::hac::sContentArchiveHeader*)(raw_hdr);
/* /*
fmt::print("NCA Header Raw:\n"); fmt::print("NCA Header Raw:\n");
fmt::print("{:s}\n", tc::cli::FormatUtil::formatBytesAsHxdHexString(sample.data() + pie::hac::ContentArchiveUtil::sectorToOffset(1), pie::hac::nca::kSectorSize)); fmt::print("{:s}\n", tc::cli::FormatUtil::formatBytesAsHxdHexString(sample.data() + nn::hac::ContentArchiveUtil::sectorToOffset(1), nn::hac::nca::kSectorSize));
fmt::print("{:s}\n", tc::cli::FormatUtil::formatBytesAsHxdHexString(raw_hdr, pie::hac::nca::kSectorSize)); fmt::print("{:s}\n", tc::cli::FormatUtil::formatBytesAsHxdHexString(raw_hdr, nn::hac::nca::kSectorSize));
*/ */
if (hdr->st_magic.unwrap() != pie::hac::nca::kNca2StructMagic && hdr->st_magic.unwrap() != pie::hac::nca::kNca3StructMagic) if (hdr->st_magic.unwrap() != nn::hac::nca::kNca2StructMagic && hdr->st_magic.unwrap() != nn::hac::nca::kNca3StructMagic)
{ {
return false; return false;
} }
@ -1056,12 +940,12 @@ bool nstool::SettingsInitializer::determineValidNcaFromSample(const tc::ByteData
bool nstool::SettingsInitializer::determineValidCnmtFromSample(const tc::ByteData& sample) const bool nstool::SettingsInitializer::determineValidCnmtFromSample(const tc::ByteData& sample) const
{ {
if (sample.size() < sizeof(pie::hac::sContentMetaHeader)) if (sample.size() < sizeof(nn::hac::sContentMetaHeader))
return false; return false;
const pie::hac::sContentMetaHeader* data = (const pie::hac::sContentMetaHeader*)sample.data(); const nn::hac::sContentMetaHeader* data = (const nn::hac::sContentMetaHeader*)sample.data();
size_t minimum_size = sizeof(pie::hac::sContentMetaHeader) + data->exhdr_size.unwrap() + data->content_count.unwrap() * sizeof(pie::hac::sContentInfo) + data->content_meta_count.unwrap() * sizeof(pie::hac::sContentMetaInfo) + pie::hac::cnmt::kDigestLen; size_t minimum_size = sizeof(nn::hac::sContentMetaHeader) + data->exhdr_size.unwrap() + data->content_count.unwrap() * sizeof(nn::hac::sContentInfo) + data->content_meta_count.unwrap() * sizeof(nn::hac::sContentMetaInfo) + nn::hac::cnmt::kDigestLen;
if (sample.size() < minimum_size) if (sample.size() < minimum_size)
return false; return false;
@ -1069,37 +953,37 @@ bool nstool::SettingsInitializer::determineValidCnmtFromSample(const tc::ByteDat
// include exthdr/data check if applicable // include exthdr/data check if applicable
if (data->exhdr_size.unwrap() > 0) if (data->exhdr_size.unwrap() > 0)
{ {
if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_Application) if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Application)
{ {
const pie::hac::sApplicationMetaExtendedHeader* meta = (const pie::hac::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader)); const nn::hac::sApplicationMetaExtendedHeader* meta = (const nn::hac::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
if ((meta->patch_id.unwrap() & data->id.unwrap()) != data->id.unwrap()) if ((meta->patch_id.unwrap() & data->id.unwrap()) != data->id.unwrap())
return false; return false;
} }
else if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_Patch) else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Patch)
{ {
const pie::hac::sPatchMetaExtendedHeader* meta = (const pie::hac::sPatchMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader)); const nn::hac::sPatchMetaExtendedHeader* meta = (const nn::hac::sPatchMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap()) if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap())
return false; return false;
minimum_size += meta->extended_data_size.unwrap(); minimum_size += meta->extended_data_size.unwrap();
} }
else if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_AddOnContent) else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::AddOnContent)
{ {
const pie::hac::sAddOnContentMetaExtendedHeader* meta = (const pie::hac::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader)); const nn::hac::sAddOnContentMetaExtendedHeader* meta = (const nn::hac::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap()) if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap())
return false; return false;
} }
else if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_Delta) else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Delta)
{ {
const pie::hac::sDeltaMetaExtendedHeader* meta = (const pie::hac::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader)); const nn::hac::sDeltaMetaExtendedHeader* meta = (const nn::hac::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap()) if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap())
return false; return false;
minimum_size += meta->extended_data_size.unwrap(); minimum_size += meta->extended_data_size.unwrap();
} }
else if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_SystemUpdate) else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::SystemUpdate)
{ {
const pie::hac::sSystemUpdateMetaExtendedHeader* meta = (const pie::hac::sSystemUpdateMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader)); const nn::hac::sSystemUpdateMetaExtendedHeader* meta = (const nn::hac::sSystemUpdateMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
minimum_size += meta->extended_data_size.unwrap(); minimum_size += meta->extended_data_size.unwrap();
} }
@ -1113,12 +997,12 @@ bool nstool::SettingsInitializer::determineValidCnmtFromSample(const tc::ByteDat
bool nstool::SettingsInitializer::determineValidNacpFromSample(const tc::ByteData& sample) const bool nstool::SettingsInitializer::determineValidNacpFromSample(const tc::ByteData& sample) const
{ {
if (sample.size() != sizeof(pie::hac::sApplicationControlProperty)) if (sample.size() != sizeof(nn::hac::sApplicationControlProperty))
return false; return false;
const pie::hac::sApplicationControlProperty* data = (const pie::hac::sApplicationControlProperty*)sample.data(); const nn::hac::sApplicationControlProperty* data = (const nn::hac::sApplicationControlProperty*)sample.data();
if (data->logo_type > (byte_t)pie::hac::nacp::LogoType_Nintendo) if (data->logo_type > (byte_t)nn::hac::nacp::LogoType::Nintendo)
return false; return false;
if (data->display_version[0] == 0) if (data->display_version[0] == 0)
@ -1138,7 +1022,7 @@ bool nstool::SettingsInitializer::determineValidNacpFromSample(const tc::ByteDat
bool nstool::SettingsInitializer::determineValidEsCertFromSample(const tc::ByteData& sample) const bool nstool::SettingsInitializer::determineValidEsCertFromSample(const tc::ByteData& sample) const
{ {
pie::hac::es::SignatureBlock sign; nn::pki::SignatureBlock sign;
try try
{ {
@ -1152,7 +1036,7 @@ bool nstool::SettingsInitializer::determineValidEsCertFromSample(const tc::ByteD
if (sign.isLittleEndian() == true) if (sign.isLittleEndian() == true)
return false; return false;
if (sign.getSignType() != pie::hac::es::sign::SIGN_ID_RSA4096_SHA256 && sign.getSignType() != pie::hac::es::sign::SIGN_ID_RSA2048_SHA256 && sign.getSignType() != pie::hac::es::sign::SIGN_ID_ECDSA240_SHA256) if (sign.getSignType() != nn::pki::sign::SIGN_ID_RSA4096_SHA256 && sign.getSignType() != nn::pki::sign::SIGN_ID_RSA2048_SHA256 && sign.getSignType() != nn::pki::sign::SIGN_ID_ECDSA240_SHA256)
return false; return false;
return true; return true;
@ -1160,7 +1044,7 @@ bool nstool::SettingsInitializer::determineValidEsCertFromSample(const tc::ByteD
bool nstool::SettingsInitializer::determineValidEsTikFromSample(const tc::ByteData& sample) const bool nstool::SettingsInitializer::determineValidEsTikFromSample(const tc::ByteData& sample) const
{ {
pie::hac::es::SignatureBlock sign; nn::pki::SignatureBlock sign;
try try
{ {
@ -1174,13 +1058,13 @@ bool nstool::SettingsInitializer::determineValidEsTikFromSample(const tc::ByteDa
if (sign.isLittleEndian() == false) if (sign.isLittleEndian() == false)
return false; return false;
if (sign.getSignType() != pie::hac::es::sign::SIGN_ID_RSA2048_SHA256) if (sign.getSignType() != nn::pki::sign::SIGN_ID_RSA2048_SHA256)
return false; return false;
const pie::hac::es::sTicketBody_v2* body = (const pie::hac::es::sTicketBody_v2*)(sample.data() + sign.getBytes().size()); const nn::es::sTicketBody_v2* body = (const nn::es::sTicketBody_v2*)(sample.data() + sign.getBytes().size());
if ((body->issuer.decode().substr(0, 5) == "Root-" if ((body->issuer.str().substr(0, 5) == "Root-"
&& body->issuer.decode().substr(16, 2) == "XS") == false) && body->issuer.str().substr(16, 2) == "XS") == false)
return false; return false;
return true; return true;

View file

@ -76,7 +76,6 @@ struct Settings
tc::Optional<tc::io::Path> part1_extract_path; tc::Optional<tc::io::Path> part1_extract_path;
tc::Optional<tc::io::Path> part2_extract_path; tc::Optional<tc::io::Path> part2_extract_path;
tc::Optional<tc::io::Path> part3_extract_path; tc::Optional<tc::io::Path> part3_extract_path;
tc::Optional<tc::io::Path> base_nca_path;
} nca; } nca;
// KIP options // KIP options
@ -111,8 +110,6 @@ struct Settings
kip.extract_path = tc::Optional<tc::io::Path>(); kip.extract_path = tc::Optional<tc::io::Path>();
nca.base_nca_path = tc::Optional<tc::io::Path>();
aset.icon_extract_path = tc::Optional<tc::io::Path>(); aset.icon_extract_path = tc::Optional<tc::io::Path>();
aset.nacp_extract_path = tc::Optional<tc::io::Path>(); aset.nacp_extract_path = tc::Optional<tc::io::Path>();
} }
@ -136,15 +133,11 @@ private:
bool mVerbose; bool mVerbose;
tc::Optional<tc::io::Path> mKeysetPath; tc::Optional<tc::io::Path> mKeysetPath;
tc::Optional<tc::io::Path> mTitleKeysetPath;
tc::Optional<KeyBag::aes128_key_t> mNcaEncryptedContentKey; tc::Optional<KeyBag::aes128_key_t> mNcaEncryptedContentKey;
tc::Optional<KeyBag::aes128_key_t> mNcaContentKey; tc::Optional<KeyBag::aes128_key_t> mNcaContentKey;
std::vector<tc::io::Path> mTikPathList; tc::Optional<tc::io::Path> mTikPath;
//tc::Optional<tc::io::Path> mTikPath;
tc::Optional<tc::io::Path> mCertPath; tc::Optional<tc::io::Path> mCertPath;
void loadKeyFile(tc::Optional<tc::io::Path>& keyfile_path, const std::string& keyfile_name, const std::string& cli_hint);
bool determineValidNcaFromSample(const tc::ByteData& raw_data) const; bool determineValidNcaFromSample(const tc::ByteData& raw_data) const;
bool determineValidEsCertFromSample(const tc::ByteData& raw_data) const; bool determineValidEsCertFromSample(const tc::ByteData& raw_data) const;
bool determineValidEsTikFromSample(const tc::ByteData& raw_data) const; bool determineValidEsTikFromSample(const tc::ByteData& raw_data) const;

View file

@ -75,7 +75,6 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
nstool::NcaProcess obj; nstool::NcaProcess obj;
obj.setInputFile(infile_stream); obj.setInputFile(infile_stream);
obj.setBaseNcaPath(set.nca.base_nca_path);
obj.setKeyCfg(set.opt.keybag); obj.setKeyCfg(set.opt.keybag);
obj.setCliOutputMode(set.opt.cli_output_mode); obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify); obj.setVerifyMode(set.opt.verify);

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#define APP_NAME "NSTool" #define APP_NAME "NSTool"
#define BIN_NAME "nstool" #define BIN_NAME "nstool"
#define VER_MAJOR 0 #define VER_MAJOR 1
#define VER_MINOR 0 #define VER_MINOR 6
#define VER_PATCH 0 #define VER_PATCH 2
#define AUTHORS "jakcron" #define AUTHORS "jakcron"