mirror of
https://github.com/jakcron/nstool.git
synced 2026-01-11 21:32:55 +00:00
Compare commits
62 commits
v1.6.2
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfb826ca6c | ||
|
|
cfadea2994 | ||
|
|
69a5f5ed2f | ||
|
|
8798776405 | ||
|
|
85dd51f496 | ||
|
|
811334bae5 | ||
|
|
1d680c2098 | ||
|
|
e205cb6a4f | ||
|
|
978899780c | ||
|
|
4922717ad0 | ||
|
|
17f9298c50 | ||
|
|
30c8751cfd | ||
|
|
0765ee5502 | ||
|
|
268f56b803 | ||
|
|
cf4d335be3 | ||
|
|
25850cd74b | ||
|
|
705cf9b4f3 | ||
|
|
0d248d1c8e | ||
|
|
c7fe8bcd0f | ||
|
|
b4a86fc826 | ||
|
|
7abcedb7e5 | ||
|
|
bcd4df2eb4 | ||
|
|
49e3729d95 | ||
|
|
8c284ba98a | ||
|
|
d87c0fcf1c | ||
|
|
e2245c2a9e | ||
|
|
76f1f87c51 | ||
|
|
21e48a680b | ||
|
|
9d7628a1c9 | ||
|
|
85a31c90af | ||
|
|
591b270ed4 | ||
|
|
fbf62a4df2 | ||
|
|
df045b5dba | ||
|
|
06b75b41cf | ||
|
|
1e81318d54 | ||
|
|
605b5c70f9 | ||
|
|
af41275c80 | ||
|
|
ccd296d144 | ||
|
|
21e1e33e55 | ||
|
|
b5e3fb56b1 | ||
|
|
80cb738b5a | ||
|
|
21f8c884f6 | ||
|
|
b0a07c061a | ||
|
|
390b544059 | ||
|
|
f17b57d2ed | ||
|
|
87459b6f8d | ||
|
|
e770a06ad4 | ||
|
|
26898c7fa3 | ||
|
|
cb46c7c7c3 | ||
|
|
5c1bd2c786 | ||
|
|
ffbcf736d2 | ||
|
|
4e8fb2d3e2 | ||
|
|
14caec3049 | ||
|
|
15b082d9d2 | ||
|
|
10dd907c6e | ||
|
|
04662e529f | ||
|
|
88e56b600d | ||
|
|
64528a0956 | ||
|
|
ebd86508ff | ||
|
|
325cfeb0e8 | ||
|
|
5230d880e1 | ||
|
|
e499e2790e |
|
|
@ -1,10 +1,10 @@
|
|||
name: Compile Master Branch
|
||||
name: Compile Project (Push/PR/Release)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [ development-tip, stable ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
branches: [ development-tip, stable ]
|
||||
release:
|
||||
types: [ created ]
|
||||
|
||||
|
|
@ -20,22 +20,25 @@ jobs:
|
|||
- dist: ubuntu_x86_64
|
||||
os: ubuntu-latest
|
||||
arch: x86_64
|
||||
bin_ext:
|
||||
- dist: macos_x86_64
|
||||
os: macos-latest
|
||||
arch: x86_64
|
||||
bin_ext:
|
||||
- dist: macos_arm64
|
||||
os: macos-latest
|
||||
arch: arm64
|
||||
bin_ext:
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clone submodules
|
||||
run: git submodule init && git submodule update
|
||||
- name: Compile ${{ matrix.prog }}
|
||||
run: make PROJECT_PLATFORM_ARCH=${{ matrix.arch }} deps all
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.prog }}-${{ matrix.dist }}
|
||||
path: ./bin/${{ matrix.prog }}
|
||||
path: ./bin/${{ matrix.prog }}${{ matrix.bin_ext }}
|
||||
build_visualstudio:
|
||||
name: Compile ${{ matrix.prog }} for ${{ matrix.dist }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
|
@ -49,21 +52,22 @@ jobs:
|
|||
platform: x64
|
||||
configuration: Release
|
||||
build_path: x64\Release
|
||||
bin_ext: .exe
|
||||
- dist: win_x86
|
||||
os: windows-latest
|
||||
platform: x86
|
||||
configuration: Release
|
||||
build_path: Release
|
||||
bin_ext: .exe
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
uses: microsoft/setup-msbuild@v1.3
|
||||
- name: Clone submodules
|
||||
run: git submodule init && git submodule update
|
||||
- name: Compile ${{ matrix.prog }}
|
||||
run: msbuild .\build\visualstudio\${{ matrix.prog }}.sln /p:configuration=${{ matrix.configuration }} /p:platform=${{ matrix.platform }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.prog }}-${{ matrix.dist }}
|
||||
path: .\build\visualstudio\${{ matrix.build_path }}\${{ matrix.prog }}.exe
|
||||
|
||||
path: .\build\visualstudio\${{ matrix.build_path }}\${{ matrix.prog }}${{ matrix.bin_ext }}
|
||||
29
.gitmodules
vendored
29
.gitmodules
vendored
|
|
@ -1,24 +1,15 @@
|
|||
[submodule "deps/liblz4"]
|
||||
path = deps/liblz4
|
||||
url = https://github.com/jakcron/liblz4.git
|
||||
[submodule "deps/libmbedtls"]
|
||||
path = deps/libmbedtls
|
||||
url = https://github.com/jakcron/libmbedtls
|
||||
[submodule "deps/libtoolchain"]
|
||||
path = deps/libtoolchain
|
||||
url = https://github.com/jakcron/libtoolchain.git
|
||||
url = https://github.com/jakcron/libmbedtls.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
|
||||
[submodule "deps/libtoolchain"]
|
||||
path = deps/libtoolchain
|
||||
url = https://github.com/jakcron/libtoolchain.git
|
||||
[submodule "deps/liblz4"]
|
||||
path = deps/liblz4
|
||||
url = https://github.com/jakcron/liblz4.git
|
||||
[submodule "deps/libpietendo"]
|
||||
path = deps/libpietendo
|
||||
url = https://github.com/jakcron/libpietendo.git
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
# 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
|
||||
### Requirements
|
||||
* `make`
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -143,6 +143,16 @@ nstool -x /path/to/a/file.bin ./extract_dir/different_name.bin some_file.bin
|
|||
* NSP
|
||||
* 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
|
||||
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.
|
||||
|
||||
|
|
|
|||
|
|
@ -203,4 +203,18 @@ nstool <32 char rightsid>.tik
|
|||
##### 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.
|
||||
|
||||
# Title
|
||||
# Title Keys (title.keys)
|
||||
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
|
||||
```
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31229.75
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32616.157
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nstool", "nstool\nstool.vcxproj", "{775EF5EB-CA49-4994-8AC4-47B4A5385266}"
|
||||
EndProject
|
||||
|
|
@ -9,23 +9,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deps", "deps", "{05929EAE-4
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4", "..\..\deps\liblz4\build\visualstudio\liblz4\liblz4.vcxproj", "{E741ADED-7900-4E07-8DB0-D008C336C3FB}"
|
||||
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}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtoolchain", "..\..\deps\libtoolchain\build\visualstudio\libtoolchain\libtoolchain.vcxproj", "{E194E4B8-1482-40A2-901B-75D4387822E9}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfmt", "..\..\deps\libfmt\build\visualstudio\libfmt\libfmt.vcxproj", "{F4B0540E-0AAE-4006-944B-356944EF61FA}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpietendo", "..\..\deps\libpietendo\build\visualstudio\libpietendo\libpietendo.vcxproj", "{5ADDD009-9D25-40BE-B2A6-2F3AB4DCBBD2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
|
|
@ -50,38 +41,6 @@ Global
|
|||
{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.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.Build.0 = Debug|x64
|
||||
{7A7C66F3-2B5B-4E23-85D8-2A74FEDAD92C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
|
|
@ -106,19 +65,24 @@ Global
|
|||
{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.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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{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}
|
||||
{E194E4B8-1482-40A2-901B-75D4387822E9} = {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
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {ABDCFB40-D6B3-44A9-92B5-0D7AB38D9FB8}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<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>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libpietendo\include</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<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>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libpietendo\include</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<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>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libpietendo\include</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<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>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libpietendo\include</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
@ -129,24 +129,15 @@
|
|||
<ProjectReference Include="$(SolutionDir)..\..\deps\liblz4\build\visualstudio\liblz4\liblz4.vcxproj">
|
||||
<Project>{e741aded-7900-4e07-8db0-d008c336c3fb}</Project>
|
||||
</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">
|
||||
<Project>{7a7c66f3-2b5b-4e23-85d8-2a74fedad92c}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)..\..\deps\libtoolchain\build\visualstudio\libtoolchain\libtoolchain.vcxproj">
|
||||
<Project>{e194e4b8-1482-40a2-901b-75d4387822e9}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)..\..\deps\libpietendo\build\visualstudio\libpietendo\libpietendo.vcxproj">
|
||||
<Project>{5addd009-9d25-40be-b2a6-2f3ab4dcbbd2}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\AssetProcess.h" />
|
||||
|
|
|
|||
2
deps/libfmt
vendored
2
deps/libfmt
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 53d084cc0c6ea61bbb535a873299b0ae5ff9a05d
|
||||
Subproject commit b03b081e026ceb1226b45de926babe629d6c0688
|
||||
2
deps/liblz4
vendored
2
deps/liblz4
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit b40b46406e87a753328abfda3b53dfabd2408da2
|
||||
Subproject commit 561775a11e00cbd21a45031c64068cb5e1242608
|
||||
2
deps/libmbedtls
vendored
2
deps/libmbedtls
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit e9e56bb773111f831af8dd36ad74de73b0c31aa2
|
||||
Subproject commit 74346376dd035e9fbc161cdb80afc646b72fde86
|
||||
1
deps/libnintendo-es
vendored
1
deps/libnintendo-es
vendored
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 984c7e6d80729eb59035932815c00e1ad614ef77
|
||||
1
deps/libnintendo-hac
vendored
1
deps/libnintendo-hac
vendored
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 19d38735ba4eb393faefefc3c923144628456857
|
||||
1
deps/libnintendo-hac-hb
vendored
1
deps/libnintendo-hac-hb
vendored
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 0635b0c532f4ef152506775c930b3d45f575a14c
|
||||
1
deps/libnintendo-pki
vendored
1
deps/libnintendo-pki
vendored
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 87fdd1be853013a95116c107520078ece7869881
|
||||
1
deps/libpietendo
vendored
Submodule
1
deps/libpietendo
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 5d50d02f8f3b8918bdfbbb599b8c4c1628660d89
|
||||
2
deps/libtoolchain
vendored
2
deps/libtoolchain
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit d7b48027a93ef69b9c6b0d78fe392abc0bce5e68
|
||||
Subproject commit 578d170f5b294e4a9feb3cc2d504896e846f204e
|
||||
37
makefile
37
makefile
|
|
@ -1,6 +1,6 @@
|
|||
# C++/C Recursive Project Makefile
|
||||
# (c) Jack
|
||||
# Version 6 (20211110)
|
||||
# Version 9 (20231231)
|
||||
|
||||
# Project Name
|
||||
PROJECT_NAME = nstool
|
||||
|
|
@ -23,16 +23,9 @@ ifeq ($(ROOT_PROJECT_NAME),)
|
|||
export ROOT_PROJECT_DEPENDENCY_PATH = $(ROOT_PROJECT_PATH)/deps
|
||||
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_DEPEND = nintendo-hac-hb nintendo-hac nintendo-es nintendo-pki toolchain fmt lz4 mbedtls
|
||||
PROJECT_DEPEND_LOCAL_DIR = libnintendo-hac-hb libnintendo-hac libnintendo-es libnintendo-pki libtoolchain libfmt liblz4 libmbedtls
|
||||
PROJECT_DEPEND = pietendo toolchain fmt lz4 mbedtls
|
||||
PROJECT_DEPEND_LOCAL_DIR = libpietendo libtoolchain libfmt liblz4 libmbedtls
|
||||
|
||||
# Generate compiler flags for including project include path
|
||||
ifneq ($(PROJECT_INCLUDE_PATH),)
|
||||
|
|
@ -82,45 +75,47 @@ ifeq ($(PROJECT_PLATFORM), WIN32)
|
|||
# Windows Flags/Libs
|
||||
CC = x86_64-w64-mingw32-gcc
|
||||
CXX = x86_64-w64-mingw32-g++
|
||||
DEFINEFLAGS =
|
||||
WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-but-set-variable
|
||||
ARCHFLAGS =
|
||||
INC +=
|
||||
LIB += -static
|
||||
ARFLAGS = cr -o
|
||||
ARFLAGS = cr
|
||||
else ifeq ($(PROJECT_PLATFORM), GNU)
|
||||
# GNU/Linux Flags/Libs
|
||||
#CC =
|
||||
#CXX =
|
||||
DEFINEFLAGS =
|
||||
WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-but-set-variable
|
||||
ARCHFLAGS =
|
||||
INC +=
|
||||
LIB +=
|
||||
ARFLAGS = cr -o
|
||||
ARFLAGS = cr
|
||||
else ifeq ($(PROJECT_PLATFORM), MACOS)
|
||||
# MacOS Flags/Libs
|
||||
#CC =
|
||||
#CXX =
|
||||
DEFINEFLAGS =
|
||||
WARNFLAGS = -Wall -Wno-unused-value -Wno-unused-private-field
|
||||
ARCHFLAGS = -arch $(PROJECT_PLATFORM_ARCH)
|
||||
INC +=
|
||||
LIB +=
|
||||
ARFLAGS = rc
|
||||
ARFLAGS = rc
|
||||
endif
|
||||
|
||||
# Compiler Flags
|
||||
CXXFLAGS = -std=c++11 $(INC) $(WARNFLAGS) $(ARCHFLAGS) -fPIC
|
||||
CFLAGS = -std=c11 $(INC) $(WARNFLAGS) $(ARCHFLAGS) -fPIC
|
||||
CXXFLAGS = -std=c++11 $(INC) $(DEFINEFLAGS) $(WARNFLAGS) $(ARCHFLAGS) -fPIC
|
||||
CFLAGS = -std=c11 $(INC) $(DEFINEFLAGS) $(WARNFLAGS) $(ARCHFLAGS) -fPIC
|
||||
|
||||
# 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)))
|
||||
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
|
||||
# - 'static_lib' for building static library
|
||||
# - 'shared_lib' for building shared library
|
||||
# - 'program' for building the program
|
||||
# - 'static_lib' for building source as a static library
|
||||
# - 'program' for building source as executable program
|
||||
# - 'test_program' for building the test program
|
||||
# These can typically be used together however *_lib and program should not be used together
|
||||
# test_program can be used with program or static_lib, but program and static_lib cannot be used together
|
||||
all: program
|
||||
|
||||
clean: clean_object_files remove_binary_dir
|
||||
|
|
@ -158,10 +153,6 @@ static_lib: $(SRC_OBJ) create_binary_dir
|
|||
@echo LINK $(PROJECT_BIN_PATH)/$(PROJECT_NAME).a
|
||||
@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
|
||||
program: $(SRC_OBJ) create_binary_dir
|
||||
@echo LINK $(PROJECT_BIN_PATH)/$(PROJECT_NAME)
|
||||
|
|
|
|||
|
|
@ -64,12 +64,12 @@ void nstool::AssetProcess::importHeader()
|
|||
throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions.");
|
||||
}
|
||||
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sAssetHeader)))
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sAssetHeader)))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt ASET: file too small");
|
||||
}
|
||||
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sAssetHeader));
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sAssetHeader));
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read(scratch.data(), scratch.size());
|
||||
|
||||
|
|
@ -85,10 +85,7 @@ void nstool::AssetProcess::processSections()
|
|||
if ((mHdr.getIconInfo().size + mHdr.getIconInfo().offset) > file_size)
|
||||
throw tc::Exception(mModuleName, "ASET geometry for icon beyond file size");
|
||||
|
||||
std::string icon_extract_path_str;
|
||||
tc::io::PathUtil::pathToUnixUTF8(mIconExtractPath.get(), icon_extract_path_str);
|
||||
|
||||
fmt::print("Saving {:s}...", icon_extract_path_str);
|
||||
fmt::print("Saving {:s}...", mIconExtractPath.get().to_string());
|
||||
writeSubStreamToFile(mFile, mHdr.getIconInfo().offset, mHdr.getIconInfo().size, mIconExtractPath.get());
|
||||
}
|
||||
|
||||
|
|
@ -99,6 +96,7 @@ void nstool::AssetProcess::processSections()
|
|||
|
||||
if (mNacpExtractPath.isSet())
|
||||
{
|
||||
fmt::print("Saving {:s}...", mNacpExtractPath.get().to_string());
|
||||
writeSubStreamToFile(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size, mNacpExtractPath.get());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include "NacpProcess.h"
|
||||
#include "RomfsProcess.h"
|
||||
|
||||
#include <nn/hac/AssetHeader.h>
|
||||
#include <pietendo/hac/AssetHeader.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ private:
|
|||
tc::Optional<tc::io::Path> mIconExtractPath;
|
||||
tc::Optional<tc::io::Path> mNacpExtractPath;
|
||||
|
||||
nn::hac::AssetHeader mHdr;
|
||||
pie::hac::AssetHeader mHdr;
|
||||
NacpProcess mNacp;
|
||||
RomfsProcess mRomfs;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "CnmtProcess.h"
|
||||
|
||||
#include <nn/hac/ContentMetaUtil.h>
|
||||
#include <pietendo/hac/ContentMetaUtil.h>
|
||||
|
||||
nstool::CnmtProcess::CnmtProcess() :
|
||||
mModuleName("nstool::CnmtProcess"),
|
||||
|
|
@ -33,7 +33,7 @@ void nstool::CnmtProcess::setVerifyMode(bool verify)
|
|||
mVerify = verify;
|
||||
}
|
||||
|
||||
const nn::hac::ContentMeta& nstool::CnmtProcess::getContentMeta() const
|
||||
const pie::hac::ContentMeta& nstool::CnmtProcess::getContentMeta() const
|
||||
{
|
||||
return mCnmt;
|
||||
}
|
||||
|
|
@ -67,11 +67,11 @@ void nstool::CnmtProcess::importCnmt()
|
|||
|
||||
void nstool::CnmtProcess::displayCnmt()
|
||||
{
|
||||
const nn::hac::sContentMetaHeader* cnmt_hdr = (const nn::hac::sContentMetaHeader*)mCnmt.getBytes().data();
|
||||
const pie::hac::sContentMetaHeader* cnmt_hdr = (const pie::hac::sContentMetaHeader*)mCnmt.getBytes().data();
|
||||
fmt::print("[ContentMeta]\n");
|
||||
fmt::print(" TitleId: 0x{:016x}\n", mCnmt.getTitleId());
|
||||
fmt::print(" Version: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getTitleVersion()), mCnmt.getTitleVersion());
|
||||
fmt::print(" Type: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()), (uint32_t)mCnmt.getContentMetaType());
|
||||
fmt::print(" Version: {:s} (v{:d})\n", pie::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(" Attributes: 0x{:x}", *((byte_t*)&cnmt_hdr->attributes));
|
||||
if (mCnmt.getAttribute().size())
|
||||
{
|
||||
|
|
@ -79,7 +79,7 @@ void nstool::CnmtProcess::displayCnmt()
|
|||
|
||||
for (auto itr = mCnmt.getAttribute().begin(); itr != mCnmt.getAttribute().end(); itr++)
|
||||
{
|
||||
attribute_list.push_back(nn::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(nn::hac::cnmt::ContentMetaAttributeFlag(*itr)));
|
||||
attribute_list.push_back(pie::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(pie::hac::cnmt::ContentMetaAttributeFlag(*itr)));
|
||||
}
|
||||
|
||||
fmt::print(" [");
|
||||
|
|
@ -95,28 +95,28 @@ void nstool::CnmtProcess::displayCnmt()
|
|||
}
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print(" StorageId: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getStorageIdAsString(mCnmt.getStorageId()), (uint32_t)mCnmt.getStorageId());
|
||||
fmt::print(" ContentInstallType: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getContentInstallTypeAsString(mCnmt.getContentInstallType()),(uint32_t)mCnmt.getContentInstallType());
|
||||
fmt::print(" RequiredDownloadSystemVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getRequiredDownloadSystemVersion()), mCnmt.getRequiredDownloadSystemVersion());
|
||||
fmt::print(" StorageId: {:s} ({:d})\n", pie::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(" RequiredDownloadSystemVersion: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getRequiredDownloadSystemVersion()), mCnmt.getRequiredDownloadSystemVersion());
|
||||
switch(mCnmt.getContentMetaType())
|
||||
{
|
||||
case (nn::hac::cnmt::ContentMetaType::Application):
|
||||
case (pie::hac::cnmt::ContentMetaType_Application):
|
||||
fmt::print(" ApplicationExtendedHeader:\n");
|
||||
fmt::print(" RequiredApplicationVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion()), mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion());
|
||||
fmt::print(" RequiredSystemVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()), mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion());
|
||||
fmt::print(" RequiredApplicationVersion: {:s} (v{:d})\n", pie::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(" PatchId: 0x{:016x}\n", mCnmt.getApplicationMetaExtendedHeader().getPatchId());
|
||||
break;
|
||||
case (nn::hac::cnmt::ContentMetaType::Patch):
|
||||
case (pie::hac::cnmt::ContentMetaType_Patch):
|
||||
fmt::print(" PatchMetaExtendedHeader:\n");
|
||||
fmt::print(" RequiredSystemVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()), mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion());
|
||||
fmt::print(" RequiredSystemVersion: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()), mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion());
|
||||
fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getPatchMetaExtendedHeader().getApplicationId());
|
||||
break;
|
||||
case (nn::hac::cnmt::ContentMetaType::AddOnContent):
|
||||
case (pie::hac::cnmt::ContentMetaType_AddOnContent):
|
||||
fmt::print(" AddOnContentMetaExtendedHeader:\n");
|
||||
fmt::print(" RequiredApplicationVersion: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()), mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion());
|
||||
fmt::print(" RequiredApplicationVersion: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()), mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion());
|
||||
fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getAddOnContentMetaExtendedHeader().getApplicationId());
|
||||
break;
|
||||
case (nn::hac::cnmt::ContentMetaType::Delta):
|
||||
case (pie::hac::cnmt::ContentMetaType_Delta):
|
||||
fmt::print(" DeltaMetaExtendedHeader:\n");
|
||||
fmt::print(" ApplicationId: 0x{:016x}\n", mCnmt.getDeltaMetaExtendedHeader().getApplicationId());
|
||||
break;
|
||||
|
|
@ -128,9 +128,9 @@ void nstool::CnmtProcess::displayCnmt()
|
|||
fmt::print(" ContentInfo:\n");
|
||||
for (size_t i = 0; i < mCnmt.getContentInfo().size(); i++)
|
||||
{
|
||||
const nn::hac::ContentInfo& info = mCnmt.getContentInfo()[i];
|
||||
const pie::hac::ContentInfo& info = mCnmt.getContentInfo()[i];
|
||||
fmt::print(" {:d}\n", i);
|
||||
fmt::print(" Type: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getContentTypeAsString(info.getContentType()), (uint32_t)info.getContentType());
|
||||
fmt::print(" Type: {:s} ({:d})\n", pie::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(" Size: 0x{:x}\n", info.getContentSize());
|
||||
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
|
||||
if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::Patch && mCnmt.getPatchMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||
if (mCnmt.getContentMetaType() == pie::hac::cnmt::ContentMetaType_Patch && mCnmt.getPatchMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||
{
|
||||
// this is stubbed as the raw output is for development purposes
|
||||
//fmt::print(" PatchMetaExtendedData:\n");
|
||||
//tc::cli::FormatUtil::formatBytesAsHxdHexString(mCnmt.getPatchMetaExtendedData().data(), mCnmt.getPatchMetaExtendedData().size());
|
||||
}
|
||||
else if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::Delta && mCnmt.getDeltaMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||
else if (mCnmt.getContentMetaType() == pie::hac::cnmt::ContentMetaType_Delta && mCnmt.getDeltaMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||
{
|
||||
// this is stubbed as the raw output is for development purposes
|
||||
//fmt::print(" DeltaMetaExtendedData:\n");
|
||||
//tc::cli::FormatUtil::formatBytesAsHxdHexString(mCnmt.getDeltaMetaExtendedData().data(), mCnmt.getDeltaMetaExtendedData().size());
|
||||
}
|
||||
else if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::SystemUpdate && mCnmt.getSystemUpdateMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||
else if (mCnmt.getContentMetaType() == pie::hac::cnmt::ContentMetaType_SystemUpdate && mCnmt.getSystemUpdateMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||
{
|
||||
fmt::print(" SystemUpdateMetaExtendedData:\n");
|
||||
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, ""));
|
||||
}
|
||||
|
||||
void nstool::CnmtProcess::displayContentMetaInfo(const nn::hac::ContentMetaInfo& content_meta_info, const std::string& prefix)
|
||||
void nstool::CnmtProcess::displayContentMetaInfo(const pie::hac::ContentMetaInfo& content_meta_info, const std::string& prefix)
|
||||
{
|
||||
const nn::hac::sContentMetaInfo* content_meta_info_raw = (const nn::hac::sContentMetaInfo*)content_meta_info.getBytes().data();
|
||||
const pie::hac::sContentMetaInfo* content_meta_info_raw = (const pie::hac::sContentMetaInfo*)content_meta_info.getBytes().data();
|
||||
fmt::print("{:s}Id: 0x{:016x}\n", prefix, content_meta_info.getTitleId());
|
||||
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, nn::hac::ContentMetaUtil::getContentMetaTypeAsString(content_meta_info.getContentMetaType()), (uint32_t)content_meta_info.getContentMetaType());
|
||||
fmt::print("{:s}Version: {:s} (v{:d})\n", prefix, pie::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}Attributes: 0x{:x}", prefix, *((byte_t*)&content_meta_info_raw->attributes) );
|
||||
if (content_meta_info.getAttribute().size())
|
||||
{
|
||||
|
|
@ -193,7 +193,7 @@ void nstool::CnmtProcess::displayContentMetaInfo(const nn::hac::ContentMetaInfo&
|
|||
|
||||
for (auto itr = content_meta_info.getAttribute().begin(); itr != content_meta_info.getAttribute().end(); itr++)
|
||||
{
|
||||
attribute_list.push_back(nn::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(nn::hac::cnmt::ContentMetaAttributeFlag(*itr)));
|
||||
attribute_list.push_back(pie::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(pie::hac::cnmt::ContentMetaAttributeFlag(*itr)));
|
||||
}
|
||||
|
||||
fmt::print(" [");
|
||||
|
|
@ -210,11 +210,11 @@ void nstool::CnmtProcess::displayContentMetaInfo(const nn::hac::ContentMetaInfo&
|
|||
fmt::print("\n");
|
||||
}
|
||||
|
||||
void nstool::CnmtProcess::displayContentMetaInfoList(const std::vector<nn::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix)
|
||||
void nstool::CnmtProcess::displayContentMetaInfoList(const std::vector<pie::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix)
|
||||
{
|
||||
for (size_t i = 0; i < content_meta_info_list.size(); i++)
|
||||
{
|
||||
const nn::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i];
|
||||
const pie::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i];
|
||||
fmt::print("{:s}{:d}\n", i);
|
||||
displayContentMetaInfo(info, prefix + " ");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
#include <nn/hac/ContentMeta.h>
|
||||
#include <pietendo/hac/ContentMeta.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ public:
|
|||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
const nn::hac::ContentMeta& getContentMeta() const;
|
||||
const pie::hac::ContentMeta& getContentMeta() const;
|
||||
private:
|
||||
std::string mModuleName;
|
||||
|
||||
|
|
@ -24,13 +24,13 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nn::hac::ContentMeta mCnmt;
|
||||
pie::hac::ContentMeta mCnmt;
|
||||
|
||||
void importCnmt();
|
||||
void displayCnmt();
|
||||
|
||||
void displayContentMetaInfo(const nn::hac::ContentMetaInfo& content_meta_info, const std::string& prefix);
|
||||
void displayContentMetaInfoList(const std::vector<nn::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix);
|
||||
void displayContentMetaInfo(const pie::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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include "PkiValidator.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <nn/pki/SignUtils.h>
|
||||
#include <pietendo/hac/es/SignUtils.h>
|
||||
|
||||
nstool::EsCertProcess::EsCertProcess() :
|
||||
mModuleName("nstool::EsCertProcess"),
|
||||
|
|
@ -66,7 +66,7 @@ void nstool::EsCertProcess::importCerts()
|
|||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read(scratch.data(), scratch.size());
|
||||
|
||||
nn::pki::SignedData<nn::pki::CertificateBody> cert;
|
||||
pie::hac::es::SignedData<pie::hac::es::CertificateBody> cert;
|
||||
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);
|
||||
|
|
@ -98,24 +98,24 @@ void nstool::EsCertProcess::displayCerts()
|
|||
}
|
||||
}
|
||||
|
||||
void nstool::EsCertProcess::displayCert(const nn::pki::SignedData<nn::pki::CertificateBody>& cert)
|
||||
void nstool::EsCertProcess::displayCert(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert)
|
||||
{
|
||||
fmt::print("[ES Certificate]\n");
|
||||
|
||||
fmt::print(" SignType {:s}", getSignTypeStr(cert.getSignature().getSignType()));
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
fmt::print(" (0x{:x}) ({:s})", cert.getSignature().getSignType(), getEndiannessStr(cert.getSignature().isLittleEndian()));
|
||||
fmt::print(" (0x{:x}) ({:s})", (uint32_t)cert.getSignature().getSignType(), getEndiannessStr(cert.getSignature().isLittleEndian()));
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print(" Issuer: {:s}\n", cert.getBody().getIssuer());
|
||||
fmt::print(" Subject: {:s}\n", cert.getBody().getSubject());
|
||||
fmt::print(" PublicKeyType: {:s}", getPublicKeyTypeStr(cert.getBody().getPublicKeyType()));
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
fmt::print(" ({:d})", cert.getBody().getPublicKeyType());
|
||||
fmt::print(" ({:d})", (uint32_t)cert.getBody().getPublicKeyType());
|
||||
fmt::print("\n");
|
||||
fmt::print(" CertID: 0x{:x}\n", cert.getBody().getCertId());
|
||||
|
||||
if (cert.getBody().getPublicKeyType() == nn::pki::cert::RSA4096)
|
||||
if (cert.getBody().getPublicKeyType() == pie::hac::es::cert::RSA4096)
|
||||
{
|
||||
fmt::print(" PublicKey:\n");
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -133,7 +133,7 @@ void nstool::EsCertProcess::displayCert(const nn::pki::SignedData<nn::pki::Certi
|
|||
fmt::print(" {:s}\n", getTruncatedBytesString(cert.getBody().getRsa4096PublicKey().e.data(), cert.getBody().getRsa4096PublicKey().e.size()));
|
||||
}
|
||||
}
|
||||
else if (cert.getBody().getPublicKeyType() == nn::pki::cert::RSA2048)
|
||||
else if (cert.getBody().getPublicKeyType() == pie::hac::es::cert::RSA2048)
|
||||
{
|
||||
fmt::print(" PublicKey:\n");
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -151,7 +151,7 @@ void nstool::EsCertProcess::displayCert(const nn::pki::SignedData<nn::pki::Certi
|
|||
fmt::print(" {:s}\n", getTruncatedBytesString(cert.getBody().getRsa2048PublicKey().e.data(), cert.getBody().getRsa2048PublicKey().e.size()));
|
||||
}
|
||||
}
|
||||
else if (cert.getBody().getPublicKeyType() == nn::pki::cert::ECDSA240)
|
||||
else if (cert.getBody().getPublicKeyType() == pie::hac::es::cert::ECDSA240)
|
||||
{
|
||||
fmt::print(" PublicKey:\n");
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -171,27 +171,27 @@ void nstool::EsCertProcess::displayCert(const nn::pki::SignedData<nn::pki::Certi
|
|||
}
|
||||
}
|
||||
|
||||
std::string nstool::EsCertProcess::getSignTypeStr(nn::pki::sign::SignatureId type) const
|
||||
std::string nstool::EsCertProcess::getSignTypeStr(pie::hac::es::sign::SignatureId type) const
|
||||
{
|
||||
std::string str;
|
||||
switch (type)
|
||||
{
|
||||
case (nn::pki::sign::SIGN_ID_RSA4096_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA1):
|
||||
str = "RSA4096-SHA1";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA2048_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA1):
|
||||
str = "RSA2048-SHA1";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
str = "ECDSA240-SHA1";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA4096_SHA256):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA256):
|
||||
str = "RSA4096-SHA256";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA2048_SHA256):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA256):
|
||||
str = "RSA2048-SHA256";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
str = "ECDSA240-SHA256";
|
||||
break;
|
||||
default:
|
||||
|
|
@ -206,18 +206,18 @@ std::string nstool::EsCertProcess::getEndiannessStr(bool isLittleEndian) const
|
|||
return isLittleEndian ? "LittleEndian" : "BigEndian";
|
||||
}
|
||||
|
||||
std::string nstool::EsCertProcess::getPublicKeyTypeStr(nn::pki::cert::PublicKeyType type) const
|
||||
std::string nstool::EsCertProcess::getPublicKeyTypeStr(pie::hac::es::cert::PublicKeyType type) const
|
||||
{
|
||||
std::string str;
|
||||
switch (type)
|
||||
{
|
||||
case (nn::pki::cert::RSA4096):
|
||||
case (pie::hac::es::cert::RSA4096):
|
||||
str = "RSA4096";
|
||||
break;
|
||||
case (nn::pki::cert::RSA2048):
|
||||
case (pie::hac::es::cert::RSA2048):
|
||||
str = "RSA2048";
|
||||
break;
|
||||
case (nn::pki::cert::ECDSA240):
|
||||
case (pie::hac::es::cert::ECDSA240):
|
||||
str = "ECDSA240";
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
#include "types.h"
|
||||
#include "KeyBag.h"
|
||||
|
||||
#include <nn/pki/SignedData.h>
|
||||
#include <nn/pki/CertificateBody.h>
|
||||
#include <pietendo/hac/es/SignedData.h>
|
||||
#include <pietendo/hac/es/CertificateBody.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -27,16 +27,16 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> mCert;
|
||||
std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>> mCert;
|
||||
|
||||
void importCerts();
|
||||
void validateCerts();
|
||||
void displayCerts();
|
||||
void displayCert(const nn::pki::SignedData<nn::pki::CertificateBody>& cert);
|
||||
void displayCert(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert);
|
||||
|
||||
std::string getSignTypeStr(nn::pki::sign::SignatureId type) const;
|
||||
std::string getSignTypeStr(pie::hac::es::sign::SignatureId type) const;
|
||||
std::string getEndiannessStr(bool isLittleEndian) const;
|
||||
std::string getPublicKeyTypeStr(nn::pki::cert::PublicKeyType type) const;
|
||||
std::string getPublicKeyTypeStr(pie::hac::es::cert::PublicKeyType type) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#include "EsTikProcess.h"
|
||||
#include "PkiValidator.h"
|
||||
|
||||
#include <nn/pki/SignUtils.h>
|
||||
#include <pietendo/hac/es/SignUtils.h>
|
||||
|
||||
nstool::EsTikProcess::EsTikProcess() :
|
||||
mModuleName("nstool::EsTikProcess"),
|
||||
|
|
@ -32,7 +32,7 @@ void nstool::EsTikProcess::setKeyCfg(const KeyBag& keycfg)
|
|||
mKeyCfg = keycfg;
|
||||
}
|
||||
|
||||
void nstool::EsTikProcess::setCertificateChain(const std::vector<nn::pki::SignedData<nn::pki::CertificateBody>>& certs)
|
||||
void nstool::EsTikProcess::setCertificateChain(const std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>>& certs)
|
||||
{
|
||||
mCerts = certs;
|
||||
}
|
||||
|
|
@ -78,15 +78,15 @@ void nstool::EsTikProcess::verifyTicket()
|
|||
PkiValidator pki_validator;
|
||||
tc::ByteData tik_hash;
|
||||
|
||||
switch (nn::pki::sign::getHashAlgo(mTik.getSignature().getSignType()))
|
||||
switch (pie::hac::es::sign::getHashAlgo(mTik.getSignature().getSignType()))
|
||||
{
|
||||
case (nn::pki::sign::HASH_ALGO_SHA1):
|
||||
case (pie::hac::es::sign::HASH_ALGO_SHA1):
|
||||
tik_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize);
|
||||
tc::crypto::GenerateSha1Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size());
|
||||
break;
|
||||
case (nn::pki::sign::HASH_ALGO_SHA256):
|
||||
tik_hash = tc::ByteData(tc::crypto::Sha256Generator::kHashSize);
|
||||
tc::crypto::GenerateSha256Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size());
|
||||
case (pie::hac::es::sign::HASH_ALGO_SHA256):
|
||||
tik_hash = tc::ByteData(tc::crypto::Sha2256Generator::kHashSize);
|
||||
tc::crypto::GenerateSha2256Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -104,24 +104,24 @@ void nstool::EsTikProcess::verifyTicket()
|
|||
|
||||
void nstool::EsTikProcess::displayTicket()
|
||||
{
|
||||
const nn::es::TicketBody_V2& body = mTik.getBody();
|
||||
const pie::hac::es::TicketBody_V2& body = mTik.getBody();
|
||||
|
||||
fmt::print("[ES Ticket]\n");
|
||||
fmt::print(" SignType: {:s}", getSignTypeStr(mTik.getSignature().getSignType()));
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
fmt::print(" (0x{:x})", mTik.getSignature().getSignType());
|
||||
fmt::print(" (0x{:x})", (uint32_t)mTik.getSignature().getSignType());
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print(" Issuer: {:s}\n", body.getIssuer());
|
||||
fmt::print(" Title Key:\n");
|
||||
fmt::print(" EncMode: {:s}\n", getTitleKeyPersonalisationStr(body.getTitleKeyEncType()));
|
||||
fmt::print(" KeyGeneration: {:d}\n", (uint32_t)body.getCommonKeyId());
|
||||
if (body.getTitleKeyEncType() == nn::es::ticket::RSA2048)
|
||||
if (body.getTitleKeyEncType() == pie::hac::es::ticket::RSA2048)
|
||||
{
|
||||
fmt::print(" Data:\n");
|
||||
fmt::print(" {:s}", tc::cli::FormatUtil::formatBytesAsStringWithLineLimit(body.getEncTitleKey(), 0x100, true, "", 0x10, 6, false));
|
||||
}
|
||||
else if (body.getTitleKeyEncType() == nn::es::ticket::AES128_CBC)
|
||||
else if (body.getTitleKeyEncType() == pie::hac::es::ticket::AES128_CBC)
|
||||
{
|
||||
fmt::print(" Data:\n");
|
||||
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()));
|
||||
if (body.getPropertyFlags().size() > 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
nn::es::sTicketBody_v2* raw_body = (nn::es::sTicketBody_v2*)body.getBytes().data();
|
||||
pie::hac::es::sTicketBody_v2* raw_body = (pie::hac::es::sTicketBody_v2*)body.getBytes().data();
|
||||
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++)
|
||||
{
|
||||
|
|
@ -167,22 +167,22 @@ std::string nstool::EsTikProcess::getSignTypeStr(uint32_t type) const
|
|||
std::string str;
|
||||
switch(type)
|
||||
{
|
||||
case (nn::pki::sign::SIGN_ID_RSA4096_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA1):
|
||||
str = "RSA4096-SHA1";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA2048_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA1):
|
||||
str = "RSA2048-SHA1";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
str = "ECDSA240-SHA1";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA4096_SHA256):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA256):
|
||||
str = "RSA4096-SHA256";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA2048_SHA256):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA256):
|
||||
str = "RSA2048-SHA256";
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
str = "ECDSA240-SHA256";
|
||||
break;
|
||||
default:
|
||||
|
|
@ -197,10 +197,10 @@ std::string nstool::EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) con
|
|||
std::string str;
|
||||
switch(flag)
|
||||
{
|
||||
case (nn::es::ticket::AES128_CBC):
|
||||
case (pie::hac::es::ticket::AES128_CBC):
|
||||
str = "Generic (AESCBC)";
|
||||
break;
|
||||
case (nn::es::ticket::RSA2048):
|
||||
case (pie::hac::es::ticket::RSA2048):
|
||||
str = "Personalised (RSA2048)";
|
||||
break;
|
||||
default:
|
||||
|
|
@ -215,22 +215,22 @@ std::string nstool::EsTikProcess::getLicenseTypeStr(byte_t flag) const
|
|||
std::string str;
|
||||
switch(flag)
|
||||
{
|
||||
case (nn::es::ticket::LICENSE_PERMANENT):
|
||||
case (pie::hac::es::ticket::LICENSE_PERMANENT):
|
||||
str = "Permanent";
|
||||
break;
|
||||
case (nn::es::ticket::LICENSE_DEMO):
|
||||
case (pie::hac::es::ticket::LICENSE_DEMO):
|
||||
str = "Demo";
|
||||
break;
|
||||
case (nn::es::ticket::LICENSE_TRIAL):
|
||||
case (pie::hac::es::ticket::LICENSE_TRIAL):
|
||||
str = "Trial";
|
||||
break;
|
||||
case (nn::es::ticket::LICENSE_RENTAL):
|
||||
case (pie::hac::es::ticket::LICENSE_RENTAL):
|
||||
str = "Rental";
|
||||
break;
|
||||
case (nn::es::ticket::LICENSE_SUBSCRIPTION):
|
||||
case (pie::hac::es::ticket::LICENSE_SUBSCRIPTION):
|
||||
str = "Subscription";
|
||||
break;
|
||||
case (nn::es::ticket::LICENSE_SERVICE):
|
||||
case (pie::hac::es::ticket::LICENSE_SERVICE):
|
||||
str = "Service";
|
||||
break;
|
||||
default:
|
||||
|
|
@ -245,22 +245,22 @@ std::string nstool::EsTikProcess::getPropertyFlagStr(byte_t flag) const
|
|||
std::string str;
|
||||
switch(flag)
|
||||
{
|
||||
case (nn::es::ticket::FLAG_PRE_INSTALL):
|
||||
case (pie::hac::es::ticket::FLAG_PRE_INSTALL):
|
||||
str = "PreInstall";
|
||||
break;
|
||||
case (nn::es::ticket::FLAG_SHARED_TITLE):
|
||||
case (pie::hac::es::ticket::FLAG_SHARED_TITLE):
|
||||
str = "SharedTitle";
|
||||
break;
|
||||
case (nn::es::ticket::FLAG_ALLOW_ALL_CONTENT):
|
||||
case (pie::hac::es::ticket::FLAG_ALLOW_ALL_CONTENT):
|
||||
str = "AllContent";
|
||||
break;
|
||||
case (nn::es::ticket::FLAG_DEVICE_LINK_INDEPENDENT):
|
||||
case (pie::hac::es::ticket::FLAG_DEVICE_LINK_INDEPENDENT):
|
||||
str = "DeviceLinkIndependent";
|
||||
break;
|
||||
case (nn::es::ticket::FLAG_VOLATILE):
|
||||
case (pie::hac::es::ticket::FLAG_VOLATILE):
|
||||
str = "Volatile";
|
||||
break;
|
||||
case (nn::es::ticket::FLAG_ELICENSE_REQUIRED):
|
||||
case (pie::hac::es::ticket::FLAG_ELICENSE_REQUIRED):
|
||||
str = "ELicenseRequired";
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
#include "types.h"
|
||||
#include "KeyBag.h"
|
||||
|
||||
#include <nn/pki/SignedData.h>
|
||||
#include <nn/pki/CertificateBody.h>
|
||||
#include <nn/es/TicketBody_V2.h>
|
||||
#include <pietendo/hac/es/SignedData.h>
|
||||
#include <pietendo/hac/es/CertificateBody.h>
|
||||
#include <pietendo/hac/es/TicketBody_V2.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ public:
|
|||
|
||||
void setInputFile(const std::shared_ptr<tc::io::IStream>& file);
|
||||
void setKeyCfg(const KeyBag& keycfg);
|
||||
void setCertificateChain(const std::vector<nn::pki::SignedData<nn::pki::CertificateBody>>& certs);
|
||||
void setCertificateChain(const std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>>& certs);
|
||||
void setCliOutputMode(CliOutputMode mode);
|
||||
void setVerifyMode(bool verify);
|
||||
private:
|
||||
|
|
@ -28,9 +28,9 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> mCerts;
|
||||
std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>> mCerts;
|
||||
|
||||
nn::pki::SignedData<nn::es::TicketBody_V2> mTik;
|
||||
pie::hac::es::SignedData<pie::hac::es::TicketBody_V2> mTik;
|
||||
|
||||
void importTicket();
|
||||
void verifyTicket();
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ void nstool::FsProcess::process()
|
|||
}
|
||||
}
|
||||
|
||||
void nstool::FsProcess::setInputFileSystem(const std::shared_ptr<tc::io::IStorage>& input_fs)
|
||||
void nstool::FsProcess::setInputFileSystem(const std::shared_ptr<tc::io::IFileSystem>& input_fs)
|
||||
{
|
||||
mInputFs = input_fs;
|
||||
}
|
||||
|
|
@ -93,15 +93,12 @@ void nstool::FsProcess::extractFs()
|
|||
|
||||
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)
|
||||
if (itr->virtual_path == tc::io::Path("/"))
|
||||
{
|
||||
visitDir(tc::io::Path("/"), itr->extract_path, true, false);
|
||||
|
||||
//fmt::print("Root Dir Virtual Path: \"{:s}\"\n", path_str);
|
||||
//fmt::print("Root Dir Virtual Path: \"{:s}\"\n", itr->virtual_path.to_string());
|
||||
|
||||
// root directory extract successful, continue to next job
|
||||
continue;
|
||||
|
|
@ -112,10 +109,10 @@ void nstool::FsProcess::extractFs()
|
|||
std::shared_ptr<tc::io::IStream> file_stream;
|
||||
mInputFs->openFile(itr->virtual_path, tc::io::FileMode::Open, tc::io::FileAccess::Read, file_stream);
|
||||
|
||||
//fmt::print("Valid File Path: \"{:s}\"\n", path_str);
|
||||
//fmt::print("Valid File Path: \"{:s}\"\n", itr->virtual_path.to_string());
|
||||
|
||||
// the output path for this file will depend on the user specified extract path
|
||||
std::shared_ptr<tc::io::IStorage> local_fs = std::make_shared<tc::io::LocalStorage>(tc::io::LocalStorage());
|
||||
std::shared_ptr<tc::io::IFileSystem> local_fs = std::make_shared<tc::io::LocalFileSystem>(tc::io::LocalFileSystem());
|
||||
|
||||
// case: the extract_path is a valid path to an existing directory
|
||||
// behaviour: extract the file, preserving the original filename, to the specified directory
|
||||
|
|
@ -127,10 +124,7 @@ void nstool::FsProcess::extractFs()
|
|||
|
||||
tc::io::Path file_extract_path = itr->extract_path + itr->virtual_path.back();
|
||||
|
||||
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);
|
||||
fmt::print("Saving {:s}...\n", file_extract_path.to_string());
|
||||
|
||||
writeStreamToFile(file_stream, itr->extract_path + itr->virtual_path.back(), mDataCache);
|
||||
|
||||
|
|
@ -145,24 +139,18 @@ 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
|
||||
|
||||
try {
|
||||
std::string test_path_str;
|
||||
|
||||
// get path to parent directory
|
||||
tc::io::Path parent_dir_path = itr->extract_path;
|
||||
|
||||
// replace final path element with the current directory alias
|
||||
parent_dir_path.pop_back(); // remove filename
|
||||
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
|
||||
tc::io::sDirectoryListing dir_listing;
|
||||
local_fs->getDirectoryListing(parent_dir_path, dir_listing);
|
||||
|
||||
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);
|
||||
fmt::print("Saving {:s} as {:s}...\n", itr->virtual_path.to_string(), itr->extract_path.to_string());
|
||||
|
||||
writeStreamToFile(file_stream, itr->extract_path, mDataCache);
|
||||
|
||||
|
|
@ -173,9 +161,7 @@ void nstool::FsProcess::extractFs()
|
|||
|
||||
|
||||
// extract path could not be determined, inform the user and skip this job
|
||||
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);
|
||||
fmt::print("[WARNING] Extract path was invalid, and was skipped: {:s}\n", itr->extract_path.to_string());
|
||||
continue;
|
||||
} catch (tc::io::FileNotFoundException&) {
|
||||
// acceptable exception, just means file didn't exist
|
||||
|
|
@ -186,10 +172,9 @@ void nstool::FsProcess::extractFs()
|
|||
tc::io::sDirectoryListing dir_listing;
|
||||
mInputFs->getDirectoryListing(itr->virtual_path, dir_listing);
|
||||
|
||||
|
||||
visitDir(itr->virtual_path, itr->extract_path, true, false);
|
||||
|
||||
//fmt::print("Valid Directory Path: \"{:s}\"\n", path_str);
|
||||
//fmt::print("Valid Directory Path: \"{:s}\"\n", itr->virtual_path.to_string());
|
||||
|
||||
// directory extract successful, continue to next job
|
||||
continue;
|
||||
|
|
@ -198,14 +183,14 @@ void nstool::FsProcess::extractFs()
|
|||
// acceptable exception, just means directory didn't exist
|
||||
}
|
||||
|
||||
fmt::print("[WARNING] Failed to extract virtual path: \"{:s}\"\n", path_str);
|
||||
fmt::print("[WARNING] Failed to extract virtual path: \"{:s}\"\n", itr->virtual_path.to_string());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void nstool::FsProcess::visitDir(const tc::io::Path& v_path, const tc::io::Path& l_path, bool extract_fs, bool print_fs)
|
||||
{
|
||||
tc::io::LocalStorage local_fs;
|
||||
tc::io::LocalFileSystem local_fs;
|
||||
|
||||
// get listing for directory
|
||||
tc::io::sDirectoryListing info;
|
||||
|
|
@ -227,7 +212,6 @@ void nstool::FsProcess::visitDir(const tc::io::Path& v_path, const tc::io::Path&
|
|||
// iterate thru child files
|
||||
size_t cache_read_len;
|
||||
tc::io::Path out_path;
|
||||
std::string out_path_str;
|
||||
std::shared_ptr<tc::io::IStream> in_stream;
|
||||
std::shared_ptr<tc::io::IStream> out_stream;
|
||||
for (auto itr = info.file_list.begin(); itr != info.file_list.end(); itr++)
|
||||
|
|
@ -242,9 +226,8 @@ void nstool::FsProcess::visitDir(const tc::io::Path& v_path, const tc::io::Path&
|
|||
{
|
||||
// build out path
|
||||
out_path = l_path + *itr;
|
||||
tc::io::PathUtil::pathToUnixUTF8(out_path, out_path_str);
|
||||
|
||||
fmt::print("Saving {:s}...\n", out_path_str);
|
||||
fmt::print("Saving {:s}...\n", out_path.to_string());
|
||||
|
||||
// begin export
|
||||
mInputFs->openFile(v_path + *itr, tc::io::FileMode::Open, tc::io::FileAccess::Read, in_stream);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public:
|
|||
|
||||
void process();
|
||||
|
||||
void setInputFileSystem(const std::shared_ptr<tc::io::IStorage>& input_fs);
|
||||
void setInputFileSystem(const std::shared_ptr<tc::io::IFileSystem>& input_fs);
|
||||
void setFsFormatName(const std::string& fs_format_name);
|
||||
void setFsProperties(const std::vector<std::string>& properties);
|
||||
void setShowFsInfo(bool show_fs_info);
|
||||
|
|
@ -24,7 +24,7 @@ public:
|
|||
private:
|
||||
std::string mModuleLabel;
|
||||
|
||||
std::shared_ptr<tc::io::IStorage> mInputFs;
|
||||
std::shared_ptr<tc::io::IFileSystem> mInputFs;
|
||||
|
||||
// fs info
|
||||
tc::Optional<std::string> mFsFormatName;
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
#include <tc/crypto.h>
|
||||
#include <tc/io/IOUtil.h>
|
||||
|
||||
#include <nn/hac/GameCardUtil.h>
|
||||
#include <nn/hac/ContentMetaUtil.h>
|
||||
#include <nn/hac/ContentArchiveUtil.h>
|
||||
#include <pietendo/hac/GameCardUtil.h>
|
||||
#include <pietendo/hac/ContentMetaUtil.h>
|
||||
#include <pietendo/hac/ContentArchiveUtil.h>
|
||||
|
||||
#include <nn/hac/GameCardFsMetaGenerator.h>
|
||||
#include <pietendo/hac/GameCardFsSnapshotGenerator.h>
|
||||
#include "FsProcess.h"
|
||||
|
||||
|
||||
|
|
@ -16,10 +16,12 @@ nstool::GameCardProcess::GameCardProcess() :
|
|||
mFile(),
|
||||
mCliOutputMode(true, false, false, false),
|
||||
mVerify(false),
|
||||
mListFs(false),
|
||||
mIsTrueSdkXci(false),
|
||||
mIsSdkXciEncrypted(false),
|
||||
mGcHeaderOffset(0),
|
||||
mProccessExtendedHeader(false),
|
||||
mRootPfs(),
|
||||
mExtractJobs()
|
||||
mFileSystem(),
|
||||
mFsProcess()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -59,14 +61,14 @@ void nstool::GameCardProcess::setVerifyMode(bool verify)
|
|||
mVerify = verify;
|
||||
}
|
||||
|
||||
void nstool::GameCardProcess::setExtractJobs(const std::vector<nstool::ExtractJob> extract_jobs)
|
||||
{
|
||||
mExtractJobs = extract_jobs;
|
||||
}
|
||||
|
||||
void nstool::GameCardProcess::setShowFsTree(bool show_fs_tree)
|
||||
{
|
||||
mListFs = show_fs_tree;
|
||||
mFsProcess.setShowFsTree(show_fs_tree);
|
||||
}
|
||||
|
||||
void nstool::GameCardProcess::setExtractJobs(const std::vector<nstool::ExtractJob> extract_jobs)
|
||||
{
|
||||
mFsProcess.setExtractJobs(extract_jobs);
|
||||
}
|
||||
|
||||
void nstool::GameCardProcess::importHeader()
|
||||
|
|
@ -81,25 +83,25 @@ void nstool::GameCardProcess::importHeader()
|
|||
}
|
||||
|
||||
// check stream is large enough for header
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sSdkGcHeader)))
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sSdkGcHeader)))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt GameCard Image: File too small.");
|
||||
}
|
||||
|
||||
// allocate memory for header
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sSdkGcHeader));
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sSdkGcHeader));
|
||||
|
||||
// read header region
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read(scratch.data(), scratch.size());
|
||||
|
||||
// determine if this is a SDK XCI or a "Community" XCI
|
||||
if (((nn::hac::sSdkGcHeader*)scratch.data())->signed_header.header.st_magic.unwrap() == nn::hac::gc::kGcHeaderStructMagic)
|
||||
if (((pie::hac::sSdkGcHeader*)scratch.data())->signed_header.header.st_magic.unwrap() == pie::hac::gc::kGcHeaderStructMagic)
|
||||
{
|
||||
mIsTrueSdkXci = true;
|
||||
mGcHeaderOffset = sizeof(nn::hac::sGcKeyDataRegion);
|
||||
mGcHeaderOffset = sizeof(pie::hac::sGcKeyDataRegion);
|
||||
}
|
||||
else if (((nn::hac::sGcHeader_Rsa2048Signed*)scratch.data())->header.st_magic.unwrap() == nn::hac::gc::kGcHeaderStructMagic)
|
||||
else if (((pie::hac::sGcHeader_Rsa2048Signed*)scratch.data())->header.st_magic.unwrap() == pie::hac::gc::kGcHeaderStructMagic)
|
||||
{
|
||||
mIsTrueSdkXci = false;
|
||||
mGcHeaderOffset = 0;
|
||||
|
|
@ -109,33 +111,33 @@ void nstool::GameCardProcess::importHeader()
|
|||
throw tc::Exception(mModuleName, "Corrupt GameCard Image: Unexpected magic bytes.");
|
||||
}
|
||||
|
||||
nn::hac::sGcHeader_Rsa2048Signed* hdr_ptr = (nn::hac::sGcHeader_Rsa2048Signed*)(scratch.data() + mGcHeaderOffset);
|
||||
pie::hac::sGcHeader_Rsa2048Signed* hdr_ptr = (pie::hac::sGcHeader_Rsa2048Signed*)(scratch.data() + mGcHeaderOffset);
|
||||
|
||||
// generate hash of raw header
|
||||
tc::crypto::GenerateSha256Hash(mHdrHash.data(), (byte_t*)&hdr_ptr->header, sizeof(nn::hac::sGcHeader));
|
||||
tc::crypto::GenerateSha2256Hash(mHdrHash.data(), (byte_t*)&hdr_ptr->header, sizeof(pie::hac::sGcHeader));
|
||||
|
||||
// save the signature
|
||||
memcpy(mHdrSignature.data(), hdr_ptr->signature.data(), mHdrSignature.size());
|
||||
|
||||
// decrypt extended header
|
||||
byte_t xci_header_key_index = hdr_ptr->header.key_flag & 7;
|
||||
byte_t xci_header_key_index = hdr_ptr->header.key_flag & 0xf;
|
||||
if (mKeyCfg.xci_header_key.find(xci_header_key_index) != mKeyCfg.xci_header_key.end())
|
||||
{
|
||||
nn::hac::GameCardUtil::decryptXciHeader(&hdr_ptr->header, mKeyCfg.xci_header_key[xci_header_key_index].data());
|
||||
pie::hac::GameCardUtil::decryptXciHeader(&hdr_ptr->header, mKeyCfg.xci_header_key[xci_header_key_index].data());
|
||||
mProccessExtendedHeader = true;
|
||||
}
|
||||
|
||||
// deserialise header
|
||||
mHdr.fromBytes((byte_t*)&hdr_ptr->header, sizeof(nn::hac::sGcHeader));
|
||||
mHdr.fromBytes((byte_t*)&hdr_ptr->header, sizeof(pie::hac::sGcHeader));
|
||||
}
|
||||
|
||||
void nstool::GameCardProcess::displayHeader()
|
||||
{
|
||||
const nn::hac::sGcHeader* raw_hdr = (const nn::hac::sGcHeader*)mHdr.getBytes().data();
|
||||
const pie::hac::sGcHeader* raw_hdr = (const pie::hac::sGcHeader*)mHdr.getBytes().data();
|
||||
|
||||
fmt::print("[GameCard/Header]\n");
|
||||
fmt::print(" CardHeaderVersion: {:d}\n", mHdr.getCardHeaderVersion());
|
||||
fmt::print(" RomSize: {:s}", nn::hac::GameCardUtil::getRomSizeAsString((nn::hac::gc::RomSize)mHdr.getRomSizeType()));
|
||||
fmt::print(" RomSize: {:s}", pie::hac::GameCardUtil::getRomSizeAsString((pie::hac::gc::RomSize)mHdr.getRomSizeType()));
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
fmt::print(" (0x{:x})", mHdr.getRomSizeType());
|
||||
fmt::print("\n");
|
||||
|
|
@ -143,13 +145,13 @@ void nstool::GameCardProcess::displayHeader()
|
|||
fmt::print(" Flags: 0x{:02x}\n", *((byte_t*)&raw_hdr->flags));
|
||||
for (auto itr = mHdr.getFlags().begin(); itr != mHdr.getFlags().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}\n", nn::hac::GameCardUtil::getHeaderFlagsAsString((nn::hac::gc::HeaderFlags)*itr));
|
||||
fmt::print(" {:s}\n", pie::hac::GameCardUtil::getHeaderFlagsAsString((pie::hac::gc::HeaderFlags)*itr));
|
||||
}
|
||||
|
||||
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" KekIndex: {:s} ({:d})\n", nn::hac::GameCardUtil::getKekIndexAsString((nn::hac::gc::KekIndex)mHdr.getKekIndex()), mHdr.getKekIndex());
|
||||
fmt::print(" KekIndex: {:s} ({:d})\n", pie::hac::GameCardUtil::getKekIndexAsString((pie::hac::gc::KekIndex)mHdr.getKekIndex()), mHdr.getKekIndex());
|
||||
fmt::print(" TitleKeyDecIndex: {:d}\n", mHdr.getTitleKeyDecIndex());
|
||||
fmt::print(" InitialData:\n");
|
||||
fmt::print(" Hash:\n");
|
||||
|
|
@ -167,22 +169,22 @@ void nstool::GameCardProcess::displayHeader()
|
|||
{
|
||||
fmt::print(" RomAreaStartPage: 0x{:x}", mHdr.getRomAreaStartPage());
|
||||
if (mHdr.getRomAreaStartPage() != (uint32_t)(-1))
|
||||
fmt::print(" (0x{:x})", nn::hac::GameCardUtil::blockToAddr(mHdr.getRomAreaStartPage()));
|
||||
fmt::print(" (0x{:x})", pie::hac::GameCardUtil::blockToAddr(mHdr.getRomAreaStartPage()));
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print(" BackupAreaStartPage: 0x{:x}", mHdr.getBackupAreaStartPage());
|
||||
if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1))
|
||||
fmt::print(" (0x{:x})", nn::hac::GameCardUtil::blockToAddr(mHdr.getBackupAreaStartPage()));
|
||||
fmt::print(" (0x{:x})", pie::hac::GameCardUtil::blockToAddr(mHdr.getBackupAreaStartPage()));
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print(" ValidDataEndPage: 0x{:x}", mHdr.getValidDataEndPage());
|
||||
if (mHdr.getValidDataEndPage() != (uint32_t)(-1))
|
||||
fmt::print(" (0x{:x})", nn::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage()));
|
||||
fmt::print(" (0x{:x})", pie::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage()));
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print(" LimArea: 0x{:x}", mHdr.getLimAreaPage());
|
||||
if (mHdr.getLimAreaPage() != (uint32_t)(-1))
|
||||
fmt::print(" (0x{:x})", nn::hac::GameCardUtil::blockToAddr(mHdr.getLimAreaPage()));
|
||||
fmt::print(" (0x{:x})", pie::hac::GameCardUtil::blockToAddr(mHdr.getLimAreaPage()));
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print(" PartitionFs Header:\n");
|
||||
|
|
@ -199,17 +201,17 @@ void nstool::GameCardProcess::displayHeader()
|
|||
if (mProccessExtendedHeader)
|
||||
{
|
||||
fmt::print("[GameCard/ExtendedHeader]\n");
|
||||
fmt::print(" FwVersion: v{:d} ({:s})\n", mHdr.getFwVersion(), nn::hac::GameCardUtil::getCardFwVersionDescriptionAsString((nn::hac::gc::FwVersion)mHdr.getFwVersion()));
|
||||
fmt::print(" FwVersion: v{:d} ({:s})\n", mHdr.getFwVersion(), pie::hac::GameCardUtil::getCardFwVersionDescriptionAsString((pie::hac::gc::FwVersion)mHdr.getFwVersion()));
|
||||
fmt::print(" AccCtrl1: 0x{:x}\n", mHdr.getAccCtrl1());
|
||||
fmt::print(" CardClockRate: {:s}\n", nn::hac::GameCardUtil::getCardClockRateAsString((nn::hac::gc::CardClockRate)mHdr.getAccCtrl1()));
|
||||
fmt::print(" CardClockRate: {:s}\n", pie::hac::GameCardUtil::getCardClockRateAsString((pie::hac::gc::CardClockRate)mHdr.getAccCtrl1()));
|
||||
fmt::print(" Wait1TimeRead: 0x{:x}\n", mHdr.getWait1TimeRead());
|
||||
fmt::print(" Wait2TimeRead: 0x{:x}\n", mHdr.getWait2TimeRead());
|
||||
fmt::print(" Wait1TimeWrite: 0x{:x}\n", mHdr.getWait1TimeWrite());
|
||||
fmt::print(" Wait2TimeWrite: 0x{:x}\n", mHdr.getWait2TimeWrite());
|
||||
fmt::print(" SdkAddon Version: {:s} (v{:d})\n", nn::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getFwMode()), mHdr.getFwMode());
|
||||
fmt::print(" CompatibilityType: {:s} ({:d})\n", nn::hac::GameCardUtil::getCompatibilityTypeAsString((nn::hac::gc::CompatibilityType)mHdr.getCompatibilityType()), mHdr.getCompatibilityType());
|
||||
fmt::print(" SdkAddon Version: {:s} (v{:d})\n", pie::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(" Update Partition Info:\n");
|
||||
fmt::print(" CUP Version: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mHdr.getUppVersion()), mHdr.getUppVersion());
|
||||
fmt::print(" CUP Version: {:s} (v{:d})\n", pie::hac::ContentMetaUtil::getVersionAsString(mHdr.getUppVersion()), mHdr.getUppVersion());
|
||||
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, ""));
|
||||
}
|
||||
|
|
@ -223,14 +225,14 @@ bool nstool::GameCardProcess::validateRegionOfFile(int64_t offset, int64_t len,
|
|||
mFile->read(scratch.data(), scratch.size());
|
||||
|
||||
// update hash
|
||||
tc::crypto::Sha256Generator sha256_gen;
|
||||
tc::crypto::Sha2256Generator sha256_gen;
|
||||
sha256_gen.initialize();
|
||||
sha256_gen.update(scratch.data(), scratch.size());
|
||||
if (use_salt)
|
||||
sha256_gen.update(&salt, sizeof(salt));
|
||||
|
||||
// calculate hash
|
||||
nn::hac::detail::sha256_hash_t calc_hash;
|
||||
pie::hac::detail::sha256_hash_t calc_hash;
|
||||
sha256_gen.getHash(calc_hash.data());
|
||||
|
||||
return memcmp(calc_hash.data(), test_hash, calc_hash.size()) == 0;
|
||||
|
|
@ -245,7 +247,7 @@ void nstool::GameCardProcess::validateXciSignature()
|
|||
{
|
||||
if (mKeyCfg.xci_header_sign_key.isSet())
|
||||
{
|
||||
if (tc::crypto::VerifyRsa2048Pkcs1Sha256(mHdrSignature.data(), mHdrHash.data(), mKeyCfg.xci_header_sign_key.get()) == false)
|
||||
if (tc::crypto::VerifyRsa2048Pkcs1Sha2256(mHdrSignature.data(), mHdrHash.data(), mKeyCfg.xci_header_sign_key.get()) == false)
|
||||
{
|
||||
fmt::print("[WARNING] GameCard Header Signature: FAIL\n");
|
||||
}
|
||||
|
|
@ -258,29 +260,24 @@ void nstool::GameCardProcess::validateXciSignature()
|
|||
|
||||
void nstool::GameCardProcess::processRootPfs()
|
||||
{
|
||||
if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().data(), mHdr.getCompatibilityType() != nn::hac::gc::COMPAT_GLOBAL, mHdr.getCompatibilityType()) == false)
|
||||
if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().data(), mHdr.getCompatibilityType() != pie::hac::gc::CompatibilityType_Global, mHdr.getCompatibilityType()) == false)
|
||||
{
|
||||
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(), nn::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(), pie::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage()+1) - mHdr.getPartitionFsAddress()));
|
||||
|
||||
auto gc_vfs_meta = nn::hac::GameCardFsMetaGenerator(gc_fs_raw, mHdr.getPartitionFsSize(), mVerify ? nn::hac::GameCardFsMetaGenerator::ValidationMode_Warn : nn::hac::GameCardFsMetaGenerator::ValidationMode_None);
|
||||
std::shared_ptr<tc::io::IStorage> gc_vfs = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(gc_vfs_meta) );
|
||||
auto gc_vfs_snapshot = pie::hac::GameCardFsSnapshotGenerator(gc_fs_raw, mHdr.getPartitionFsSize(), mVerify ? pie::hac::GameCardFsSnapshotGenerator::ValidationMode_Warn : pie::hac::GameCardFsSnapshotGenerator::ValidationMode_None);
|
||||
mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(gc_vfs_snapshot) );
|
||||
|
||||
FsProcess fs_proc;
|
||||
|
||||
fs_proc.setInputFileSystem(gc_vfs);
|
||||
fs_proc.setFsFormatName("PartitionFs");
|
||||
fs_proc.setFsProperties({
|
||||
mFsProcess.setInputFileSystem(mFileSystem);
|
||||
mFsProcess.setFsFormatName("PartitionFs");
|
||||
mFsProcess.setFsProperties({
|
||||
fmt::format("Type: Nested HFS0"),
|
||||
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_meta.file_entries.size())
|
||||
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("FileNum: {:d}", gc_vfs_snapshot.file_entries.size())
|
||||
});
|
||||
fs_proc.setShowFsInfo(mCliOutputMode.show_basic_info);
|
||||
fs_proc.setShowFsTree(mListFs);
|
||||
fs_proc.setFsRootLabel(kXciMountPointName);
|
||||
fs_proc.setExtractJobs(mExtractJobs);
|
||||
|
||||
fs_proc.process();
|
||||
mFsProcess.setShowFsInfo(mCliOutputMode.show_basic_info);
|
||||
mFsProcess.setFsRootLabel(kXciMountPointName);
|
||||
mFsProcess.process();
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
#include "KeyBag.h"
|
||||
#include "PfsProcess.h"
|
||||
|
||||
#include <nn/hac/GameCardHeader.h>
|
||||
#include <pietendo/hac/GameCardHeader.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -32,18 +32,18 @@ private:
|
|||
KeyBag mKeyCfg;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
bool mListFs;
|
||||
|
||||
bool mIsTrueSdkXci;
|
||||
bool mIsSdkXciEncrypted;
|
||||
size_t mGcHeaderOffset;
|
||||
bool mProccessExtendedHeader;
|
||||
nn::hac::detail::rsa2048_signature_t mHdrSignature;
|
||||
nn::hac::detail::sha256_hash_t mHdrHash;
|
||||
nn::hac::GameCardHeader mHdr;
|
||||
pie::hac::detail::rsa2048_signature_t mHdrSignature;
|
||||
pie::hac::detail::sha256_hash_t mHdrHash;
|
||||
pie::hac::GameCardHeader mHdr;
|
||||
|
||||
PfsProcess mRootPfs;
|
||||
std::vector<nstool::ExtractJob> mExtractJobs;
|
||||
// fs processing
|
||||
std::shared_ptr<tc::io::IFileSystem> mFileSystem;
|
||||
FsProcess mFsProcess;
|
||||
|
||||
void importHeader();
|
||||
void displayHeader();
|
||||
|
|
|
|||
|
|
@ -59,13 +59,13 @@ void nstool::IniProcess::importHeader()
|
|||
}
|
||||
|
||||
// check if file_size is smaller than INI header size
|
||||
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sIniHeader))
|
||||
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(pie::hac::sIniHeader))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt INI: file too small.");
|
||||
}
|
||||
|
||||
// read ini
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sIniHeader));
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sIniHeader));
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read(scratch.data(), scratch.size());
|
||||
|
||||
|
|
@ -76,12 +76,12 @@ void nstool::IniProcess::importHeader()
|
|||
void nstool::IniProcess::importKipList()
|
||||
{
|
||||
// kip pos info
|
||||
int64_t kip_pos = tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sIniHeader));
|
||||
int64_t kip_pos = tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sIniHeader));
|
||||
int64_t kip_size = 0;
|
||||
|
||||
// tmp data to determine size
|
||||
nn::hac::sKipHeader hdr_raw;
|
||||
nn::hac::KernelInitialProcessHeader hdr;
|
||||
pie::hac::sKipHeader hdr_raw;
|
||||
pie::hac::KernelInitialProcessHeader hdr;
|
||||
|
||||
for (size_t i = 0; i < mHdr.getKipNum(); i++)
|
||||
{
|
||||
|
|
@ -121,12 +121,11 @@ void nstool::IniProcess::extractKipList()
|
|||
tc::ByteData cache = tc::ByteData(kCacheSize);
|
||||
|
||||
// make extract dir
|
||||
tc::io::LocalStorage local_fs;
|
||||
tc::io::LocalFileSystem local_fs;
|
||||
local_fs.createDirectory(mKipExtractPath.get());
|
||||
|
||||
// out path for extracted KIP
|
||||
tc::io::Path out_path;
|
||||
std::string out_path_str;
|
||||
|
||||
// extract KIPs
|
||||
for (auto itr = mKipList.begin(); itr != mKipList.end(); itr++)
|
||||
|
|
@ -134,17 +133,15 @@ void nstool::IniProcess::extractKipList()
|
|||
out_path = mKipExtractPath.get();
|
||||
out_path += fmt::format("{:s}.kip", itr->hdr.getName());
|
||||
|
||||
tc::io::PathUtil::pathToUnixUTF8(out_path, out_path_str);
|
||||
|
||||
if (mCliOutputMode.show_basic_info)
|
||||
fmt::print("Saving {:s}...\n", out_path_str);
|
||||
fmt::print("Saving {:s}...\n", out_path.to_string());
|
||||
|
||||
writeStreamToFile(itr->stream, out_path, cache);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t nstool::IniProcess::getKipSizeFromHeader(const nn::hac::KernelInitialProcessHeader& hdr) const
|
||||
int64_t nstool::IniProcess::getKipSizeFromHeader(const pie::hac::KernelInitialProcessHeader& hdr) const
|
||||
{
|
||||
// the order of elements in a KIP are sequential, there are no file offsets
|
||||
return int64_t(sizeof(nn::hac::sKipHeader)) + int64_t(hdr.getTextSegmentInfo().file_layout.size + hdr.getRoSegmentInfo().file_layout.size + hdr.getDataSegmentInfo().file_layout.size);
|
||||
return int64_t(sizeof(pie::hac::sKipHeader)) + int64_t(hdr.getTextSegmentInfo().file_layout.size + hdr.getRoSegmentInfo().file_layout.size + hdr.getDataSegmentInfo().file_layout.size);
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
#include <nn/hac/IniHeader.h>
|
||||
#include <nn/hac/KernelInitialProcessHeader.h>
|
||||
#include <pietendo/hac/IniHeader.h>
|
||||
#include <pietendo/hac/KernelInitialProcessHeader.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -29,10 +29,10 @@ private:
|
|||
|
||||
tc::Optional<tc::io::Path> mKipExtractPath;
|
||||
|
||||
nn::hac::IniHeader mHdr;
|
||||
pie::hac::IniHeader mHdr;
|
||||
struct InnerKipInfo
|
||||
{
|
||||
nn::hac::KernelInitialProcessHeader hdr;
|
||||
pie::hac::KernelInitialProcessHeader hdr;
|
||||
std::shared_ptr<tc::io::IStream> stream;
|
||||
};
|
||||
std::vector<InnerKipInfo> mKipList;
|
||||
|
|
@ -43,7 +43,7 @@ private:
|
|||
void displayKipList();
|
||||
void extractKipList();
|
||||
|
||||
int64_t getKipSizeFromHeader(const nn::hac::KernelInitialProcessHeader& hdr) const;
|
||||
int64_t getKipSizeFromHeader(const pie::hac::KernelInitialProcessHeader& hdr) const;
|
||||
};
|
||||
|
||||
}
|
||||
162
src/KeyBag.cpp
162
src/KeyBag.cpp
|
|
@ -3,28 +3,33 @@
|
|||
#include "util.h"
|
||||
#include <tc/cli/FormatUtil.h>
|
||||
|
||||
#include <nn/hac/define/types.h>
|
||||
#include <nn/hac/define/gc.h>
|
||||
#include <nn/hac/AesKeygen.h>
|
||||
#include <pietendo/hac/define/types.h>
|
||||
#include <pietendo/hac/define/gc.h>
|
||||
#include <pietendo/hac/AesKeygen.h>
|
||||
|
||||
#include <nn/pki/SignUtils.h>
|
||||
#include <nn/pki/SignedData.h>
|
||||
#include <nn/pki/CertificateBody.h>
|
||||
#include <nn/es/TicketBody_V2.h>
|
||||
#include <pietendo/hac/es/SignUtils.h>
|
||||
#include <pietendo/hac/es/SignedData.h>
|
||||
#include <pietendo/hac/es/CertificateBody.h>
|
||||
#include <pietendo/hac/es/TicketBody_V2.h>
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
if (keyfile_path.isSet())
|
||||
{
|
||||
importBaseKeyFile(keyfile_path.get(), isDev);
|
||||
}
|
||||
if (titlekeyfile_path.isSet())
|
||||
{
|
||||
importTitleKeyFile(titlekeyfile_path.get());
|
||||
}
|
||||
if (cert_path.isSet())
|
||||
{
|
||||
importCertificateChain(cert_path.get());
|
||||
}
|
||||
if (tik_path.isSet())
|
||||
if (!tik_path_list.empty())
|
||||
{
|
||||
importTicket(tik_path.get());
|
||||
for (auto itr = tik_path_list.begin(); itr != tik_path_list.end(); itr++)
|
||||
importTicket(*itr);
|
||||
}
|
||||
|
||||
// this will populate known keys if they aren't supplied by the user provided keyfiles.
|
||||
|
|
@ -352,7 +357,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)
|
||||
//fmt::print("{:s}_{:s}\n", kXciHeaderBase[name_idx], kKeyStr);
|
||||
_SAVE_AES128KEY(fmt::format("{:s}_{:s}", kXciHeaderBase[name_idx], kKeyStr), xci_header_key[isDev ? nn::hac::gc::KEK_DEV : nn::hac::gc::KEK_PROD]);
|
||||
_SAVE_AES128KEY(fmt::format("{:s}_{:s}", kXciHeaderBase[name_idx], kKeyStr), xci_header_key[isDev ? pie::hac::gc::KekIndex_Dev : pie::hac::gc::KekIndex_Prod]);
|
||||
|
||||
// xci header sign key
|
||||
//fmt::print("{:s}_{:s}_{:s}\n", kXciHeaderBase[name_idx], kSignKey, kPrivateStr);
|
||||
|
|
@ -404,22 +409,22 @@ void nstool::KeyBagInitializer::importBaseKeyFile(const tc::io::Path& keyfile_pa
|
|||
if (nca_header_key.isNull())
|
||||
{
|
||||
aes128_key_t nca_header_kek_tmp;
|
||||
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());
|
||||
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());
|
||||
|
||||
aes128_xtskey_t nca_header_key_tmp;
|
||||
nn::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[1].data(), nca_header_key_source.get()[1].data(), nca_header_kek_tmp.data());
|
||||
pie::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());
|
||||
|
||||
nca_header_key = nca_header_key_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t keak_idx = 0; keak_idx < nn::hac::nca::kKeyAreaEncryptionKeyNum; keak_idx++)
|
||||
for (size_t keak_idx = 0; keak_idx < pie::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;
|
||||
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());
|
||||
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());
|
||||
nca_key_area_encryption_key[keak_idx][itr->first] = nca_key_area_encryption_key_tmp;
|
||||
}
|
||||
}
|
||||
|
|
@ -427,13 +432,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())
|
||||
{
|
||||
aes128_key_t etik_common_key_tmp;
|
||||
nn::hac::AesKeygen::generateKey(etik_common_key_tmp.data(), ticket_titlekek_source.get().data(), itr->second.data());
|
||||
pie::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;
|
||||
}
|
||||
if (package2_key_source.isSet() && pkg2_key.find(itr->first) == pkg2_key.end())
|
||||
{
|
||||
aes128_key_t pkg2_key_tmp;
|
||||
nn::hac::AesKeygen::generateKey(pkg2_key_tmp.data(), package2_key_source.get().data(), itr->second.data());
|
||||
pie::hac::AesKeygen::generateKey(pkg2_key_tmp.data(), package2_key_source.get().data(), itr->second.data());
|
||||
pkg2_key[itr->first] = pkg2_key_tmp;
|
||||
}
|
||||
}
|
||||
|
|
@ -441,28 +446,58 @@ void nstool::KeyBagInitializer::importBaseKeyFile(const tc::io::Path& keyfile_pa
|
|||
// Save PKI Root Key
|
||||
if (pki_root_sign_key.isSet())
|
||||
{
|
||||
broadon_signer["Root"] = { tc::ByteData(), nn::pki::sign::SIGN_ALGO_RSA4096, pki_root_sign_key.get() };
|
||||
broadon_signer["Root"] = { tc::ByteData(), pie::hac::es::sign::SIGN_ALGO_RSA4096, pki_root_sign_key.get() };
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// save file path string for error messages
|
||||
std::string cert_path_str;
|
||||
tc::io::PathUtil::pathToUnixUTF8(cert_path, cert_path_str);
|
||||
|
||||
// open cert file
|
||||
std::shared_ptr<tc::io::FileStream> certfile_stream;
|
||||
try {
|
||||
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) {
|
||||
fmt::print("[WARNING] Failed to open certificate file \"{:s}\" ({:s}).\n", cert_path_str, e.error());
|
||||
fmt::print("[WARNING] Failed to open certificate file \"{:s}\" ({:s}).\n", cert_path.to_string(), e.error());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -470,7 +505,7 @@ void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_
|
|||
size_t cert_raw_size = tc::io::IOUtil::castInt64ToSize(certfile_stream->length());
|
||||
if (cert_raw_size > 0x10000)
|
||||
{
|
||||
fmt::print("[WARNING] Certificate file \"{:s}\" was too large.\n", cert_path_str);
|
||||
fmt::print("[WARNING] Certificate file \"{:s}\" was too large.\n", cert_path.to_string());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -479,7 +514,7 @@ void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_
|
|||
certfile_stream->seek(0, tc::io::SeekOrigin::Begin);
|
||||
certfile_stream->read(cert_raw.data(), cert_raw.size());
|
||||
|
||||
nn::pki::SignedData<nn::pki::CertificateBody> cert;
|
||||
pie::hac::es::SignedData<pie::hac::es::CertificateBody> cert;
|
||||
try {
|
||||
for (size_t f_pos = 0; f_pos < cert_raw.size(); f_pos += cert.getBytes().size())
|
||||
{
|
||||
|
|
@ -488,14 +523,14 @@ void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_
|
|||
std::string cert_identity = fmt::format("{:s}-{:s}", cert.getBody().getIssuer(), cert.getBody().getSubject());
|
||||
|
||||
switch (cert.getBody().getPublicKeyType()) {
|
||||
case nn::pki::cert::PublicKeyType::RSA2048:
|
||||
broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_RSA2048, cert.getBody().getRsa2048PublicKey() };
|
||||
case pie::hac::es::cert::PublicKeyType::RSA2048:
|
||||
broadon_signer[cert_identity] = { cert.getBytes(), pie::hac::es::sign::SIGN_ALGO_RSA2048, cert.getBody().getRsa2048PublicKey() };
|
||||
break;
|
||||
case nn::pki::cert::PublicKeyType::RSA4096:
|
||||
broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_RSA4096, cert.getBody().getRsa4096PublicKey() };
|
||||
case pie::hac::es::cert::PublicKeyType::RSA4096:
|
||||
broadon_signer[cert_identity] = { cert.getBytes(), pie::hac::es::sign::SIGN_ALGO_RSA4096, cert.getBody().getRsa4096PublicKey() };
|
||||
break;
|
||||
case nn::pki::cert::PublicKeyType::ECDSA240:
|
||||
// broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_ECDSA240, cert.getBody().getRsa4096PublicKey() };
|
||||
case pie::hac::es::cert::PublicKeyType::ECDSA240:
|
||||
// broadon_signer[cert_identity] = { cert.getBytes(), pie::hac::es::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);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -504,24 +539,20 @@ void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_
|
|||
}
|
||||
}
|
||||
catch (tc::Exception& e) {
|
||||
fmt::print("[WARNING] Certificate file \"{:s}\" is corrupted ({:s}).\n", cert_path_str, e.error());
|
||||
fmt::print("[WARNING] Certificate file \"{:s}\" is corrupted ({:s}).\n", cert_path.to_string(), e.error());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
std::shared_ptr<tc::io::FileStream> tik_stream;
|
||||
try {
|
||||
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) {
|
||||
fmt::print("[WARNING] Failed to open ticket \"{:s}\" ({:s}).\n", tik_path_str, e.error());
|
||||
fmt::print("[WARNING] Failed to open ticket \"{:s}\" ({:s}).\n", tik_path.to_string(), e.error());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -529,7 +560,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
|
|||
size_t tik_raw_size = tc::io::IOUtil::castInt64ToSize(tik_stream->length());
|
||||
if (tik_raw_size > 0x10000)
|
||||
{
|
||||
fmt::print("[WARNING] Ticket \"{:s}\" was too large.\n", tik_path_str);
|
||||
fmt::print("[WARNING] Ticket \"{:s}\" was too large.\n", tik_path.to_string());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -538,7 +569,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
|
|||
tik_stream->seek(0, tc::io::SeekOrigin::Begin);
|
||||
tik_stream->read(tik_raw.data(), tik_raw.size());
|
||||
|
||||
nn::pki::SignedData<nn::es::TicketBody_V2> tik;
|
||||
pie::hac::es::SignedData<pie::hac::es::TicketBody_V2> tik;
|
||||
try {
|
||||
// de serialise ticket
|
||||
tik.fromBytes(tik_raw.data(), tik_raw.size());
|
||||
|
|
@ -548,7 +579,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
|
|||
memcpy(rights_id.data(), tik.getBody().getRightsId(), rights_id.size());
|
||||
|
||||
// check ticket is not personalised
|
||||
if (tik.getBody().getTitleKeyEncType() != nn::es::ticket::AES128_CBC)
|
||||
if (tik.getBody().getTitleKeyEncType() != pie::hac::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, ""));
|
||||
return;
|
||||
|
|
@ -559,10 +590,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
|
|||
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
|
||||
if (fallback_enc_content_key.isNull())
|
||||
{
|
||||
fallback_enc_content_key = enc_title_key;
|
||||
}
|
||||
external_enc_content_keys[rights_id] = enc_title_key;
|
||||
|
||||
// determine key to decrypt title key
|
||||
byte_t common_key_index = tik.getBody().getCommonKeyId();
|
||||
|
|
@ -577,7 +605,7 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
|
|||
}
|
||||
|
||||
// convert key_generation
|
||||
common_key_index = nn::hac::AesKeygen::getMasterKeyRevisionFromKeyGeneration(common_key_index);
|
||||
common_key_index = pie::hac::AesKeygen::getMasterKeyRevisionFromKeyGeneration(common_key_index);
|
||||
|
||||
if (etik_common_key.find(common_key_index) == etik_common_key.end())
|
||||
{
|
||||
|
|
@ -589,19 +617,19 @@ void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
|
|||
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));
|
||||
|
||||
// add to key dict
|
||||
// add to decrypted key dict
|
||||
external_content_keys[rights_id] = dec_title_key;
|
||||
|
||||
}
|
||||
catch (tc::Exception& e) {
|
||||
fmt::print("[WARNING] Ticket \"{:s}\" is corrupted ({:s}).\n", tik_path_str, e.error());
|
||||
fmt::print("[WARNING] Ticket \"{:s}\" is corrupted ({:s}).\n", tik_path.to_string(), e.error());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
||||
{
|
||||
static const nn::hac::detail::rsa2048_block_t kXciHeaderSignModulus = {
|
||||
static const pie::hac::detail::rsa2048_block_t kXciHeaderSignModulus = {
|
||||
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,
|
||||
0x8D, 0xFA, 0x17, 0xAA, 0x6B, 0xC6, 0x36, 0x6D, 0x4C, 0x9A, 0x6D, 0x57, 0x2F, 0x80, 0xA2, 0xBC,
|
||||
|
|
@ -620,7 +648,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|||
0x9A, 0xC1, 0xDD, 0x62, 0x86, 0x9C, 0x2E, 0xE1, 0x2D, 0x6F, 0x62, 0x67, 0x51, 0x08, 0x0E, 0xCF
|
||||
};
|
||||
|
||||
static const nn::hac::detail::rsa2048_block_t kXciCertSignModulus = {
|
||||
static const pie::hac::detail::rsa2048_block_t kXciCertSignModulus = {
|
||||
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,
|
||||
0xB1, 0x55, 0x23, 0xD8, 0xA5, 0x60, 0x91, 0x26, 0x48, 0x1A, 0x80, 0x4A, 0xEA, 0x00, 0x98, 0x2A,
|
||||
|
|
@ -641,7 +669,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|||
|
||||
/* Keydata for very early beta NCA0 archives' RSA-OAEP. */
|
||||
/*
|
||||
static const nn::hac::detail::rsa2048_block_t beta_nca0_modulus = {
|
||||
static const pie::hac::detail::rsa2048_block_t beta_nca0_modulus = {
|
||||
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,
|
||||
0xB7, 0xEB, 0x40, 0xA1, 0xE7, 0xEB, 0xDC, 0x60, 0xD0, 0x3D, 0xC5, 0x50, 0x92, 0xAD, 0x3D, 0xC4,
|
||||
|
|
@ -660,7 +688,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|||
0xB0, 0xB4, 0xD0, 0x17, 0xA1, 0x0F, 0x73, 0x98, 0x5A, 0xF6, 0xEE, 0xC0, 0x2F, 0x9E, 0xCE, 0xC5
|
||||
};
|
||||
|
||||
static const nn::hac::detail::sha256_hash_t beta_nca0_label_hash = {
|
||||
static const pie::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,
|
||||
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
|
||||
};
|
||||
|
|
@ -668,10 +696,10 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|||
|
||||
struct sRsaKeyForGeneration {
|
||||
byte_t generation;
|
||||
nn::hac::detail::rsa2048_block_t modulus;
|
||||
pie::hac::detail::rsa2048_block_t modulus;
|
||||
};
|
||||
|
||||
static const nn::hac::detail::rsa2048_block_t kProdPackage2HeaderModulus = {
|
||||
static const pie::hac::detail::rsa2048_block_t kProdPackage2HeaderModulus = {
|
||||
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,
|
||||
0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5,
|
||||
|
|
@ -774,7 +802,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|||
},
|
||||
};
|
||||
|
||||
static const nn::hac::detail::rsa2048_block_t kDevPackage2HeaderModulus = {
|
||||
static const pie::hac::detail::rsa2048_block_t kDevPackage2HeaderModulus = {
|
||||
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,
|
||||
0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6,
|
||||
|
|
@ -880,7 +908,7 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|||
struct sBroadOnRsaKeyAndCert
|
||||
{
|
||||
std::string issuer;
|
||||
nn::pki::sign::SignatureAlgo key_type;
|
||||
pie::hac::es::sign::SignatureAlgo key_type;
|
||||
tc::ByteData modulus;
|
||||
tc::ByteData certificate;
|
||||
};
|
||||
|
|
@ -889,31 +917,31 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|||
{
|
||||
{
|
||||
"Root",
|
||||
nn::pki::sign::SIGN_ALGO_RSA4096,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA4096,
|
||||
tc::cli::FormatUtil::hexStringToBytes("F8246C58BAE7500301FBB7C2EBE0010571DA922378F0514EC0031DD0D21ED3D07EFC852069B5DE9BB951A8BC90A244926D379295AE9436AAA6A302510C7B1DEDD5FB20869D7F3016F6BE65D383A16DB3321B95351890B17002937EE193F57E99A2474E9D3824C7AEE38541F567E7518C7A0E38E7EBAF41191BCFF17B42A6B4EDE6CE8DE7318F7F5204B3990E226745AFD485B24493008B08C7F6B7E56B02B3E8FE0C9D859CB8B68223B8AB27EE5F6538078B2DB91E2A153E85818072A23B6DD93281054F6FB0F6F5AD283ECA0B7AF35455E03DA7B68326F3EC834AF314048AC6DF20D28508673CAB62A2C7BC131A533E0B66806B1C30664B372331BDC4B0CAD8D11EE7BBD9285548AAEC1F66E821B3C8A0476900C5E688E80CCE3C61D69CBBA137C6604F7A72DD8C7B3E3D51290DAA6A597B081F9D3633A3467A356109ACA7DD7D2E2FB2C1AEB8E20F4892D8B9F8B46F4E3C11F4F47D8B757DFEFEA3899C33595C5EFDEBCBABE8413E3A9A803C69356EB2B2AD5CC4C858455EF5F7B30644B47C64068CDF809F76025A2DB446E03D7CF62F34E702457B02A4CF5D9DD53CA53A7CA629788C67CA08BFECCA43A957AD16C94E1CD875CA107DCE7E0118F0DF6BFEE51DDBD991C26E60CD4858AA592C820075F29F526C917C6FE5403EA7D4A50CEC3B7384DE886E82D2EB4D4E42B5F2B149A81EA7CE7144DC2994CFC44E1F91CBD495"),
|
||||
tc::ByteData()
|
||||
},
|
||||
{
|
||||
"Root-CA00000003",
|
||||
nn::pki::sign::SIGN_ALGO_RSA2048,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA2048,
|
||||
tc::cli::FormatUtil::hexStringToBytes("B279C9E2EEE121C6EAF44FF639F88F078B4B77ED9F9560B0358281B50E55AB721115A177703C7A30FE3AE9EF1C60BC1D974676B23A68CC04B198525BC968F11DE2DB50E4D9E7F071E562DAE2092233E9D363F61DD7C19FF3A4A91E8F6553D471DD7B84B9F1B8CE7335F0F5540563A1EAB83963E09BE901011F99546361287020E9CC0DAB487F140D6626A1836D27111F2068DE4772149151CF69C61BA60EF9D949A0F71F5499F2D39AD28C7005348293C431FFBD33F6BCA60DC7195EA2BCC56D200BAF6D06D09C41DB8DE9C720154CA4832B69C08C69CD3B073A0063602F462D338061A5EA6C915CD5623579C3EB64CE44EF586D14BAAA8834019B3EEBEED379"),
|
||||
tc::cli::FormatUtil::hexStringToBytes("00010003704138EFBBBDA16A987DD901326D1C9459484C88A2861B91A312587AE70EF6237EC50E1032DC39DDE89A96A8E859D76A98A6E7E36A0CFE352CA893058234FF833FCB3B03811E9F0DC0D9A52F8045B4B2F9411B67A51C44B5EF8CE77BD6D56BA75734A1856DE6D4BED6D3A242C7C8791B3422375E5C779ABF072F7695EFA0F75BCB83789FC30E3FE4CC8392207840638949C7F688565F649B74D63D8D58FFADDA571E9554426B1318FC468983D4C8A5628B06B6FC5D507C13E7A18AC1511EB6D62EA5448F83501447A9AFB3ECC2903C9DD52F922AC9ACDBEF58C6021848D96E208732D3D1D9D9EA440D91621C7A99DB8843C59C1F2E2C7D9B577D512C166D6F7E1AAD4A774A37447E78FE2021E14A95D112A068ADA019F463C7A55685AABB6888B9246483D18B9C806F474918331782344A4B8531334B26303263D9D2EB4F4BB99602B352F6AE4046C69A5E7E8E4A18EF9BC0A2DED61310417012FD824CC116CFB7C4C1F7EC7177A17446CBDE96F3EDD88FCD052F0B888A45FDAF2B631354F40D16E5FA9C2C4EDA98E798D15E6046DC5363F3096B2C607A9D8DD55B1502A6AC7D3CC8D8C575998E7D796910C804C495235057E91ECD2637C9C1845151AC6B9A0490AE3EC6F47740A0DB0BA36D075956CEE7354EA3E9A4F2720B26550C7D394324BC0CB7E9317D8A8661F42191FF10B08256CE3FD25B745E5194906B4D61CB4C2E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001434130303030303030330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007BE8EF6CB279C9E2EEE121C6EAF44FF639F88F078B4B77ED9F9560B0358281B50E55AB721115A177703C7A30FE3AE9EF1C60BC1D974676B23A68CC04B198525BC968F11DE2DB50E4D9E7F071E562DAE2092233E9D363F61DD7C19FF3A4A91E8F6553D471DD7B84B9F1B8CE7335F0F5540563A1EAB83963E09BE901011F99546361287020E9CC0DAB487F140D6626A1836D27111F2068DE4772149151CF69C61BA60EF9D949A0F71F5499F2D39AD28C7005348293C431FFBD33F6BCA60DC7195EA2BCC56D200BAF6D06D09C41DB8DE9C720154CA4832B69C08C69CD3B073A0063602F462D338061A5EA6C915CD5623579C3EB64CE44EF586D14BAAA8834019B3EEBEED3790001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
},
|
||||
{
|
||||
"Root-CA00000003-XS00000020",
|
||||
nn::pki::sign::SIGN_ALGO_RSA2048,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA2048,
|
||||
tc::cli::FormatUtil::hexStringToBytes("D21D3CE67C1069DA049D5E5310E76B907E18EEC80B337C4723E339573F4C664907DB2F0832D03DF5EA5F160A4AF24100D71AFAC2E3AE75AFA1228012A9A21616597DF71EAFCB65941470D1B40F5EF83A597E179FCB5B57C2EE17DA3BC3769864CB47856767229D67328141FC9AB1DF149E0C5C15AEB80BC58FC71BE18966642D68308B506934B8EF779F78E4DDF30A0DCF93FCAFBFA131A8839FD641949F47EE25CEECF814D55B0BE6E5677C1EFFEC6F29871EF29AA3ED9197B0D83852E050908031EF1ABBB5AFC8B3DD937A076FF6761AB362405C3F7D86A3B17A6170A659C16008950F7F5E06A5DE3E5998895EFA7DEEA060BE9575668F78AB1907B3BA1B7D"),
|
||||
tc::cli::FormatUtil::hexStringToBytes("00010004969FE8288DA6B9DD52C7BD63642A4A9AE5F053ECCB93613FDA37992087BD9199DA5E6797618D77098133FD5B05CD8288139E2E975CD2608003878CDAF020F51A0E5B7692780845561B31C61808E8A47C3462224D94F736E9A14E56ACBF71B7F11BBDEE38DDB846D6BD8F0AB4E4948C5434EAF9BF26529B7EB83671D3CE60A6D7A850DBE6801EC52A7B7A3E5A27BC675BA3C53377CFC372EBCE02062F59F37003AA23AE35D4880E0E4B69F982FB1BAC806C2F75BA29587F2815FD7783998C354D52B19E3FAD9FBEF444C48579288DB0978116AFC82CE54DACB9ED7E1BFD50938F22F85EECF3A4F426AE5FEB15B72F022FB36ECCE9314DAD131429BFC9675F58EE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D21D3CE67C1069DA049D5E5310E76B907E18EEC80B337C4723E339573F4C664907DB2F0832D03DF5EA5F160A4AF24100D71AFAC2E3AE75AFA1228012A9A21616597DF71EAFCB65941470D1B40F5EF83A597E179FCB5B57C2EE17DA3BC3769864CB47856767229D67328141FC9AB1DF149E0C5C15AEB80BC58FC71BE18966642D68308B506934B8EF779F78E4DDF30A0DCF93FCAFBFA131A8839FD641949F47EE25CEECF814D55B0BE6E5677C1EFFEC6F29871EF29AA3ED9197B0D83852E050908031EF1ABBB5AFC8B3DD937A076FF6761AB362405C3F7D86A3B17A6170A659C16008950F7F5E06A5DE3E5998895EFA7DEEA060BE9575668F78AB1907B3BA1B7D0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
},
|
||||
{
|
||||
"Root-CA00000003-XS00000022",
|
||||
nn::pki::sign::SIGN_ALGO_RSA2048,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA2048,
|
||||
tc::cli::FormatUtil::hexStringToBytes("E29775264ADC30C0FDE2DEFCFBBAC406A3B1C2ADDC2644C4C3E46DAD11E4F1ED7BC8B6E8CDBBE87E01020DF807520CE8A8F88BB53BE82CAFF4A1AF7FC5CD69EB34E24BEA74781203B611D09EBF56F82E3F21A494549F407FABA948545B34B64F487E1F27B031A83D337CE40496A3034AC6A2DB9E9353A1967EC7A07A4B3672B5B3F7934FF166D90EC131D8A75DC925ED629F8381A586589A82790489D4BF170F29F8E4BE50811ECBA9564D5517362D8DE777B01FC0A0AD8DED692CEAFD028A468CD6A6BF18A2767801AF8BB954EDB4DA3CED78337F3E9B6A1602B94752C85A53993678FDFA0300A4200CA752FA0D94E5A4B74B726FB61876146E49EC148508F5"),
|
||||
tc::cli::FormatUtil::hexStringToBytes("0001000458C7FFCDB0A1758925286C3C5029942683A8ED614A4E5C24EECE90548F99A0E59429C3D7D9CA37910CC1F5974E3AA2D7438627FBE456C9C830E5BF5B4440013CD41AA6F0AE02307E3EDEF3EDE0E6404A87234786FED37878F4BF4D964C2290C66AF167AC94869DC2F8378FA3FE0B764F776F9CE479B9E7A4EAE77FCA924B84035C9C06075F5F23BBF3A202AC1AF6A640C62BEEE4603925534783642663238A803D5FC87C5BEA58E09B0669CE9273509A87FACEDA94333FC6264D095708C18F9A50963F0E02A0771AEBC7174D4A89BE158C6CF407BD11658363E924F2808B15C7FE00267565CBD386E576540C906F9B2FFB3AFC64BA1198FA711A48F107E6A9AD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E29775264ADC30C0FDE2DEFCFBBAC406A3B1C2ADDC2644C4C3E46DAD11E4F1ED7BC8B6E8CDBBE87E01020DF807520CE8A8F88BB53BE82CAFF4A1AF7FC5CD69EB34E24BEA74781203B611D09EBF56F82E3F21A494549F407FABA948545B34B64F487E1F27B031A83D337CE40496A3034AC6A2DB9E9353A1967EC7A07A4B3672B5B3F7934FF166D90EC131D8A75DC925ED629F8381A586589A82790489D4BF170F29F8E4BE50811ECBA9564D5517362D8DE777B01FC0A0AD8DED692CEAFD028A468CD6A6BF18A2767801AF8BB954EDB4DA3CED78337F3E9B6A1602B94752C85A53993678FDFA0300A4200CA752FA0D94E5A4B74B726FB61876146E49EC148508F50001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
},
|
||||
{
|
||||
"Root-CA00000003-XS00000024",
|
||||
nn::pki::sign::SIGN_ALGO_RSA2048,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA2048,
|
||||
tc::cli::FormatUtil::hexStringToBytes("C694562BBDC74E83069876608EAD1EE7B1BC715036E9A6BDF58A6D22FD660ABD9CF360AA893D7746C92C5B9D20E480EAD1387786739956E060EBA79BD6ED7C06B2FCC6DBC1734ED12999AFEE5396FEE722FE3B96846D903F00A32671AC0CEDAAAB0C933C950304650A76152ED1B69547031793755599939B42F075CDF137F8C16D35870DE90D1BACBDB4B746F814AED0D3CB7F7C1B789A1FDF9947717B641BA972A6460D3258F5561CAA1D8E20085E8E3B9EBC92C9B6DCBB872A2AE02D74577F65EFA5AAFF29FD52EAA400D1408B2815C5C96CD2B54DF0F6708A755FB1DFA694A7794C4A0422F1BF8FAFE9E6870578133D50FD3D5356506CFCEC94EF79D6B639"),
|
||||
tc::cli::FormatUtil::hexStringToBytes("000100046EEED0424FF97D659DA43F85DF01E0997BA1FD1593997145BDE95703AABBDB7EFDE315F8CFE8AEC0F710FFF002938AEF8CEF7EBF90F725B6AC4EDA66DCF85132435E974DDBBE8F8C725CD114CE38C83404DFC0123BB4137C676C5C86EB4E211B7C35A03AB0C7E7637F1BF2486FDF0A5CCE5B047483841B5EA6BDC09AE770951ACA79EFB5497C46750585CF6C3FE4159ACE1CDFAB1BA8C00AB2446B57383F2F063344052E48E1557BD60BF973B252AC5AB4F5A12323AFCC1B06718775F3EDA4DD580A47A04D8063844235DC35D21A4FDED5A44EA401519920B73D15C66FDDF9F8286CF9122795EB9D5EA95C6E51603F6E62AA1631549EBE9E272B4BC3AEBC0D89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C694562BBDC74E83069876608EAD1EE7B1BC715036E9A6BDF58A6D22FD660ABD9CF360AA893D7746C92C5B9D20E480EAD1387786739956E060EBA79BD6ED7C06B2FCC6DBC1734ED12999AFEE5396FEE722FE3B96846D903F00A32671AC0CEDAAAB0C933C950304650A76152ED1B69547031793755599939B42F075CDF137F8C16D35870DE90D1BACBDB4B746F814AED0D3CB7F7C1B789A1FDF9947717B641BA972A6460D3258F5561CAA1D8E20085E8E3B9EBC92C9B6DCBB872A2AE02D74577F65EFA5AAFF29FD52EAA400D1408B2815C5C96CD2B54DF0F6708A755FB1DFA694A7794C4A0422F1BF8FAFE9E6870578133D50FD3D5356506CFCEC94EF79D6B6390001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
}
|
||||
|
|
@ -923,31 +951,31 @@ void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|||
{
|
||||
{
|
||||
"Root",
|
||||
nn::pki::sign::SIGN_ALGO_RSA4096,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA4096,
|
||||
tc::cli::FormatUtil::hexStringToBytes("D01FE100D43556B24B56DAE971B5A5D384B93003BE1BBF28A2305B060645467D5B0251D2561A274F9E9F9CEC646150AB3D2AE3366866ACA4BAE81AE3D79AA6B04A8BCBA7E6FB648945EBDFDB85BA091FD7D114B5A3A780E3A22E6ECD87B5A4C6F910E4032208814B0CEEA1A17DF739695F617EF63528DB949637A056037F7B32413895C0A8F1982E1565E38EEDC22E590EE2677B8609F48C2E303FBC405CAC18042F822084E4936803DA7F41349248562B8EE12F78F803246330BC7BE7EE724AF458A472E7AB46A1A7C10C2F18FA07C3DDD89806A11C9CC130B247A33C8D47DE67F29E5577B11C43493D5BBA7634A7E4E71531B7DF5981FE24A114554CBD8F005CE1DB35085CCFC77806B6DE254068A26CB5492D4580438FE1E5A9ED75C5ED451DCE789439CCC3BA28A2312A1B8719EF0F73B713950C02591A7462A607F37C0AA7A18FA943A36D752A5F4192F0136100AA9CB41BBE14BEB1F9FC692FDFA09446DE5A9DDE2CA5F68C1C0C21429287CB2DAAA3D263752F73E09FAF4479D2817429F69800AFDE6B592DC19882BDF581CCABF2CB91029EF35C4CFDBBFF49C1FA1B2FE31DE7A560ECB47EBCFE32425B956F81B69917487E3B789151DB2E78B1FD2EBE7E626B3EA165B4FB00CCB751AF507329C4A3939EA6DD9C50A0E7386B0145796B41AF61F78555944F3BC22DC3BD0D00F8798A42B1AAA08320659AC7395AB4F329"),
|
||||
tc::ByteData()
|
||||
},
|
||||
{
|
||||
"Root-CA00000004",
|
||||
nn::pki::sign::SIGN_ALGO_RSA2048,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA2048,
|
||||
tc::cli::FormatUtil::hexStringToBytes("C9CC2DC4DF2930E4DF3F8C70A078948775AD5E9AA604C5B4D8EAFF2AA1D214676564EFCA28CC00154554A1A3EA1379E9E6CAACED1593FE88D89AC6B8ACCCAB6E207CEB7CCA29809E2980440662B7D4382A15DA43085745A9AAE59AA05BDB32F66869A2DD4295386C87ECDD3508A2CF60D01E23EC2FE698F470D6001549A2F06759131E534C7006057DEF1D18A83F0AC79CFE80FF5A91F2BED4A0837061190A0329902165403C9A908FB615739F3CE33BF1BAEA16C25BCED7963FACC9D24D9C0AD76FC020B2C4B84C10A741A2CC7D9BAC3AACCCA3529BAC316A9AA75D2A26C7D7D288CBA466C5FE5F454AE679744A90A15772DB3B0E47A49AF031D16DBEAB332B"),
|
||||
tc::cli::FormatUtil::hexStringToBytes("000100031949429D1E58A62E7E8B56D1B76AE302FD8B97491F778745F75388C4DD0BEB1DF122FB9642151497764A53CF78151845E42CA8FDE486FD2A4F53F8A1BA008A7485FF73B3BF7E3C980729D0656B693219ADE835EB5FFFFCCB7CBB5E307FE0688B888EF2D2053FB7E791E985FD15EF10D79CCA88D6BB15E8E4714A98EE09BF7B8AF053232B6450E6D5FDFFC20A6D1EA6A23812E1014525D56D4082703B86986959A73CD1A14364D2C2DAEA96B095F76C46E4FF4155465E70EF1ED31053D97011E010CC93E7914013687FA3A802996D1E557B1CCC7A7E8F5865C1742E28E26DEF38A93AB5D82D43ECCCBF0BEF22E1FD57E2864333582FEDEABC012F986DDFC3E9447973470308455BDC57AA170B84427F73A29B48F6DA135F66C745C142A84AFB0E6A5EED85D7B9719936F8CE2B621F395F40DC03BEF8854C1117FF0C128641CC7843B97B4346DB226F6026ACB56C278B8E0EA79A2D65EF798E1078AD80ED4B9604D2F08B2CD64A23A3DB270833B402F80851F35BED3EE4577C6660FBF16D9413E09C917A49D42C6DA375BC27F0230DB98F8973AB027B522CD57EC03D25E8B3FC3494C97FB108FE18C68A4336E46C26B6F280D27E34BE287C3E4687BC9D776B76D928D1B6352EC0347D7294AA9360268D26F5F652064AF240D7D00C7C5EA3C32DE62D9B5C4B4CAB6FD7BD371D57C2166095910E4AD8E9ED181EF761936153892D77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081122A46C9CC2DC4DF2930E4DF3F8C70A078948775AD5E9AA604C5B4D8EAFF2AA1D214676564EFCA28CC00154554A1A3EA1379E9E6CAACED1593FE88D89AC6B8ACCCAB6E207CEB7CCA29809E2980440662B7D4382A15DA43085745A9AAE59AA05BDB32F66869A2DD4295386C87ECDD3508A2CF60D01E23EC2FE698F470D6001549A2F06759131E534C7006057DEF1D18A83F0AC79CFE80FF5A91F2BED4A0837061190A0329902165403C9A908FB615739F3CE33BF1BAEA16C25BCED7963FACC9D24D9C0AD76FC020B2C4B84C10A741A2CC7D9BAC3AACCCA3529BAC316A9AA75D2A26C7D7D288CBA466C5FE5F454AE679744A90A15772DB3B0E47A49AF031D16DBEAB332B0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
},
|
||||
{
|
||||
"Root-CA00000004-XS00000020",
|
||||
nn::pki::sign::SIGN_ALGO_RSA2048,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA2048,
|
||||
tc::cli::FormatUtil::hexStringToBytes("BA278428765D879A7F215404C6EE4E0A0D3F66C33BC7F8A32FD898E52CB7B63443CED8B00527D89DEDC6BBF60AD1C5C9923021DD555F9BAD4BE0C0C406D3702915E5B34AC2D2ABE503C32A3A23B43834C9157B9A0AF2E4E9C03BEDE2B4C115F5353DFC66BD04A6C079970E38CBDD5A50A2B98FF2D765FCF83381E9E0E849C3573578378FF65951613E95F75EE8EF26183A40AAE4A76D7384EA478D2CDCE80FBA0321A6BF8D69983C3AA7AE5443B72BFE410BF1323CBD88C3560EA13D17D38A2E34041DE7AAF389DE4375225CA87EE349C760C7D99BE7E737C6261CC74E25AE46527AC9619F939057088D7435A6DE7B25AB82DD5410F2579CAEF1491A909D302B"),
|
||||
tc::cli::FormatUtil::hexStringToBytes("00010004603483F7F4EF3C863FF7B46821E9D83983EFB0BA29C45B10DFB2E8A268AE06084DFEB0B9680B6D40D6DF82CAE7D651E28F31364F5AB567DD9DCCFCBB5EFF8F1CEA92489C046E8BED2AF0D7F9CA0BD50F683633D681B08D1AF417D7B7F8762AD88E3AF0D1C45DAC5407B9D8F24F167AEDC7C5DBCF4E0E176EC341D4F9BA8ADFE749CF37F45688653886566A9045ED89AD353DD289E32631867BDFD7FC67738BDF0E1E858F3BF9DEE25B02206F0B7FFB61F866DA4D862D77DDBDA9668BB61CBDEFACB2583CE5C9FAB22FC90EF8EB06954743E5A32A37A3513C6C795BC8E0C65E2F170B435A8C447765381C4050427F88E9828E6E94144D28441C7F9C7F6D92FE5B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BA278428765D879A7F215404C6EE4E0A0D3F66C33BC7F8A32FD898E52CB7B63443CED8B00527D89DEDC6BBF60AD1C5C9923021DD555F9BAD4BE0C0C406D3702915E5B34AC2D2ABE503C32A3A23B43834C9157B9A0AF2E4E9C03BEDE2B4C115F5353DFC66BD04A6C079970E38CBDD5A50A2B98FF2D765FCF83381E9E0E849C3573578378FF65951613E95F75EE8EF26183A40AAE4A76D7384EA478D2CDCE80FBA0321A6BF8D69983C3AA7AE5443B72BFE410BF1323CBD88C3560EA13D17D38A2E34041DE7AAF389DE4375225CA87EE349C760C7D99BE7E737C6261CC74E25AE46527AC9619F939057088D7435A6DE7B25AB82DD5410F2579CAEF1491A909D302B0001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
},
|
||||
{
|
||||
"Root-CA00000004-XS00000021",
|
||||
nn::pki::sign::SIGN_ALGO_RSA2048,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA2048,
|
||||
tc::cli::FormatUtil::hexStringToBytes("CA303087732E88FB2736A4644B6A84DF02393786EBE3DBE914F92224126AB3C38D7CA67322B7D3107B9AC0E00AED9AF13DEDDC62BCB8AC889A47B07196B45BC97AC5DD333CC63E872E30CDB52BD35E055FBA56C2521AFC8BBFC8B06390522E99699750B457C8647A42D6318BE5EAA192ADA35DA7023FC348215613141919821FD5599B93497893CA58E7A88C8D6E6E9EB0A57567BF8C12EB25241BB6082BED7A696658A58DDB66E7CC2562F2EA061E5373E6A5397BF6299F7EA9065B0047AA408F24A5D6F6E4050B99DA86831F663792E08D96F182400182D9BECB917AE315A238CA89741B6AEAF52E238590CDA60FC5B74DC638F9D6FCAF95D2CA7AE005A7B1"),
|
||||
tc::cli::FormatUtil::hexStringToBytes("000100041282394569ED63B5C4E54747B31E3B32C68B0EB90712E3C04662101CA77A551A0394CC36CB28E369DFBBB9FD78C9C503C3B1F184729C2B05B4D1691581A877AF82F8EC3D70E95B27F459039B65D8221D4864CCB282FF721EBDD6C46863F8C95591C1BF36D0AC118C0027FA3E2D434821A5FEF123C65F17885321F9A520C22B9EE6FC533EEF582706A95DD0CEABACE87B0169E136336E2E9CC0399637CE4CC77B6DA418671A277614F80A0A909569018F624DE0C5E1A67DB134C63F1FFE30BB64C201FDD8DAD42F4C88B247C1C6133CC554DE6B15684320D6AA1E09CB59EAD15F37140C9DD4BE69D87CC90DD8F733C946FBA6C576C70533601AF4E8294A3B5DD4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA303087732E88FB2736A4644B6A84DF02393786EBE3DBE914F92224126AB3C38D7CA67322B7D3107B9AC0E00AED9AF13DEDDC62BCB8AC889A47B07196B45BC97AC5DD333CC63E872E30CDB52BD35E055FBA56C2521AFC8BBFC8B06390522E99699750B457C8647A42D6318BE5EAA192ADA35DA7023FC348215613141919821FD5599B93497893CA58E7A88C8D6E6E9EB0A57567BF8C12EB25241BB6082BED7A696658A58DDB66E7CC2562F2EA061E5373E6A5397BF6299F7EA9065B0047AA408F24A5D6F6E4050B99DA86831F663792E08D96F182400182D9BECB917AE315A238CA89741B6AEAF52E238590CDA60FC5B74DC638F9D6FCAF95D2CA7AE005A7B10001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
},
|
||||
{
|
||||
"Root-CA00000004-XS00000024",
|
||||
nn::pki::sign::SIGN_ALGO_RSA2048,
|
||||
pie::hac::es::sign::SIGN_ALGO_RSA2048,
|
||||
tc::cli::FormatUtil::hexStringToBytes("E5E262EA591EEB885DE5A3CA451CE9E4FEA0E89DAA9BBCD9EC6C23E3FEFCE31BE7C7217DAC3E1F5A8331EF3F0C738E9310E765E71AAAB92C6E18D36071E7F93446E06E2581A28483AE9EB9C8217C1D68A21FD098E186C71B6A1E1E2626C80B69FFD562EAD515C77D616554F6B74B34DEEB0DE905F44631F56A6FF12B47AC0190578267559592FAB173146071ECFBB014951512E45299A21C0B8B3377E55DCD95625130E533877BF11157585D43DB00F61DFE77CFA44F5F29F44945DBF4214F37214921C16ED7D74455B2AE7C8CA15DFBD20A4D5E6501965B78C2C542727D7A91C071C56403738F07E858239CD150DB304BA5ACD8751145A9A91D3E97085AD217"),
|
||||
tc::cli::FormatUtil::hexStringToBytes("000100049EA82934BD64EDCED4D506BB68BF1F217BAD912BEF134B687C8E590F2A9355D8EDD9BE00D85735A83820F69978B3E2876FE07BBB7F356B25CDCC98EEEA17BFA9EF649769E921BFDA7867D0570D2F0A7A223E7ACD8D9AE1F304F8EEC6C96B11805436CF686FBD05969E4C0D19A63EF89DA00899222D2CF006776FF027118E96CB027114AABBA268CB1775022B25EAF045C9E4A328A55FF85CFFFFFEAEFB78F1CD184ED9042D23A06F0161E5FBADE92638A483A1A3680DC9994A03D02F1D76EB0EE793843D31CCC172A3993C7344B2C5E634F2B89C47F85FD8B74D21745AEBCFD55E32FC03F6BCD40421499261F8AB93AC8A07E6EF5436036283A3B86192890A78000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000526F6F742D4341303030303030303400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015853303030303030323400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E5E262EA591EEB885DE5A3CA451CE9E4FEA0E89DAA9BBCD9EC6C23E3FEFCE31BE7C7217DAC3E1F5A8331EF3F0C738E9310E765E71AAAB92C6E18D36071E7F93446E06E2581A28483AE9EB9C8217C1D68A21FD098E186C71B6A1E1E2626C80B69FFD562EAD515C77D616554F6B74B34DEEB0DE905F44631F56A6FF12B47AC0190578267559592FAB173146071ECFBB014951512E45299A21C0B8B3377E55DCD95625130E533877BF11157585D43DB00F61DFE77CFA44F5F29F44945DBF4214F37214921C16ED7D74455B2AE7C8CA15DFBD20A4D5E6501965B78C2C542727D7A91C071C56403738F07E858239CD150DB304BA5ACD8751145A9A91D3E97085AD2170001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
||||
}
|
||||
|
|
|
|||
19
src/KeyBag.h
19
src/KeyBag.h
|
|
@ -5,22 +5,22 @@
|
|||
#include <map>
|
||||
#include <tc/Optional.h>
|
||||
#include <tc/io.h>
|
||||
#include <nn/pki/SignUtils.h>
|
||||
#include <nn/hac/define/types.h>
|
||||
#include <nn/hac/define/nca.h>
|
||||
#include <pietendo/hac/es/SignUtils.h>
|
||||
#include <pietendo/hac/define/types.h>
|
||||
#include <pietendo/hac/define/nca.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
struct KeyBag
|
||||
{
|
||||
using aes128_key_t = nn::hac::detail::aes128_key_t;
|
||||
using aes128_xtskey_t = nn::hac::detail::aes128_xtskey_t;
|
||||
using aes128_key_t = pie::hac::detail::aes128_key_t;
|
||||
using aes128_xtskey_t = pie::hac::detail::aes128_xtskey_t;
|
||||
using rsa_key_t = tc::crypto::RsaKey;
|
||||
//using ecc_key_t = tc::crypto::EccKey;
|
||||
using rights_id_t = nn::hac::detail::rights_id_t;
|
||||
using rights_id_t = pie::hac::detail::rights_id_t;
|
||||
using key_generation_t = byte_t;
|
||||
using broadon_issuer_t = std::string;
|
||||
static const size_t kNcaKeakNum = nn::hac::nca::kKeyAreaEncryptionKeyNum;
|
||||
static const size_t kNcaKeakNum = pie::hac::nca::kKeyAreaEncryptionKeyNum;
|
||||
|
||||
|
||||
// acid
|
||||
|
|
@ -39,6 +39,7 @@ struct KeyBag
|
|||
|
||||
// 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_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_content_key; // content key to be used when external_content_keys does not have the required content key (usually already decrypted from ticket)
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ struct KeyBag
|
|||
{
|
||||
tc::ByteData certificate;
|
||||
|
||||
nn::pki::sign::SignatureAlgo key_type;
|
||||
pie::hac::es::sign::SignatureAlgo key_type;
|
||||
rsa_key_t rsa_key;
|
||||
// ecc_key_t ecc_key;
|
||||
};
|
||||
|
|
@ -70,7 +71,7 @@ struct KeyBag
|
|||
class KeyBagInitializer : public KeyBag
|
||||
{
|
||||
public:
|
||||
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);
|
||||
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);
|
||||
private:
|
||||
KeyBagInitializer();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "KipProcess.h"
|
||||
|
||||
#include <nn/hac/KernelCapabilityUtil.h>
|
||||
#include <pietendo/hac/KernelCapabilityUtil.h>
|
||||
|
||||
#include <tc/NotImplementedException.h>
|
||||
|
||||
|
|
@ -50,13 +50,13 @@ void nstool::KipProcess::importHeader()
|
|||
}
|
||||
|
||||
// check if file_size is smaller than KIP header size
|
||||
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sKipHeader))
|
||||
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(pie::hac::sKipHeader))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt KIP: file too small.");
|
||||
}
|
||||
|
||||
// read kip
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sKipHeader));
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sKipHeader));
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read(scratch.data(), scratch.size());
|
||||
|
||||
|
|
@ -189,12 +189,12 @@ void nstool::KipProcess::displayHeader()
|
|||
|
||||
}
|
||||
|
||||
void nstool::KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||
void nstool::KipProcess::displayKernelCap(const pie::hac::KernelCapabilityControl& kern)
|
||||
{
|
||||
fmt::print("[Kernel Capabilities]\n");
|
||||
if (kern.getThreadInfo().isSet())
|
||||
{
|
||||
nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo();
|
||||
pie::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo();
|
||||
fmt::print(" Thread Priority:\n");
|
||||
fmt::print(" Min: {:d}\n", threadInfo.getMinPriority());
|
||||
fmt::print(" Max: {:d}\n", threadInfo.getMaxPriority());
|
||||
|
|
@ -211,7 +211,7 @@ void nstool::KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl
|
|||
for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++)
|
||||
{
|
||||
if (syscall_ids.test(syscall_id))
|
||||
syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id)));
|
||||
syscall_names.push_back(pie::hac::KernelCapabilityUtil::getSystemCallIdAsString(pie::hac::kc::SystemCallId(syscall_id)));
|
||||
}
|
||||
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(syscall_names, 60, 4));
|
||||
}
|
||||
|
|
@ -243,7 +243,7 @@ void nstool::KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl
|
|||
}
|
||||
if (kern.getMiscParams().isSet())
|
||||
{
|
||||
fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), kern.getMiscParams().getProgramType());
|
||||
fmt::print(" ProgramType: {:s} ({:d})\n", pie::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), (uint32_t)kern.getMiscParams().getProgramType());
|
||||
}
|
||||
if (kern.getKernelVersion().isSet())
|
||||
{
|
||||
|
|
@ -261,13 +261,13 @@ void nstool::KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl
|
|||
for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++)
|
||||
{
|
||||
if (misc_flags.test(misc_flags_bit))
|
||||
misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit)));
|
||||
misc_flags_names.push_back(pie::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(pie::hac::kc::MiscFlagsBit(misc_flags_bit)));
|
||||
}
|
||||
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(misc_flags_names, 60, 4));
|
||||
}
|
||||
}
|
||||
|
||||
std::string nstool::KipProcess::formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const
|
||||
std::string nstool::KipProcess::formatMappingAsString(const pie::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), nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), nn::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), pie::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), pie::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type));
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
#include <nn/hac/KernelInitialProcessHeader.h>
|
||||
#include <pietendo/hac/KernelInitialProcessHeader.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -22,16 +22,16 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nn::hac::KernelInitialProcessHeader mHdr;
|
||||
pie::hac::KernelInitialProcessHeader mHdr;
|
||||
tc::ByteData mTextBlob, mRoBlob, mDataBlob;
|
||||
|
||||
void importHeader();
|
||||
void importCodeSegments();
|
||||
size_t decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity);
|
||||
void displayHeader();
|
||||
void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
|
||||
void displayKernelCap(const pie::hac::KernelCapabilityControl& kern);
|
||||
|
||||
std::string formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const;
|
||||
std::string formatMappingAsString(const pie::hac::MemoryMappingHandler::sMemoryMapping& map) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#include "MetaProcess.h"
|
||||
|
||||
#include <nn/hac/AccessControlInfoUtil.h>
|
||||
#include <nn/hac/FileSystemAccessUtil.h>
|
||||
#include <nn/hac/KernelCapabilityUtil.h>
|
||||
#include <nn/hac/MetaUtil.h>
|
||||
#include <pietendo/hac/AccessControlInfoUtil.h>
|
||||
#include <pietendo/hac/FileSystemAccessUtil.h>
|
||||
#include <pietendo/hac/KernelCapabilityUtil.h>
|
||||
#include <pietendo/hac/MetaUtil.h>
|
||||
|
||||
nstool::MetaProcess::MetaProcess() :
|
||||
mModuleName("nstool::MetaProcess"),
|
||||
|
|
@ -65,7 +65,7 @@ void nstool::MetaProcess::setVerifyMode(bool verify)
|
|||
mVerify = verify;
|
||||
}
|
||||
|
||||
const nn::hac::Meta& nstool::MetaProcess::getMeta() const
|
||||
const pie::hac::Meta& nstool::MetaProcess::getMeta() const
|
||||
{
|
||||
return mMeta;
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ void nstool::MetaProcess::importMeta()
|
|||
mMeta.fromBytes(scratch.data(), scratch.size());
|
||||
}
|
||||
|
||||
void nstool::MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid, byte_t key_generation)
|
||||
void nstool::MetaProcess::validateAcidSignature(const pie::hac::AccessControlInfoDesc& acid, byte_t key_generation)
|
||||
{
|
||||
try {
|
||||
if (mKeyCfg.acid_sign_key.find(key_generation) == mKeyCfg.acid_sign_key.end())
|
||||
|
|
@ -112,7 +112,7 @@ void nstool::MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfo
|
|||
|
||||
}
|
||||
|
||||
void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, const nn::hac::AccessControlInfoDesc& acid)
|
||||
void nstool::MetaProcess::validateAciFromAcid(const pie::hac::AccessControlInfo& aci, const pie::hac::AccessControlInfoDesc& acid)
|
||||
{
|
||||
// check Program ID
|
||||
if (acid.getProgramIdRestrict().min > 0 && aci.getProgramId() < acid.getProgramIdRestrict().min)
|
||||
|
|
@ -137,7 +137,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
|
|||
|
||||
if (rightFound == false)
|
||||
{
|
||||
fmt::print("[WARNING] ACI/FAC FsaRights: FAIL ({:s} not permitted)\n", nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(fs_access[i]));
|
||||
fmt::print("[WARNING] ACI/FAC FsaRights: FAIL ({:s} not permitted)\n", pie::hac::FileSystemAccessUtil::getFsAccessFlagAsString(fs_access[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,6 +157,9 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::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++)
|
||||
{
|
||||
bool rightFound = false;
|
||||
|
|
@ -169,9 +172,10 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
|
|||
if (rightFound == false)
|
||||
{
|
||||
|
||||
fmt::print("[WARNING] ACI/FAC SaveDataOwnerId: FAIL (0x{:016x} ({:d}) not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id, aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type);
|
||||
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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// check SAC
|
||||
for (size_t i = 0; i < aci.getServiceAccessControl().getServiceList().size(); i++)
|
||||
|
|
@ -214,7 +218,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
|
|||
{
|
||||
if (syscall_ids.test(i) && desc_syscall_ids.test(i) == false)
|
||||
{
|
||||
fmt::print("[WARNING] ACI/KC SystemCallList: FAIL ({:s} not permitted)\n", nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(i)));
|
||||
fmt::print("[WARNING] ACI/KC SystemCallList: FAIL ({:s} not permitted)\n", pie::hac::KernelCapabilityUtil::getSystemCallIdAsString(pie::hac::kc::SystemCallId(i)));
|
||||
}
|
||||
}
|
||||
// check memory maps
|
||||
|
|
@ -268,7 +272,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
|
|||
// check misc params
|
||||
if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType())
|
||||
{
|
||||
fmt::print("[WARNING] ACI/KC ProgramType: FAIL ({:d} not permitted)\n", aci.getKernelCapabilities().getMiscParams().getProgramType());
|
||||
fmt::print("[WARNING] ACI/KC ProgramType: FAIL ({:d} not permitted)\n", (uint32_t)aci.getKernelCapabilities().getMiscParams().getProgramType());
|
||||
}
|
||||
// check kernel version
|
||||
uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor();
|
||||
|
|
@ -289,18 +293,18 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
|
|||
{
|
||||
if (misc_flags.test(i) && desc_misc_flags.test(i) == false)
|
||||
{
|
||||
fmt::print("[WARNING] ACI/KC MiscFlag: FAIL ({:s} not permitted)\n", nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(i)));
|
||||
fmt::print("[WARNING] ACI/KC MiscFlag: FAIL ({:s} not permitted)\n", pie::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(pie::hac::kc::MiscFlagsBit(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nstool::MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr)
|
||||
void nstool::MetaProcess::displayMetaHeader(const pie::hac::Meta& hdr)
|
||||
{
|
||||
fmt::print("[Meta Header]\n");
|
||||
fmt::print(" ACID KeyGeneration: {:d}\n", hdr.getAccessControlInfoDescKeyGeneration());
|
||||
fmt::print(" Flags:\n");
|
||||
fmt::print(" Is64BitInstruction: {}\n", hdr.getIs64BitInstructionFlag());
|
||||
fmt::print(" ProcessAddressSpace: {:s}\n", nn::hac::MetaUtil::getProcessAddressSpaceAsString(hdr.getProcessAddressSpace()));
|
||||
fmt::print(" ProcessAddressSpace: {:s}\n", pie::hac::MetaUtil::getProcessAddressSpaceAsString(hdr.getProcessAddressSpace()));
|
||||
fmt::print(" OptimizeMemoryAllocation: {}\n", hdr.getOptimizeMemoryAllocationFlag());
|
||||
fmt::print(" SystemResourceSize: 0x{:x}\n", hdr.getSystemResourceSize());
|
||||
fmt::print(" Main Thread Params:\n");
|
||||
|
|
@ -316,25 +320,25 @@ void nstool::MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr)
|
|||
}
|
||||
}
|
||||
|
||||
void nstool::MetaProcess::displayAciHdr(const nn::hac::AccessControlInfo& aci)
|
||||
void nstool::MetaProcess::displayAciHdr(const pie::hac::AccessControlInfo& aci)
|
||||
{
|
||||
fmt::print("[Access Control Info]\n");
|
||||
fmt::print(" ProgramID: 0x{:016x}\n", aci.getProgramId());
|
||||
}
|
||||
|
||||
void nstool::MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc& acid)
|
||||
void nstool::MetaProcess::displayAciDescHdr(const pie::hac::AccessControlInfoDesc& acid)
|
||||
{
|
||||
fmt::print("[Access Control Info Desc]\n");
|
||||
fmt::print(" Flags: \n");
|
||||
fmt::print(" Production: {}\n", acid.getProductionFlag());
|
||||
fmt::print(" Unqualified Approval: {}\n", acid.getUnqualifiedApprovalFlag());
|
||||
fmt::print(" Memory Region: {:s} ({:d})\n", nn::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()), acid.getMemoryRegion());
|
||||
fmt::print(" Memory Region: {:s} ({:d})\n", pie::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()), (uint32_t)acid.getMemoryRegion());
|
||||
fmt::print(" ProgramID Restriction\n");
|
||||
fmt::print(" Min: 0x{:016x}\n", acid.getProgramIdRestrict().min);
|
||||
fmt::print(" Max: 0x{:016x}\n", acid.getProgramIdRestrict().max);
|
||||
}
|
||||
|
||||
void nstool::MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac)
|
||||
void nstool::MetaProcess::displayFac(const pie::hac::FileSystemAccessControl& fac)
|
||||
{
|
||||
fmt::print("[FS Access Control]\n");
|
||||
fmt::print(" Format Version: {:d}\n", fac.getFormatVersion());
|
||||
|
|
@ -344,10 +348,10 @@ void nstool::MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac
|
|||
std::vector<std::string> fs_access_str_list;
|
||||
for (auto itr = fac.getFsAccess().begin(); itr != fac.getFsAccess().end(); itr++)
|
||||
{
|
||||
std::string flag_string = nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(*itr));
|
||||
std::string flag_string = pie::hac::FileSystemAccessUtil::getFsAccessFlagAsString(pie::hac::fac::FsAccessFlag(*itr));
|
||||
if (mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fs_access_str_list.push_back(fmt::format("{:s} (bit {:d})", flag_string, *itr));
|
||||
fs_access_str_list.push_back(fmt::format("{:s} (bit {:d})", flag_string, (uint32_t)*itr));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -374,12 +378,12 @@ void nstool::MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac
|
|||
fmt::print(" Save Data Owner IDs:\n");
|
||||
for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++)
|
||||
{
|
||||
fmt::print(" 0x{:016x} ({:s})\n", fac.getSaveDataOwnerIdList()[i].id, nn::hac::FileSystemAccessUtil::getSaveDataOwnerAccessModeAsString(fac.getSaveDataOwnerIdList()[i].access_type));
|
||||
fmt::print(" 0x{:016x} ({:s})\n", fac.getSaveDataOwnerIdList()[i].id, pie::hac::FileSystemAccessUtil::getSaveDataOwnerAccessModeAsString(fac.getSaveDataOwnerIdList()[i].access_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nstool::MetaProcess::displaySac(const nn::hac::ServiceAccessControl& sac)
|
||||
void nstool::MetaProcess::displaySac(const pie::hac::ServiceAccessControl& sac)
|
||||
{
|
||||
fmt::print("[Service Access Control]\n");
|
||||
fmt::print(" Service List:\n");
|
||||
|
|
@ -391,12 +395,12 @@ void nstool::MetaProcess::displaySac(const nn::hac::ServiceAccessControl& sac)
|
|||
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(service_name_list, 60, 4));
|
||||
}
|
||||
|
||||
void nstool::MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||
void nstool::MetaProcess::displayKernelCap(const pie::hac::KernelCapabilityControl& kern)
|
||||
{
|
||||
fmt::print("[Kernel Capabilities]\n");
|
||||
if (kern.getThreadInfo().isSet())
|
||||
{
|
||||
nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo();
|
||||
pie::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo();
|
||||
fmt::print(" Thread Priority:\n");
|
||||
fmt::print(" Min: {:d}\n", threadInfo.getMinPriority());
|
||||
fmt::print(" Max: {:d}\n", threadInfo.getMaxPriority());
|
||||
|
|
@ -413,7 +417,7 @@ void nstool::MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityContro
|
|||
for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++)
|
||||
{
|
||||
if (syscall_ids.test(syscall_id))
|
||||
syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id)));
|
||||
syscall_names.push_back(pie::hac::KernelCapabilityUtil::getSystemCallIdAsString(pie::hac::kc::SystemCallId(syscall_id)));
|
||||
}
|
||||
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(syscall_names, 60, 4));
|
||||
}
|
||||
|
|
@ -445,7 +449,7 @@ void nstool::MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityContro
|
|||
}
|
||||
if (kern.getMiscParams().isSet())
|
||||
{
|
||||
fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), kern.getMiscParams().getProgramType());
|
||||
fmt::print(" ProgramType: {:s} ({:d})\n", pie::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), (uint32_t)kern.getMiscParams().getProgramType());
|
||||
}
|
||||
if (kern.getKernelVersion().isSet())
|
||||
{
|
||||
|
|
@ -463,13 +467,13 @@ void nstool::MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityContro
|
|||
for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++)
|
||||
{
|
||||
if (misc_flags.test(misc_flags_bit))
|
||||
misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit)));
|
||||
misc_flags_names.push_back(pie::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(pie::hac::kc::MiscFlagsBit(misc_flags_bit)));
|
||||
}
|
||||
fmt::print("{:s}", tc::cli::FormatUtil::formatListWithLineLimit(misc_flags_names, 60, 4));
|
||||
}
|
||||
}
|
||||
|
||||
std::string nstool::MetaProcess::formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const
|
||||
std::string nstool::MetaProcess::formatMappingAsString(const pie::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), nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), nn::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), pie::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm), pie::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type));
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include "types.h"
|
||||
#include "KeyBag.h"
|
||||
|
||||
#include <nn/hac/Meta.h>
|
||||
#include <pietendo/hac/Meta.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ public:
|
|||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
const nn::hac::Meta& getMeta() const;
|
||||
const pie::hac::Meta& getMeta() const;
|
||||
|
||||
private:
|
||||
std::string mModuleName;
|
||||
|
|
@ -28,21 +28,21 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nn::hac::Meta mMeta;
|
||||
pie::hac::Meta mMeta;
|
||||
|
||||
void importMeta();
|
||||
|
||||
void validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid, byte_t key_generation);
|
||||
void validateAciFromAcid(const nn::hac::AccessControlInfo& aci, const nn::hac::AccessControlInfoDesc& acid);
|
||||
void validateAcidSignature(const pie::hac::AccessControlInfoDesc& acid, byte_t key_generation);
|
||||
void validateAciFromAcid(const pie::hac::AccessControlInfo& aci, const pie::hac::AccessControlInfoDesc& acid);
|
||||
|
||||
void displayMetaHeader(const nn::hac::Meta& hdr);
|
||||
void displayAciHdr(const nn::hac::AccessControlInfo& aci);
|
||||
void displayAciDescHdr(const nn::hac::AccessControlInfoDesc& aci);
|
||||
void displayFac(const nn::hac::FileSystemAccessControl& fac);
|
||||
void displaySac(const nn::hac::ServiceAccessControl& sac);
|
||||
void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
|
||||
void displayMetaHeader(const pie::hac::Meta& hdr);
|
||||
void displayAciHdr(const pie::hac::AccessControlInfo& aci);
|
||||
void displayAciDescHdr(const pie::hac::AccessControlInfoDesc& aci);
|
||||
void displayFac(const pie::hac::FileSystemAccessControl& fac);
|
||||
void displaySac(const pie::hac::ServiceAccessControl& sac);
|
||||
void displayKernelCap(const pie::hac::KernelCapabilityControl& kern);
|
||||
|
||||
std::string formatMappingAsString(const nn::hac::MemoryMappingHandler::sMemoryMapping& map) const;
|
||||
std::string formatMappingAsString(const pie::hac::MemoryMappingHandler::sMemoryMapping& map) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "NacpProcess.h"
|
||||
|
||||
#include <nn/hac/ApplicationControlPropertyUtil.h>
|
||||
#include <pietendo/hac/ApplicationControlPropertyUtil.h>
|
||||
|
||||
nstool::NacpProcess::NacpProcess() :
|
||||
mModuleName("nstool::NacpProcess"),
|
||||
|
|
@ -33,7 +33,7 @@ void nstool::NacpProcess::setVerifyMode(bool verify)
|
|||
mVerify = verify;
|
||||
}
|
||||
|
||||
const nn::hac::ApplicationControlProperty& nstool::NacpProcess::getApplicationControlProperty() const
|
||||
const pie::hac::ApplicationControlProperty& nstool::NacpProcess::getApplicationControlProperty() const
|
||||
{
|
||||
return mNacp;
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ void nstool::NacpProcess::importNacp()
|
|||
|
||||
// check if file_size does matches expected size
|
||||
size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
|
||||
if (file_size != sizeof(nn::hac::sApplicationControlProperty))
|
||||
if (file_size != sizeof(pie::hac::sApplicationControlProperty))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "File was incorrect size.");
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
fmt::print(" Title:\n");
|
||||
for (auto itr = mNacp.getTitle().begin(); itr != mNacp.getTitle().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}:\n", nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(itr->language));
|
||||
fmt::print(" {:s}:\n", pie::hac::ApplicationControlPropertyUtil::getLanguageAsString(itr->language));
|
||||
fmt::print(" Name: {:s}\n", itr->name);
|
||||
fmt::print(" Publisher: {:s}\n", itr->publisher);
|
||||
}
|
||||
|
|
@ -95,21 +95,21 @@ void nstool::NacpProcess::displayNacp()
|
|||
}
|
||||
|
||||
// StartupUserAccount
|
||||
if (mNacp.getStartupUserAccount() != nn::hac::nacp::StartupUserAccount::None || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getStartupUserAccount() != pie::hac::nacp::StartupUserAccount_None || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" StartupUserAccount: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getStartupUserAccountAsString(mNacp.getStartupUserAccount()));
|
||||
fmt::print(" StartupUserAccount: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getStartupUserAccountAsString(mNacp.getStartupUserAccount()));
|
||||
}
|
||||
|
||||
// UserAccountSwitchLock
|
||||
if (mNacp.getUserAccountSwitchLock() != nn::hac::nacp::UserAccountSwitchLock::Disable || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getUserAccountSwitchLock() != pie::hac::nacp::UserAccountSwitchLock_Disable || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" UserAccountSwitchLock: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getUserAccountSwitchLockAsString(mNacp.getUserAccountSwitchLock()));
|
||||
fmt::print(" UserAccountSwitchLock: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getUserAccountSwitchLockAsString(mNacp.getUserAccountSwitchLock()));
|
||||
}
|
||||
|
||||
// AddOnContentRegistrationType
|
||||
if (mNacp.getAddOnContentRegistrationType() != nn::hac::nacp::AddOnContentRegistrationType::AllOnLaunch || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getAddOnContentRegistrationType() != pie::hac::nacp::AddOnContentRegistrationType_AllOnLaunch || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" AddOnContentRegistrationType: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getAddOnContentRegistrationTypeAsString(mNacp.getAddOnContentRegistrationType()));
|
||||
fmt::print(" AddOnContentRegistrationType: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getAddOnContentRegistrationTypeAsString(mNacp.getAddOnContentRegistrationType()));
|
||||
}
|
||||
|
||||
// Attribute
|
||||
|
|
@ -118,7 +118,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
fmt::print(" Attribute:\n");
|
||||
for (auto itr = mNacp.getAttribute().begin(); itr != mNacp.getAttribute().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getAttributeFlagAsString(*itr));
|
||||
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getAttributeFlagAsString(*itr));
|
||||
}
|
||||
}
|
||||
else if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -132,7 +132,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
fmt::print(" SupportedLanguage:\n");
|
||||
for (auto itr = mNacp.getSupportedLanguage().begin(); itr != mNacp.getSupportedLanguage().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(*itr));
|
||||
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getLanguageAsString(*itr));
|
||||
}
|
||||
}
|
||||
else if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -146,7 +146,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
fmt::print(" ParentalControl:\n");
|
||||
for (auto itr = mNacp.getParentalControl().begin(); itr != mNacp.getParentalControl().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getParentalControlFlagAsString(*itr));
|
||||
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getParentalControlFlagAsString(*itr));
|
||||
}
|
||||
}
|
||||
else if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -155,27 +155,27 @@ void nstool::NacpProcess::displayNacp()
|
|||
}
|
||||
|
||||
// Screenshot
|
||||
if (mNacp.getScreenshot() != nn::hac::nacp::Screenshot::Allow || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getScreenshot() != pie::hac::nacp::Screenshot_Allow || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" Screenshot: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getScreenshotAsString(mNacp.getScreenshot()));
|
||||
fmt::print(" Screenshot: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getScreenshotAsString(mNacp.getScreenshot()));
|
||||
}
|
||||
|
||||
// VideoCapture
|
||||
if (mNacp.getVideoCapture() != nn::hac::nacp::VideoCapture::Disable || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getVideoCapture() != pie::hac::nacp::VideoCapture_Disable || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" VideoCapture: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getVideoCaptureAsString(mNacp.getVideoCapture()));
|
||||
fmt::print(" VideoCapture: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getVideoCaptureAsString(mNacp.getVideoCapture()));
|
||||
}
|
||||
|
||||
// DataLossConfirmation
|
||||
if (mNacp.getDataLossConfirmation() != nn::hac::nacp::DataLossConfirmation::None || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getDataLossConfirmation() != pie::hac::nacp::DataLossConfirmation_None || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" DataLossConfirmation: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getDataLossConfirmationAsString(mNacp.getDataLossConfirmation()));
|
||||
fmt::print(" DataLossConfirmation: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getDataLossConfirmationAsString(mNacp.getDataLossConfirmation()));
|
||||
}
|
||||
|
||||
// PlayLogPolicy
|
||||
if (mNacp.getPlayLogPolicy() != nn::hac::nacp::PlayLogPolicy::All || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getPlayLogPolicy() != pie::hac::nacp::PlayLogPolicy_All || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" PlayLogPolicy: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getPlayLogPolicyAsString(mNacp.getPlayLogPolicy()));
|
||||
fmt::print(" PlayLogPolicy: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getPlayLogPolicyAsString(mNacp.getPlayLogPolicy()));
|
||||
}
|
||||
|
||||
// PresenceGroupId
|
||||
|
|
@ -191,7 +191,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
|
||||
for (auto itr = mNacp.getRatingAge().begin(); itr != mNacp.getRatingAge().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}:\n", nn::hac::ApplicationControlPropertyUtil::getOrganisationAsString(itr->organisation));
|
||||
fmt::print(" {:s}:\n", pie::hac::ApplicationControlPropertyUtil::getOrganisationAsString(itr->organisation));
|
||||
fmt::print(" Age: {:d}\n", itr->age);
|
||||
}
|
||||
}
|
||||
|
|
@ -225,31 +225,31 @@ void nstool::NacpProcess::displayNacp()
|
|||
// UserAccountSaveDataSize
|
||||
if (mNacp.getUserAccountSaveDataSize().size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" UserAccountSaveDataSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().size));
|
||||
fmt::print(" UserAccountSaveDataSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().size));
|
||||
}
|
||||
|
||||
// UserAccountSaveDataJournalSize
|
||||
if (mNacp.getUserAccountSaveDataSize().journal_size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" UserAccountSaveDataJournalSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().journal_size));
|
||||
fmt::print(" UserAccountSaveDataJournalSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().journal_size));
|
||||
}
|
||||
|
||||
// DeviceSaveDataSize
|
||||
if (mNacp.getDeviceSaveDataSize().size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" DeviceSaveDataSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().size));
|
||||
fmt::print(" DeviceSaveDataSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().size));
|
||||
}
|
||||
|
||||
// DeviceSaveDataJournalSize
|
||||
if (mNacp.getDeviceSaveDataSize().journal_size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" DeviceSaveDataJournalSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().journal_size));
|
||||
fmt::print(" DeviceSaveDataJournalSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().journal_size));
|
||||
}
|
||||
|
||||
// BcatDeliveryCacheStorageSize
|
||||
if (mNacp.getBcatDeliveryCacheStorageSize() != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" BcatDeliveryCacheStorageSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getBcatDeliveryCacheStorageSize()));
|
||||
fmt::print(" BcatDeliveryCacheStorageSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getBcatDeliveryCacheStorageSize()));
|
||||
}
|
||||
|
||||
// ApplicationErrorCodeCategory
|
||||
|
|
@ -277,39 +277,39 @@ void nstool::NacpProcess::displayNacp()
|
|||
}
|
||||
|
||||
// LogoType
|
||||
//if (mNacp.getLogoType() != nn::hac::nacp::LogoType::Nintendo || mCliOutputMode.show_extended_info)
|
||||
//if (mNacp.getLogoType() != pie::hac::nacp::LogoType_Nintendo || mCliOutputMode.show_extended_info)
|
||||
//{
|
||||
fmt::print(" LogoType: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getLogoTypeAsString(mNacp.getLogoType()));
|
||||
fmt::print(" LogoType: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getLogoTypeAsString(mNacp.getLogoType()));
|
||||
//}
|
||||
|
||||
// LogoHandling
|
||||
if (mNacp.getLogoHandling() != nn::hac::nacp::LogoHandling::Auto || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getLogoHandling() != pie::hac::nacp::LogoHandling_Auto || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" LogoHandling: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getLogoHandlingAsString(mNacp.getLogoHandling()));
|
||||
fmt::print(" LogoHandling: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getLogoHandlingAsString(mNacp.getLogoHandling()));
|
||||
}
|
||||
|
||||
// RuntimeAddOnContentInstall
|
||||
if (mNacp.getRuntimeAddOnContentInstall() != nn::hac::nacp::RuntimeAddOnContentInstall::Deny || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getRuntimeAddOnContentInstall() != pie::hac::nacp::RuntimeAddOnContentInstall_Deny || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" RuntimeAddOnContentInstall: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getRuntimeAddOnContentInstallAsString(mNacp.getRuntimeAddOnContentInstall()));
|
||||
fmt::print(" RuntimeAddOnContentInstall: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getRuntimeAddOnContentInstallAsString(mNacp.getRuntimeAddOnContentInstall()));
|
||||
}
|
||||
|
||||
// RuntimeParameterDelivery
|
||||
if (mNacp.getRuntimeParameterDelivery() != nn::hac::nacp::RuntimeParameterDelivery::Always || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getRuntimeParameterDelivery() != pie::hac::nacp::RuntimeParameterDelivery_Always || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" RuntimeParameterDelivery: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getRuntimeParameterDeliveryAsString(mNacp.getRuntimeParameterDelivery()));
|
||||
fmt::print(" RuntimeParameterDelivery: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getRuntimeParameterDeliveryAsString(mNacp.getRuntimeParameterDelivery()));
|
||||
}
|
||||
|
||||
// CrashReport
|
||||
if (mNacp.getCrashReport() != nn::hac::nacp::CrashReport::Deny || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getCrashReport() != pie::hac::nacp::CrashReport_Deny || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" CrashReport: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getCrashReportAsString(mNacp.getCrashReport()));
|
||||
fmt::print(" CrashReport: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getCrashReportAsString(mNacp.getCrashReport()));
|
||||
}
|
||||
|
||||
// Hdcp
|
||||
if (mNacp.getHdcp() != nn::hac::nacp::Hdcp::None || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getHdcp() != pie::hac::nacp::Hdcp_None || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" Hdcp: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getHdcpAsString(mNacp.getHdcp()));
|
||||
fmt::print(" Hdcp: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getHdcpAsString(mNacp.getHdcp()));
|
||||
}
|
||||
|
||||
// SeedForPsuedoDeviceId
|
||||
|
|
@ -334,7 +334,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
fmt::print(" StartupUserAccountOption:\n");
|
||||
for (auto itr = mNacp.getStartupUserAccountOption().begin(); itr != mNacp.getStartupUserAccountOption().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getStartupUserAccountOptionFlagAsString(*itr));
|
||||
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getStartupUserAccountOptionFlagAsString(*itr));
|
||||
}
|
||||
}
|
||||
else if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -345,49 +345,49 @@ void nstool::NacpProcess::displayNacp()
|
|||
// UserAccountSaveDataSizeMax
|
||||
if (mNacp.getUserAccountSaveDataMax().size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" UserAccountSaveDataSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().size));
|
||||
fmt::print(" UserAccountSaveDataSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().size));
|
||||
}
|
||||
|
||||
// UserAccountSaveDataJournalSizeMax
|
||||
if (mNacp.getUserAccountSaveDataMax().journal_size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" UserAccountSaveDataJournalSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().journal_size));
|
||||
fmt::print(" UserAccountSaveDataJournalSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().journal_size));
|
||||
}
|
||||
|
||||
// DeviceSaveDataSizeMax
|
||||
if (mNacp.getDeviceSaveDataMax().size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" DeviceSaveDataSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().size));
|
||||
fmt::print(" DeviceSaveDataSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().size));
|
||||
}
|
||||
|
||||
// DeviceSaveDataJournalSizeMax
|
||||
if (mNacp.getDeviceSaveDataMax().journal_size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" DeviceSaveDataJournalSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().journal_size));
|
||||
fmt::print(" DeviceSaveDataJournalSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().journal_size));
|
||||
}
|
||||
|
||||
// TemporaryStorageSize
|
||||
if (mNacp.getTemporaryStorageSize() != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" TemporaryStorageSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getTemporaryStorageSize()));
|
||||
fmt::print(" TemporaryStorageSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getTemporaryStorageSize()));
|
||||
}
|
||||
|
||||
// CacheStorageSize
|
||||
if (mNacp.getCacheStorageSize().size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" CacheStorageSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().size));
|
||||
fmt::print(" CacheStorageSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().size));
|
||||
}
|
||||
|
||||
// CacheStorageJournalSize
|
||||
if (mNacp.getCacheStorageSize().journal_size != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" CacheStorageJournalSize: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().journal_size));
|
||||
fmt::print(" CacheStorageJournalSize: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().journal_size));
|
||||
}
|
||||
|
||||
// CacheStorageDataAndJournalSizeMax
|
||||
if (mNacp.getCacheStorageDataAndJournalSizeMax() != 0 || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" CacheStorageDataAndJournalSizeMax: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageDataAndJournalSizeMax()));
|
||||
fmt::print(" CacheStorageDataAndJournalSizeMax: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageDataAndJournalSizeMax()));
|
||||
}
|
||||
|
||||
// CacheStorageIndexMax
|
||||
|
|
@ -411,9 +411,9 @@ void nstool::NacpProcess::displayNacp()
|
|||
}
|
||||
|
||||
// PlayLogQueryCapability
|
||||
if (mNacp.getPlayLogQueryCapability() != nn::hac::nacp::PlayLogQueryCapability::None || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getPlayLogQueryCapability() != pie::hac::nacp::PlayLogQueryCapability_None || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" PlayLogQueryCapability: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getPlayLogQueryCapabilityAsString(mNacp.getPlayLogQueryCapability()));
|
||||
fmt::print(" PlayLogQueryCapability: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getPlayLogQueryCapabilityAsString(mNacp.getPlayLogQueryCapability()));
|
||||
}
|
||||
|
||||
// Repair
|
||||
|
|
@ -422,7 +422,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
fmt::print(" Repair:\n");
|
||||
for (auto itr = mNacp.getRepair().begin(); itr != mNacp.getRepair().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getRepairFlagAsString(*itr));
|
||||
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getRepairFlagAsString(*itr));
|
||||
}
|
||||
}
|
||||
else if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -442,7 +442,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
fmt::print(" RequiredNetworkServiceLicenseOnLaunch:\n");
|
||||
for (auto itr = mNacp.getRequiredNetworkServiceLicenseOnLaunch().begin(); itr != mNacp.getRequiredNetworkServiceLicenseOnLaunch().end(); itr++)
|
||||
{
|
||||
fmt::print(" {:s}\n", nn::hac::ApplicationControlPropertyUtil::getRequiredNetworkServiceLicenseOnLaunchFlagAsString(*itr));
|
||||
fmt::print(" {:s}\n", pie::hac::ApplicationControlPropertyUtil::getRequiredNetworkServiceLicenseOnLaunchFlagAsString(*itr));
|
||||
}
|
||||
}
|
||||
else if (mCliOutputMode.show_extended_info)
|
||||
|
|
@ -468,7 +468,7 @@ void nstool::NacpProcess::displayNacp()
|
|||
if (detect_config.countReceivableGroupConfig() > 0)
|
||||
{
|
||||
fmt::print(" ReceivableGroupConfig:\n");
|
||||
for (size_t i = 0; i < nn::hac::nacp::kReceivableGroupConfigurationCount; i++)
|
||||
for (size_t i = 0; i < pie::hac::nacp::kReceivableGroupConfigurationCount; i++)
|
||||
{
|
||||
if (detect_config.receivable_data_configuration[i].isNull())
|
||||
continue;
|
||||
|
|
@ -496,21 +496,21 @@ void nstool::NacpProcess::displayNacp()
|
|||
}
|
||||
|
||||
// PlayReportPermission
|
||||
if (mNacp.getPlayReportPermission() != nn::hac::nacp::PlayReportPermission::None || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getPlayReportPermission() != pie::hac::nacp::PlayReportPermission_None || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" PlayReportPermission: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getPlayReportPermissionAsString(mNacp.getPlayReportPermission()));
|
||||
fmt::print(" PlayReportPermission: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getPlayReportPermissionAsString(mNacp.getPlayReportPermission()));
|
||||
}
|
||||
|
||||
// CrashScreenshotForProd
|
||||
if (mNacp.getCrashScreenshotForProd() != nn::hac::nacp::CrashScreenshotForProd::Deny || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getCrashScreenshotForProd() != pie::hac::nacp::CrashScreenshotForProd_Deny || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" CrashScreenshotForProd: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getCrashScreenshotForProdAsString(mNacp.getCrashScreenshotForProd()));
|
||||
fmt::print(" CrashScreenshotForProd: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getCrashScreenshotForProdAsString(mNacp.getCrashScreenshotForProd()));
|
||||
}
|
||||
|
||||
// CrashScreenshotForDev
|
||||
if (mNacp.getCrashScreenshotForDev() != nn::hac::nacp::CrashScreenshotForDev::Deny || mCliOutputMode.show_extended_info)
|
||||
if (mNacp.getCrashScreenshotForDev() != pie::hac::nacp::CrashScreenshotForDev_Deny || mCliOutputMode.show_extended_info)
|
||||
{
|
||||
fmt::print(" CrashScreenshotForDev: {:s}\n", nn::hac::ApplicationControlPropertyUtil::getCrashScreenshotForDevAsString(mNacp.getCrashScreenshotForDev()));
|
||||
fmt::print(" CrashScreenshotForDev: {:s}\n", pie::hac::ApplicationControlPropertyUtil::getCrashScreenshotForDevAsString(mNacp.getCrashScreenshotForDev()));
|
||||
}
|
||||
|
||||
// AccessibleLaunchRequiredVersion
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
#include <nn/hac/ApplicationControlProperty.h>
|
||||
#include <pietendo/hac/ApplicationControlProperty.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ public:
|
|||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
const nn::hac::ApplicationControlProperty& getApplicationControlProperty() const;
|
||||
const pie::hac::ApplicationControlProperty& getApplicationControlProperty() const;
|
||||
|
||||
private:
|
||||
std::string mModuleName;
|
||||
|
|
@ -25,7 +25,7 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nn::hac::ApplicationControlProperty mNacp;
|
||||
pie::hac::ApplicationControlProperty mNacp;
|
||||
|
||||
void importNacp();
|
||||
void displayNacp();
|
||||
|
|
|
|||
|
|
@ -2,15 +2,14 @@
|
|||
#include "MetaProcess.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <tc/crypto/detail/BlockUtilImpl.h>
|
||||
|
||||
#include <nn/hac/ContentArchiveUtil.h>
|
||||
#include <nn/hac/AesKeygen.h>
|
||||
#include <nn/hac/HierarchicalSha256Stream.h>
|
||||
#include <nn/hac/HierarchicalIntegrityStream.h>
|
||||
#include <nn/hac/PartitionFsMetaGenerator.h>
|
||||
#include <nn/hac/RomFsMetaGenerator.h>
|
||||
#include <nn/hac/CombinedFsMetaGenerator.h>
|
||||
#include <pietendo/hac/ContentArchiveUtil.h>
|
||||
#include <pietendo/hac/AesKeygen.h>
|
||||
#include <pietendo/hac/HierarchicalSha256Stream.h>
|
||||
#include <pietendo/hac/HierarchicalIntegrityStream.h>
|
||||
#include <pietendo/hac/BKTREncryptedStream.h>
|
||||
#include <pietendo/hac/PartitionFsSnapshotGenerator.h>
|
||||
#include <pietendo/hac/RomFsSnapshotGenerator.h>
|
||||
#include <pietendo/hac/CombinedFsSnapshotGenerator.h>
|
||||
|
||||
nstool::NcaProcess::NcaProcess() :
|
||||
mModuleName("nstool::NcaProcess"),
|
||||
|
|
@ -50,6 +49,11 @@ void nstool::NcaProcess::setInputFile(const std::shared_ptr<tc::io::IStream>& fi
|
|||
mFile = file;
|
||||
}
|
||||
|
||||
void nstool::NcaProcess::setBaseNcaPath(const tc::Optional<tc::io::Path>& nca_path)
|
||||
{
|
||||
mBaseNcaPath = nca_path;
|
||||
}
|
||||
|
||||
void nstool::NcaProcess::setKeyCfg(const KeyBag& keycfg)
|
||||
{
|
||||
mKeyCfg = keycfg;
|
||||
|
|
@ -80,7 +84,7 @@ void nstool::NcaProcess::setExtractJobs(const std::vector<nstool::ExtractJob>& e
|
|||
mFsProcess.setExtractJobs(extract_jobs);
|
||||
}
|
||||
|
||||
const std::shared_ptr<tc::io::IStorage>& nstool::NcaProcess::getFileSystem() const
|
||||
const std::shared_ptr<tc::io::IFileSystem>& nstool::NcaProcess::getFileSystem() const
|
||||
{
|
||||
return mFileSystem;
|
||||
}
|
||||
|
|
@ -97,25 +101,25 @@ void nstool::NcaProcess::importHeader()
|
|||
}
|
||||
|
||||
// read header block
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sContentArchiveHeaderBlock)))
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sContentArchiveHeaderBlock)))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt NCA: File too small.");
|
||||
}
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read((byte_t*)(&mHdrBlock), sizeof(nn::hac::sContentArchiveHeaderBlock));
|
||||
mFile->read((byte_t*)(&mHdrBlock), sizeof(pie::hac::sContentArchiveHeaderBlock));
|
||||
|
||||
// decrypt header block
|
||||
if (mKeyCfg.nca_header_key.isNull())
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Failed to decrypt NCA header. (nca_header_key could not be loaded)");
|
||||
}
|
||||
nn::hac::ContentArchiveUtil::decryptContentArchiveHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyCfg.nca_header_key.get());
|
||||
pie::hac::ContentArchiveUtil::decryptContentArchiveHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyCfg.nca_header_key.get());
|
||||
|
||||
// generate header hash
|
||||
tc::crypto::GenerateSha256Hash(mHdrHash.data(), (byte_t*)&mHdrBlock.header, sizeof(nn::hac::sContentArchiveHeader));
|
||||
tc::crypto::GenerateSha2256Hash(mHdrHash.data(), (byte_t*)&mHdrBlock.header, sizeof(pie::hac::sContentArchiveHeader));
|
||||
|
||||
// proccess main header
|
||||
mHdr.fromBytes((byte_t*)&mHdrBlock.header, sizeof(nn::hac::sContentArchiveHeader));
|
||||
mHdr.fromBytes((byte_t*)&mHdrBlock.header, sizeof(pie::hac::sContentArchiveHeader));
|
||||
}
|
||||
|
||||
void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
|
||||
|
|
@ -125,7 +129,7 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
|
|||
memset(zero_aesctr_key.data(), 0, zero_aesctr_key.size());
|
||||
|
||||
// get key data from header
|
||||
byte_t masterkey_rev = nn::hac::AesKeygen::getMasterKeyRevisionFromKeyGeneration(mHdr.getKeyGeneration());
|
||||
byte_t masterkey_rev = pie::hac::AesKeygen::getMasterKeyRevisionFromKeyGeneration(mHdr.getKeyGeneration());
|
||||
byte_t keak_index = mHdr.getKeyAreaEncryptionKeyIndex();
|
||||
|
||||
// process key area
|
||||
|
|
@ -141,13 +145,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())
|
||||
{
|
||||
kak.decrypted = true;
|
||||
nn::hac::AesKeygen::generateKey(kak.dec.data(), kak.enc.data(), mKeyCfg.nca_key_area_encryption_key[keak_index][masterkey_rev].data());
|
||||
pie::hac::AesKeygen::generateKey(kak.dec.data(), kak.enc.data(), mKeyCfg.nca_key_area_encryption_key[keak_index][masterkey_rev].data());
|
||||
}
|
||||
// key[KEY_AESCTR_HW]
|
||||
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())
|
||||
// key[KeyBankIndex_AesCtrHw]
|
||||
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())
|
||||
{
|
||||
kak.decrypted = true;
|
||||
nn::hac::AesKeygen::generateKey(kak.dec.data(), kak.enc.data(), mKeyCfg.nca_key_area_encryption_key_hw[keak_index][masterkey_rev].data());
|
||||
pie::hac::AesKeygen::generateKey(kak.dec.data(), kak.enc.data(), mKeyCfg.nca_key_area_encryption_key_hw[keak_index][masterkey_rev].data());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -158,7 +162,7 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
|
|||
}
|
||||
|
||||
// clear content key
|
||||
mContentKey.aes_ctr = tc::Optional<nn::hac::detail::aes128_key_t>();
|
||||
mContentKey.aes_ctr = tc::Optional<pie::hac::detail::aes128_key_t>();
|
||||
|
||||
// if this has a rights id, the key needs to be sourced from a ticket
|
||||
if (mHdr.hasRightsId() == true)
|
||||
|
|
@ -172,12 +176,21 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
|
|||
{
|
||||
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())
|
||||
{
|
||||
tmp_key = mKeyCfg.fallback_enc_content_key.get();
|
||||
if (mKeyCfg.etik_common_key.find(masterkey_rev) != mKeyCfg.etik_common_key.end())
|
||||
{
|
||||
nn::hac::AesKeygen::generateKey(tmp_key.data(), tmp_key.data(), mKeyCfg.etik_common_key[masterkey_rev].data());
|
||||
pie::hac::AesKeygen::generateKey(tmp_key.data(), tmp_key.data(), mKeyCfg.etik_common_key[masterkey_rev].data());
|
||||
mContentKey.aes_ctr = tmp_key;
|
||||
}
|
||||
}
|
||||
|
|
@ -187,7 +200,7 @@ void nstool::NcaProcess::generateNcaBodyEncryptionKeys()
|
|||
{
|
||||
for (size_t i = 0; i < mContentKey.kak_list.size(); i++)
|
||||
{
|
||||
if (mContentKey.kak_list[i].index == nn::hac::nca::KEY_AESCTR && mContentKey.kak_list[i].decrypted)
|
||||
if (mContentKey.kak_list[i].index == pie::hac::nca::KeyBankIndex_AesCtr && mContentKey.kak_list[i].decrypted)
|
||||
{
|
||||
mContentKey.aes_ctr = mContentKey.kak_list[i].dec;
|
||||
}
|
||||
|
|
@ -213,44 +226,72 @@ 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()
|
||||
{
|
||||
for (size_t i = 0; i < mHdr.getPartitionEntryList().size(); i++)
|
||||
{
|
||||
// get reference to relevant structures
|
||||
const nn::hac::ContentArchiveHeader::sPartitionEntry& partition = mHdr.getPartitionEntryList()[i];
|
||||
nn::hac::sContentArchiveFsHeader& fs_header = mHdrBlock.fs_header[partition.header_index];
|
||||
const pie::hac::ContentArchiveHeader::sPartitionEntry& partition = mHdr.getPartitionEntryList()[i];
|
||||
pie::hac::sContentArchiveFsHeader& fs_header = mHdrBlock.fs_header[partition.header_index];
|
||||
|
||||
// output structure
|
||||
sPartitionInfo& info = mPartitions[partition.header_index];
|
||||
|
||||
// validate header hash
|
||||
nn::hac::detail::sha256_hash_t fs_header_hash;
|
||||
tc::crypto::GenerateSha256Hash(fs_header_hash.data(), (const byte_t*)&mHdrBlock.fs_header[partition.header_index], sizeof(nn::hac::sContentArchiveFsHeader));
|
||||
pie::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));
|
||||
if (fs_header_hash != partition.fs_header_hash)
|
||||
{
|
||||
throw tc::Exception(mModuleName, fmt::format("NCA FS Header [{:d}] Hash: FAIL", partition.header_index));
|
||||
}
|
||||
|
||||
if (fs_header.version.unwrap() != nn::hac::nca::kDefaultFsHeaderVersion)
|
||||
if (fs_header.version.unwrap() != pie::hac::nca::kDefaultFsHeaderVersion)
|
||||
{
|
||||
throw tc::Exception(mModuleName, fmt::format("NCA FS Header [{:d}] Version({:d}): UNSUPPORTED", partition.header_index, fs_header.version.unwrap()));
|
||||
}
|
||||
|
||||
// setup AES-CTR
|
||||
nn::hac::ContentArchiveUtil::getNcaPartitionAesCtr(&fs_header, info.aes_ctr.data());
|
||||
pie::hac::ContentArchiveUtil::getNcaPartitionAesCtr(&fs_header, info.aes_ctr.data());
|
||||
|
||||
// save partition configinfo
|
||||
info.offset = partition.offset;
|
||||
info.size = partition.size;
|
||||
info.format_type = (nn::hac::nca::FormatType)fs_header.format_type;
|
||||
info.hash_type = (nn::hac::nca::HashType)fs_header.hash_type;
|
||||
info.enc_type = (nn::hac::nca::EncryptionType)fs_header.encryption_type;
|
||||
if (info.hash_type == nn::hac::nca::HashType::HierarchicalSha256)
|
||||
info.format_type = (pie::hac::nca::FormatType)fs_header.format_type;
|
||||
info.hash_type = (pie::hac::nca::HashType)fs_header.hash_type;
|
||||
info.enc_type = (pie::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 == pie::hac::nca::HashType_HierarchicalSha256)
|
||||
{
|
||||
info.hierarchicalsha256_hdr.fromBytes(fs_header.hash_info.data(), fs_header.hash_info.size());
|
||||
}
|
||||
else if (info.hash_type == nn::hac::nca::HashType::HierarchicalIntegrity)
|
||||
else if (info.hash_type == pie::hac::nca::HashType_HierarchicalIntegrity)
|
||||
{
|
||||
info.hierarchicalintegrity_hdr.fromBytes(fs_header.hash_info.data(), fs_header.hash_info.size());
|
||||
}
|
||||
|
|
@ -266,68 +307,106 @@ void nstool::NcaProcess::generatePartitionConfiguration()
|
|||
else
|
||||
{
|
||||
// create raw partition
|
||||
info.reader = std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, info.offset, info.size));
|
||||
info.raw_reader = std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, info.offset, info.size));
|
||||
|
||||
// handle encryption if required reader based on encryption type
|
||||
if (info.enc_type == nn::hac::nca::EncryptionType::None)
|
||||
if (info.enc_type == pie::hac::nca::EncryptionType_None)
|
||||
{
|
||||
// no encryption so do nothing
|
||||
//info.reader = info.reader;
|
||||
info.decrypt_reader = info.raw_reader;
|
||||
}
|
||||
else if (info.enc_type == nn::hac::nca::EncryptionType::AesCtr)
|
||||
else if (info.enc_type == pie::hac::nca::EncryptionType_AesCtr)
|
||||
{
|
||||
if (mContentKey.aes_ctr.isNull())
|
||||
throw tc::Exception(mModuleName, "AES-CTR Key was not determined");
|
||||
|
||||
// get partition key
|
||||
nn::hac::detail::aes128_key_t partition_key = mContentKey.aes_ctr.get();
|
||||
pie::hac::detail::aes128_key_t partition_key = mContentKey.aes_ctr.get();
|
||||
|
||||
// get partition counter
|
||||
nn::hac::detail::aes_iv_t partition_ctr = info.aes_ctr;
|
||||
tc::crypto::detail::incr_counter<16>(partition_ctr.data(), info.offset>>4);
|
||||
pie::hac::detail::aes_iv_t partition_ctr = info.aes_ctr;
|
||||
tc::crypto::IncrementCounterAes128Ctr(partition_ctr.data(), info.offset >> 4);
|
||||
|
||||
// create decryption stream
|
||||
info.reader = std::make_shared<tc::crypto::Aes128CtrEncryptedStream>(tc::crypto::Aes128CtrEncryptedStream(info.reader, partition_key, partition_ctr));
|
||||
|
||||
info.decrypt_reader = std::make_shared<tc::crypto::Aes128CtrEncryptedStream>(tc::crypto::Aes128CtrEncryptedStream(info.raw_reader, partition_key, partition_ctr));
|
||||
}
|
||||
else if (info.enc_type == nn::hac::nca::EncryptionType::AesXts || info.enc_type == nn::hac::nca::EncryptionType::AesCtrEx)
|
||||
else if (info.enc_type == pie::hac::nca::EncryptionType_AesCtrEx)
|
||||
{
|
||||
throw tc::Exception(mModuleName, fmt::format("EncryptionType({:s}): UNSUPPORTED", nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type)));
|
||||
if (mContentKey.aes_ctr.isNull())
|
||||
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
|
||||
{
|
||||
throw tc::Exception(mModuleName, fmt::format("EncryptionType({:s}): UNKNOWN", nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type)));
|
||||
throw tc::Exception(mModuleName, fmt::format("EncryptionType({:s}): UNKNOWN", pie::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type)));
|
||||
}
|
||||
}
|
||||
|
||||
// filter out unrecognised hash types, and hash based readers
|
||||
switch (info.hash_type)
|
||||
{
|
||||
case (nn::hac::nca::HashType::None):
|
||||
case (pie::hac::nca::HashType_None):
|
||||
// no hash layer, do nothing
|
||||
info.reader = info.decrypt_reader;
|
||||
break;
|
||||
case (nn::hac::nca::HashType::HierarchicalSha256):
|
||||
info.reader = std::make_shared<nn::hac::HierarchicalSha256Stream>(nn::hac::HierarchicalSha256Stream(info.reader, info.hierarchicalsha256_hdr));
|
||||
case (pie::hac::nca::HashType_HierarchicalSha256):
|
||||
info.reader = std::make_shared<pie::hac::HierarchicalSha256Stream>(pie::hac::HierarchicalSha256Stream(info.decrypt_reader, info.hierarchicalsha256_hdr));
|
||||
break;
|
||||
case (nn::hac::nca::HashType::HierarchicalIntegrity):
|
||||
info.reader = std::make_shared<nn::hac::HierarchicalIntegrityStream>(nn::hac::HierarchicalIntegrityStream(info.reader, info.hierarchicalintegrity_hdr));
|
||||
case (pie::hac::nca::HashType_HierarchicalIntegrity):
|
||||
info.reader = std::make_shared<pie::hac::HierarchicalIntegrityStream>(pie::hac::HierarchicalIntegrityStream(info.decrypt_reader, info.hierarchicalintegrity_hdr));
|
||||
break;
|
||||
default:
|
||||
throw tc::Exception(mModuleName, fmt::format("HashType({:s}): UNKNOWN", nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type)));
|
||||
throw tc::Exception(mModuleName, fmt::format("HashType({:s}): UNKNOWN", pie::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type)));
|
||||
}
|
||||
|
||||
// filter out unrecognised format types
|
||||
switch (info.format_type)
|
||||
{
|
||||
case (nn::hac::nca::FormatType::PartitionFs):
|
||||
info.fs_meta = nn::hac::PartitionFsMetaGenerator(info.reader);
|
||||
info.fs_reader = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(info.fs_meta));
|
||||
case (pie::hac::nca::FormatType_PartitionFs):
|
||||
info.fs_snapshot = pie::hac::PartitionFsSnapshotGenerator(info.reader);
|
||||
info.fs_reader = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(info.fs_snapshot));
|
||||
break;
|
||||
case (nn::hac::nca::FormatType::RomFs):
|
||||
info.fs_meta = nn::hac::RomFsMetaGenerator(info.reader);
|
||||
info.fs_reader = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(info.fs_meta));
|
||||
case (pie::hac::nca::FormatType_RomFs):
|
||||
info.fs_snapshot = pie::hac::RomFsSnapshotGenerator(info.reader);
|
||||
info.fs_reader = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(info.fs_snapshot));
|
||||
break;
|
||||
default:
|
||||
throw tc::Exception(mModuleName, fmt::format("FormatType({:s}): UNKNOWN", nn::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type)));
|
||||
throw tc::Exception(mModuleName, fmt::format("FormatType({:s}): UNKNOWN", pie::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type)));
|
||||
}
|
||||
}
|
||||
catch (const tc::Exception& e)
|
||||
|
|
@ -342,7 +421,7 @@ void nstool::NcaProcess::validateNcaSignatures()
|
|||
// validate signature[0]
|
||||
if (mKeyCfg.nca_header_sign0_key.find(mHdr.getSignatureKeyGeneration()) != mKeyCfg.nca_header_sign0_key.end())
|
||||
{
|
||||
if (tc::crypto::VerifyRsa2048PssSha256(mHdrBlock.signature_main.data(), mHdrHash.data(), mKeyCfg.nca_header_sign0_key[mHdr.getSignatureKeyGeneration()]) == false)
|
||||
if (tc::crypto::VerifyRsa2048PssSha2256(mHdrBlock.signature_main.data(), mHdrHash.data(), mKeyCfg.nca_header_sign0_key[mHdr.getSignatureKeyGeneration()]) == false)
|
||||
{
|
||||
fmt::print("[WARNING] NCA Header Main Signature: FAIL\n");
|
||||
}
|
||||
|
|
@ -354,16 +433,16 @@ void nstool::NcaProcess::validateNcaSignatures()
|
|||
|
||||
|
||||
// validate signature[1]
|
||||
if (mHdr.getContentType() == nn::hac::nca::ContentType::Program)
|
||||
if (mHdr.getContentType() == pie::hac::nca::ContentType_Program)
|
||||
{
|
||||
try {
|
||||
if (mPartitions[nn::hac::nca::PARTITION_CODE].format_type == nn::hac::nca::FormatType::PartitionFs)
|
||||
if (mPartitions[pie::hac::nca::ProgramContentPartitionIndex_Code].format_type == pie::hac::nca::FormatType_PartitionFs)
|
||||
{
|
||||
if (mPartitions[nn::hac::nca::PARTITION_CODE].fs_reader != nullptr)
|
||||
if (mPartitions[pie::hac::nca::ProgramContentPartitionIndex_Code].fs_reader != nullptr)
|
||||
{
|
||||
std::shared_ptr<tc::io::IStream> npdm_file;
|
||||
try {
|
||||
mPartitions[nn::hac::nca::PARTITION_CODE].fs_reader->openFile(tc::io::Path(kNpdmExefsPath), tc::io::FileMode::Open, tc::io::FileAccess::Read, npdm_file);
|
||||
mPartitions[pie::hac::nca::ProgramContentPartitionIndex_Code].fs_reader->openFile(tc::io::Path(kNpdmExefsPath), tc::io::FileMode::Open, tc::io::FileAccess::Read, npdm_file);
|
||||
}
|
||||
catch (tc::io::FileNotFoundException&) {
|
||||
throw tc::Exception(fmt::format("\"{:s}\" not present in ExeFs", kNpdmExefsPath));
|
||||
|
|
@ -376,7 +455,7 @@ void nstool::NcaProcess::validateNcaSignatures()
|
|||
npdm.setCliOutputMode(CliOutputMode(false, false, false, false));
|
||||
npdm.process();
|
||||
|
||||
if (tc::crypto::VerifyRsa2048PssSha256(mHdrBlock.signature_acid.data(), mHdrHash.data(), npdm.getMeta().getAccessControlInfoDesc().getContentArchiveHeaderSignature2Key()) == false)
|
||||
if (tc::crypto::VerifyRsa2048PssSha2256(mHdrBlock.signature_acid.data(), mHdrHash.data(), npdm.getMeta().getAccessControlInfoDesc().getContentArchiveHeaderSignature2Key()) == false)
|
||||
{
|
||||
throw tc::Exception("Bad signature");
|
||||
}
|
||||
|
|
@ -400,16 +479,16 @@ void nstool::NcaProcess::validateNcaSignatures()
|
|||
void nstool::NcaProcess::displayHeader()
|
||||
{
|
||||
fmt::print("[NCA Header]\n");
|
||||
fmt::print(" Format Type: {:s}\n", nn::hac::ContentArchiveUtil::getFormatHeaderVersionAsString((nn::hac::nca::HeaderFormatVersion)mHdr.getFormatVersion()));
|
||||
fmt::print(" Dist. Type: {:s}\n", nn::hac::ContentArchiveUtil::getDistributionTypeAsString(mHdr.getDistributionType()));
|
||||
fmt::print(" Content Type: {:s}\n", nn::hac::ContentArchiveUtil::getContentTypeAsString(mHdr.getContentType()));
|
||||
fmt::print(" Format Type: {:s}\n", pie::hac::ContentArchiveUtil::getFormatHeaderVersionAsString((pie::hac::nca::HeaderFormatVersion)mHdr.getFormatVersion()));
|
||||
fmt::print(" Dist. Type: {:s}\n", pie::hac::ContentArchiveUtil::getDistributionTypeAsString(mHdr.getDistributionType()));
|
||||
fmt::print(" Content Type: {:s}\n", pie::hac::ContentArchiveUtil::getContentTypeAsString(mHdr.getContentType()));
|
||||
fmt::print(" Key Generation: {:d}\n", mHdr.getKeyGeneration());
|
||||
fmt::print(" Sig. Generation: {:d}\n", mHdr.getSignatureKeyGeneration());
|
||||
fmt::print(" Kaek Index: {:s} ({:d})\n", nn::hac::ContentArchiveUtil::getKeyAreaEncryptionKeyIndexAsString((nn::hac::nca::KeyAreaEncryptionKeyIndex)mHdr.getKeyAreaEncryptionKeyIndex()), mHdr.getKeyAreaEncryptionKeyIndex());
|
||||
fmt::print(" Kaek Index: {:s} ({:d})\n", pie::hac::ContentArchiveUtil::getKeyAreaEncryptionKeyIndexAsString((pie::hac::nca::KeyAreaEncryptionKeyIndex)mHdr.getKeyAreaEncryptionKeyIndex()), mHdr.getKeyAreaEncryptionKeyIndex());
|
||||
fmt::print(" Size: 0x{:x}\n", mHdr.getContentSize());
|
||||
fmt::print(" ProgID: 0x{:016x}\n", mHdr.getProgramId());
|
||||
fmt::print(" Content Index: {:d}\n", mHdr.getContentIndex());
|
||||
fmt::print(" SdkAddon Ver.: {:s} (v{:d})\n", nn::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getSdkAddonVersion()), mHdr.getSdkAddonVersion());
|
||||
fmt::print(" SdkAddon Ver.: {:s} (v{:d})\n", pie::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getSdkAddonVersion()), mHdr.getSdkAddonVersion());
|
||||
if (mHdr.hasRightsId())
|
||||
{
|
||||
fmt::print(" RightsId: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getRightsId().data(), mHdr.getRightsId().size(), true, ""));
|
||||
|
|
@ -418,22 +497,18 @@ void nstool::NcaProcess::displayHeader()
|
|||
if (mContentKey.kak_list.size() > 0 && mCliOutputMode.show_keydata)
|
||||
{
|
||||
fmt::print(" Key Area:\n");
|
||||
fmt::print(" <--------------------------------------------------------------------------------------------------------->\n");
|
||||
fmt::print(" | IDX | ENCRYPTED KEY | DECRYPTED KEY |\n");
|
||||
fmt::print(" |-----|-------------------------------------------------|-------------------------------------------------|\n");
|
||||
fmt::print(" <--------------------------------------------------------------------------->\n");
|
||||
fmt::print(" | IDX | ENCRYPTED KEY | DECRYPTED KEY |\n");
|
||||
fmt::print(" |-----|----------------------------------|----------------------------------|\n");
|
||||
for (size_t i = 0; i < mContentKey.kak_list.size(); i++)
|
||||
{
|
||||
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 enc_key = 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>";
|
||||
|
||||
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(" | {:3d} | {:32s} | {:32s} |\n", mContentKey.kak_list[i].index, enc_key, dec_key);
|
||||
|
||||
}
|
||||
fmt::print(" <--------------------------------------------------------------------------------------------------------->\n");
|
||||
fmt::print(" <--------------------------------------------------------------------------->\n");
|
||||
}
|
||||
|
||||
if (mCliOutputMode.show_layout)
|
||||
|
|
@ -448,18 +523,18 @@ void nstool::NcaProcess::displayHeader()
|
|||
fmt::print(" {:d}:\n", index);
|
||||
fmt::print(" Offset: 0x{:x}\n", info.offset);
|
||||
fmt::print(" Size: 0x{:x}\n", info.size);
|
||||
fmt::print(" Format Type: {:s}\n", nn::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type));
|
||||
fmt::print(" Hash Type: {:s}\n", nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type));
|
||||
fmt::print(" Enc. Type: {:s}\n", nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type));
|
||||
if (info.enc_type == nn::hac::nca::EncryptionType::AesCtr)
|
||||
fmt::print(" Format Type: {:s}\n", pie::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type));
|
||||
fmt::print(" Hash Type: {:s}\n", pie::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type));
|
||||
fmt::print(" Enc. Type: {:s}\n", pie::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type));
|
||||
if (info.enc_type == pie::hac::nca::EncryptionType_AesCtr)
|
||||
{
|
||||
nn::hac::detail::aes_iv_t aes_ctr;
|
||||
pie::hac::detail::aes_iv_t aes_ctr;
|
||||
memcpy(aes_ctr.data(), info.aes_ctr.data(), aes_ctr.size());
|
||||
tc::crypto::detail::incr_counter<16>(aes_ctr.data(), info.offset>>4);
|
||||
tc::crypto::IncrementCounterAes128Ctr(aes_ctr.data(), info.offset>>4);
|
||||
fmt::print(" AesCtr Counter:\n");
|
||||
fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(aes_ctr.data(), aes_ctr.size(), true, ""));
|
||||
}
|
||||
if (info.hash_type == nn::hac::nca::HashType::HierarchicalIntegrity)
|
||||
if (info.hash_type == pie::hac::nca::HashType_HierarchicalIntegrity)
|
||||
{
|
||||
auto hash_hdr = info.hierarchicalintegrity_hdr;
|
||||
fmt::print(" HierarchicalIntegrity Header:\n");
|
||||
|
|
@ -484,7 +559,7 @@ void nstool::NcaProcess::displayHeader()
|
|||
fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(hash_hdr.getMasterHashList()[j].data()+0x10, 0x10, true, ""));
|
||||
}
|
||||
}
|
||||
else if (info.hash_type == nn::hac::nca::HashType::HierarchicalSha256)
|
||||
else if (info.hash_type == pie::hac::nca::HashType_HierarchicalSha256)
|
||||
{
|
||||
auto hash_hdr = info.hierarchicalsha256_hdr;
|
||||
fmt::print(" HierarchicalSha256 Header:\n");
|
||||
|
|
@ -513,7 +588,7 @@ void nstool::NcaProcess::displayHeader()
|
|||
|
||||
void nstool::NcaProcess::processPartitions()
|
||||
{
|
||||
std::vector<nn::hac::CombinedFsMetaGenerator::MountPointInfo> mount_points;
|
||||
std::vector<pie::hac::CombinedFsSnapshotGenerator::MountPointInfo> mount_points;
|
||||
|
||||
for (size_t i = 0; i < mHdr.getPartitionEntryList().size(); i++)
|
||||
{
|
||||
|
|
@ -534,9 +609,9 @@ void nstool::NcaProcess::processPartitions()
|
|||
|
||||
std::string mount_point_name;
|
||||
/*
|
||||
if (mHdr.getContentType() == nn::hac::nca::ContentType::Program)
|
||||
if (mHdr.getContentType() == pie::hac::nca::ContentType_Program)
|
||||
{
|
||||
mount_point_name = nn::hac::ContentArchiveUtil::getProgramContentParititionIndexAsString((nn::hac::nca::ProgramContentPartitionIndex)index);
|
||||
mount_point_name = pie::hac::ContentArchiveUtil::getProgramContentParititionIndexAsString((pie::hac::nca::ProgramContentPartitionIndex)index);
|
||||
}
|
||||
else
|
||||
*/
|
||||
|
|
@ -544,12 +619,12 @@ void nstool::NcaProcess::processPartitions()
|
|||
mount_point_name = fmt::format("{:d}", index);
|
||||
}
|
||||
|
||||
mount_points.push_back( { mount_point_name, partition.fs_meta } );
|
||||
mount_points.push_back( { mount_point_name, partition.fs_snapshot } );
|
||||
}
|
||||
|
||||
tc::io::VirtualFileSystem::FileSystemMeta fs_meta = nn::hac::CombinedFsMetaGenerator(mount_points);
|
||||
tc::io::VirtualFileSystem::FileSystemSnapshot fs_snapshot = pie::hac::CombinedFsSnapshotGenerator(mount_points);
|
||||
|
||||
std::shared_ptr<tc::io::IStorage> nca_fs = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(fs_meta));
|
||||
std::shared_ptr<tc::io::IFileSystem> nca_fs = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(fs_snapshot));
|
||||
|
||||
mFsProcess.setInputFileSystem(nca_fs);
|
||||
mFsProcess.setFsFormatName("ContentArchive");
|
||||
|
|
@ -557,28 +632,28 @@ void nstool::NcaProcess::processPartitions()
|
|||
mFsProcess.process();
|
||||
}
|
||||
|
||||
std::string nstool::NcaProcess::getContentTypeForMountStr(nn::hac::nca::ContentType cont_type) const
|
||||
std::string nstool::NcaProcess::getContentTypeForMountStr(pie::hac::nca::ContentType cont_type) const
|
||||
{
|
||||
std::string str;
|
||||
|
||||
switch (cont_type)
|
||||
{
|
||||
case (nn::hac::nca::ContentType::Program):
|
||||
case (pie::hac::nca::ContentType_Program):
|
||||
str = "program";
|
||||
break;
|
||||
case (nn::hac::nca::ContentType::Meta):
|
||||
case (pie::hac::nca::ContentType_Meta):
|
||||
str = "meta";
|
||||
break;
|
||||
case (nn::hac::nca::ContentType::Control):
|
||||
case (pie::hac::nca::ContentType_Control):
|
||||
str = "control";
|
||||
break;
|
||||
case (nn::hac::nca::ContentType::Manual):
|
||||
case (pie::hac::nca::ContentType_Manual):
|
||||
str = "manual";
|
||||
break;
|
||||
case (nn::hac::nca::ContentType::Data):
|
||||
case (pie::hac::nca::ContentType_Data):
|
||||
str = "data";
|
||||
break;
|
||||
case (nn::hac::nca::ContentType::PublicData):
|
||||
case (pie::hac::nca::ContentType_PublicData):
|
||||
str = "publicdata";
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
#include "KeyBag.h"
|
||||
#include "FsProcess.h"
|
||||
|
||||
#include <nn/hac/ContentArchiveHeader.h>
|
||||
#include <nn/hac/HierarchicalIntegrityHeader.h>
|
||||
#include <nn/hac/HierarchicalSha256Header.h>
|
||||
#include <pietendo/hac/ContentArchiveHeader.h>
|
||||
#include <pietendo/hac/HierarchicalIntegrityHeader.h>
|
||||
#include <pietendo/hac/HierarchicalSha256Header.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -21,6 +21,8 @@ public:
|
|||
void setKeyCfg(const KeyBag& keycfg);
|
||||
void setCliOutputMode(CliOutputMode type);
|
||||
void setVerifyMode(bool verify);
|
||||
void setBaseNcaPath(const tc::Optional<tc::io::Path>& nca_path);
|
||||
|
||||
|
||||
// fs specific
|
||||
void setShowFsTree(bool show_fs_tree);
|
||||
|
|
@ -28,7 +30,7 @@ public:
|
|||
void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);
|
||||
|
||||
// post process() get FS out
|
||||
const std::shared_ptr<tc::io::IStorage>& getFileSystem() const;
|
||||
const std::shared_ptr<tc::io::IFileSystem>& getFileSystem() const;
|
||||
private:
|
||||
const std::string kNpdmExefsPath = "/main.npdm";
|
||||
|
||||
|
|
@ -39,15 +41,16 @@ private:
|
|||
KeyBag mKeyCfg;
|
||||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
tc::Optional<tc::io::Path> mBaseNcaPath;
|
||||
|
||||
// fs processing
|
||||
std::shared_ptr<tc::io::IStorage> mFileSystem;
|
||||
std::shared_ptr<tc::io::IFileSystem> mFileSystem;
|
||||
FsProcess mFsProcess;
|
||||
|
||||
// nca data
|
||||
nn::hac::sContentArchiveHeaderBlock mHdrBlock;
|
||||
nn::hac::detail::sha256_hash_t mHdrHash;
|
||||
nn::hac::ContentArchiveHeader mHdr;
|
||||
pie::hac::sContentArchiveHeaderBlock mHdrBlock;
|
||||
pie::hac::detail::sha256_hash_t mHdrHash;
|
||||
pie::hac::ContentArchiveHeader mHdr;
|
||||
|
||||
// crypto
|
||||
struct sKeys
|
||||
|
|
@ -82,7 +85,7 @@ private:
|
|||
};
|
||||
std::vector<sKeyAreaKey> kak_list;
|
||||
|
||||
tc::Optional<nn::hac::detail::aes128_key_t> aes_ctr;
|
||||
tc::Optional<pie::hac::detail::aes128_key_t> aes_ctr;
|
||||
} mContentKey;
|
||||
|
||||
struct SparseInfo
|
||||
|
|
@ -93,30 +96,33 @@ private:
|
|||
// raw partition data
|
||||
struct sPartitionInfo
|
||||
{
|
||||
std::shared_ptr<tc::io::IStream> reader;
|
||||
tc::io::VirtualFileSystem::FileSystemMeta fs_meta;
|
||||
std::shared_ptr<tc::io::IStorage> fs_reader;
|
||||
std::shared_ptr<tc::io::IStream> raw_reader; // raw unprocessed partition stream
|
||||
std::shared_ptr<tc::io::IStream> decrypt_reader; // partition stream with transparent decryption
|
||||
std::shared_ptr<tc::io::IStream> reader; // partition stream with transparent decryption & hash layer processing
|
||||
tc::io::VirtualFileSystem::FileSystemSnapshot fs_snapshot;
|
||||
std::shared_ptr<tc::io::IFileSystem> fs_reader;
|
||||
std::string fail_reason;
|
||||
int64_t offset;
|
||||
int64_t size;
|
||||
|
||||
// meta data
|
||||
nn::hac::nca::FormatType format_type;
|
||||
nn::hac::nca::HashType hash_type;
|
||||
nn::hac::nca::EncryptionType enc_type;
|
||||
pie::hac::nca::FormatType format_type;
|
||||
pie::hac::nca::HashType hash_type;
|
||||
pie::hac::nca::EncryptionType enc_type;
|
||||
pie::hac::nca::MetaDataHashType metadata_hash_type;
|
||||
|
||||
// hash meta data
|
||||
nn::hac::HierarchicalIntegrityHeader hierarchicalintegrity_hdr;
|
||||
nn::hac::HierarchicalSha256Header hierarchicalsha256_hdr;
|
||||
pie::hac::HierarchicalIntegrityHeader hierarchicalintegrity_hdr;
|
||||
pie::hac::HierarchicalSha256Header hierarchicalsha256_hdr;
|
||||
|
||||
// crypto metadata
|
||||
nn::hac::detail::aes_iv_t aes_ctr;
|
||||
pie::hac::detail::aes_iv_t aes_ctr;
|
||||
|
||||
// sparse metadata
|
||||
SparseInfo sparse_info;
|
||||
};
|
||||
|
||||
std::array<sPartitionInfo, nn::hac::nca::kPartitionNum> mPartitions;
|
||||
std::array<sPartitionInfo, pie::hac::nca::kPartitionNum> mPartitions;
|
||||
|
||||
void importHeader();
|
||||
void generateNcaBodyEncryptionKeys();
|
||||
|
|
@ -125,7 +131,9 @@ private:
|
|||
void displayHeader();
|
||||
void processPartitions();
|
||||
|
||||
std::string getContentTypeForMountStr(nn::hac::nca::ContentType cont_type) const;
|
||||
NcaProcess readBaseNCA();
|
||||
|
||||
std::string getContentTypeForMountStr(pie::hac::nca::ContentType cont_type) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
#include "NroProcess.h"
|
||||
|
||||
#include <nn/hac/define/nro-hb.h>
|
||||
|
||||
nstool::NroProcess::NroProcess() :
|
||||
mModuleName("nstool::NroProcess"),
|
||||
mFile(),
|
||||
|
|
@ -91,13 +89,13 @@ void nstool::NroProcess::importHeader()
|
|||
}
|
||||
|
||||
// check if file_size is smaller than NRO header size
|
||||
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sNroHeader))
|
||||
if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(pie::hac::sNroHeader))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt NRO: file too small.");
|
||||
}
|
||||
|
||||
// read nro
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sNroHeader));
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sNroHeader));
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read(scratch.data(), scratch.size());
|
||||
|
||||
|
|
@ -105,10 +103,10 @@ void nstool::NroProcess::importHeader()
|
|||
mHdr.fromBytes(scratch.data(), scratch.size());
|
||||
|
||||
// setup homebrew extension
|
||||
nn::hac::sNroHeader* raw_hdr = (nn::hac::sNroHeader*)scratch.data();
|
||||
pie::hac::sNroHeader* raw_hdr = (pie::hac::sNroHeader*)scratch.data();
|
||||
|
||||
int64_t file_size = mFile->length();
|
||||
if (((tc::bn::le64<uint64_t>*)raw_hdr->reserved_0.data())->unwrap() == nn::hac::nro::kNroHomebrewStructMagic && file_size > int64_t(mHdr.getNroSize()))
|
||||
if (((tc::bn::le64<uint64_t>*)raw_hdr->reserved_0.data())->unwrap() == pie::hac::nro::kNroHomebrewStructMagic && file_size > int64_t(mHdr.getNroSize()))
|
||||
{
|
||||
mIsHomebrewNro = true;
|
||||
mAssetProc.setInputFile(std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, int64_t(mHdr.getNroSize()), file_size - int64_t(mHdr.getNroSize()))));
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include "RoMetadataProcess.h"
|
||||
#include "AssetProcess.h"
|
||||
|
||||
#include <nn/hac/NroHeader.h>
|
||||
#include <pietendo/hac/NroHeader.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nn::hac::NroHeader mHdr;
|
||||
pie::hac::NroHeader mHdr;
|
||||
tc::ByteData mTextBlob, mRoBlob, mDataBlob;
|
||||
nstool::RoMetadataProcess mRoMeta;
|
||||
bool mIsHomebrewNro;
|
||||
|
|
|
|||
|
|
@ -71,13 +71,13 @@ void nstool::NsoProcess::importHeader()
|
|||
|
||||
// check if file_size is smaller than NSO header size
|
||||
size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
|
||||
if (file_size < sizeof(nn::hac::sNsoHeader))
|
||||
if (file_size < sizeof(pie::hac::sNsoHeader))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt NSO: file too small.");
|
||||
}
|
||||
|
||||
// read nso
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sNsoHeader));
|
||||
tc::ByteData scratch = tc::ByteData(sizeof(pie::hac::sNsoHeader));
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read(scratch.data(), scratch.size());
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ void nstool::NsoProcess::importHeader()
|
|||
void nstool::NsoProcess::importCodeSegments()
|
||||
{
|
||||
tc::ByteData scratch;
|
||||
nn::hac::detail::sha256_hash_t calc_hash;
|
||||
pie::hac::detail::sha256_hash_t calc_hash;
|
||||
|
||||
// process text segment
|
||||
if (mHdr.getTextSegmentInfo().is_compressed)
|
||||
|
|
@ -116,7 +116,7 @@ void nstool::NsoProcess::importCodeSegments()
|
|||
}
|
||||
if (mHdr.getTextSegmentInfo().is_hashed)
|
||||
{
|
||||
tc::crypto::GenerateSha256Hash(calc_hash.data(), mTextBlob.data(), mTextBlob.size());
|
||||
tc::crypto::GenerateSha2256Hash(calc_hash.data(), mTextBlob.data(), mTextBlob.size());
|
||||
if (calc_hash != mHdr.getTextSegmentInfo().hash)
|
||||
{
|
||||
throw tc::Exception(mModuleName, "NSO text segment failed SHA256 verification");
|
||||
|
|
@ -149,7 +149,7 @@ void nstool::NsoProcess::importCodeSegments()
|
|||
}
|
||||
if (mHdr.getRoSegmentInfo().is_hashed)
|
||||
{
|
||||
tc::crypto::GenerateSha256Hash(calc_hash.data(), mRoBlob.data(), mRoBlob.size());
|
||||
tc::crypto::GenerateSha2256Hash(calc_hash.data(), mRoBlob.data(), mRoBlob.size());
|
||||
if (calc_hash != mHdr.getRoSegmentInfo().hash)
|
||||
{
|
||||
throw tc::Exception(mModuleName, "NSO ro segment failed SHA256 verification");
|
||||
|
|
@ -182,7 +182,7 @@ void nstool::NsoProcess::importCodeSegments()
|
|||
}
|
||||
if (mHdr.getDataSegmentInfo().is_hashed)
|
||||
{
|
||||
tc::crypto::GenerateSha256Hash(calc_hash.data(), mDataBlob.data(), mDataBlob.size());
|
||||
tc::crypto::GenerateSha2256Hash(calc_hash.data(), mDataBlob.data(), mDataBlob.size());
|
||||
if (calc_hash != mHdr.getDataSegmentInfo().hash)
|
||||
{
|
||||
throw tc::Exception(mModuleName, "NSO data segment failed SHA256 verification");
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
#include "types.h"
|
||||
#include "RoMetadataProcess.h"
|
||||
|
||||
#include <nn/hac/define/meta.h>
|
||||
#include <nn/hac/NsoHeader.h>
|
||||
#include <pietendo/hac/define/meta.h>
|
||||
#include <pietendo/hac/NsoHeader.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ private:
|
|||
bool mListApi;
|
||||
bool mListSymbols;
|
||||
|
||||
nn::hac::NsoHeader mHdr;
|
||||
pie::hac::NsoHeader mHdr;
|
||||
tc::ByteData mTextBlob, mRoBlob, mDataBlob;
|
||||
nstool::RoMetadataProcess mRoMeta;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#include "PfsProcess.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <nn/hac/PartitionFsUtil.h>
|
||||
#include <tc/io/LocalStorage.h>
|
||||
#include <pietendo/hac/PartitionFsUtil.h>
|
||||
#include <tc/io/LocalFileSystem.h>
|
||||
|
||||
#include <tc/io/VirtualFileSystem.h>
|
||||
#include <nn/hac/PartitionFsMetaGenerator.h>
|
||||
#include <pietendo/hac/PartitionFsSnapshotGenerator.h>
|
||||
|
||||
|
||||
nstool::PfsProcess::PfsProcess() :
|
||||
|
|
@ -34,21 +34,21 @@ void nstool::PfsProcess::process()
|
|||
tc::ByteData scratch;
|
||||
|
||||
// read base header to determine complete header size
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sPfsHeader)))
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sPfsHeader)))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt PartitionFs: File too small");
|
||||
}
|
||||
|
||||
scratch = tc::ByteData(sizeof(nn::hac::sPfsHeader));
|
||||
scratch = tc::ByteData(sizeof(pie::hac::sPfsHeader));
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read(scratch.data(), scratch.size());
|
||||
if (validateHeaderMagic(((nn::hac::sPfsHeader*)scratch.data())) == false)
|
||||
if (validateHeaderMagic(((pie::hac::sPfsHeader*)scratch.data())) == false)
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt PartitionFs: Header had incorrect struct magic.");
|
||||
}
|
||||
|
||||
// read complete size header
|
||||
size_t pfsHeaderSize = determineHeaderSize(((nn::hac::sPfsHeader*)scratch.data()));
|
||||
size_t pfsHeaderSize = determineHeaderSize(((pie::hac::sPfsHeader*)scratch.data()));
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(pfsHeaderSize))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt PartitionFs: File too small");
|
||||
|
|
@ -62,12 +62,12 @@ void nstool::PfsProcess::process()
|
|||
mPfs.fromBytes(scratch.data(), scratch.size());
|
||||
|
||||
// create virtual filesystem
|
||||
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)));
|
||||
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)));
|
||||
mFsProcess.setInputFileSystem(mFileSystem);
|
||||
|
||||
// set properties for FsProcess
|
||||
mFsProcess.setFsProperties({
|
||||
fmt::format("Type: {:s}", nn::hac::PartitionFsUtil::getFsTypeAsString(mPfs.getFsType())),
|
||||
fmt::format("Type: {:s}", pie::hac::PartitionFsUtil::getFsTypeAsString(mPfs.getFsType())),
|
||||
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);
|
||||
}
|
||||
|
||||
const nn::hac::PartitionFsHeader& nstool::PfsProcess::getPfsHeader() const
|
||||
const pie::hac::PartitionFsHeader& nstool::PfsProcess::getPfsHeader() const
|
||||
{
|
||||
return mPfs;
|
||||
}
|
||||
|
||||
const std::shared_ptr<tc::io::IStorage>& nstool::PfsProcess::getFileSystem() const
|
||||
const std::shared_ptr<tc::io::IFileSystem>& nstool::PfsProcess::getFileSystem() const
|
||||
{
|
||||
return mFileSystem;
|
||||
}
|
||||
|
||||
size_t nstool::PfsProcess::determineHeaderSize(const nn::hac::sPfsHeader* hdr)
|
||||
size_t nstool::PfsProcess::determineHeaderSize(const pie::hac::sPfsHeader* hdr)
|
||||
{
|
||||
size_t fileEntrySize = 0;
|
||||
if (hdr->st_magic.unwrap() == nn::hac::pfs::kPfsStructMagic)
|
||||
fileEntrySize = sizeof(nn::hac::sPfsFile);
|
||||
if (hdr->st_magic.unwrap() == pie::hac::pfs::kPfsStructMagic)
|
||||
fileEntrySize = sizeof(pie::hac::sPfsFile);
|
||||
else
|
||||
fileEntrySize = sizeof(nn::hac::sHashedPfsFile);
|
||||
fileEntrySize = sizeof(pie::hac::sHashedPfsFile);
|
||||
|
||||
return sizeof(nn::hac::sPfsHeader) + hdr->file_num.unwrap() * fileEntrySize + hdr->name_table_size.unwrap();
|
||||
return sizeof(pie::hac::sPfsHeader) + hdr->file_num.unwrap() * fileEntrySize + hdr->name_table_size.unwrap();
|
||||
}
|
||||
|
||||
bool nstool::PfsProcess::validateHeaderMagic(const nn::hac::sPfsHeader* hdr)
|
||||
bool nstool::PfsProcess::validateHeaderMagic(const pie::hac::sPfsHeader* hdr)
|
||||
{
|
||||
return hdr->st_magic.unwrap() == nn::hac::pfs::kPfsStructMagic || hdr->st_magic.unwrap() == nn::hac::pfs::kHashedPfsStructMagic;
|
||||
return hdr->st_magic.unwrap() == pie::hac::pfs::kPfsStructMagic || hdr->st_magic.unwrap() == pie::hac::pfs::kHashedPfsStructMagic;
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include "types.h"
|
||||
#include "FsProcess.h"
|
||||
|
||||
#include <nn/hac/PartitionFsHeader.h>
|
||||
#include <pietendo/hac/PartitionFsHeader.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -24,8 +24,8 @@ public:
|
|||
void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);
|
||||
|
||||
// post process() get PFS/FS out
|
||||
const nn::hac::PartitionFsHeader& getPfsHeader() const;
|
||||
const std::shared_ptr<tc::io::IStorage>& getFileSystem() const;
|
||||
const pie::hac::PartitionFsHeader& getPfsHeader() const;
|
||||
const std::shared_ptr<tc::io::IFileSystem>& getFileSystem() const;
|
||||
|
||||
private:
|
||||
static const size_t kCacheSize = 0x10000;
|
||||
|
|
@ -36,13 +36,13 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nn::hac::PartitionFsHeader mPfs;
|
||||
pie::hac::PartitionFsHeader mPfs;
|
||||
|
||||
std::shared_ptr<tc::io::IStorage> mFileSystem;
|
||||
std::shared_ptr<tc::io::IFileSystem> mFileSystem;
|
||||
FsProcess mFsProcess;
|
||||
|
||||
size_t determineHeaderSize(const nn::hac::sPfsHeader* hdr);
|
||||
bool validateHeaderMagic(const nn::hac::sPfsHeader* hdr);
|
||||
size_t determineHeaderSize(const pie::hac::sPfsHeader* hdr);
|
||||
bool validateHeaderMagic(const pie::hac::sPfsHeader* hdr);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#include "PkiValidator.h"
|
||||
|
||||
#include <tc/crypto.h>
|
||||
#include <nn/hac/define/types.h>
|
||||
#include <nn/pki/SignUtils.h>
|
||||
#include <pietendo/hac/define/types.h>
|
||||
#include <pietendo/hac/es/SignUtils.h>
|
||||
|
||||
nstool::PkiValidator::PkiValidator() :
|
||||
mModuleName("nstool::PkiValidator")
|
||||
|
|
@ -13,7 +13,7 @@ nstool::PkiValidator::PkiValidator() :
|
|||
void nstool::PkiValidator::setKeyCfg(const KeyBag& keycfg)
|
||||
{
|
||||
// save a copy of the certificate bank
|
||||
std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> old_certs = mCertificateBank;
|
||||
std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>> old_certs = mCertificateBank;
|
||||
|
||||
// clear the certificate bank
|
||||
mCertificateBank.clear();
|
||||
|
|
@ -28,7 +28,7 @@ void nstool::PkiValidator::setKeyCfg(const KeyBag& keycfg)
|
|||
}
|
||||
}
|
||||
|
||||
void nstool::PkiValidator::addCertificates(const std::vector<nn::pki::SignedData<nn::pki::CertificateBody>>& certs)
|
||||
void nstool::PkiValidator::addCertificates(const std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>>& certs)
|
||||
{
|
||||
for (size_t i = 0; i < certs.size(); i++)
|
||||
{
|
||||
|
|
@ -36,11 +36,10 @@ void nstool::PkiValidator::addCertificates(const std::vector<nn::pki::SignedData
|
|||
}
|
||||
}
|
||||
|
||||
void nstool::PkiValidator::addCertificate(const nn::pki::SignedData<nn::pki::CertificateBody>& cert)
|
||||
void nstool::PkiValidator::addCertificate(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert)
|
||||
{
|
||||
std::string cert_ident;
|
||||
nn::pki::sign::SignatureAlgo cert_sign_algo;
|
||||
nn::pki::sign::HashAlgo cert_hash_algo;
|
||||
pie::hac::es::sign::HashAlgo cert_hash_algo;
|
||||
tc::ByteData cert_hash;
|
||||
|
||||
try
|
||||
|
|
@ -52,20 +51,19 @@ void nstool::PkiValidator::addCertificate(const nn::pki::SignedData<nn::pki::Cer
|
|||
throw tc::Exception(mModuleName, "Certificate already exists");
|
||||
}
|
||||
|
||||
cert_sign_algo = nn::pki::sign::getSignatureAlgo(cert.getSignature().getSignType());
|
||||
cert_hash_algo = nn::pki::sign::getHashAlgo(cert.getSignature().getSignType());
|
||||
cert_hash_algo = pie::hac::es::sign::getHashAlgo(cert.getSignature().getSignType());
|
||||
|
||||
// get cert hash
|
||||
switch (cert_hash_algo)
|
||||
{
|
||||
case (nn::pki::sign::HASH_ALGO_SHA1):
|
||||
case (pie::hac::es::sign::HASH_ALGO_SHA1):
|
||||
|
||||
cert_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize);
|
||||
tc::crypto::GenerateSha1Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size());
|
||||
break;
|
||||
case (nn::pki::sign::HASH_ALGO_SHA256):
|
||||
cert_hash = tc::ByteData(tc::crypto::Sha256Generator::kHashSize);
|
||||
tc::crypto::GenerateSha256Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size());
|
||||
case (pie::hac::es::sign::HASH_ALGO_SHA256):
|
||||
cert_hash = tc::ByteData(tc::crypto::Sha2256Generator::kHashSize);
|
||||
tc::crypto::GenerateSha2256Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size());
|
||||
break;
|
||||
default:
|
||||
throw tc::Exception(mModuleName, "Unrecognised hash type");
|
||||
|
|
@ -86,9 +84,9 @@ void nstool::PkiValidator::clearCertificates()
|
|||
mCertificateBank.clear();
|
||||
}
|
||||
|
||||
void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const
|
||||
void nstool::PkiValidator::validateSignature(const std::string& issuer, pie::hac::es::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const
|
||||
{
|
||||
nn::pki::sign::SignatureAlgo sign_algo = nn::pki::sign::getSignatureAlgo(signature_id);
|
||||
pie::hac::es::sign::SignatureAlgo sign_algo = pie::hac::es::sign::getSignatureAlgo(signature_id);
|
||||
|
||||
// validate signature
|
||||
bool sig_valid = false;
|
||||
|
|
@ -112,7 +110,7 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki:
|
|||
throw tc::Exception(mModuleName, fmt::format("Public key for issuer \"{:s}\" cannot verify this signature.", issuer));
|
||||
}
|
||||
|
||||
if (sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
|
||||
if (sign_algo == pie::hac::es::sign::SIGN_ALGO_ECDSA240)
|
||||
{
|
||||
throw tc::Exception(mModuleName, "ECDSA signatures are not supported");
|
||||
}
|
||||
|
|
@ -122,18 +120,18 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki:
|
|||
else
|
||||
{
|
||||
// try to find issuer cert
|
||||
const nn::pki::CertificateBody& issuer_cert = getCert(issuer).getBody();
|
||||
nn::pki::cert::PublicKeyType issuer_pubk_type = issuer_cert.getPublicKeyType();
|
||||
const pie::hac::es::CertificateBody& issuer_cert = getCert(issuer).getBody();
|
||||
pie::hac::es::cert::PublicKeyType issuer_pubk_type = issuer_cert.getPublicKeyType();
|
||||
|
||||
if (issuer_pubk_type == nn::pki::cert::RSA4096 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096)
|
||||
if (issuer_pubk_type == pie::hac::es::cert::RSA4096 && sign_algo == pie::hac::es::sign::SIGN_ALGO_RSA4096)
|
||||
{
|
||||
rsa_key = issuer_cert.getRsa4096PublicKey();
|
||||
}
|
||||
else if (issuer_pubk_type == nn::pki::cert::RSA2048 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048)
|
||||
else if (issuer_pubk_type == pie::hac::es::cert::RSA2048 && sign_algo == pie::hac::es::sign::SIGN_ALGO_RSA2048)
|
||||
{
|
||||
rsa_key = issuer_cert.getRsa2048PublicKey();
|
||||
}
|
||||
else if (issuer_pubk_type == nn::pki::cert::ECDSA240 && sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
|
||||
else if (issuer_pubk_type == pie::hac::es::cert::ECDSA240 && sign_algo == pie::hac::es::sign::SIGN_ALGO_ECDSA240)
|
||||
{
|
||||
// ecc_key = issuer_cert.getEcdsa240PublicKey();
|
||||
throw tc::Exception(mModuleName, "ECDSA signatures are not supported");
|
||||
|
|
@ -146,22 +144,22 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki:
|
|||
|
||||
// verify signature
|
||||
switch (signature_id) {
|
||||
case (nn::pki::sign::SIGN_ID_RSA4096_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA1):
|
||||
sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha1(signature.data(), hash.data(), rsa_key);
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA2048_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA1):
|
||||
sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha1(signature.data(), hash.data(), rsa_key);
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA1):
|
||||
sig_valid = false;
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA4096_SHA256):
|
||||
sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha256(signature.data(), hash.data(), rsa_key);
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA4096_SHA256):
|
||||
sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha2256(signature.data(), hash.data(), rsa_key);
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_RSA2048_SHA256):
|
||||
sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha256(signature.data(), hash.data(), rsa_key);
|
||||
case (pie::hac::es::sign::SIGN_ID_RSA2048_SHA256):
|
||||
sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha2256(signature.data(), hash.data(), rsa_key);
|
||||
break;
|
||||
case (nn::pki::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
case (pie::hac::es::sign::SIGN_ID_ECDSA240_SHA256):
|
||||
sig_valid = false;
|
||||
break;
|
||||
}
|
||||
|
|
@ -174,14 +172,14 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki:
|
|||
|
||||
}
|
||||
|
||||
void nstool::PkiValidator::makeCertIdent(const nn::pki::SignedData<nn::pki::CertificateBody>& cert, std::string& ident) const
|
||||
void nstool::PkiValidator::makeCertIdent(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert, std::string& ident) const
|
||||
{
|
||||
makeCertIdent(cert.getBody().getIssuer(), cert.getBody().getSubject(), ident);
|
||||
}
|
||||
|
||||
void nstool::PkiValidator::makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const
|
||||
{
|
||||
ident = issuer + nn::pki::sign::kIdentDelimiter + subject;
|
||||
ident = issuer + pie::hac::es::sign::kIdentDelimiter + subject;
|
||||
ident = ident.substr(0, std::min<size_t>(ident.length(),64));
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +200,7 @@ bool nstool::PkiValidator::doesCertExist(const std::string& ident) const
|
|||
return exists;
|
||||
}
|
||||
|
||||
const nn::pki::SignedData<nn::pki::CertificateBody>& nstool::PkiValidator::getCert(const std::string& ident) const
|
||||
const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& nstool::PkiValidator::getCert(const std::string& ident) const
|
||||
{
|
||||
std::string full_cert_name;
|
||||
for (size_t i = 0; i < mCertificateBank.size(); i++)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
#include "types.h"
|
||||
#include "KeyBag.h"
|
||||
|
||||
#include <nn/pki/SignedData.h>
|
||||
#include <nn/pki/CertificateBody.h>
|
||||
#include <pietendo/hac/es/SignedData.h>
|
||||
#include <pietendo/hac/es/CertificateBody.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -13,22 +13,22 @@ public:
|
|||
PkiValidator();
|
||||
|
||||
void setKeyCfg(const KeyBag& keycfg);
|
||||
void addCertificates(const std::vector<nn::pki::SignedData<nn::pki::CertificateBody>>& certs);
|
||||
void addCertificate(const nn::pki::SignedData<nn::pki::CertificateBody>& cert);
|
||||
void addCertificates(const std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>>& certs);
|
||||
void addCertificate(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert);
|
||||
void clearCertificates();
|
||||
|
||||
void validateSignature(const std::string& issuer, nn::pki::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const;
|
||||
void validateSignature(const std::string& issuer, pie::hac::es::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const;
|
||||
|
||||
private:
|
||||
std::string mModuleName;
|
||||
|
||||
KeyBag mKeyCfg;
|
||||
std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> mCertificateBank;
|
||||
std::vector<pie::hac::es::SignedData<pie::hac::es::CertificateBody>> mCertificateBank;
|
||||
|
||||
void makeCertIdent(const nn::pki::SignedData<nn::pki::CertificateBody>& cert, std::string& ident) const;
|
||||
void makeCertIdent(const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& cert, 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;
|
||||
const nn::pki::SignedData<nn::pki::CertificateBody>& getCert(const std::string& ident) const;
|
||||
const pie::hac::es::SignedData<pie::hac::es::CertificateBody>& getCert(const std::string& ident) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
#include "SdkApiString.h"
|
||||
#include "ElfSymbolParser.h"
|
||||
|
||||
#include <nn/hac/define/meta.h>
|
||||
#include <pietendo/hac/define/meta.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include "util.h"
|
||||
|
||||
#include <tc/io/VirtualFileSystem.h>
|
||||
#include <nn/hac/RomFsMetaGenerator.h>
|
||||
#include <pietendo/hac/RomFsSnapshotGenerator.h>
|
||||
|
||||
|
||||
nstool::RomfsProcess::RomfsProcess() :
|
||||
|
|
@ -20,6 +20,7 @@ nstool::RomfsProcess::RomfsProcess() :
|
|||
|
||||
void nstool::RomfsProcess::process()
|
||||
{
|
||||
// state checks
|
||||
if (mFile == nullptr)
|
||||
{
|
||||
throw tc::Exception(mModuleName, "No file reader set.");
|
||||
|
|
@ -29,38 +30,62 @@ void nstool::RomfsProcess::process()
|
|||
throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions.");
|
||||
}
|
||||
|
||||
tc::ByteData scratch;
|
||||
|
||||
// read base header to determine complete header size
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(nn::hac::sRomfsHeader)))
|
||||
if (mFile->length() < tc::io::IOUtil::castSizeToInt64(sizeof(pie::hac::sRomfsHeader)))
|
||||
{
|
||||
throw tc::Exception(mModuleName, "Corrupt RomFs: File too small");
|
||||
}
|
||||
|
||||
mFile->seek(0, tc::io::SeekOrigin::Begin);
|
||||
mFile->read((byte_t*)&mRomfsHeader, sizeof(mRomfsHeader));
|
||||
if (mRomfsHeader.header_size.unwrap() != sizeof(nn::hac::sRomfsHeader) ||
|
||||
if (mRomfsHeader.header_size.unwrap() != sizeof(pie::hac::sRomfsHeader) ||
|
||||
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(), nn::hac::romfs::kRomfsHeaderAlign))
|
||||
mRomfsHeader.data_offset.unwrap() != align<int64_t>(mRomfsHeader.header_size.unwrap(), pie::hac::romfs::kRomfsHeaderAlign))
|
||||
{
|
||||
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
|
||||
tc::ByteData 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());
|
||||
tc::ByteData dir_entry_table = tc::ByteData();
|
||||
if (mRomfsHeader.dir_entry.size.unwrap() > 0)
|
||||
{
|
||||
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
|
||||
tc::ByteData 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());
|
||||
|
||||
tc::ByteData file_entry_table = tc::ByteData();
|
||||
if (mRomfsHeader.file_entry.size.unwrap() > 0)
|
||||
{
|
||||
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
|
||||
mDirNum = 0;
|
||||
for (uint32_t v_addr = 0; size_t(v_addr) < dir_entry_table.size();)
|
||||
{
|
||||
uint32_t total_size = sizeof(nn::hac::sRomfsDirEntry) + align<uint32_t>(((nn::hac::sRomfsDirEntry*)(dir_entry_table.data() + v_addr))->name_size.unwrap(), 4);
|
||||
uint32_t total_size = sizeof(pie::hac::sRomfsDirEntry) + align<uint32_t>(((pie::hac::sRomfsDirEntry*)(dir_entry_table.data() + v_addr))->name_size.unwrap(), 4);
|
||||
|
||||
// don't count root directory
|
||||
if (v_addr != 0)
|
||||
|
|
@ -75,7 +100,7 @@ void nstool::RomfsProcess::process()
|
|||
mFileNum = 0;
|
||||
for (uint32_t v_addr = 0; size_t(v_addr) < file_entry_table.size();)
|
||||
{
|
||||
uint32_t total_size = sizeof(nn::hac::sRomfsFileEntry) + align<uint32_t>(((nn::hac::sRomfsFileEntry*)(file_entry_table.data() + v_addr))->name_size.unwrap(), 4);
|
||||
uint32_t total_size = sizeof(pie::hac::sRomfsFileEntry) + align<uint32_t>(((pie::hac::sRomfsFileEntry*)(file_entry_table.data() + v_addr))->name_size.unwrap(), 4);
|
||||
|
||||
mFileNum += 1;
|
||||
|
||||
|
|
@ -83,7 +108,7 @@ void nstool::RomfsProcess::process()
|
|||
}
|
||||
|
||||
// create virtual filesystem
|
||||
mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(nn::hac::RomFsMetaGenerator(mFile)));
|
||||
mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(pie::hac::RomFsSnapshotGenerator(mFile)));
|
||||
mFsProcess.setInputFileSystem(mFileSystem);
|
||||
|
||||
// set properties for FsProcess
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include "types.h"
|
||||
#include "FsProcess.h"
|
||||
|
||||
#include <nn/hac/define/romfs.h>
|
||||
#include <pietendo/hac/define/romfs.h>
|
||||
|
||||
namespace nstool {
|
||||
|
||||
|
|
@ -31,11 +31,11 @@ private:
|
|||
CliOutputMode mCliOutputMode;
|
||||
bool mVerify;
|
||||
|
||||
nn::hac::sRomfsHeader mRomfsHeader;
|
||||
pie::hac::sRomfsHeader mRomfsHeader;
|
||||
size_t mDirNum;
|
||||
size_t mFileNum;
|
||||
|
||||
std::shared_ptr<tc::io::IStorage> mFileSystem;
|
||||
std::shared_ptr<tc::io::IFileSystem> mFileSystem;
|
||||
FsProcess mFsProcess;
|
||||
};
|
||||
|
||||
|
|
|
|||
358
src/Settings.cpp
358
src/Settings.cpp
|
|
@ -9,27 +9,24 @@
|
|||
#include <tc/io/FileStream.h>
|
||||
#include <tc/io/StreamSource.h>
|
||||
|
||||
|
||||
|
||||
#include <nn/hac/ContentArchiveUtil.h>
|
||||
#include <nn/hac/AesKeygen.h>
|
||||
#include <nn/hac/define/gc.h>
|
||||
#include <nn/hac/define/pfs.h>
|
||||
#include <nn/hac/define/nca.h>
|
||||
#include <nn/hac/define/meta.h>
|
||||
#include <nn/hac/define/romfs.h>
|
||||
#include <nn/hac/define/cnmt.h>
|
||||
#include <nn/hac/define/nacp.h>
|
||||
#include <nn/hac/define/nso.h>
|
||||
#include <nn/hac/define/nro.h>
|
||||
#include <nn/hac/define/ini.h>
|
||||
#include <nn/hac/define/kip.h>
|
||||
#include <nn/hac/define/aset.h>
|
||||
#include <nn/pki/SignedData.h>
|
||||
#include <nn/pki/CertificateBody.h>
|
||||
#include <nn/pki/SignUtils.h>
|
||||
#include <nn/es/TicketBody_V2.h>
|
||||
|
||||
#include <pietendo/hac/ContentArchiveUtil.h>
|
||||
#include <pietendo/hac/AesKeygen.h>
|
||||
#include <pietendo/hac/define/gc.h>
|
||||
#include <pietendo/hac/define/pfs.h>
|
||||
#include <pietendo/hac/define/nca.h>
|
||||
#include <pietendo/hac/define/meta.h>
|
||||
#include <pietendo/hac/define/romfs.h>
|
||||
#include <pietendo/hac/define/cnmt.h>
|
||||
#include <pietendo/hac/define/nacp.h>
|
||||
#include <pietendo/hac/define/nso.h>
|
||||
#include <pietendo/hac/define/nro.h>
|
||||
#include <pietendo/hac/define/ini.h>
|
||||
#include <pietendo/hac/define/kip.h>
|
||||
#include <pietendo/hac/define/aset.h>
|
||||
#include <pietendo/hac/es/SignedData.h>
|
||||
#include <pietendo/hac/es/CertificateBody.h>
|
||||
#include <pietendo/hac/es/SignUtils.h>
|
||||
#include <pietendo/hac/es/TicketBody_V2.h>
|
||||
|
||||
class UnkOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
{
|
||||
|
|
@ -42,6 +39,11 @@ public:
|
|||
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)
|
||||
{
|
||||
throw tc::Exception(mModuleLabel, "Unrecognized option: \"" + option + "\"");
|
||||
|
|
@ -55,7 +57,8 @@ class DeprecatedOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
|||
public:
|
||||
DeprecatedOptionHandler(const std::string& warn_message, const std::vector<std::string>& opts) :
|
||||
mWarnMessage(warn_message),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -63,6 +66,11 @@ public:
|
|||
return mOptStrings;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getOptionRegexPatterns() const
|
||||
{
|
||||
return mOptRegex;
|
||||
}
|
||||
|
||||
void processOption(const std::string& option, const std::vector<std::string>& params)
|
||||
{
|
||||
fmt::print("[WARNING] Option \"{}\" is deprecated.{}{}\n", option, (mWarnMessage.empty() ? "" : " "), mWarnMessage);
|
||||
|
|
@ -70,6 +78,7 @@ public:
|
|||
private:
|
||||
std::string mWarnMessage;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
};
|
||||
|
||||
class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
|
|
@ -77,7 +86,8 @@ class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
|||
public:
|
||||
FlagOptionHandler(bool& flag, const std::vector<std::string>& opts) :
|
||||
mFlag(flag),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -85,6 +95,11 @@ public:
|
|||
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() != 0)
|
||||
|
|
@ -97,6 +112,7 @@ public:
|
|||
private:
|
||||
bool& mFlag;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
};
|
||||
|
||||
class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
|
|
@ -104,7 +120,8 @@ class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHand
|
|||
public:
|
||||
SingleParamStringOptionHandler(tc::Optional<std::string>& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -112,6 +129,11 @@ public:
|
|||
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)
|
||||
|
|
@ -124,6 +146,7 @@ public:
|
|||
private:
|
||||
tc::Optional<std::string>& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
};
|
||||
|
||||
class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
|
|
@ -131,7 +154,8 @@ class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandle
|
|||
public:
|
||||
SingleParamPathOptionHandler(tc::Optional<tc::io::Path>& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -139,6 +163,11 @@ public:
|
|||
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)
|
||||
|
|
@ -151,6 +180,7 @@ public:
|
|||
private:
|
||||
tc::Optional<tc::io::Path>& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
};
|
||||
|
||||
class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
|
|
@ -158,7 +188,8 @@ class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandl
|
|||
public:
|
||||
SingleParamSizetOptionHandler(size_t& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -166,6 +197,11 @@ public:
|
|||
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)
|
||||
|
|
@ -178,6 +214,7 @@ public:
|
|||
private:
|
||||
size_t& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
};
|
||||
|
||||
class SingleParamAesKeyOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
|
|
@ -185,7 +222,8 @@ class SingleParamAesKeyOptionHandler : public tc::cli::OptionParser::IOptionHand
|
|||
public:
|
||||
SingleParamAesKeyOptionHandler(tc::Optional<nstool::KeyBag::aes128_key_t>& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -193,6 +231,11 @@ public:
|
|||
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)
|
||||
|
|
@ -214,6 +257,41 @@ public:
|
|||
private:
|
||||
tc::Optional<nstool::KeyBag::aes128_key_t>& mParam;
|
||||
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
|
||||
|
|
@ -221,7 +299,8 @@ class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
|||
public:
|
||||
FileTypeOptionHandler(nstool::Settings::FileType& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -229,6 +308,11 @@ public:
|
|||
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)
|
||||
|
|
@ -310,6 +394,7 @@ public:
|
|||
private:
|
||||
nstool::Settings::FileType& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
};
|
||||
|
||||
class InstructionTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
|
|
@ -317,7 +402,8 @@ class InstructionTypeOptionHandler : public tc::cli::OptionParser::IOptionHandle
|
|||
public:
|
||||
InstructionTypeOptionHandler(bool& param, const std::vector<std::string>& opts) :
|
||||
mParam(param),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -325,6 +411,11 @@ public:
|
|||
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)
|
||||
|
|
@ -348,6 +439,7 @@ public:
|
|||
private:
|
||||
bool& mParam;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
};
|
||||
|
||||
class ExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
|
|
@ -355,7 +447,8 @@ class ExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandle
|
|||
public:
|
||||
ExtractDataPathOptionHandler(std::vector<nstool::ExtractJob>& jobs, const std::vector<std::string>& opts) :
|
||||
mJobs(jobs),
|
||||
mOptStrings(opts)
|
||||
mOptStrings(opts),
|
||||
mOptRegex()
|
||||
{}
|
||||
|
||||
const std::vector<std::string>& getOptionStrings() const
|
||||
|
|
@ -363,6 +456,11 @@ public:
|
|||
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)
|
||||
|
|
@ -381,6 +479,7 @@ public:
|
|||
private:
|
||||
std::vector<nstool::ExtractJob>& mJobs;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
};
|
||||
|
||||
class CustomExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
|
||||
|
|
@ -389,6 +488,7 @@ public:
|
|||
CustomExtractDataPathOptionHandler(std::vector<nstool::ExtractJob>& jobs, const std::vector<std::string>& opts, const tc::io::Path& custom_path) :
|
||||
mJobs(jobs),
|
||||
mOptStrings(opts),
|
||||
mOptRegex(),
|
||||
mCustomPath(custom_path)
|
||||
{}
|
||||
|
||||
|
|
@ -397,6 +497,11 @@ public:
|
|||
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)
|
||||
|
|
@ -404,9 +509,6 @@ public:
|
|||
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]);
|
||||
// if custom path is root path, use the shortened version of -x
|
||||
if (mCustomPath == tc::io::Path("/"))
|
||||
|
|
@ -415,7 +517,7 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
fmt::print("Consider using \"-x {:s} {:s}\" instead.\n", custom_path_str, params[0]);
|
||||
fmt::print("Consider using \"-x {:s} {:s}\" instead.\n", mCustomPath.to_string(), params[0]);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -424,6 +526,7 @@ public:
|
|||
private:
|
||||
std::vector<nstool::ExtractJob>& mJobs;
|
||||
std::vector<std::string> mOptStrings;
|
||||
std::vector<std::string> mOptRegex;
|
||||
tc::io::Path mCustomPath;
|
||||
};
|
||||
|
||||
|
|
@ -435,7 +538,7 @@ nstool::SettingsInitializer::SettingsInitializer(const std::vector<std::string>&
|
|||
mVerbose(false),
|
||||
mNcaEncryptedContentKey(),
|
||||
mNcaContentKey(),
|
||||
mTikPath(),
|
||||
mTikPathList(),
|
||||
mCertPath()
|
||||
{
|
||||
// parse input arguments
|
||||
|
|
@ -463,29 +566,16 @@ nstool::SettingsInitializer::SettingsInitializer(const std::vector<std::string>&
|
|||
// locate key file, if not specfied
|
||||
if (mKeysetPath.isNull())
|
||||
{
|
||||
std::string home_path_str;
|
||||
if (tc::os::getEnvVar("HOME", home_path_str) || tc::os::getEnvVar("USERPROFILE", home_path_str))
|
||||
{
|
||||
tc::io::Path keyfile_path = tc::io::Path(home_path_str);
|
||||
keyfile_path.push_back(".switch");
|
||||
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");
|
||||
}
|
||||
loadKeyFile(mKeysetPath, opt.is_dev ? "dev.keys" : "prod.keys", "Maybe specify it with \"-k <path>\"?\n");
|
||||
}
|
||||
// locate title key file, if not specfied
|
||||
if (mTitleKeysetPath.isNull())
|
||||
{
|
||||
loadKeyFile(mTitleKeysetPath, "title.keys", "");
|
||||
}
|
||||
|
||||
// generate keybag
|
||||
opt.keybag = KeyBagInitializer(opt.is_dev, mKeysetPath, mTikPath, mCertPath);
|
||||
opt.keybag = KeyBagInitializer(opt.is_dev, mKeysetPath, mTitleKeysetPath, mTikPathList, mCertPath);
|
||||
opt.keybag.fallback_enc_content_key = mNcaEncryptedContentKey;
|
||||
opt.keybag.fallback_content_key = mNcaContentKey;
|
||||
|
||||
|
|
@ -549,9 +639,10 @@ void nstool::SettingsInitializer::parse_args(const std::vector<std::string>& arg
|
|||
|
||||
// get user-provided keydata
|
||||
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(mNcaContentKey, {"--contentkey", "--bodykey"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mTikPath, {"--tik"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathArrayOptionHandler>(new SingleParamPathArrayOptionHandler(mTikPathList, {"--tik"})));
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(mCertPath, {"--cert"})));
|
||||
|
||||
// code options
|
||||
|
|
@ -576,6 +667,8 @@ 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, { "--part3" }, tc::io::Path("/3/"))));
|
||||
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(nca.base_nca_path, { "--basenca" })));
|
||||
|
||||
// kip options
|
||||
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(kip.extract_path, { "--kipdir" })));
|
||||
|
||||
|
|
@ -590,9 +683,7 @@ void nstool::SettingsInitializer::parse_args(const std::vector<std::string>& arg
|
|||
|
||||
void nstool::SettingsInitializer::determine_filetype()
|
||||
{
|
||||
//std::string infile_path_str;
|
||||
//tc::io::PathUtil::pathToUnixUTF8(infile.path.get(), infile_path_str);
|
||||
//fmt::print("infile path = \"{}\"\n", infile_path_str);
|
||||
//fmt::print("infile path = \"{}\"\n", infile.path.get().to_string());
|
||||
|
||||
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)));
|
||||
|
||||
|
|
@ -604,69 +695,69 @@ void nstool::SettingsInitializer::determine_filetype()
|
|||
// do easy tests
|
||||
|
||||
// detect "scene" XCI
|
||||
if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sGcHeader_Rsa2048Signed))
|
||||
&& _TYPE_PTR(nn::hac::sGcHeader_Rsa2048Signed)->header.st_magic.unwrap() == nn::hac::gc::kGcHeaderStructMagic)
|
||||
if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sGcHeader_Rsa2048Signed))
|
||||
&& _TYPE_PTR(pie::hac::sGcHeader_Rsa2048Signed)->header.st_magic.unwrap() == pie::hac::gc::kGcHeaderStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_GAMECARD;
|
||||
}
|
||||
// detect "SDK" XCI
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sSdkGcHeader))
|
||||
&& _TYPE_PTR(nn::hac::sSdkGcHeader)->signed_header.header.st_magic.unwrap() == nn::hac::gc::kGcHeaderStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sSdkGcHeader))
|
||||
&& _TYPE_PTR(pie::hac::sSdkGcHeader)->signed_header.header.st_magic.unwrap() == pie::hac::gc::kGcHeaderStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_GAMECARD;
|
||||
}
|
||||
// detect PFS0
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sPfsHeader))
|
||||
&& _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.unwrap() == nn::hac::pfs::kPfsStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sPfsHeader))
|
||||
&& _TYPE_PTR(pie::hac::sPfsHeader)->st_magic.unwrap() == pie::hac::pfs::kPfsStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_PARTITIONFS;
|
||||
}
|
||||
// detect HFS0
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sPfsHeader))
|
||||
&& _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.unwrap() == nn::hac::pfs::kHashedPfsStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sPfsHeader))
|
||||
&& _TYPE_PTR(pie::hac::sPfsHeader)->st_magic.unwrap() == pie::hac::pfs::kHashedPfsStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_PARTITIONFS;
|
||||
}
|
||||
// detect ROMFS
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sRomfsHeader))
|
||||
&& _TYPE_PTR(nn::hac::sRomfsHeader)->header_size.unwrap() == sizeof(nn::hac::sRomfsHeader)
|
||||
&& _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()))
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sRomfsHeader))
|
||||
&& _TYPE_PTR(pie::hac::sRomfsHeader)->header_size.unwrap() == sizeof(pie::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()))
|
||||
{
|
||||
infile.filetype = FILE_TYPE_ROMFS;
|
||||
}
|
||||
// detect NPDM
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sMetaHeader))
|
||||
&& _TYPE_PTR(nn::hac::sMetaHeader)->st_magic.unwrap() == nn::hac::meta::kMetaStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sMetaHeader))
|
||||
&& _TYPE_PTR(pie::hac::sMetaHeader)->st_magic.unwrap() == pie::hac::meta::kMetaStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_META;
|
||||
}
|
||||
// detect NSO
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sNsoHeader))
|
||||
&& _TYPE_PTR(nn::hac::sNsoHeader)->st_magic.unwrap() == nn::hac::nso::kNsoStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sNsoHeader))
|
||||
&& _TYPE_PTR(pie::hac::sNsoHeader)->st_magic.unwrap() == pie::hac::nso::kNsoStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_NSO;
|
||||
}
|
||||
// detect NRO
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sNroHeader))
|
||||
&& _TYPE_PTR(nn::hac::sNroHeader)->st_magic.unwrap() == nn::hac::nro::kNroStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sNroHeader))
|
||||
&& _TYPE_PTR(pie::hac::sNroHeader)->st_magic.unwrap() == pie::hac::nro::kNroStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_NRO;
|
||||
}
|
||||
// detect INI
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sIniHeader))
|
||||
&& _TYPE_PTR(nn::hac::sIniHeader)->st_magic.unwrap() == nn::hac::ini::kIniStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sIniHeader))
|
||||
&& _TYPE_PTR(pie::hac::sIniHeader)->st_magic.unwrap() == pie::hac::ini::kIniStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_INI;
|
||||
}
|
||||
// detect KIP
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sKipHeader))
|
||||
&& _TYPE_PTR(nn::hac::sKipHeader)->st_magic.unwrap() == nn::hac::kip::kKipStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sKipHeader))
|
||||
&& _TYPE_PTR(pie::hac::sKipHeader)->st_magic.unwrap() == pie::hac::kip::kKipStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_KIP;
|
||||
}
|
||||
// detect HB ASET
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(nn::hac::sAssetHeader))
|
||||
&& _TYPE_PTR(nn::hac::sAssetHeader)->st_magic.unwrap() == nn::hac::aset::kAssetStructMagic)
|
||||
else if (_ASSERT_FILE_SIZE(sizeof(pie::hac::sAssetHeader))
|
||||
&& _TYPE_PTR(pie::hac::sAssetHeader)->st_magic.unwrap() == pie::hac::aset::kAssetStructMagic)
|
||||
{
|
||||
infile.filetype = FILE_TYPE_KIP;
|
||||
}
|
||||
|
|
@ -729,7 +820,7 @@ void nstool::SettingsInitializer::usage_text() const
|
|||
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("\n NCA (Nintendo Content Archive)\n");
|
||||
fmt::print(" {:s} [--fstree] [-x [<virtual path>] <out path>] [--bodykey <key> --titlekey <key> -tik <tik path>] <.nca file>\n", BIN_NAME);
|
||||
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(" --fstree Print filesystem tree.\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");
|
||||
|
|
@ -740,6 +831,7 @@ void nstool::SettingsInitializer::usage_text() const
|
|||
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(" --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(" {:s} [--listapi --listsym] [--insttype <inst. type>] <file>\n", BIN_NAME);
|
||||
fmt::print(" --listapi Print SDK API List.\n");
|
||||
|
|
@ -836,24 +928,24 @@ void nstool::SettingsInitializer::dump_keys() const
|
|||
fmt::print(" {:s}:\n", itr->first);
|
||||
fmt::print(" SignType: ");
|
||||
switch(itr->second.key_type) {
|
||||
case nn::pki::sign::SIGN_ALGO_RSA2048:
|
||||
case pie::hac::es::sign::SIGN_ALGO_RSA2048:
|
||||
fmt::print("RSA-2048\n");
|
||||
break;
|
||||
case nn::pki::sign::SIGN_ALGO_RSA4096:
|
||||
case pie::hac::es::sign::SIGN_ALGO_RSA4096:
|
||||
fmt::print("RSA-4096\n");
|
||||
break;
|
||||
case nn::pki::sign::SIGN_ALGO_ECDSA240:
|
||||
case pie::hac::es::sign::SIGN_ALGO_ECDSA240:
|
||||
fmt::print("ECDSA-240\n");
|
||||
break;
|
||||
default:
|
||||
fmt::print("Unknown\n");
|
||||
}
|
||||
switch(itr->second.key_type) {
|
||||
case nn::pki::sign::SIGN_ALGO_RSA2048:
|
||||
case nn::pki::sign::SIGN_ALGO_RSA4096:
|
||||
case pie::hac::es::sign::SIGN_ALGO_RSA2048:
|
||||
case pie::hac::es::sign::SIGN_ALGO_RSA4096:
|
||||
dump_rsa_key(itr->second.rsa_key, "RsaKey", 6, opt.cli_output_mode.show_extended_info);
|
||||
break;
|
||||
case nn::pki::sign::SIGN_ALGO_ECDSA240:
|
||||
case pie::hac::es::sign::SIGN_ALGO_ECDSA240:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -897,10 +989,34 @@ 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
|
||||
{
|
||||
if (sample.size() < nn::hac::nca::kHeaderSize)
|
||||
if (sample.size() < pie::hac::nca::kHeaderSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -911,26 +1027,26 @@ bool nstool::SettingsInitializer::determineValidNcaFromSample(const tc::ByteData
|
|||
return false;
|
||||
}
|
||||
|
||||
nn::hac::detail::aes128_xtskey_t key = opt.keybag.nca_header_key.get();
|
||||
pie::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, ""));
|
||||
|
||||
// init aes-xts
|
||||
tc::crypto::Aes128XtsEncryptor enc;
|
||||
enc.initialize(key[0].data(), key[0].size(), key[1].data(), key[1].size(), nn::hac::nca::kSectorSize, false);
|
||||
enc.initialize(key[0].data(), key[0].size(), key[1].data(), key[1].size(), pie::hac::nca::kSectorSize, false);
|
||||
|
||||
// decrypt main header
|
||||
byte_t raw_hdr[nn::hac::nca::kSectorSize];
|
||||
enc.decrypt(raw_hdr, sample.data() + nn::hac::ContentArchiveUtil::sectorToOffset(1), nn::hac::nca::kSectorSize, 1);
|
||||
nn::hac::sContentArchiveHeader* hdr = (nn::hac::sContentArchiveHeader*)(raw_hdr);
|
||||
byte_t raw_hdr[pie::hac::nca::kSectorSize];
|
||||
enc.decrypt(raw_hdr, sample.data() + pie::hac::ContentArchiveUtil::sectorToOffset(1), pie::hac::nca::kSectorSize, 1);
|
||||
pie::hac::sContentArchiveHeader* hdr = (pie::hac::sContentArchiveHeader*)(raw_hdr);
|
||||
|
||||
/*
|
||||
fmt::print("NCA Header Raw:\n");
|
||||
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, nn::hac::nca::kSectorSize));
|
||||
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(raw_hdr, pie::hac::nca::kSectorSize));
|
||||
*/
|
||||
|
||||
if (hdr->st_magic.unwrap() != nn::hac::nca::kNca2StructMagic && hdr->st_magic.unwrap() != nn::hac::nca::kNca3StructMagic)
|
||||
if (hdr->st_magic.unwrap() != pie::hac::nca::kNca2StructMagic && hdr->st_magic.unwrap() != pie::hac::nca::kNca3StructMagic)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -940,12 +1056,12 @@ bool nstool::SettingsInitializer::determineValidNcaFromSample(const tc::ByteData
|
|||
|
||||
bool nstool::SettingsInitializer::determineValidCnmtFromSample(const tc::ByteData& sample) const
|
||||
{
|
||||
if (sample.size() < sizeof(nn::hac::sContentMetaHeader))
|
||||
if (sample.size() < sizeof(pie::hac::sContentMetaHeader))
|
||||
return false;
|
||||
|
||||
const nn::hac::sContentMetaHeader* data = (const nn::hac::sContentMetaHeader*)sample.data();
|
||||
const pie::hac::sContentMetaHeader* data = (const pie::hac::sContentMetaHeader*)sample.data();
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
if (sample.size() < minimum_size)
|
||||
return false;
|
||||
|
|
@ -953,37 +1069,37 @@ bool nstool::SettingsInitializer::determineValidCnmtFromSample(const tc::ByteDat
|
|||
// include exthdr/data check if applicable
|
||||
if (data->exhdr_size.unwrap() > 0)
|
||||
{
|
||||
if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Application)
|
||||
if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_Application)
|
||||
{
|
||||
const nn::hac::sApplicationMetaExtendedHeader* meta = (const nn::hac::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||
const pie::hac::sApplicationMetaExtendedHeader* meta = (const pie::hac::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader));
|
||||
if ((meta->patch_id.unwrap() & data->id.unwrap()) != data->id.unwrap())
|
||||
return false;
|
||||
}
|
||||
else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Patch)
|
||||
else if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_Patch)
|
||||
{
|
||||
const nn::hac::sPatchMetaExtendedHeader* meta = (const nn::hac::sPatchMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||
const pie::hac::sPatchMetaExtendedHeader* meta = (const pie::hac::sPatchMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader));
|
||||
if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap())
|
||||
return false;
|
||||
|
||||
minimum_size += meta->extended_data_size.unwrap();
|
||||
}
|
||||
else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::AddOnContent)
|
||||
else if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_AddOnContent)
|
||||
{
|
||||
const nn::hac::sAddOnContentMetaExtendedHeader* meta = (const nn::hac::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||
const pie::hac::sAddOnContentMetaExtendedHeader* meta = (const pie::hac::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader));
|
||||
if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap())
|
||||
return false;
|
||||
}
|
||||
else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Delta)
|
||||
else if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_Delta)
|
||||
{
|
||||
const nn::hac::sDeltaMetaExtendedHeader* meta = (const nn::hac::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||
const pie::hac::sDeltaMetaExtendedHeader* meta = (const pie::hac::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader));
|
||||
if ((meta->application_id.unwrap() & data->id.unwrap()) != meta->application_id.unwrap())
|
||||
return false;
|
||||
|
||||
minimum_size += meta->extended_data_size.unwrap();
|
||||
}
|
||||
else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::SystemUpdate)
|
||||
else if (data->type == (byte_t)pie::hac::cnmt::ContentMetaType_SystemUpdate)
|
||||
{
|
||||
const nn::hac::sSystemUpdateMetaExtendedHeader* meta = (const nn::hac::sSystemUpdateMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||
const pie::hac::sSystemUpdateMetaExtendedHeader* meta = (const pie::hac::sSystemUpdateMetaExtendedHeader*)(sample.data() + sizeof(pie::hac::sContentMetaHeader));
|
||||
|
||||
minimum_size += meta->extended_data_size.unwrap();
|
||||
}
|
||||
|
|
@ -997,12 +1113,12 @@ bool nstool::SettingsInitializer::determineValidCnmtFromSample(const tc::ByteDat
|
|||
|
||||
bool nstool::SettingsInitializer::determineValidNacpFromSample(const tc::ByteData& sample) const
|
||||
{
|
||||
if (sample.size() != sizeof(nn::hac::sApplicationControlProperty))
|
||||
if (sample.size() != sizeof(pie::hac::sApplicationControlProperty))
|
||||
return false;
|
||||
|
||||
const nn::hac::sApplicationControlProperty* data = (const nn::hac::sApplicationControlProperty*)sample.data();
|
||||
const pie::hac::sApplicationControlProperty* data = (const pie::hac::sApplicationControlProperty*)sample.data();
|
||||
|
||||
if (data->logo_type > (byte_t)nn::hac::nacp::LogoType::Nintendo)
|
||||
if (data->logo_type > (byte_t)pie::hac::nacp::LogoType_Nintendo)
|
||||
return false;
|
||||
|
||||
if (data->display_version[0] == 0)
|
||||
|
|
@ -1022,7 +1138,7 @@ bool nstool::SettingsInitializer::determineValidNacpFromSample(const tc::ByteDat
|
|||
|
||||
bool nstool::SettingsInitializer::determineValidEsCertFromSample(const tc::ByteData& sample) const
|
||||
{
|
||||
nn::pki::SignatureBlock sign;
|
||||
pie::hac::es::SignatureBlock sign;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -1036,7 +1152,7 @@ bool nstool::SettingsInitializer::determineValidEsCertFromSample(const tc::ByteD
|
|||
if (sign.isLittleEndian() == true)
|
||||
return false;
|
||||
|
||||
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)
|
||||
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)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -1044,7 +1160,7 @@ bool nstool::SettingsInitializer::determineValidEsCertFromSample(const tc::ByteD
|
|||
|
||||
bool nstool::SettingsInitializer::determineValidEsTikFromSample(const tc::ByteData& sample) const
|
||||
{
|
||||
nn::pki::SignatureBlock sign;
|
||||
pie::hac::es::SignatureBlock sign;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -1058,13 +1174,13 @@ bool nstool::SettingsInitializer::determineValidEsTikFromSample(const tc::ByteDa
|
|||
if (sign.isLittleEndian() == false)
|
||||
return false;
|
||||
|
||||
if (sign.getSignType() != nn::pki::sign::SIGN_ID_RSA2048_SHA256)
|
||||
if (sign.getSignType() != pie::hac::es::sign::SIGN_ID_RSA2048_SHA256)
|
||||
return false;
|
||||
|
||||
const nn::es::sTicketBody_v2* body = (const nn::es::sTicketBody_v2*)(sample.data() + sign.getBytes().size());
|
||||
const pie::hac::es::sTicketBody_v2* body = (const pie::hac::es::sTicketBody_v2*)(sample.data() + sign.getBytes().size());
|
||||
|
||||
if ((body->issuer.str().substr(0, 5) == "Root-"
|
||||
&& body->issuer.str().substr(16, 2) == "XS") == false)
|
||||
if ((body->issuer.decode().substr(0, 5) == "Root-"
|
||||
&& body->issuer.decode().substr(16, 2) == "XS") == false)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ struct Settings
|
|||
tc::Optional<tc::io::Path> part1_extract_path;
|
||||
tc::Optional<tc::io::Path> part2_extract_path;
|
||||
tc::Optional<tc::io::Path> part3_extract_path;
|
||||
tc::Optional<tc::io::Path> base_nca_path;
|
||||
} nca;
|
||||
|
||||
// KIP options
|
||||
|
|
@ -110,6 +111,8 @@ struct Settings
|
|||
|
||||
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.nacp_extract_path = tc::Optional<tc::io::Path>();
|
||||
}
|
||||
|
|
@ -133,11 +136,15 @@ private:
|
|||
bool mVerbose;
|
||||
|
||||
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> mNcaContentKey;
|
||||
tc::Optional<tc::io::Path> mTikPath;
|
||||
std::vector<tc::io::Path> mTikPathList;
|
||||
//tc::Optional<tc::io::Path> mTikPath;
|
||||
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 determineValidEsCertFromSample(const tc::ByteData& raw_data) const;
|
||||
bool determineValidEsTikFromSample(const tc::ByteData& raw_data) const;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
|
|||
nstool::NcaProcess obj;
|
||||
|
||||
obj.setInputFile(infile_stream);
|
||||
obj.setBaseNcaPath(set.nca.base_nca_path);
|
||||
obj.setKeyCfg(set.opt.keybag);
|
||||
obj.setCliOutputMode(set.opt.cli_output_mode);
|
||||
obj.setVerifyMode(set.opt.verify);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#define APP_NAME "NSTool"
|
||||
#define BIN_NAME "nstool"
|
||||
#define VER_MAJOR 1
|
||||
#define VER_MINOR 6
|
||||
#define VER_PATCH 2
|
||||
#define VER_MAJOR 0
|
||||
#define VER_MINOR 0
|
||||
#define VER_PATCH 0
|
||||
#define AUTHORS "jakcron"
|
||||
Loading…
Reference in a new issue