diff --git a/NNTools.sln b/NNTools.sln index 3abe916..249f281 100644 --- a/NNTools.sln +++ b/NNTools.sln @@ -1,124 +1,124 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27428.2015 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{170B4A09-1B67-4A62-93AB-116EBCFF4A8C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Programs", "Programs", "{E0863FCC-8E72-490D-BE1B-458F12CA8298}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8F6C846D-35E2-47FD-AF42-7A3FD036346E}" - ProjectSection(SolutionItems) = preProject - .gitignore = .gitignore - LICENSE = LICENSE - makefile = makefile - README.md = README.md - SWITCH_KEYS.md = SWITCH_KEYS.md - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nstool", "programs\nstool\nstool.vcxproj", "{AF09FA96-4463-417D-8FE6-526063F41349}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfnd", "lib\libfnd\libfnd.vcxproj", "{4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpolarssl", "lib\libpolarssl\libpolarssl.vcxproj", "{394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4", "lib\liblz4\liblz4.vcxproj", "{AB0C3362-63AB-480A-ADBC-2EF7D859778B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpki", "lib\libpki\libpki.vcxproj", "{B9113734-6E84-44FF-8CF7-58199AA815C5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libes", "lib\libes\libes.vcxproj", "{7BE99936-0D40-410D-944B-4513C2EFF8DC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhac", "lib\libhac\libhac.vcxproj", "{91BA9E79-8242-4F7D-B997-0DFEC95EA22B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhac-hb", "lib\libhac-hb\libhac-hb.vcxproj", "{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AF09FA96-4463-417D-8FE6-526063F41349}.Debug|x64.ActiveCfg = Debug|x64 - {AF09FA96-4463-417D-8FE6-526063F41349}.Debug|x64.Build.0 = Debug|x64 - {AF09FA96-4463-417D-8FE6-526063F41349}.Debug|x86.ActiveCfg = Debug|Win32 - {AF09FA96-4463-417D-8FE6-526063F41349}.Debug|x86.Build.0 = Debug|Win32 - {AF09FA96-4463-417D-8FE6-526063F41349}.Release|x64.ActiveCfg = Release|x64 - {AF09FA96-4463-417D-8FE6-526063F41349}.Release|x64.Build.0 = Release|x64 - {AF09FA96-4463-417D-8FE6-526063F41349}.Release|x86.ActiveCfg = Release|Win32 - {AF09FA96-4463-417D-8FE6-526063F41349}.Release|x86.Build.0 = Release|Win32 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x64.ActiveCfg = Debug|x64 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x64.Build.0 = Debug|x64 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x86.ActiveCfg = Debug|Win32 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x86.Build.0 = Debug|Win32 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x64.ActiveCfg = Release|x64 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x64.Build.0 = Release|x64 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x86.ActiveCfg = Release|Win32 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x86.Build.0 = Release|Win32 - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Debug|x64.ActiveCfg = Debug|x64 - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Debug|x64.Build.0 = Debug|x64 - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Debug|x86.ActiveCfg = Debug|Win32 - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Debug|x86.Build.0 = Debug|Win32 - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Release|x64.ActiveCfg = Release|x64 - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Release|x64.Build.0 = Release|x64 - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Release|x86.ActiveCfg = Release|Win32 - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Release|x86.Build.0 = Release|Win32 - {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Debug|x64.ActiveCfg = Debug|x64 - {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Debug|x64.Build.0 = Debug|x64 - {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Debug|x86.ActiveCfg = Debug|Win32 - {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Debug|x86.Build.0 = Debug|Win32 - {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Release|x64.ActiveCfg = Release|x64 - {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Release|x64.Build.0 = Release|x64 - {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Release|x86.ActiveCfg = Release|Win32 - {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Release|x86.Build.0 = Release|Win32 - {B9113734-6E84-44FF-8CF7-58199AA815C5}.Debug|x64.ActiveCfg = Debug|x64 - {B9113734-6E84-44FF-8CF7-58199AA815C5}.Debug|x64.Build.0 = Debug|x64 - {B9113734-6E84-44FF-8CF7-58199AA815C5}.Debug|x86.ActiveCfg = Debug|Win32 - {B9113734-6E84-44FF-8CF7-58199AA815C5}.Debug|x86.Build.0 = Debug|Win32 - {B9113734-6E84-44FF-8CF7-58199AA815C5}.Release|x64.ActiveCfg = Release|x64 - {B9113734-6E84-44FF-8CF7-58199AA815C5}.Release|x64.Build.0 = Release|x64 - {B9113734-6E84-44FF-8CF7-58199AA815C5}.Release|x86.ActiveCfg = Release|Win32 - {B9113734-6E84-44FF-8CF7-58199AA815C5}.Release|x86.Build.0 = Release|Win32 - {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Debug|x64.ActiveCfg = Debug|x64 - {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Debug|x64.Build.0 = Debug|x64 - {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Debug|x86.ActiveCfg = Debug|Win32 - {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Debug|x86.Build.0 = Debug|Win32 - {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Release|x64.ActiveCfg = Release|x64 - {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Release|x64.Build.0 = Release|x64 - {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Release|x86.ActiveCfg = Release|Win32 - {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Release|x86.Build.0 = Release|Win32 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x64.ActiveCfg = Debug|x64 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x64.Build.0 = Debug|x64 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x86.ActiveCfg = Debug|Win32 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x86.Build.0 = Debug|Win32 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x64.ActiveCfg = Release|x64 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x64.Build.0 = Release|x64 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x86.ActiveCfg = Release|Win32 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x86.Build.0 = Release|Win32 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Debug|x64.ActiveCfg = Debug|x64 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Debug|x64.Build.0 = Debug|x64 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Debug|x86.ActiveCfg = Debug|Win32 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Debug|x86.Build.0 = Debug|Win32 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x64.ActiveCfg = Release|x64 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x64.Build.0 = Release|x64 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x86.ActiveCfg = Release|Win32 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {AF09FA96-4463-417D-8FE6-526063F41349} = {E0863FCC-8E72-490D-BE1B-458F12CA8298} - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} - {AB0C3362-63AB-480A-ADBC-2EF7D859778B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} - {B9113734-6E84-44FF-8CF7-58199AA815C5} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} - {7BE99936-0D40-410D-944B-4513C2EFF8DC} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {07DCCACC-D10D-47C9-85AE-FB9C54DB7D62} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2015 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{170B4A09-1B67-4A62-93AB-116EBCFF4A8C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Programs", "Programs", "{E0863FCC-8E72-490D-BE1B-458F12CA8298}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8F6C846D-35E2-47FD-AF42-7A3FD036346E}" + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + LICENSE = LICENSE + makefile = makefile + README.md = README.md + SWITCH_KEYS.md = SWITCH_KEYS.md + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nstool", "programs\nstool\nstool.vcxproj", "{AF09FA96-4463-417D-8FE6-526063F41349}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfnd", "lib\libfnd\libfnd.vcxproj", "{4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpolarssl", "lib\libpolarssl\libpolarssl.vcxproj", "{394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4", "lib\liblz4\liblz4.vcxproj", "{AB0C3362-63AB-480A-ADBC-2EF7D859778B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpki", "lib\libpki\libpki.vcxproj", "{B9113734-6E84-44FF-8CF7-58199AA815C5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libes", "lib\libes\libes.vcxproj", "{7BE99936-0D40-410D-944B-4513C2EFF8DC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhac", "lib\libhac\libhac.vcxproj", "{91BA9E79-8242-4F7D-B997-0DFEC95EA22B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhac-hb", "lib\libhac-hb\libhac-hb.vcxproj", "{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AF09FA96-4463-417D-8FE6-526063F41349}.Debug|x64.ActiveCfg = Debug|x64 + {AF09FA96-4463-417D-8FE6-526063F41349}.Debug|x64.Build.0 = Debug|x64 + {AF09FA96-4463-417D-8FE6-526063F41349}.Debug|x86.ActiveCfg = Debug|Win32 + {AF09FA96-4463-417D-8FE6-526063F41349}.Debug|x86.Build.0 = Debug|Win32 + {AF09FA96-4463-417D-8FE6-526063F41349}.Release|x64.ActiveCfg = Release|x64 + {AF09FA96-4463-417D-8FE6-526063F41349}.Release|x64.Build.0 = Release|x64 + {AF09FA96-4463-417D-8FE6-526063F41349}.Release|x86.ActiveCfg = Release|Win32 + {AF09FA96-4463-417D-8FE6-526063F41349}.Release|x86.Build.0 = Release|Win32 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x64.ActiveCfg = Debug|x64 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x64.Build.0 = Debug|x64 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x86.ActiveCfg = Debug|Win32 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Debug|x86.Build.0 = Debug|Win32 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x64.ActiveCfg = Release|x64 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x64.Build.0 = Release|x64 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x86.ActiveCfg = Release|Win32 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}.Release|x86.Build.0 = Release|Win32 + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Debug|x64.ActiveCfg = Debug|x64 + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Debug|x64.Build.0 = Debug|x64 + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Debug|x86.ActiveCfg = Debug|Win32 + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Debug|x86.Build.0 = Debug|Win32 + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Release|x64.ActiveCfg = Release|x64 + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Release|x64.Build.0 = Release|x64 + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Release|x86.ActiveCfg = Release|Win32 + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1}.Release|x86.Build.0 = Release|Win32 + {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Debug|x64.ActiveCfg = Debug|x64 + {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Debug|x64.Build.0 = Debug|x64 + {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Debug|x86.ActiveCfg = Debug|Win32 + {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Debug|x86.Build.0 = Debug|Win32 + {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Release|x64.ActiveCfg = Release|x64 + {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Release|x64.Build.0 = Release|x64 + {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Release|x86.ActiveCfg = Release|Win32 + {AB0C3362-63AB-480A-ADBC-2EF7D859778B}.Release|x86.Build.0 = Release|Win32 + {B9113734-6E84-44FF-8CF7-58199AA815C5}.Debug|x64.ActiveCfg = Debug|x64 + {B9113734-6E84-44FF-8CF7-58199AA815C5}.Debug|x64.Build.0 = Debug|x64 + {B9113734-6E84-44FF-8CF7-58199AA815C5}.Debug|x86.ActiveCfg = Debug|Win32 + {B9113734-6E84-44FF-8CF7-58199AA815C5}.Debug|x86.Build.0 = Debug|Win32 + {B9113734-6E84-44FF-8CF7-58199AA815C5}.Release|x64.ActiveCfg = Release|x64 + {B9113734-6E84-44FF-8CF7-58199AA815C5}.Release|x64.Build.0 = Release|x64 + {B9113734-6E84-44FF-8CF7-58199AA815C5}.Release|x86.ActiveCfg = Release|Win32 + {B9113734-6E84-44FF-8CF7-58199AA815C5}.Release|x86.Build.0 = Release|Win32 + {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Debug|x64.ActiveCfg = Debug|x64 + {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Debug|x64.Build.0 = Debug|x64 + {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Debug|x86.ActiveCfg = Debug|Win32 + {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Debug|x86.Build.0 = Debug|Win32 + {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Release|x64.ActiveCfg = Release|x64 + {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Release|x64.Build.0 = Release|x64 + {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Release|x86.ActiveCfg = Release|Win32 + {7BE99936-0D40-410D-944B-4513C2EFF8DC}.Release|x86.Build.0 = Release|Win32 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x64.ActiveCfg = Debug|x64 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x64.Build.0 = Debug|x64 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x86.ActiveCfg = Debug|Win32 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Debug|x86.Build.0 = Debug|Win32 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x64.ActiveCfg = Release|x64 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x64.Build.0 = Release|x64 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x86.ActiveCfg = Release|Win32 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B}.Release|x86.Build.0 = Release|Win32 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Debug|x64.ActiveCfg = Debug|x64 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Debug|x64.Build.0 = Debug|x64 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Debug|x86.ActiveCfg = Debug|Win32 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Debug|x86.Build.0 = Debug|Win32 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x64.ActiveCfg = Release|x64 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x64.Build.0 = Release|x64 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x86.ActiveCfg = Release|Win32 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {AF09FA96-4463-417D-8FE6-526063F41349} = {E0863FCC-8E72-490D-BE1B-458F12CA8298} + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} + {AB0C3362-63AB-480A-ADBC-2EF7D859778B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} + {B9113734-6E84-44FF-8CF7-58199AA815C5} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} + {7BE99936-0D40-410D-944B-4513C2EFF8DC} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {07DCCACC-D10D-47C9-85AE-FB9C54DB7D62} + EndGlobalSection +EndGlobal diff --git a/lib/libes/include/nn/es/SectionHeader_V2.h b/lib/libes/include/nn/es/SectionHeader_V2.h index eb7558b..f472b6f 100644 --- a/lib/libes/include/nn/es/SectionHeader_V2.h +++ b/lib/libes/include/nn/es/SectionHeader_V2.h @@ -1,58 +1,58 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace es -{ - class SectionHeader_V2 : - public fnd::ISerialisable - { - public: - SectionHeader_V2(); - SectionHeader_V2(const SectionHeader_V2& other); - - void operator=(const SectionHeader_V2& other); - bool operator==(const SectionHeader_V2& other) const; - bool operator!=(const SectionHeader_V2& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* data, size_t len); - const fnd::Vec& getBytes() const; - - // variables - virtual void clear(); - - uint32_t getSectionOffset() const; - void setSectionOffset(uint32_t offset); - - uint32_t getRecordSize() const; - void setRecordSize(uint32_t size); - - uint32_t getSectionSize() const; - void getSectionSize(uint32_t size); - - uint16_t getRecordNum() const; - void setRecordNum(uint16_t record_num); - - ticket::SectionType getSectionType() const; - void setSectionType(ticket::SectionType type); - - private: - const std::string kModuleName = "SECTION_HEADER_V2"; - - // raw binary - fnd::Vec mRawBinary; - - // variables - uint32_t mSectionOffset; - uint32_t mRecordSize; - uint32_t mSectionSize; - uint16_t mRecordNum; - ticket::SectionType mSectionType; - }; -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace es +{ + class SectionHeader_V2 : + public fnd::IByteModel + { + public: + SectionHeader_V2(); + SectionHeader_V2(const SectionHeader_V2& other); + + void operator=(const SectionHeader_V2& other); + bool operator==(const SectionHeader_V2& other) const; + bool operator!=(const SectionHeader_V2& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* data, size_t len); + const fnd::Vec& getBytes() const; + + // variables + virtual void clear(); + + uint32_t getSectionOffset() const; + void setSectionOffset(uint32_t offset); + + uint32_t getRecordSize() const; + void setRecordSize(uint32_t size); + + uint32_t getSectionSize() const; + void getSectionSize(uint32_t size); + + uint16_t getRecordNum() const; + void setRecordNum(uint16_t record_num); + + ticket::SectionType getSectionType() const; + void setSectionType(ticket::SectionType type); + + private: + const std::string kModuleName = "SECTION_HEADER_V2"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + uint32_t mSectionOffset; + uint32_t mRecordSize; + uint32_t mSectionSize; + uint16_t mRecordNum; + ticket::SectionType mSectionType; + }; +} } \ No newline at end of file diff --git a/lib/libes/include/nn/es/TicketBody_V2.h b/lib/libes/include/nn/es/TicketBody_V2.h index 6c7150a..2a068b4 100644 --- a/lib/libes/include/nn/es/TicketBody_V2.h +++ b/lib/libes/include/nn/es/TicketBody_V2.h @@ -1,103 +1,103 @@ -#pragma once -#include -#include -#include -#include - -namespace nn -{ -namespace es -{ - class TicketBody_V2 : - public fnd::ISerialisable - { - public: - TicketBody_V2(); - TicketBody_V2(const TicketBody_V2& other); - - void operator=(const TicketBody_V2& other); - bool operator==(const TicketBody_V2& other) const; - bool operator!=(const TicketBody_V2& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const std::string& getIssuer() const; - void setIssuer(const std::string& issuer); - - const byte_t* getEncTitleKey() const; - void setEncTitleKey(const byte_t* data, size_t len); - - ticket::TitleKeyEncType getTitleKeyEncType() const; - void setTitleKeyEncType(ticket::TitleKeyEncType type); - - uint16_t getTicketVersion() const; - void setTicketVersion(uint16_t version); - - ticket::LicenseType getLicenseType() const; - void setLicenseType(ticket::LicenseType type); - - byte_t getCommonKeyId() const; - void setCommonKeyId(byte_t id); - - const fnd::List& getPropertyFlags() const; - void setPropertyFlags(const fnd::List& flags); - - const byte_t* getReservedRegion() const; - void setReservedRegion(const byte_t* data, size_t len); - - uint64_t getTicketId() const; - void setTicketId(uint64_t id); - - uint64_t getDeviceId() const; - void setDeviceId(uint64_t id); - - const byte_t* getRightsId() const; - void setRightsId(const byte_t* id); - - uint32_t getAccountId() const; - void setAccountId(uint32_t id); - - uint32_t getSectionTotalSize() const; - void setSectionTotalSize(uint32_t size); - - uint32_t getSectionHeaderOffset() const; - void setSectionHeaderOffset(uint32_t offset); - - uint16_t getSectionNum() const; - void setSectionNum(uint16_t num); - - uint16_t getSectionEntrySize() const; - void setSectionEntrySize(uint16_t size); - - private: - const std::string kModuleName = "TICKET_BODY_V2"; - - // raw binary - fnd::Vec mRawBinary; - - // variables - std::string mIssuer; - byte_t mEncTitleKey[ticket::kEncTitleKeySize]; - ticket::TitleKeyEncType mEncType; - uint16_t mTicketVersion; - ticket::LicenseType mLicenseType; - byte_t mCommonKeyId; - fnd::List mPropertyFlags; - byte_t mReservedRegion[ticket::kReservedRegionSize]; // explicitly reserved - uint64_t mTicketId; - uint64_t mDeviceId; - byte_t mRightsId[ticket::kRightsIdSize]; - uint32_t mAccountId; - uint32_t mSectTotalSize; - uint32_t mSectHeaderOffset; - uint16_t mSectNum; - uint16_t mSectEntrySize; - }; -} +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace es +{ + class TicketBody_V2 : + public fnd::IByteModel + { + public: + TicketBody_V2(); + TicketBody_V2(const TicketBody_V2& other); + + void operator=(const TicketBody_V2& other); + bool operator==(const TicketBody_V2& other) const; + bool operator!=(const TicketBody_V2& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const std::string& getIssuer() const; + void setIssuer(const std::string& issuer); + + const byte_t* getEncTitleKey() const; + void setEncTitleKey(const byte_t* data, size_t len); + + ticket::TitleKeyEncType getTitleKeyEncType() const; + void setTitleKeyEncType(ticket::TitleKeyEncType type); + + uint16_t getTicketVersion() const; + void setTicketVersion(uint16_t version); + + ticket::LicenseType getLicenseType() const; + void setLicenseType(ticket::LicenseType type); + + byte_t getCommonKeyId() const; + void setCommonKeyId(byte_t id); + + const fnd::List& getPropertyFlags() const; + void setPropertyFlags(const fnd::List& flags); + + const byte_t* getReservedRegion() const; + void setReservedRegion(const byte_t* data, size_t len); + + uint64_t getTicketId() const; + void setTicketId(uint64_t id); + + uint64_t getDeviceId() const; + void setDeviceId(uint64_t id); + + const byte_t* getRightsId() const; + void setRightsId(const byte_t* id); + + uint32_t getAccountId() const; + void setAccountId(uint32_t id); + + uint32_t getSectionTotalSize() const; + void setSectionTotalSize(uint32_t size); + + uint32_t getSectionHeaderOffset() const; + void setSectionHeaderOffset(uint32_t offset); + + uint16_t getSectionNum() const; + void setSectionNum(uint16_t num); + + uint16_t getSectionEntrySize() const; + void setSectionEntrySize(uint16_t size); + + private: + const std::string kModuleName = "TICKET_BODY_V2"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + std::string mIssuer; + byte_t mEncTitleKey[ticket::kEncTitleKeySize]; + ticket::TitleKeyEncType mEncType; + uint16_t mTicketVersion; + ticket::LicenseType mLicenseType; + byte_t mCommonKeyId; + fnd::List mPropertyFlags; + byte_t mReservedRegion[ticket::kReservedRegionSize]; // explicitly reserved + uint64_t mTicketId; + uint64_t mDeviceId; + byte_t mRightsId[ticket::kRightsIdSize]; + uint32_t mAccountId; + uint32_t mSectTotalSize; + uint32_t mSectHeaderOffset; + uint16_t mSectNum; + uint16_t mSectEntrySize; + }; +} } \ No newline at end of file diff --git a/lib/libfnd/include/fnd/ISerialisable.h b/lib/libfnd/include/fnd/IByteModel.h similarity index 81% rename from lib/libfnd/include/fnd/ISerialisable.h rename to lib/libfnd/include/fnd/IByteModel.h index b0d49c7..6f92187 100644 --- a/lib/libfnd/include/fnd/ISerialisable.h +++ b/lib/libfnd/include/fnd/IByteModel.h @@ -1,23 +1,23 @@ -#pragma once -#include -#include - -namespace fnd -{ - class ISerialisable - { - public: - virtual ~ISerialisable() = default; - - // serialise - virtual void toBytes() = 0; - // deserialise - virtual void fromBytes(const byte_t* data, size_t len) = 0; - - // get byte vector - virtual const fnd::Vec& getBytes() const = 0; - - // clear data - virtual void clear() = 0; - }; +#pragma once +#include +#include + +namespace fnd +{ + class IByteModel + { + public: + virtual ~IByteModel() = default; + + // serialise + virtual void toBytes() = 0; + // deserialise + virtual void fromBytes(const byte_t* data, size_t len) = 0; + + // get byte vector + virtual const fnd::Vec& getBytes() const = 0; + + // clear data + virtual void clear() = 0; + }; } \ No newline at end of file diff --git a/lib/libfnd/libfnd.vcxproj b/lib/libfnd/libfnd.vcxproj index 0603ace..927922b 100644 --- a/lib/libfnd/libfnd.vcxproj +++ b/lib/libfnd/libfnd.vcxproj @@ -1,170 +1,170 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B} - 10.0.16299.0 - - - - StaticLibrary - true - v141 - MultiByte - - - StaticLibrary - false - v141 - true - MultiByte - - - StaticLibrary - true - v141 - MultiByte - - - StaticLibrary - false - v141 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - true - ..\libfnd\include;..\libpolarssl\include;..\liblz4\include; - _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - - - Level3 - Disabled - true - ..\libfnd\include;..\libpolarssl\include;..\liblz4\include; - _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - - - Level3 - MaxSpeed - true - true - true - ..\libfnd\include;..\libpolarssl\include;..\liblz4\include; - _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - true - true - - - - - Level3 - MaxSpeed - true - true - true - ..\libfnd\include;..\libpolarssl\include;..\liblz4\include; - _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B} + 10.0.16299.0 + + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + false + v141 + true + MultiByte + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + ..\libfnd\include;..\libpolarssl\include;..\liblz4\include; + _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + + + Level3 + Disabled + true + ..\libfnd\include;..\libpolarssl\include;..\liblz4\include; + _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + + + Level3 + MaxSpeed + true + true + true + ..\libfnd\include;..\libpolarssl\include;..\liblz4\include; + _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + ..\libfnd\include;..\libpolarssl\include;..\liblz4\include; + _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/libfnd/libfnd.vcxproj.filters b/lib/libfnd/libfnd.vcxproj.filters index 56f7ae5..95e68e0 100644 --- a/lib/libfnd/libfnd.vcxproj.filters +++ b/lib/libfnd/libfnd.vcxproj.filters @@ -1,144 +1,144 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/lib/libhac-hb/include/nn/hac/AssetHeader.h b/lib/libhac-hb/include/nn/hac/AssetHeader.h index bbef068..fe2c077 100644 --- a/lib/libhac-hb/include/nn/hac/AssetHeader.h +++ b/lib/libhac-hb/include/nn/hac/AssetHeader.h @@ -1,72 +1,72 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class AssetHeader : - public fnd::ISerialisable - { - public: - struct sSection - { - uint64_t offset; - uint64_t size; - - void operator=(const sSection& other) - { - offset = other.offset; - size = other.size; - } - - bool operator==(const sSection& other) const - { - return (offset == other.offset) \ - && (size == other.size); - } - - bool operator!=(const sSection& other) const - { - return !operator==(other); - } - }; - - AssetHeader(); - AssetHeader(const AssetHeader& other); - - void operator=(const AssetHeader& other); - bool operator==(const AssetHeader& other) const; - bool operator!=(const AssetHeader& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const sSection& getIconInfo() const; - void setIconInfo(const sSection& info); - - const sSection& getNacpInfo() const; - void setNacpInfo(const sSection& info); - - const sSection& getRomfsInfo() const; - void setRomfsInfo(const sSection& info); - private: - const std::string kModuleName = "NRO_ASSET_HEADER"; - - // binary - fnd::Vec mRawBinary; - - // data - sSection mIconInfo; - sSection mNacpInfo; - sSection mRomfsInfo; - }; -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class AssetHeader : + public fnd::IByteModel + { + public: + struct sSection + { + uint64_t offset; + uint64_t size; + + void operator=(const sSection& other) + { + offset = other.offset; + size = other.size; + } + + bool operator==(const sSection& other) const + { + return (offset == other.offset) \ + && (size == other.size); + } + + bool operator!=(const sSection& other) const + { + return !operator==(other); + } + }; + + AssetHeader(); + AssetHeader(const AssetHeader& other); + + void operator=(const AssetHeader& other); + bool operator==(const AssetHeader& other) const; + bool operator!=(const AssetHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const sSection& getIconInfo() const; + void setIconInfo(const sSection& info); + + const sSection& getNacpInfo() const; + void setNacpInfo(const sSection& info); + + const sSection& getRomfsInfo() const; + void setRomfsInfo(const sSection& info); + private: + const std::string kModuleName = "NRO_ASSET_HEADER"; + + // binary + fnd::Vec mRawBinary; + + // data + sSection mIconInfo; + sSection mNacpInfo; + sSection mRomfsInfo; + }; +} } \ No newline at end of file diff --git a/lib/libhac-hb/include/nn/hac/aset.h b/lib/libhac-hb/include/nn/hac/define/aset.h similarity index 88% rename from lib/libhac-hb/include/nn/hac/aset.h rename to lib/libhac-hb/include/nn/hac/define/aset.h index f7c1bfd..c22b2eb 100644 --- a/lib/libhac-hb/include/nn/hac/aset.h +++ b/lib/libhac-hb/include/nn/hac/define/aset.h @@ -1,33 +1,33 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - namespace aset - { - static const uint32_t kAssetStructMagic = _MAKE_STRUCT_MAGIC_U32("ASET"); - - static const uint32_t kDefaultAssetFormatVersion = 0; - } - -#pragma pack(push,1) - struct sAssetSection - { - le_uint64_t offset; - le_uint64_t size; - }; - - struct sAssetHeader - { - le_uint32_t st_magic; - le_uint32_t format_version; - sAssetSection icon; - sAssetSection nacp; - sAssetSection romfs; - }; -#pragma pack(pop) -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + namespace aset + { + static const uint32_t kAssetStructMagic = _MAKE_STRUCT_MAGIC_U32("ASET"); + + static const uint32_t kDefaultAssetFormatVersion = 0; + } + +#pragma pack(push,1) + struct sAssetSection + { + le_uint64_t offset; + le_uint64_t size; + }; + + struct sAssetHeader + { + le_uint32_t st_magic; + le_uint32_t format_version; + sAssetSection icon; + sAssetSection nacp; + sAssetSection romfs; + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac-hb/include/nn/hac/nro-hb.h b/lib/libhac-hb/include/nn/hac/define/nro-hb.h similarity index 66% rename from lib/libhac-hb/include/nn/hac/nro-hb.h rename to lib/libhac-hb/include/nn/hac/define/nro-hb.h index a1dcc67..172850c 100644 --- a/lib/libhac-hb/include/nn/hac/nro-hb.h +++ b/lib/libhac-hb/include/nn/hac/define/nro-hb.h @@ -1,14 +1,14 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - namespace nro - { - static const uint64_t kNroHomebrewStructMagic = _MAKE_STRUCT_MAGIC_U64("HOMEBREW"); - } -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + namespace nro + { + static const uint64_t kNroHomebrewStructMagic = _MAKE_STRUCT_MAGIC_U64("HOMEBREW"); + } +} } \ No newline at end of file diff --git a/lib/libhac-hb/libhac-hb.vcxproj b/lib/libhac-hb/libhac-hb.vcxproj index bcee07e..58ff29a 100644 --- a/lib/libhac-hb/libhac-hb.vcxproj +++ b/lib/libhac-hb/libhac-hb.vcxproj @@ -1,134 +1,134 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63} - 10.0.16299.0 - - - - StaticLibrary - true - v141 - MultiByte - - - StaticLibrary - false - v141 - true - MultiByte - - - StaticLibrary - true - v141 - MultiByte - - - StaticLibrary - false - v141 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - - Level3 - MaxSpeed - true - true - true - true - ..\libfnd\include;..\libhac\include;..\libhac-hb\include; - - - true - true - - - - - Level3 - Disabled - true - true - ..\libfnd\include;..\libhac\include;..\libhac-hb\include; - - - - - Level3 - Disabled - true - true - ..\libfnd\include;..\libhac\include;..\libhac-hb\include; - - - - - Level3 - MaxSpeed - true - true - true - true - ..\libfnd\include;..\libhac\include;..\libhac-hb\include; - - - true - true - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {738CB4FC-CD9E-4B81-A04B-DEADBFA71C63} + 10.0.16299.0 + + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + false + v141 + true + MultiByte + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + MaxSpeed + true + true + true + true + ..\libfnd\include;..\libhac\include;..\libhac-hb\include; + + + true + true + + + + + Level3 + Disabled + true + true + ..\libfnd\include;..\libhac\include;..\libhac-hb\include; + + + + + Level3 + Disabled + true + true + ..\libfnd\include;..\libhac\include;..\libhac-hb\include; + + + + + Level3 + MaxSpeed + true + true + true + true + ..\libfnd\include;..\libhac\include;..\libhac-hb\include; + + + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/libhac-hb/libhac-hb.vcxproj.filters b/lib/libhac-hb/libhac-hb.vcxproj.filters index 02e64c2..8b43938 100644 --- a/lib/libhac-hb/libhac-hb.vcxproj.filters +++ b/lib/libhac-hb/libhac-hb.vcxproj.filters @@ -1,36 +1,39 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {33064298-d382-4e79-9fcd-bc401bdaa763} + + + + + Header Files + + + Header Files\define + + + Header Files\define + + + + + Source Files + + + + + \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/AccessControlInfo.h b/lib/libhac/include/nn/hac/AccessControlInfo.h new file mode 100644 index 0000000..d25a182 --- /dev/null +++ b/lib/libhac/include/nn/hac/AccessControlInfo.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class AccessControlInfo : + public fnd::IByteModel + { + public: + AccessControlInfo(); + AccessControlInfo(const AccessControlInfo& other); + + void operator=(const AccessControlInfo& other); + bool operator==(const AccessControlInfo& other) const; + bool operator!=(const AccessControlInfo& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* data, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint64_t getProgramId() const; + void setProgramId(uint64_t program_id); + + const nn::hac::FileSystemAccessControl& getFileSystemAccessControl() const; + void setFileSystemAccessControl(const FileSystemAccessControl& fac); + + const nn::hac::ServiceAccessControl& getServiceAccessControl() const; + void setServiceAccessControl(const ServiceAccessControl& sac); + + const nn::hac::KernelCapabilityControl& getKernelCapabilities() const; + void setKernelCapabilities(const KernelCapabilityControl& kc); + private: + const std::string kModuleName = "ACCESS_CONTROL_INFO_BINARY"; + + // raw data + fnd::Vec mRawBinary; + + // variables + uint64_t mProgramId; + nn::hac::FileSystemAccessControl mFileSystemAccessControl; + nn::hac::ServiceAccessControl mServiceAccessControl; + nn::hac::KernelCapabilityControl mKernelCapabilities; + }; +} +} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/AccessControlInfoBinary.h b/lib/libhac/include/nn/hac/AccessControlInfoBinary.h deleted file mode 100644 index 3fa1763..0000000 --- a/lib/libhac/include/nn/hac/AccessControlInfoBinary.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class AccessControlInfoBinary : public fnd::ISerialisable - { - public: - AccessControlInfoBinary(); - AccessControlInfoBinary(const AccessControlInfoBinary& other); - - void operator=(const AccessControlInfoBinary& other); - bool operator==(const AccessControlInfoBinary& other) const; - bool operator!=(const AccessControlInfoBinary& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* data, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - uint64_t getProgramId() const; - void setProgramId(uint64_t program_id); - - const nn::hac::FileSystemAccessControlBinary& getFileSystemAccessControl() const; - void setFileSystemAccessControl(const FileSystemAccessControlBinary& fac); - - const nn::hac::ServiceAccessControlBinary& getServiceAccessControl() const; - void setServiceAccessControl(const ServiceAccessControlBinary& sac); - - const nn::hac::KernelCapabilityBinary& getKernelCapabilities() const; - void setKernelCapabilities(const KernelCapabilityBinary& kc); - private: - const std::string kModuleName = "ACCESS_CONTROL_INFO_BINARY"; - - // raw data - fnd::Vec mRawBinary; - - // variables - uint64_t mProgramId; - nn::hac::FileSystemAccessControlBinary mFileSystemAccessControl; - nn::hac::ServiceAccessControlBinary mServiceAccessControl; - nn::hac::KernelCapabilityBinary mKernelCapabilities; - }; -} -} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/AccessControlInfoDesc.h b/lib/libhac/include/nn/hac/AccessControlInfoDesc.h new file mode 100644 index 0000000..93da791 --- /dev/null +++ b/lib/libhac/include/nn/hac/AccessControlInfoDesc.h @@ -0,0 +1,92 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class AccessControlInfoDesc : + public fnd::IByteModel + { + public: + struct sProgramIdRestrict + { + uint64_t min; + uint64_t max; + + void operator=(const sProgramIdRestrict& other) + { + min = other.min; + max = other.max; + } + + bool operator==(const sProgramIdRestrict& other) const + { + return (min == other.min) \ + && (max == other.max); + } + + bool operator!=(const sProgramIdRestrict& other) const + { + return !(*this == other); + } + }; + + AccessControlInfoDesc(); + AccessControlInfoDesc(const AccessControlInfoDesc& other); + + void operator=(const AccessControlInfoDesc& other); + bool operator==(const AccessControlInfoDesc& other) const; + bool operator!=(const AccessControlInfoDesc& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* data, size_t len); + const fnd::Vec& getBytes() const; + + void generateSignature(const fnd::rsa::sRsa2048Key& key); + void validateSignature(const fnd::rsa::sRsa2048Key& key) const; + + // variables + void clear(); + + const fnd::rsa::sRsa2048Key& getContentArchiveHeaderSignature2Key() const; + void setContentArchiveHeaderSignature2Key(const fnd::rsa::sRsa2048Key& key); + + const fnd::List& getFlagList() const; + void setFlagList(const fnd::List& flags); + + const sProgramIdRestrict& getProgramIdRestrict() const; + void setProgramIdRestrict(const sProgramIdRestrict& pid_restrict); + + const nn::hac::FileSystemAccessControl& getFileSystemAccessControl() const; + void setFileSystemAccessControl(const FileSystemAccessControl& fac); + + const nn::hac::ServiceAccessControl& getServiceAccessControl() const; + void setServiceAccessControl(const ServiceAccessControl& sac); + + const nn::hac::KernelCapabilityControl& getKernelCapabilities() const; + void setKernelCapabilities(const KernelCapabilityControl& kc); + private: + const std::string kModuleName = "ACCESS_CONTROL_INFO_DESC_BINARY"; + + // raw data + fnd::Vec mRawBinary; + + // variables + fnd::rsa::sRsa2048Key mContentArchiveHeaderSignature2Key; + fnd::List mFlags; + sProgramIdRestrict mProgramIdRestrict; + nn::hac::FileSystemAccessControl mFileSystemAccessControl; + nn::hac::ServiceAccessControl mServiceAccessControl; + nn::hac::KernelCapabilityControl mKernelCapabilities; + }; +} +} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/AccessControlInfoDescBinary.h b/lib/libhac/include/nn/hac/AccessControlInfoDescBinary.h deleted file mode 100644 index df7b004..0000000 --- a/lib/libhac/include/nn/hac/AccessControlInfoDescBinary.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class AccessControlInfoDescBinary : public fnd::ISerialisable - { - public: - struct sProgramIdRestrict - { - uint64_t min; - uint64_t max; - - void operator=(const sProgramIdRestrict& other) - { - min = other.min; - max = other.max; - } - - bool operator==(const sProgramIdRestrict& other) const - { - return (min == other.min) \ - && (max == other.max); - } - - bool operator!=(const sProgramIdRestrict& other) const - { - return !(*this == other); - } - }; - - AccessControlInfoDescBinary(); - AccessControlInfoDescBinary(const AccessControlInfoDescBinary& other); - - void operator=(const AccessControlInfoDescBinary& other); - bool operator==(const AccessControlInfoDescBinary& other) const; - bool operator!=(const AccessControlInfoDescBinary& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* data, size_t len); - const fnd::Vec& getBytes() const; - - void generateSignature(const fnd::rsa::sRsa2048Key& key); - void validateSignature(const fnd::rsa::sRsa2048Key& key) const; - - // variables - void clear(); - - const fnd::rsa::sRsa2048Key& getNcaHeaderSignature2Key() const; - void setNcaHeaderSignature2Key(const fnd::rsa::sRsa2048Key& key); - - const fnd::List& getFlagList() const; - void setFlagList(const fnd::List& flags); - - const sProgramIdRestrict& getProgramIdRestrict() const; - void setProgramIdRestrict(const sProgramIdRestrict& pid_restrict); - - const nn::hac::FileSystemAccessControlBinary& getFileSystemAccessControl() const; - void setFileSystemAccessControl(const FileSystemAccessControlBinary& fac); - - const nn::hac::ServiceAccessControlBinary& getServiceAccessControl() const; - void setServiceAccessControl(const ServiceAccessControlBinary& sac); - - const nn::hac::KernelCapabilityBinary& getKernelCapabilities() const; - void setKernelCapabilities(const KernelCapabilityBinary& kc); - private: - const std::string kModuleName = "ACCESS_CONTROL_INFO_DESC_BINARY"; - - // raw data - fnd::Vec mRawBinary; - - // variables - fnd::rsa::sRsa2048Key mNcaHeaderSignature2Key; - fnd::List mFlags; - sProgramIdRestrict mProgramIdRestrict; - nn::hac::FileSystemAccessControlBinary mFileSystemAccessControl; - nn::hac::ServiceAccessControlBinary mServiceAccessControl; - nn::hac::KernelCapabilityBinary mKernelCapabilities; - }; -} -} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/AddOnContentMetaExtendedHeader.h b/lib/libhac/include/nn/hac/AddOnContentMetaExtendedHeader.h new file mode 100644 index 0000000..b3519b5 --- /dev/null +++ b/lib/libhac/include/nn/hac/AddOnContentMetaExtendedHeader.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class AddOnContentMetaExtendedHeader : + public fnd::IByteModel + { + public: + AddOnContentMetaExtendedHeader(); + AddOnContentMetaExtendedHeader(const AddOnContentMetaExtendedHeader& other); + + void operator=(const AddOnContentMetaExtendedHeader& other); + bool operator==(const AddOnContentMetaExtendedHeader& other) const; + bool operator!=(const AddOnContentMetaExtendedHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint64_t getApplicationId() const; + void setApplicationId(uint64_t application_id); + + uint32_t getRequiredApplicationVersion() const; + void setRequiredApplicationVersion(uint32_t app_ver); + private: + const std::string kModuleName = "ADD_ON_CONTENT_META_EXTENDED_HEADER"; + + // binary blob + fnd::Vec mRawBinary; + + // variables + uint64_t mApplicationId; + uint32_t mRequiredApplicationVersion; + }; +} +} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/ApplicationControlPropertyBinary.h b/lib/libhac/include/nn/hac/ApplicationControlProperty.h similarity index 91% rename from lib/libhac/include/nn/hac/ApplicationControlPropertyBinary.h rename to lib/libhac/include/nn/hac/ApplicationControlProperty.h index af69e42..73e250d 100644 --- a/lib/libhac/include/nn/hac/ApplicationControlPropertyBinary.h +++ b/lib/libhac/include/nn/hac/ApplicationControlProperty.h @@ -1,269 +1,269 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class ApplicationControlPropertyBinary : - public fnd::ISerialisable - { - public: - struct sTitle - { - nacp::Language language; - std::string name; - std::string publisher; - - void operator=(const sTitle& other) - { - language = other.language; - name = other.name; - publisher = other.publisher; - } - - bool operator==(const sTitle& other) const - { - return (language == other.language) \ - && (name == other.name) \ - && (publisher == other.publisher); - } - - bool operator!=(const sTitle& other) const - { - return !operator==(other); - } - }; - - struct sRating - { - nacp::Organisation organisation; - int8_t age; - - void operator=(const sRating& other) - { - organisation = other.organisation; - age = other.age; - } - - bool operator==(const sRating& other) const - { - return (organisation == other.organisation) \ - && (age == other.age); - } - - bool operator!=(const sRating& other) const - { - return !operator==(other); - } - }; - - struct sStorageSize - { - int64_t size; - int64_t journal_size; - - void operator=(const sStorageSize& other) - { - size = other.size; - journal_size = other.journal_size; - } - - bool operator==(const sStorageSize& other) const - { - return (size == other.size) \ - && (journal_size == other.journal_size); - } - - bool operator!=(const sStorageSize& other) const - { - return !operator==(other); - } - }; - - ApplicationControlPropertyBinary(); - ApplicationControlPropertyBinary(const ApplicationControlPropertyBinary& other); - - void operator=(const ApplicationControlPropertyBinary& other); - bool operator==(const ApplicationControlPropertyBinary& other) const; - bool operator!=(const ApplicationControlPropertyBinary& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const fnd::List& getTitle() const; - void setTitle(const fnd::List& title); - - const std::string& getIsbn() const; - void setIsbn(const std::string& isbn); - - nacp::StartupUserAccount getStartupUserAccount() const; - void setStartupUserAccount(nacp::StartupUserAccount var); - - nacp::TouchScreenUsageMode getTouchScreenUsageMode() const; - void setTouchScreenUsageMode(nacp::TouchScreenUsageMode var); - - nacp::AocRegistrationType getAocRegistrationType() const; - void setAocRegistrationType(nacp::AocRegistrationType var); - - nacp::AttributeFlag getAttributeFlag() const; - void setAttributeFlag(nacp::AttributeFlag var); - - const fnd::List& getSupportedLanguages() const; - void setSupportedLanguages(const fnd::List& var); - - nacp::ParentalControlFlag getParentalControlFlag() const; - void setParentalControlFlag(nacp::ParentalControlFlag var); - - nacp::ScreenshotMode getScreenshotMode() const; - void setScreenshotMode(nacp::ScreenshotMode var); - - nacp::VideoCaptureMode getVideoCaptureMode() const; - void setVideoCaptureMode(nacp::VideoCaptureMode var); - - nacp::DataLossConfirmation getDataLossConfirmation() const; - void setDataLossConfirmation(nacp::DataLossConfirmation var); - - nacp::PlayLogPolicy getPlayLogPolicy() const; - void setPlayLogPolicy(nacp::PlayLogPolicy var); - - uint64_t getPresenceGroupId() const; - void setPresenceGroupId(uint64_t var); - - const fnd::List& getRatingAge() const; - void setRatingAge(const fnd::List& var); - - const std::string& getDisplayVersion() const; - void setDisplayVersion(const std::string& var); - - uint64_t getAocBaseId() const; - void setAocBaseId(uint64_t var); - - uint64_t getSaveDatawOwnerId() const; - void setSaveDatawOwnerId(uint64_t var); - - const sStorageSize& getUserAccountSaveDataSize() const; - void setUserAccountSaveDataSize(const sStorageSize& var); - - const sStorageSize& getDeviceSaveDataSize() const; - void setDeviceSaveDataSize(const sStorageSize& var); - - int64_t getBcatDeliveryCacheStorageSize() const; - void setBcatDeliveryCacheStorageSize(int64_t var); - - const std::string& getApplicationErrorCodeCategory() const; - void setApplicationErrorCodeCategory(const std::string& var); - - const fnd::List& getLocalCommunicationId() const; - void setLocalCommunicationId(const fnd::List& var); - - nacp::LogoType getLogoType() const; - void setLogoType(nacp::LogoType var); - - nacp::LogoHandling getLogoHandling() const; - void setLogoHandling(nacp::LogoHandling var); - - nacp::RuntimeAocInstallMode getRuntimeAocInstallMode() const; - void setRuntimeAocInstallMode(nacp::RuntimeAocInstallMode var); - - nacp::CrashReportMode getCrashReportMode() const; - void setCrashReportMode(nacp::CrashReportMode var); - - nacp::Hdcp getHdcp() const; - void setHdcp(nacp::Hdcp var); - - uint64_t getSeedForPsuedoDeviceId() const; - void setSeedForPsuedoDeviceId(uint64_t var); - - const std::string& getBcatPassphase() const; - void setBcatPassphase(const std::string& var); - - const sStorageSize& getUserAccountSaveDataMax() const; - void setUserAccountSaveDataMax(const sStorageSize& var); - - const sStorageSize& getDeviceSaveDataMax() const; - void setDeviceSaveDataMax(const sStorageSize& var); - - int64_t getTemporaryStorageSize() const; - void setTemporaryStorageSize(int64_t var); - - const sStorageSize& getCacheStorageSize() const; - void setCacheStorageSize(const sStorageSize& var); - - int64_t getCacheStorageDataAndJournalSizeMax() const; - void setCacheStorageDataAndJournalSizeMax(int64_t var); - - uint16_t getCacheStorageIndexMax() const; - void setCacheStorageIndexMax(uint16_t var); - - const fnd::List& getPlayLogQueryableApplicationId() const; - void setPlayLogQueryableApplicationId(const fnd::List& var); - - nacp::PlayLogQueryCapability getPlayLogQueryCapability() const; - void setPlayLogQueryCapability(nacp::PlayLogQueryCapability var); - - nacp::RepairFlag getRepairFlag() const; - void setRepairFlag(nacp::RepairFlag var); - - byte_t getProgramIndex() const; - void setProgramIndex(byte_t var); - - - private: - const std::string kModuleName = "APPLICATION_CONTROL_PROPERTY"; - - // raw data - fnd::Vec mRawBinary; - - // variables - fnd::List mTitle; - std::string mIsbn; - nacp::StartupUserAccount mStartupUserAccount; - nacp::TouchScreenUsageMode mTouchScreenUsageMode; - nacp::AocRegistrationType mAocRegistrationType; - nacp::AttributeFlag mAttributeFlag; - fnd::List mSupportedLanguages; - nacp::ParentalControlFlag mParentalControlFlag; - nacp::ScreenshotMode mScreenshotMode; - nacp::VideoCaptureMode mVideoCaptureMode; - nacp::DataLossConfirmation mDataLossConfirmation; - nacp::PlayLogPolicy mPlayLogPolicy; - uint64_t mPresenceGroupId; - fnd::List mRatingAge; - std::string mDisplayVersion; - uint64_t mAocBaseId; - uint64_t mSaveDatawOwnerId; - sStorageSize mUserAccountSaveDataSize; - sStorageSize mDeviceSaveDataSize; - int64_t mBcatDeliveryCacheStorageSize; - std::string mApplicationErrorCodeCategory; - fnd::List mLocalCommunicationId; - nacp::LogoType mLogoType; - nacp::LogoHandling mLogoHandling; - nacp::RuntimeAocInstallMode mRuntimeAocInstallMode; - nacp::CrashReportMode mCrashReportMode; - nacp::Hdcp mHdcp; - uint64_t mSeedForPsuedoDeviceId; - std::string mBcatPassphase; - sStorageSize mUserAccountSaveDataMax; - sStorageSize mDeviceSaveDataMax; - int64_t mTemporaryStorageSize; - sStorageSize mCacheStorageSize; - int64_t mCacheStorageDataAndJournalSizeMax; - uint16_t mCacheStorageIndexMax; - fnd::List mPlayLogQueryableApplicationId; - nacp::PlayLogQueryCapability mPlayLogQueryCapability; - nacp::RepairFlag mRepairFlag; - byte_t mProgramIndex; - }; -} +#pragma once +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class ApplicationControlProperty : + public fnd::IByteModel + { + public: + struct sTitle + { + nacp::Language language; + std::string name; + std::string publisher; + + void operator=(const sTitle& other) + { + language = other.language; + name = other.name; + publisher = other.publisher; + } + + bool operator==(const sTitle& other) const + { + return (language == other.language) \ + && (name == other.name) \ + && (publisher == other.publisher); + } + + bool operator!=(const sTitle& other) const + { + return !operator==(other); + } + }; + + struct sRating + { + nacp::Organisation organisation; + int8_t age; + + void operator=(const sRating& other) + { + organisation = other.organisation; + age = other.age; + } + + bool operator==(const sRating& other) const + { + return (organisation == other.organisation) \ + && (age == other.age); + } + + bool operator!=(const sRating& other) const + { + return !operator==(other); + } + }; + + struct sStorageSize + { + int64_t size; + int64_t journal_size; + + void operator=(const sStorageSize& other) + { + size = other.size; + journal_size = other.journal_size; + } + + bool operator==(const sStorageSize& other) const + { + return (size == other.size) \ + && (journal_size == other.journal_size); + } + + bool operator!=(const sStorageSize& other) const + { + return !operator==(other); + } + }; + + ApplicationControlProperty(); + ApplicationControlProperty(const ApplicationControlProperty& other); + + void operator=(const ApplicationControlProperty& other); + bool operator==(const ApplicationControlProperty& other) const; + bool operator!=(const ApplicationControlProperty& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const fnd::List& getTitle() const; + void setTitle(const fnd::List& title); + + const std::string& getIsbn() const; + void setIsbn(const std::string& isbn); + + nacp::StartupUserAccount getStartupUserAccount() const; + void setStartupUserAccount(nacp::StartupUserAccount var); + + nacp::TouchScreenUsageMode getTouchScreenUsageMode() const; + void setTouchScreenUsageMode(nacp::TouchScreenUsageMode var); + + nacp::AocRegistrationType getAocRegistrationType() const; + void setAocRegistrationType(nacp::AocRegistrationType var); + + nacp::AttributeFlag getAttributeFlag() const; + void setAttributeFlag(nacp::AttributeFlag var); + + const fnd::List& getSupportedLanguages() const; + void setSupportedLanguages(const fnd::List& var); + + nacp::ParentalControlFlag getParentalControlFlag() const; + void setParentalControlFlag(nacp::ParentalControlFlag var); + + nacp::ScreenshotMode getScreenshotMode() const; + void setScreenshotMode(nacp::ScreenshotMode var); + + nacp::VideoCaptureMode getVideoCaptureMode() const; + void setVideoCaptureMode(nacp::VideoCaptureMode var); + + nacp::DataLossConfirmation getDataLossConfirmation() const; + void setDataLossConfirmation(nacp::DataLossConfirmation var); + + nacp::PlayLogPolicy getPlayLogPolicy() const; + void setPlayLogPolicy(nacp::PlayLogPolicy var); + + uint64_t getPresenceGroupId() const; + void setPresenceGroupId(uint64_t var); + + const fnd::List& getRatingAge() const; + void setRatingAge(const fnd::List& var); + + const std::string& getDisplayVersion() const; + void setDisplayVersion(const std::string& var); + + uint64_t getAocBaseId() const; + void setAocBaseId(uint64_t var); + + uint64_t getSaveDatawOwnerId() const; + void setSaveDatawOwnerId(uint64_t var); + + const sStorageSize& getUserAccountSaveDataSize() const; + void setUserAccountSaveDataSize(const sStorageSize& var); + + const sStorageSize& getDeviceSaveDataSize() const; + void setDeviceSaveDataSize(const sStorageSize& var); + + int64_t getBcatDeliveryCacheStorageSize() const; + void setBcatDeliveryCacheStorageSize(int64_t var); + + const std::string& getApplicationErrorCodeCategory() const; + void setApplicationErrorCodeCategory(const std::string& var); + + const fnd::List& getLocalCommunicationId() const; + void setLocalCommunicationId(const fnd::List& var); + + nacp::LogoType getLogoType() const; + void setLogoType(nacp::LogoType var); + + nacp::LogoHandling getLogoHandling() const; + void setLogoHandling(nacp::LogoHandling var); + + nacp::RuntimeAocInstallMode getRuntimeAocInstallMode() const; + void setRuntimeAocInstallMode(nacp::RuntimeAocInstallMode var); + + nacp::CrashReportMode getCrashReportMode() const; + void setCrashReportMode(nacp::CrashReportMode var); + + nacp::Hdcp getHdcp() const; + void setHdcp(nacp::Hdcp var); + + uint64_t getSeedForPsuedoDeviceId() const; + void setSeedForPsuedoDeviceId(uint64_t var); + + const std::string& getBcatPassphase() const; + void setBcatPassphase(const std::string& var); + + const sStorageSize& getUserAccountSaveDataMax() const; + void setUserAccountSaveDataMax(const sStorageSize& var); + + const sStorageSize& getDeviceSaveDataMax() const; + void setDeviceSaveDataMax(const sStorageSize& var); + + int64_t getTemporaryStorageSize() const; + void setTemporaryStorageSize(int64_t var); + + const sStorageSize& getCacheStorageSize() const; + void setCacheStorageSize(const sStorageSize& var); + + int64_t getCacheStorageDataAndJournalSizeMax() const; + void setCacheStorageDataAndJournalSizeMax(int64_t var); + + uint16_t getCacheStorageIndexMax() const; + void setCacheStorageIndexMax(uint16_t var); + + const fnd::List& getPlayLogQueryableApplicationId() const; + void setPlayLogQueryableApplicationId(const fnd::List& var); + + nacp::PlayLogQueryCapability getPlayLogQueryCapability() const; + void setPlayLogQueryCapability(nacp::PlayLogQueryCapability var); + + nacp::RepairFlag getRepairFlag() const; + void setRepairFlag(nacp::RepairFlag var); + + byte_t getProgramIndex() const; + void setProgramIndex(byte_t var); + + + private: + const std::string kModuleName = "APPLICATION_CONTROL_PROPERTY"; + + // raw data + fnd::Vec mRawBinary; + + // variables + fnd::List mTitle; + std::string mIsbn; + nacp::StartupUserAccount mStartupUserAccount; + nacp::TouchScreenUsageMode mTouchScreenUsageMode; + nacp::AocRegistrationType mAocRegistrationType; + nacp::AttributeFlag mAttributeFlag; + fnd::List mSupportedLanguages; + nacp::ParentalControlFlag mParentalControlFlag; + nacp::ScreenshotMode mScreenshotMode; + nacp::VideoCaptureMode mVideoCaptureMode; + nacp::DataLossConfirmation mDataLossConfirmation; + nacp::PlayLogPolicy mPlayLogPolicy; + uint64_t mPresenceGroupId; + fnd::List mRatingAge; + std::string mDisplayVersion; + uint64_t mAocBaseId; + uint64_t mSaveDatawOwnerId; + sStorageSize mUserAccountSaveDataSize; + sStorageSize mDeviceSaveDataSize; + int64_t mBcatDeliveryCacheStorageSize; + std::string mApplicationErrorCodeCategory; + fnd::List mLocalCommunicationId; + nacp::LogoType mLogoType; + nacp::LogoHandling mLogoHandling; + nacp::RuntimeAocInstallMode mRuntimeAocInstallMode; + nacp::CrashReportMode mCrashReportMode; + nacp::Hdcp mHdcp; + uint64_t mSeedForPsuedoDeviceId; + std::string mBcatPassphase; + sStorageSize mUserAccountSaveDataMax; + sStorageSize mDeviceSaveDataMax; + int64_t mTemporaryStorageSize; + sStorageSize mCacheStorageSize; + int64_t mCacheStorageDataAndJournalSizeMax; + uint16_t mCacheStorageIndexMax; + fnd::List mPlayLogQueryableApplicationId; + nacp::PlayLogQueryCapability mPlayLogQueryCapability; + nacp::RepairFlag mRepairFlag; + byte_t mProgramIndex; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/ApplicationControlPropertyUtils.h b/lib/libhac/include/nn/hac/ApplicationControlPropertyUtils.h index 9955de3..feeb666 100644 --- a/lib/libhac/include/nn/hac/ApplicationControlPropertyUtils.h +++ b/lib/libhac/include/nn/hac/ApplicationControlPropertyUtils.h @@ -1,15 +1,15 @@ -#pragma once -#include - -namespace nn -{ -namespace hac -{ - class ApplicationControlPropertyUtils - { - public: - static bool validateSaveDataSizeMax(int64_t size, int64_t alignment); - static bool validateSaveDataSize(int64_t size); - }; -} +#pragma once +#include + +namespace nn +{ +namespace hac +{ + class ApplicationControlPropertyUtils + { + public: + static bool validateSaveDataSizeMax(int64_t size, int64_t alignment); + static bool validateSaveDataSize(int64_t size); + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/ApplicationMetaExtendedHeader.h b/lib/libhac/include/nn/hac/ApplicationMetaExtendedHeader.h new file mode 100644 index 0000000..498567a --- /dev/null +++ b/lib/libhac/include/nn/hac/ApplicationMetaExtendedHeader.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class ApplicationMetaExtendedHeader : + public fnd::IByteModel + { + public: + ApplicationMetaExtendedHeader(); + ApplicationMetaExtendedHeader(const ApplicationMetaExtendedHeader& other); + + void operator=(const ApplicationMetaExtendedHeader& other); + bool operator==(const ApplicationMetaExtendedHeader& other) const; + bool operator!=(const ApplicationMetaExtendedHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint64_t getPatchId() const; + void setPatchId(uint64_t patch_id); + + uint32_t getRequiredSystemVersion() const; + void setRequiredSystemVersion(uint32_t sys_ver); + private: + const std::string kModuleName = "APPLICATION_META_EXTENDED_HEADER"; + + // binary blob + fnd::Vec mRawBinary; + + // variables + uint64_t mPatchId; + uint32_t mRequiredSystemVersion; + }; +} +} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/ContentArchiveHeader.h b/lib/libhac/include/nn/hac/ContentArchiveHeader.h new file mode 100644 index 0000000..fe2c399 --- /dev/null +++ b/lib/libhac/include/nn/hac/ContentArchiveHeader.h @@ -0,0 +1,121 @@ +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class ContentArchiveHeader : + public fnd::IByteModel + { + public: + struct sPartitionEntry + { + byte_t header_index; + uint64_t offset; + uint64_t size; + fnd::sha::sSha256Hash fs_header_hash; + + const sPartitionEntry& operator=(const sPartitionEntry& other) + { + header_index = other.header_index; + offset = other.offset; + size = other.size; + fs_header_hash = other.fs_header_hash; + + return *this; + } + + bool operator==(const sPartitionEntry& other) const + { + return (header_index == other.header_index) \ + && (offset == other.offset) \ + && (size == other.size) \ + && (fs_header_hash == other.fs_header_hash); + } + + bool operator!=(const sPartitionEntry& other) const + { + return !operator==(other); + } + }; + + ContentArchiveHeader(); + ContentArchiveHeader(const ContentArchiveHeader& other); + + void operator=(const ContentArchiveHeader& other); + bool operator==(const ContentArchiveHeader& other) const; + bool operator!=(const ContentArchiveHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + byte_t getFormatVersion() const; + void setFormatVersion(byte_t ver); + + nca::DistributionType getDistributionType() const; + void setDistributionType(nca::DistributionType type); + + nca::ContentType getContentType() const; + void setContentType(nca::ContentType type); + + byte_t getKeyGeneration() const; + void setKeyGeneration(byte_t gen); + + byte_t getKeyAreaEncryptionKeyIndex() const; + void setKeyAreaEncryptionKeyIndex(byte_t index); + + uint64_t getContentSize() const; + void setContentSize(uint64_t size); + + uint64_t getProgramId() const; + void setProgramId(uint64_t program_id); + + uint32_t getContentIndex() const; + void setContentIndex(uint32_t index); + + uint32_t getSdkAddonVersion() const; + void setSdkAddonVersion(uint32_t version); + + bool hasRightsId() const; + const byte_t* getRightsId() const; + void setRightsId(const byte_t* rights_id); + + const fnd::List& getPartitionEntryList() const; + void setPartitionEntryList(const fnd::List& partition_entry_list); + + const byte_t* getKeyArea() const; + void setKeyArea(const byte_t* key_area); + + private: + const std::string kModuleName = "CONTENT_ARCHIVE_HEADER"; + + // binary + fnd::Vec mRawBinary; + + // data + byte_t mFormatVersion; + nca::DistributionType mDistributionType; + nca::ContentType mContentType; + byte_t mKeyGeneration; + byte_t mKaekIndex; + uint64_t mContentSize; + uint64_t mProgramId; + uint32_t mContentIndex; + uint32_t mSdkAddonVersion; + fnd::Vec mRightsId; + fnd::List mPartitionEntryList; + fnd::Vec mKeyArea; + + uint64_t blockNumToSize(uint32_t block_num) const; + uint32_t sizeToBlockNum(uint64_t real_size) const; + }; +} +} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/NcaUtils.h b/lib/libhac/include/nn/hac/ContentArchiveUtils.h similarity index 64% rename from lib/libhac/include/nn/hac/NcaUtils.h rename to lib/libhac/include/nn/hac/ContentArchiveUtils.h index 0b4da75..62315d8 100644 --- a/lib/libhac/include/nn/hac/NcaUtils.h +++ b/lib/libhac/include/nn/hac/ContentArchiveUtils.h @@ -1,17 +1,17 @@ -#pragma once -#include - -namespace nn -{ -namespace hac -{ - class NcaUtils - { - public: - static inline size_t sectorToOffset(size_t sector_index) { return sector_index * nn::hac::nca::kSectorSize; } - static void decryptNcaHeader(const byte_t* src, byte_t* dst, const fnd::aes::sAesXts128Key& key); - static byte_t getMasterKeyRevisionFromKeyGeneration(byte_t key_generation); - static void getNcaPartitionAesCtr(const nn::hac::sNcaFsHeader* hdr, byte_t* ctr); - }; -} +#pragma once +#include + +namespace nn +{ +namespace hac +{ + class ContentArchiveUtils + { + public: + static inline size_t sectorToOffset(size_t sector_index) { return sector_index * nn::hac::nca::kSectorSize; } + static void decryptContentArchiveHeader(const byte_t* src, byte_t* dst, const fnd::aes::sAesXts128Key& key); + static byte_t getMasterKeyRevisionFromKeyGeneration(byte_t key_generation); + static void getNcaPartitionAesCtr(const nn::hac::sNcaFsHeader* hdr, byte_t* ctr); + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/ContentInfo.h b/lib/libhac/include/nn/hac/ContentInfo.h new file mode 100644 index 0000000..eb644c5 --- /dev/null +++ b/lib/libhac/include/nn/hac/ContentInfo.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class ContentInfo : + public fnd::IByteModel + { + public: + ContentInfo(); + ContentInfo(const ContentInfo& other); + + void operator=(const ContentInfo& other); + bool operator==(const ContentInfo& other) const; + bool operator!=(const ContentInfo& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const fnd::sha::sSha256Hash& getContentHash() const; + void setContentHash(const fnd::sha::sSha256Hash& hash); + + const cnmt::sContentId& getContentId() const; + void setContentId(const cnmt::sContentId& content_id); + + size_t getContentSize() const; + void setContentSize(size_t size); + + cnmt::ContentType getContentType() const; + void setContentType(cnmt::ContentType type); + + byte_t getIdOffset() const; + void setIdOffset(byte_t id_offset); + + private: + const std::string kModuleName = "CONTENT_INFO"; + + // binary blob + fnd::Vec mRawBinary; + + // variables + fnd::sha::sSha256Hash mHash; + cnmt::sContentId mContentId; + size_t mSize; + cnmt::ContentType mType; + byte_t mIdOffset; + }; +} +} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/ContentMeta.h b/lib/libhac/include/nn/hac/ContentMeta.h new file mode 100644 index 0000000..f7c0765 --- /dev/null +++ b/lib/libhac/include/nn/hac/ContentMeta.h @@ -0,0 +1,113 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class ContentMeta : + public fnd::IByteModel + { + public: + ContentMeta(); + ContentMeta(const ContentMeta& other); + + void operator=(const ContentMeta& other); + bool operator==(const ContentMeta& other) const; + bool operator!=(const ContentMeta& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint64_t getTitleId() const; + void setTitleId(uint64_t title_id); + + uint32_t getTitleVersion() const; + void setTitleVersion(uint32_t version); + + cnmt::ContentMetaType getContentMetaType() const; + void setContentMetaType(cnmt::ContentMetaType type); + + byte_t getAttributes() const; + void setAttributes(byte_t attributes); + + uint32_t getRequiredDownloadSystemVersion() const; + void setRequiredDownloadSystemVersion(uint32_t version); + + const ApplicationMetaExtendedHeader& getApplicationMetaExtendedHeader() const; + void setApplicationMetaExtendedHeader(const ApplicationMetaExtendedHeader& exhdr); + + const PatchMetaExtendedHeader& getPatchMetaExtendedHeader() const; + void setPatchMetaExtendedHeader(const PatchMetaExtendedHeader& exhdr); + + const AddOnContentMetaExtendedHeader& getAddOnContentMetaExtendedHeader() const; + void setAddOnContentMetaExtendedHeader(const AddOnContentMetaExtendedHeader& exhdr); + + const DeltaMetaExtendedHeader& getDeltaMetaExtendedHeader() const; + void setDeltaMetaExtendedHeader(const DeltaMetaExtendedHeader& exhdr); + + const fnd::List& getContentInfo() const; + void setContentInfo(const fnd::List& info); + + const fnd::List& getContentMetaInfo() const; + void setContentMetaInfo(const fnd::List& info); + + const fnd::Vec& getExtendedData() const; + void setExtendedData(const fnd::Vec& data); + + const cnmt::sDigest& getDigest() const; + void setDigest(const cnmt::sDigest& digest); + + + private: + const std::string kModuleName = "CONTENT_META"; + + // binary blob + fnd::Vec mRawBinary; + + // variables + uint64_t mTitleId; + uint32_t mTitleVersion; + cnmt::ContentMetaType mType; + byte_t mAttributes; + uint32_t mRequiredDownloadSystemVersion; + fnd::Vec mExtendedHeader; + + ApplicationMetaExtendedHeader mApplicationMetaExtendedHeader; + PatchMetaExtendedHeader mPatchMetaExtendedHeader; + AddOnContentMetaExtendedHeader mAddOnContentMetaExtendedHeader; + DeltaMetaExtendedHeader mDeltaMetaExtendedHeader; + + fnd::List mContentInfo; + fnd::List mContentMetaInfo; + fnd::Vec mExtendedData; + cnmt::sDigest mDigest; + + inline size_t getExtendedHeaderOffset() const { return sizeof(sContentMetaHeader); } + inline size_t getContentInfoOffset(size_t exhdrSize) const { return getExtendedHeaderOffset() + exhdrSize; } + inline size_t getContentMetaInfoOffset(size_t exhdrSize, size_t contentInfoNum) const { return getContentInfoOffset(exhdrSize) + contentInfoNum * sizeof(sContentInfo); } + inline size_t getExtendedDataOffset(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum) const { return getContentMetaInfoOffset(exhdrSize, contentInfoNum) + contentMetaNum * sizeof(sContentMetaInfo); } + inline size_t getDigestOffset(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum, size_t exdataSize) const { return getExtendedDataOffset(exhdrSize, contentInfoNum, contentMetaNum) + exdataSize; } + inline size_t getTotalSize(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum, size_t exdataSize) const { return getDigestOffset(exhdrSize, contentInfoNum, contentMetaNum, exdataSize) + cnmt::kDigestLen; } + + bool validateExtendedHeaderSize(cnmt::ContentMetaType type, size_t exhdrSize) const; + size_t getExtendedDataSize(cnmt::ContentMetaType type, const byte_t* data) const; + void validateBinary(const byte_t* bytes, size_t len) const; + }; +} +} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/ContentMetaBinary.h b/lib/libhac/include/nn/hac/ContentMetaBinary.h deleted file mode 100644 index 8c57644..0000000 --- a/lib/libhac/include/nn/hac/ContentMetaBinary.h +++ /dev/null @@ -1,254 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class ContentMetaBinary : - public fnd::ISerialisable - { - public: - struct ContentInfo - { - fnd::sha::sSha256Hash hash; - byte_t nca_id[cnmt::kContentIdLen]; - size_t size; - cnmt::ContentType type; - - void operator=(const ContentInfo& other) - { - hash = other.hash; - memcpy(nca_id, other.nca_id, cnmt::kContentIdLen); - size = other.size; - type = other.type; - } - - bool operator==(const ContentInfo& other) const - { - return (hash == other.hash) \ - && (memcmp(nca_id, other.nca_id, cnmt::kContentIdLen) == 0) \ - && (size == other.size) \ - && (type == other.type); - } - - bool operator!=(const ContentInfo& other) const - { - return !operator==(other); - } - }; - - struct ContentMetaInfo - { - uint64_t id; - uint32_t version; - cnmt::ContentMetaType type; - byte_t attributes; - - void operator=(const ContentMetaInfo& other) - { - id = other.id; - version = other.version; - type = other.type; - attributes = other.attributes; - } - - bool operator==(const ContentMetaInfo& other) const - { - return (id == other.id) \ - && (version == other.version) \ - && (type == other.type) \ - && (attributes == other.attributes); - } - - bool operator!=(const ContentMetaInfo& other) const - { - return !operator==(other); - } - }; - - struct ApplicationMetaExtendedHeader - { - uint64_t patch_id; - uint32_t required_system_version; - - void operator=(const ApplicationMetaExtendedHeader& other) - { - patch_id = other.patch_id; - required_system_version = other.required_system_version; - } - - bool operator==(const ApplicationMetaExtendedHeader& other) const - { - return (patch_id == other.patch_id) \ - && (required_system_version == other.required_system_version); - } - - bool operator!=(const ApplicationMetaExtendedHeader& other) const - { - return !operator==(other); - } - }; - - struct PatchMetaExtendedHeader - { - uint64_t application_id; - uint32_t required_system_version; - - void operator=(const PatchMetaExtendedHeader& other) - { - application_id = other.application_id; - required_system_version = other.required_system_version; - } - - bool operator==(const PatchMetaExtendedHeader& other) const - { - return (application_id == other.application_id) \ - && (required_system_version == other.required_system_version); - } - - bool operator!=(const PatchMetaExtendedHeader& other) const - { - return !operator==(other); - } - }; - - struct AddOnContentMetaExtendedHeader - { - uint64_t application_id; - uint32_t required_application_version; - - void operator=(const AddOnContentMetaExtendedHeader& other) - { - application_id = other.application_id; - required_application_version = other.required_application_version; - } - - bool operator==(const AddOnContentMetaExtendedHeader& other) const - { - return (application_id == other.application_id) \ - && (required_application_version == other.required_application_version); - } - - bool operator!=(const AddOnContentMetaExtendedHeader& other) const - { - return !operator==(other); - } - }; - - struct DeltaMetaExtendedHeader - { - uint64_t application_id; - - void operator=(const DeltaMetaExtendedHeader& other) - { - application_id = other.application_id; - } - - bool operator==(const DeltaMetaExtendedHeader& other) const - { - return (application_id == other.application_id); - } - - bool operator!=(const DeltaMetaExtendedHeader& other) const - { - return !operator==(other); - } - }; - - ContentMetaBinary(); - ContentMetaBinary(const ContentMetaBinary& other); - - void operator=(const ContentMetaBinary& other); - bool operator==(const ContentMetaBinary& other) const; - bool operator!=(const ContentMetaBinary& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - uint64_t getTitleId() const; - void setTitleId(uint64_t title_id); - - uint32_t getTitleVersion() const; - void setTitleVersion(uint32_t version); - - cnmt::ContentMetaType getType() const; - void setType(cnmt::ContentMetaType type); - - byte_t getAttributes() const; - void setAttributes(byte_t attributes); - - uint32_t getRequiredDownloadSystemVersion() const; - void setRequiredDownloadSystemVersion(uint32_t version); - - const ApplicationMetaExtendedHeader& getApplicationMetaExtendedHeader() const; - void setApplicationMetaExtendedHeader(const ApplicationMetaExtendedHeader& exhdr); - - const PatchMetaExtendedHeader& getPatchMetaExtendedHeader() const; - void setPatchMetaExtendedHeader(const PatchMetaExtendedHeader& exhdr); - - const AddOnContentMetaExtendedHeader& getAddOnContentMetaExtendedHeader() const; - void setAddOnContentMetaExtendedHeader(const AddOnContentMetaExtendedHeader& exhdr); - - const DeltaMetaExtendedHeader& getDeltaMetaExtendedHeader() const; - void setDeltaMetaExtendedHeader(const DeltaMetaExtendedHeader& exhdr); - - const fnd::List& getContentInfo() const; - void setContentInfo(const fnd::List& info); - - const fnd::List& getContentMetaInfo() const; - void setContentMetaInfo(const fnd::List& info); - - const fnd::Vec& getExtendedData() const; - void setExtendedData(const fnd::Vec& data); - - const nn::hac::sDigest& getDigest() const; - void setDigest(const nn::hac::sDigest& digest); - - - private: - const std::string kModuleName = "CONTENT_META_BINARY"; - - // binary blob - fnd::Vec mRawBinary; - - // variables - uint64_t mTitleId; - uint32_t mTitleVersion; - cnmt::ContentMetaType mType; - byte_t mAttributes; - uint32_t mRequiredDownloadSystemVersion; - fnd::Vec mExtendedHeader; - - ApplicationMetaExtendedHeader mApplicationMetaExtendedHeader; - PatchMetaExtendedHeader mPatchMetaExtendedHeader; - AddOnContentMetaExtendedHeader mAddOnContentMetaExtendedHeader; - DeltaMetaExtendedHeader mDeltaMetaExtendedHeader; - - fnd::List mContentInfo; - fnd::List mContentMetaInfo; - fnd::Vec mExtendedData; - nn::hac::sDigest mDigest; - - inline size_t getExtendedHeaderOffset() const { return sizeof(sContentMetaHeader); } - inline size_t getContentInfoOffset(size_t exhdrSize) const { return getExtendedHeaderOffset() + exhdrSize; } - inline size_t getContentMetaInfoOffset(size_t exhdrSize, size_t contentInfoNum) const { return getContentInfoOffset(exhdrSize) + contentInfoNum * sizeof(sContentInfo); } - inline size_t getExtendedDataOffset(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum) const { return getContentMetaInfoOffset(exhdrSize, contentInfoNum) + contentMetaNum * sizeof(sContentMetaInfo); } - inline size_t getDigestOffset(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum, size_t exdataSize) const { return getExtendedDataOffset(exhdrSize, contentInfoNum, contentMetaNum) + exdataSize; } - inline size_t getTotalSize(size_t exhdrSize, size_t contentInfoNum, size_t contentMetaNum, size_t exdataSize) const { return getDigestOffset(exhdrSize, contentInfoNum, contentMetaNum, exdataSize) + cnmt::kDigestLen; } - - bool validateExtendedHeaderSize(cnmt::ContentMetaType type, size_t exhdrSize) const; - size_t getExtendedDataSize(cnmt::ContentMetaType type, const byte_t* data) const; - void validateBinary(const byte_t* bytes, size_t len) const; - }; -} -} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/ContentMetaInfo.h b/lib/libhac/include/nn/hac/ContentMetaInfo.h new file mode 100644 index 0000000..f6a680e --- /dev/null +++ b/lib/libhac/include/nn/hac/ContentMetaInfo.h @@ -0,0 +1,55 @@ +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class ContentMetaInfo : + public fnd::IByteModel + { + public: + ContentMetaInfo(); + ContentMetaInfo(const ContentMetaInfo& other); + + void operator=(const ContentMetaInfo& other); + bool operator==(const ContentMetaInfo& other) const; + bool operator!=(const ContentMetaInfo& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint64_t getTitleId() const; + void setTitleId(uint64_t title_id); + + uint32_t getTitleVersion() const; + void setTitleVersion(uint32_t ver); + + cnmt::ContentMetaType getContentMetaType() const; + void setContentMetaType(cnmt::ContentMetaType type); + + byte_t getAttributes() const; + void setAttributes(byte_t attr); + + private: + const std::string kModuleName = "CONTENT_META_INFO"; + + // byte model + fnd::Vec mRawBinary; + + // variables + uint64_t mTitleId; + uint32_t mTitleVersion; + cnmt::ContentMetaType mType; + byte_t mAttributes; + }; +} +} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/DeltaMetaExtendedHeader.h b/lib/libhac/include/nn/hac/DeltaMetaExtendedHeader.h new file mode 100644 index 0000000..de12ad5 --- /dev/null +++ b/lib/libhac/include/nn/hac/DeltaMetaExtendedHeader.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class DeltaMetaExtendedHeader : + public fnd::IByteModel + { + public: + DeltaMetaExtendedHeader(); + DeltaMetaExtendedHeader(const DeltaMetaExtendedHeader& other); + + void operator=(const DeltaMetaExtendedHeader& other); + bool operator==(const DeltaMetaExtendedHeader& other) const; + bool operator!=(const DeltaMetaExtendedHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint64_t getApplicationId() const; + void setApplicationId(uint64_t application_id); + + uint32_t getExtendedDataSize() const; + void setExtendedDataSize(uint32_t size); + + private: + const std::string kModuleName = "DELTA_META_EXTENDED_HEADER"; + + // binary blob + fnd::Vec mRawBinary; + + // variables + uint64_t mApplicationId; + uint32_t mExtendedDataSize; + }; +} +} diff --git a/lib/libhac/include/nn/hac/FileSystemAccessControlBinary.h b/lib/libhac/include/nn/hac/FileSystemAccessControl.h similarity index 72% rename from lib/libhac/include/nn/hac/FileSystemAccessControlBinary.h rename to lib/libhac/include/nn/hac/FileSystemAccessControl.h index dbf898a..c39303c 100644 --- a/lib/libhac/include/nn/hac/FileSystemAccessControlBinary.h +++ b/lib/libhac/include/nn/hac/FileSystemAccessControl.h @@ -1,77 +1,78 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class FileSystemAccessControlBinary : public fnd::ISerialisable - { - public: - struct sSaveDataOwnerId - { - nn::hac::fac::SaveDataOwnerIdAccessType access_type; - uint64_t id; - - void operator=(const sSaveDataOwnerId& other) - { - access_type = other.access_type; - id = other.id; - } - - bool operator==(const sSaveDataOwnerId& other) const - { - return (access_type == other.access_type) \ - && (id == other.id); - } - - bool operator!=(const sSaveDataOwnerId& other) const - { - return !(*this == other); - } - }; - - FileSystemAccessControlBinary(); - FileSystemAccessControlBinary(const FileSystemAccessControlBinary& other); - - void operator=(const FileSystemAccessControlBinary& other); - bool operator==(const FileSystemAccessControlBinary& other) const; - bool operator!=(const FileSystemAccessControlBinary& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* data, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - uint32_t getFormatVersion() const; - void setFormatVersion(uint32_t version); - - const fnd::List& getFsaRightsList() const; - void setFsaRightsList(const fnd::List& list); - - const fnd::List& getContentOwnerIdList() const; - void setContentOwnerIdList(const fnd::List& list); - - const fnd::List& getSaveDataOwnerIdList() const; - void setSaveDataOwnerIdList(const fnd::List& list); - private: - const std::string kModuleName = "FILE_SYSTEM_ACCESS_CONTROL_BINARY"; - - // raw data - fnd::Vec mRawBinary; - - // variables - uint32_t mVersion; - fnd::List mFsaRights; - fnd::List mContentOwnerIdList; - fnd::List mSaveDataOwnerIdList; - }; -} +#pragma once +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class FileSystemAccessControl : + public fnd::IByteModel + { + public: + struct sSaveDataOwnerId + { + nn::hac::fac::SaveDataOwnerIdAccessType access_type; + uint64_t id; + + void operator=(const sSaveDataOwnerId& other) + { + access_type = other.access_type; + id = other.id; + } + + bool operator==(const sSaveDataOwnerId& other) const + { + return (access_type == other.access_type) \ + && (id == other.id); + } + + bool operator!=(const sSaveDataOwnerId& other) const + { + return !(*this == other); + } + }; + + FileSystemAccessControl(); + FileSystemAccessControl(const FileSystemAccessControl& other); + + void operator=(const FileSystemAccessControl& other); + bool operator==(const FileSystemAccessControl& other) const; + bool operator!=(const FileSystemAccessControl& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* data, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint32_t getFormatVersion() const; + void setFormatVersion(uint32_t version); + + const fnd::List& getFsaRightsList() const; + void setFsaRightsList(const fnd::List& list); + + const fnd::List& getContentOwnerIdList() const; + void setContentOwnerIdList(const fnd::List& list); + + const fnd::List& getSaveDataOwnerIdList() const; + void setSaveDataOwnerIdList(const fnd::List& list); + private: + const std::string kModuleName = "FILE_SYSTEM_ACCESS_CONTROL"; + + // raw data + fnd::Vec mRawBinary; + + // variables + uint32_t mVersion; + fnd::List mFsaRights; + fnd::List mContentOwnerIdList; + fnd::List mSaveDataOwnerIdList; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/XciHeader.h b/lib/libhac/include/nn/hac/GameCardHeader.h similarity index 85% rename from lib/libhac/include/nn/hac/XciHeader.h rename to lib/libhac/include/nn/hac/GameCardHeader.h index 8ed9d4c..416afa7 100644 --- a/lib/libhac/include/nn/hac/XciHeader.h +++ b/lib/libhac/include/nn/hac/GameCardHeader.h @@ -1,127 +1,127 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class XciHeader : - public fnd::ISerialisable - { - public: - XciHeader(); - XciHeader(const XciHeader& other); - - void operator=(const XciHeader& other); - bool operator==(const XciHeader& other) const; - bool operator!=(const XciHeader& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - uint32_t getRomAreaStartPage() const; - void setRomAreaStartPage(uint32_t startPage); - uint32_t getBackupAreaStartPage() const; - void setBackupAreaStartPage(uint32_t startPage); - byte_t getKekIndex() const; - void setKekIndex(byte_t kekIndex); - byte_t getTitleKeyDecIndex() const; - void setTitleKeyDecIndex(byte_t index); - byte_t getRomSizeType() const; - void setRomSizeType(byte_t romSizeType); - byte_t getCardHeaderVersion() const; - void setCardHeaderVersion(byte_t version); - byte_t getFlags() const; - void setFlags(byte_t flags); - uint64_t getPackageId() const; - void setPackageId(uint64_t id); - uint32_t getValidDataEndPage() const; - void setValidDataEndPage(uint32_t page); - const fnd::aes::sAesIvCtr& getAesCbcIv() const; - void setAesCbcIv(const fnd::aes::sAesIvCtr& iv); - uint64_t getPartitionFsAddress() const; - void setPartitionFsAddress(uint64_t address); - uint64_t getPartitionFsSize() const; - void setPartitionFsSize(uint64_t size); - const fnd::sha::sSha256Hash& getPartitionFsHash() const; - void setPartitionFsHash(const fnd::sha::sSha256Hash& hash); - const fnd::sha::sSha256Hash& getInitialDataHash() const; - void setInitialDataHash(const fnd::sha::sSha256Hash& hash); - uint32_t getSelSec() const; - void setSelSec(uint32_t sel_sec); - uint32_t getSelT1Key() const; - void setSelT1Key(uint32_t sel_t1_key); - uint32_t getSelKey() const; - void setSelKey(uint32_t sel_key); - uint32_t getLimAreaPage() const; - void setLimAreaPage(uint32_t page); - - uint32_t getFwVerMajor() const; - void setFwVerMajor(uint32_t ver); - uint32_t getFwVerMinor() const; - void setFwVerMinor(uint32_t ver); - uint32_t getAccCtrl1() const; - void setAccCtrl1(uint32_t acc_ctrl_1); - uint32_t getWait1TimeRead() const; - void setWait1TimeRead(uint32_t seconds); - uint32_t getWait2TimeRead() const; - void setWait2TimeRead(uint32_t seconds); - uint32_t getWait1TimeWrite() const; - void setWait1TimeWrite(uint32_t seconds); - uint32_t getWait2TimeWrite() const; - void setWait2TimeWrite(uint32_t seconds); - uint32_t getFwMode() const; - void setFwMode(uint32_t fw_mode); - uint32_t getUppVersion() const; - void setUppVersion(uint32_t version); - const byte_t* getUppHash() const; - void setUppHash(const byte_t* hash); - uint64_t getUppId() const; - void setUppId(uint64_t id); - - private: - const std::string kModuleName = "XCI_HEADER"; - - // binary - fnd::Vec mRawBinary; - - // data - uint32_t mRomAreaStartPage; - uint32_t mBackupAreaStartPage; - byte_t mKekIndex; - byte_t mTitleKeyDecIndex; - byte_t mRomSize; - byte_t mCardHeaderVersion; - byte_t mFlags; - uint64_t mPackageId; - uint32_t mValidDataEndPage; - fnd::aes::sAesIvCtr mAesCbcIv; - uint64_t mPartitionFsHeaderAddress; - uint64_t mPartitionFsHeaderSize; - fnd::sha::sSha256Hash mPartitionFsHeaderHash; - fnd::sha::sSha256Hash mInitialDataHash; - uint32_t mSelSec; - uint32_t mSelT1Key; - uint32_t mSelKey; - uint32_t mLimAreaPage; - - // Encrypted Data - uint32_t mFwVersion[2]; - uint32_t mAccCtrl1; - uint32_t mWait1TimeRead; - uint32_t mWait2TimeRead; - uint32_t mWait1TimeWrite; - uint32_t mWait2TimeWrite; - uint32_t mFwMode; - uint32_t mUppVersion; - byte_t mUppHash[8]; - uint64_t mUppId; - }; -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class GameCardHeader : + public fnd::IByteModel + { + public: + GameCardHeader(); + GameCardHeader(const GameCardHeader& other); + + void operator=(const GameCardHeader& other); + bool operator==(const GameCardHeader& other) const; + bool operator!=(const GameCardHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + uint32_t getRomAreaStartPage() const; + void setRomAreaStartPage(uint32_t startPage); + uint32_t getBackupAreaStartPage() const; + void setBackupAreaStartPage(uint32_t startPage); + byte_t getKekIndex() const; + void setKekIndex(byte_t kekIndex); + byte_t getTitleKeyDecIndex() const; + void setTitleKeyDecIndex(byte_t index); + byte_t getRomSizeType() const; + void setRomSizeType(byte_t romSizeType); + byte_t getCardHeaderVersion() const; + void setCardHeaderVersion(byte_t version); + byte_t getFlags() const; + void setFlags(byte_t flags); + uint64_t getPackageId() const; + void setPackageId(uint64_t id); + uint32_t getValidDataEndPage() const; + void setValidDataEndPage(uint32_t page); + const fnd::aes::sAesIvCtr& getAesCbcIv() const; + void setAesCbcIv(const fnd::aes::sAesIvCtr& iv); + uint64_t getPartitionFsAddress() const; + void setPartitionFsAddress(uint64_t address); + uint64_t getPartitionFsSize() const; + void setPartitionFsSize(uint64_t size); + const fnd::sha::sSha256Hash& getPartitionFsHash() const; + void setPartitionFsHash(const fnd::sha::sSha256Hash& hash); + const fnd::sha::sSha256Hash& getInitialDataHash() const; + void setInitialDataHash(const fnd::sha::sSha256Hash& hash); + uint32_t getSelSec() const; + void setSelSec(uint32_t sel_sec); + uint32_t getSelT1Key() const; + void setSelT1Key(uint32_t sel_t1_key); + uint32_t getSelKey() const; + void setSelKey(uint32_t sel_key); + uint32_t getLimAreaPage() const; + void setLimAreaPage(uint32_t page); + + uint32_t getFwVerMajor() const; + void setFwVerMajor(uint32_t ver); + uint32_t getFwVerMinor() const; + void setFwVerMinor(uint32_t ver); + uint32_t getAccCtrl1() const; + void setAccCtrl1(uint32_t acc_ctrl_1); + uint32_t getWait1TimeRead() const; + void setWait1TimeRead(uint32_t seconds); + uint32_t getWait2TimeRead() const; + void setWait2TimeRead(uint32_t seconds); + uint32_t getWait1TimeWrite() const; + void setWait1TimeWrite(uint32_t seconds); + uint32_t getWait2TimeWrite() const; + void setWait2TimeWrite(uint32_t seconds); + uint32_t getFwMode() const; + void setFwMode(uint32_t fw_mode); + uint32_t getUppVersion() const; + void setUppVersion(uint32_t version); + const byte_t* getUppHash() const; + void setUppHash(const byte_t* hash); + uint64_t getUppId() const; + void setUppId(uint64_t id); + + private: + const std::string kModuleName = "GAMECARD_HEADER"; + + // binary + fnd::Vec mRawBinary; + + // data + uint32_t mRomAreaStartPage; + uint32_t mBackupAreaStartPage; + byte_t mKekIndex; + byte_t mTitleKeyDecIndex; + byte_t mRomSize; + byte_t mCardHeaderVersion; + byte_t mFlags; + uint64_t mPackageId; + uint32_t mValidDataEndPage; + fnd::aes::sAesIvCtr mAesCbcIv; + uint64_t mPartitionFsHeaderAddress; + uint64_t mPartitionFsHeaderSize; + fnd::sha::sSha256Hash mPartitionFsHeaderHash; + fnd::sha::sSha256Hash mInitialDataHash; + uint32_t mSelSec; + uint32_t mSelT1Key; + uint32_t mSelKey; + uint32_t mLimAreaPage; + + // Encrypted/Extended Data + uint32_t mFwVersion[2]; + uint32_t mAccCtrl1; + uint32_t mWait1TimeRead; + uint32_t mWait2TimeRead; + uint32_t mWait1TimeWrite; + uint32_t mWait2TimeWrite; + uint32_t mFwMode; + uint32_t mUppVersion; + byte_t mUppHash[8]; + uint64_t mUppId; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/XciUtils.h b/lib/libhac/include/nn/hac/GameCardUtils.h similarity index 62% rename from lib/libhac/include/nn/hac/XciUtils.h rename to lib/libhac/include/nn/hac/GameCardUtils.h index 7ba7eaa..fd6f400 100644 --- a/lib/libhac/include/nn/hac/XciUtils.h +++ b/lib/libhac/include/nn/hac/GameCardUtils.h @@ -1,16 +1,16 @@ -#pragma once -#include - -namespace nn -{ -namespace hac -{ - class XciUtils - { - public: - static inline uint64_t blockToAddr(uint32_t block) { return ((uint64_t)block) << 9; } - static void getXciHeaderAesIv(const nn::hac::sXciHeader* hdr, byte_t* iv); - static void decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key); - }; -} +#pragma once +#include + +namespace nn +{ +namespace hac +{ + class GameCardUtils + { + public: + static inline uint64_t blockToAddr(uint32_t block) { return ((uint64_t)block) << 9; } + static void getXciHeaderAesIv(const nn::hac::sGcHeader* hdr, byte_t* iv); + static void decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key); + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/HierarchicalIntegrityHeader.h b/lib/libhac/include/nn/hac/HierarchicalIntegrityHeader.h index 953b225..5f4d312 100644 --- a/lib/libhac/include/nn/hac/HierarchicalIntegrityHeader.h +++ b/lib/libhac/include/nn/hac/HierarchicalIntegrityHeader.h @@ -1,70 +1,70 @@ -#pragma once -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class HierarchicalIntegrityHeader : - public fnd::ISerialisable - { - public: - struct sLayer - { - size_t offset; - size_t size; - size_t block_size; - - void operator=(const sLayer& other) - { - offset = other.offset; - size = other.size; - block_size = other.block_size; - } - - bool operator==(const sLayer& other) const - { - return (offset == other.offset && size == other.size && block_size == other.block_size); - } - - bool operator!=(const sLayer& other) const - { - return !(*this == other); - } - }; - - HierarchicalIntegrityHeader(); - HierarchicalIntegrityHeader(const HierarchicalIntegrityHeader& other); - - void operator=(const HierarchicalIntegrityHeader& other); - bool operator==(const HierarchicalIntegrityHeader& other) const; - bool operator!=(const HierarchicalIntegrityHeader& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const fnd::List& getLayerInfo() const; - void setLayerInfo(const fnd::List& layer_info); - - const fnd::List& getMasterHashList() const; - void setMasterHashList(const fnd::List& master_hash_list); - private: - const std::string kModuleName = "HIERARCHICAL_INTEGRITY_HEADER"; - - // binary - fnd::Vec mRawBinary; - - // data - fnd::List mLayerInfo; - fnd::List mMasterHashList; - }; -} +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class HierarchicalIntegrityHeader : + public fnd::IByteModel + { + public: + struct sLayer + { + size_t offset; + size_t size; + size_t block_size; + + void operator=(const sLayer& other) + { + offset = other.offset; + size = other.size; + block_size = other.block_size; + } + + bool operator==(const sLayer& other) const + { + return (offset == other.offset && size == other.size && block_size == other.block_size); + } + + bool operator!=(const sLayer& other) const + { + return !(*this == other); + } + }; + + HierarchicalIntegrityHeader(); + HierarchicalIntegrityHeader(const HierarchicalIntegrityHeader& other); + + void operator=(const HierarchicalIntegrityHeader& other); + bool operator==(const HierarchicalIntegrityHeader& other) const; + bool operator!=(const HierarchicalIntegrityHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const fnd::List& getLayerInfo() const; + void setLayerInfo(const fnd::List& layer_info); + + const fnd::List& getMasterHashList() const; + void setMasterHashList(const fnd::List& master_hash_list); + private: + const std::string kModuleName = "HIERARCHICAL_INTEGRITY_HEADER"; + + // binary + fnd::Vec mRawBinary; + + // data + fnd::List mLayerInfo; + fnd::List mMasterHashList; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/HierarchicalSha256Header.h b/lib/libhac/include/nn/hac/HierarchicalSha256Header.h index fe38b87..0ec96ae 100644 --- a/lib/libhac/include/nn/hac/HierarchicalSha256Header.h +++ b/lib/libhac/include/nn/hac/HierarchicalSha256Header.h @@ -1,71 +1,71 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class HierarchicalSha256Header : - public fnd::ISerialisable - { - public: - struct sLayer - { - size_t offset; - size_t size; - - void operator=(const sLayer& other) - { - offset = other.offset; - size = other.size; - } - - bool operator==(const sLayer& other) const - { - return (offset == other.offset && size == other.size); - } - - bool operator!=(const sLayer& other) const - { - return !(*this == other); - } - }; - - HierarchicalSha256Header(); - HierarchicalSha256Header(const HierarchicalSha256Header& other); - - void operator=(const HierarchicalSha256Header& other); - bool operator==(const HierarchicalSha256Header& other) const; - bool operator!=(const HierarchicalSha256Header& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const fnd::sha::sSha256Hash& getMasterHash() const; - void setMasterHash(const fnd::sha::sSha256Hash& master_hash); - - size_t getHashBlockSize() const; - void setHashBlockSize(size_t hash_block_size); - - const fnd::List& getLayerInfo() const; - void setLayerInfo(const fnd::List& layer_info); - private: - const std::string kModuleName = "HIERARCHICAL_SHA256_HEADER"; - - // binary - fnd::Vec mRawBinary; - - // data - fnd::sha::sSha256Hash mMasterHash; - size_t mHashBlockSize; - fnd::List mLayerInfo; - }; -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class HierarchicalSha256Header : + public fnd::IByteModel + { + public: + struct sLayer + { + size_t offset; + size_t size; + + void operator=(const sLayer& other) + { + offset = other.offset; + size = other.size; + } + + bool operator==(const sLayer& other) const + { + return (offset == other.offset && size == other.size); + } + + bool operator!=(const sLayer& other) const + { + return !(*this == other); + } + }; + + HierarchicalSha256Header(); + HierarchicalSha256Header(const HierarchicalSha256Header& other); + + void operator=(const HierarchicalSha256Header& other); + bool operator==(const HierarchicalSha256Header& other) const; + bool operator!=(const HierarchicalSha256Header& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const fnd::sha::sSha256Hash& getMasterHash() const; + void setMasterHash(const fnd::sha::sSha256Hash& master_hash); + + size_t getHashBlockSize() const; + void setHashBlockSize(size_t hash_block_size); + + const fnd::List& getLayerInfo() const; + void setLayerInfo(const fnd::List& layer_info); + private: + const std::string kModuleName = "HIERARCHICAL_SHA256_HEADER"; + + // binary + fnd::Vec mRawBinary; + + // data + fnd::sha::sSha256Hash mMasterHash; + size_t mHashBlockSize; + fnd::List mLayerInfo; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/KernelCapabilityBinary.h b/lib/libhac/include/nn/hac/KernelCapabilityControl.h similarity index 76% rename from lib/libhac/include/nn/hac/KernelCapabilityBinary.h rename to lib/libhac/include/nn/hac/KernelCapabilityControl.h index 72869c3..475c2c2 100644 --- a/lib/libhac/include/nn/hac/KernelCapabilityBinary.h +++ b/lib/libhac/include/nn/hac/KernelCapabilityControl.h @@ -1,78 +1,78 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class KernelCapabilityBinary : - public fnd::ISerialisable - { - public: - KernelCapabilityBinary(); - KernelCapabilityBinary(const KernelCapabilityBinary& other); - - void operator=(const KernelCapabilityBinary& other); - bool operator==(const KernelCapabilityBinary& other) const; - bool operator!=(const KernelCapabilityBinary& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - virtual const fnd::Vec& getBytes() const; - - // variables (consider further abstraction?) - void clear(); - const ThreadInfoHandler& getThreadInfo() const; - ThreadInfoHandler& getThreadInfo(); - - const SystemCallHandler& getSystemCalls() const; - SystemCallHandler& getSystemCalls(); - - const MemoryMappingHandler& getMemoryMaps() const; - MemoryMappingHandler& getMemoryMaps(); - - const InteruptHandler& getInterupts() const; - InteruptHandler& getInterupts(); - - const MiscParamsHandler& getMiscParams() const; - MiscParamsHandler& getMiscParams(); - - const KernelVersionHandler& getKernelVersion() const; - KernelVersionHandler& getKernelVersion(); - - const HandleTableSizeHandler& getHandleTableSize() const; - HandleTableSizeHandler& getHandleTableSize(); - - const MiscFlagsHandler& getMiscFlags() const; - MiscFlagsHandler& getMiscFlags(); - - private: - const std::string kModuleName = "KC_BINARY"; - - // raw binary - fnd::Vec mRawBinary; - - // variables - ThreadInfoHandler mThreadInfo; - SystemCallHandler mSystemCalls; - MemoryMappingHandler mMemoryMap; - InteruptHandler mInterupts; - MiscParamsHandler mMiscParams; - KernelVersionHandler mKernelVersion; - HandleTableSizeHandler mHandleTableSize; - MiscFlagsHandler mMiscFlags; - }; -} +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class KernelCapabilityControl : + public fnd::IByteModel + { + public: + KernelCapabilityControl(); + KernelCapabilityControl(const KernelCapabilityControl& other); + + void operator=(const KernelCapabilityControl& other); + bool operator==(const KernelCapabilityControl& other) const; + bool operator!=(const KernelCapabilityControl& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + virtual const fnd::Vec& getBytes() const; + + // variables (consider further abstraction?) + void clear(); + const ThreadInfoHandler& getThreadInfo() const; + ThreadInfoHandler& getThreadInfo(); + + const SystemCallHandler& getSystemCalls() const; + SystemCallHandler& getSystemCalls(); + + const MemoryMappingHandler& getMemoryMaps() const; + MemoryMappingHandler& getMemoryMaps(); + + const InteruptHandler& getInterupts() const; + InteruptHandler& getInterupts(); + + const MiscParamsHandler& getMiscParams() const; + MiscParamsHandler& getMiscParams(); + + const KernelVersionHandler& getKernelVersion() const; + KernelVersionHandler& getKernelVersion(); + + const HandleTableSizeHandler& getHandleTableSize() const; + HandleTableSizeHandler& getHandleTableSize(); + + const MiscFlagsHandler& getMiscFlags() const; + MiscFlagsHandler& getMiscFlags(); + + private: + const std::string kModuleName = "KERNEL_CAPABILITY_CONTROL"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + ThreadInfoHandler mThreadInfo; + SystemCallHandler mSystemCalls; + MemoryMappingHandler mMemoryMap; + InteruptHandler mInterupts; + MiscParamsHandler mMiscParams; + KernelVersionHandler mKernelVersion; + HandleTableSizeHandler mHandleTableSize; + MiscFlagsHandler mMiscFlags; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/KernelCapabilityEntry.h b/lib/libhac/include/nn/hac/KernelCapabilityEntry.h index e8711e3..1a5f3cc 100644 --- a/lib/libhac/include/nn/hac/KernelCapabilityEntry.h +++ b/lib/libhac/include/nn/hac/KernelCapabilityEntry.h @@ -1,52 +1,52 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - class KernelCapabilityEntry - { - public: - - KernelCapabilityEntry(); - KernelCapabilityEntry(kc::KernelCapId type); - KernelCapabilityEntry(kc::KernelCapId type, uint32_t field); - - void operator=(const KernelCapabilityEntry& other); - bool operator==(const KernelCapabilityEntry& other) const; - bool operator!=(const KernelCapabilityEntry& other) const; - - uint32_t getCap() const; - void setCap(uint32_t cap); - - kc::KernelCapId getType() const; - void setType(kc::KernelCapId type); - - uint32_t getField() const; - void setField(uint32_t field); - - private: - kc::KernelCapId mType; - uint32_t mField; - - inline uint32_t getFieldShift() const { return mType + 1; } - inline uint32_t getFieldMask() const { return BIT(31 - mType) - 1; } - inline uint32_t getCapMask() const { return BIT(mType) - 1; } - inline kc::KernelCapId getCapId(uint32_t cap) const - { - kc::KernelCapId id = kc::KC_INVALID; - for (byte_t tmp = 0; tmp < 31; tmp++) - { - if (((cap >> tmp) & 1) == 0) - { - id = (kc::KernelCapId)tmp; - break; - } - } - return id; - } - }; -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + class KernelCapabilityEntry + { + public: + + KernelCapabilityEntry(); + KernelCapabilityEntry(kc::KernelCapId type); + KernelCapabilityEntry(kc::KernelCapId type, uint32_t field); + + void operator=(const KernelCapabilityEntry& other); + bool operator==(const KernelCapabilityEntry& other) const; + bool operator!=(const KernelCapabilityEntry& other) const; + + uint32_t getCap() const; + void setCap(uint32_t cap); + + kc::KernelCapId getType() const; + void setType(kc::KernelCapId type); + + uint32_t getField() const; + void setField(uint32_t field); + + private: + kc::KernelCapId mType; + uint32_t mField; + + inline uint32_t getFieldShift() const { return mType + 1; } + inline uint32_t getFieldMask() const { return BIT(31 - mType) - 1; } + inline uint32_t getCapMask() const { return BIT(mType) - 1; } + inline kc::KernelCapId getCapId(uint32_t cap) const + { + kc::KernelCapId id = kc::KC_INVALID; + for (byte_t tmp = 0; tmp < 31; tmp++) + { + if (((cap >> tmp) & 1) == 0) + { + id = (kc::KernelCapId)tmp; + break; + } + } + return id; + } + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/MetaBinary.h b/lib/libhac/include/nn/hac/Meta.h similarity index 63% rename from lib/libhac/include/nn/hac/MetaBinary.h rename to lib/libhac/include/nn/hac/Meta.h index 4f981da..40a6905 100644 --- a/lib/libhac/include/nn/hac/MetaBinary.h +++ b/lib/libhac/include/nn/hac/Meta.h @@ -1,80 +1,80 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class MetaBinary : - public fnd::ISerialisable - { - public: - MetaBinary(); - MetaBinary(const MetaBinary& other); - - void operator=(const MetaBinary& other); - bool operator==(const MetaBinary& other) const; - bool operator!=(const MetaBinary& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - meta::InstructionType getInstructionType() const; - void setInstructionType(meta::InstructionType type); - - meta::ProcAddrSpaceType getProcAddressSpaceType() const; - void setProcAddressSpaceType(meta::ProcAddrSpaceType type); - - byte_t getMainThreadPriority() const; - void setMainThreadPriority(byte_t priority); - - byte_t getMainThreadCpuId() const; - void setMainThreadCpuId(byte_t cpu_id); - - uint32_t getVersion() const; - void setVersion(uint32_t version); - - uint32_t getMainThreadStackSize() const; - void setMainThreadStackSize(uint32_t size); - - const std::string& getName() const; - void setName(const std::string& name); - - const std::string& getProductCode() const; - void setProductCode(const std::string& product_code); - - const AccessControlInfoBinary& getAci() const; - void setAci(const AccessControlInfoBinary& aci); - - const AccessControlInfoDescBinary& getAcid() const; - void setAcid(const AccessControlInfoDescBinary& acid); - private: - const std::string kModuleName = "META_BINARY"; - - // raw binary - fnd::Vec mRawBinary; - - // variables - meta::InstructionType mInstructionType; - meta::ProcAddrSpaceType mProcAddressSpaceType; - byte_t mMainThreadPriority; - byte_t mMainThreadCpuId; - uint32_t mVersion; - uint32_t mMainThreadStackSize; - std::string mName; - std::string mProductCode; - AccessControlInfoBinary mAci; - AccessControlInfoDescBinary mAcid; - }; -} -} \ No newline at end of file +#pragma once +#include +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class Meta : + public fnd::IByteModel + { + public: + Meta(); + Meta(const Meta& other); + + void operator=(const Meta& other); + bool operator==(const Meta& other) const; + bool operator!=(const Meta& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + meta::InstructionType getInstructionType() const; + void setInstructionType(meta::InstructionType type); + + meta::ProcAddrSpaceType getProcAddressSpaceType() const; + void setProcAddressSpaceType(meta::ProcAddrSpaceType type); + + byte_t getMainThreadPriority() const; + void setMainThreadPriority(byte_t priority); + + byte_t getMainThreadCpuId() const; + void setMainThreadCpuId(byte_t cpu_id); + + uint32_t getVersion() const; + void setVersion(uint32_t version); + + uint32_t getMainThreadStackSize() const; + void setMainThreadStackSize(uint32_t size); + + const std::string& getName() const; + void setName(const std::string& name); + + const std::string& getProductCode() const; + void setProductCode(const std::string& product_code); + + const AccessControlInfo& getAci() const; + void setAci(const AccessControlInfo& aci); + + const AccessControlInfoDesc& getAcid() const; + void setAcid(const AccessControlInfoDesc& acid); + private: + const std::string kModuleName = "META"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + meta::InstructionType mInstructionType; + meta::ProcAddrSpaceType mProcAddressSpaceType; + byte_t mMainThreadPriority; + byte_t mMainThreadCpuId; + uint32_t mVersion; + uint32_t mMainThreadStackSize; + std::string mName; + std::string mProductCode; + AccessControlInfo mAci; + AccessControlInfoDesc mAcid; + }; +} +} diff --git a/lib/libhac/include/nn/hac/NcaHeader.h b/lib/libhac/include/nn/hac/NcaHeader.h deleted file mode 100644 index 0ddbe76..0000000 --- a/lib/libhac/include/nn/hac/NcaHeader.h +++ /dev/null @@ -1,115 +0,0 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class NcaHeader : - public fnd::ISerialisable - { - public: - enum FormatVersion - { - NCA2_FORMAT, - NCA3_FORMAT - }; - - struct sPartition - { - byte_t index; - uint64_t offset; - uint64_t size; - fnd::sha::sSha256Hash hash; - - const sPartition& operator=(const sPartition& other) - { - index = other.index; - offset = other.offset; - size = other.size; - hash = other.hash; - - return *this; - } - - bool operator==(const sPartition& other) const - { - return (index == other.index) \ - && (offset == other.offset) \ - && (size == other.size) \ - && (hash == other.hash); - } - - bool operator!=(const sPartition& other) const - { - return !operator==(other); - } - }; - - NcaHeader(); - NcaHeader(const NcaHeader& other); - - void operator=(const NcaHeader& other); - bool operator==(const NcaHeader& other) const; - bool operator!=(const NcaHeader& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - FormatVersion getFormatVersion() const; - void setFormatVersion(FormatVersion ver); - nca::DistributionType getDistributionType() const; - void setDistributionType(nca::DistributionType type); - nca::ContentType getContentType() const; - void setContentType(nca::ContentType type); - byte_t getKeyGeneration() const; - void setKeyGeneration(byte_t gen); - byte_t getKaekIndex() const; - void setKaekIndex(byte_t index); - uint64_t getContentSize() const; - void setContentSize(uint64_t size); - uint64_t getProgramId() const; - void setProgramId(uint64_t program_id); - uint32_t getContentIndex() const; - void setContentIndex(uint32_t index); - uint32_t getSdkAddonVersion() const; - void setSdkAddonVersion(uint32_t version); - bool hasRightsId() const; - const byte_t* getRightsId() const; - void setRightsId(const byte_t* rights_id); - const fnd::List& getPartitions() const; - void setPartitions(const fnd::List& partitions); - const fnd::List& getEncAesKeys() const; - void setEncAesKeys(const fnd::List& keys); - - private: - const std::string kModuleName = "NCA_HEADER"; - - // binary - fnd::Vec mRawBinary; - - // data - FormatVersion mFormatVersion; - nca::DistributionType mDistributionType; - nca::ContentType mContentType; - byte_t mKeyGeneration; - byte_t mKaekIndex; - uint64_t mContentSize; - uint64_t mProgramId; - uint32_t mContentIndex; - uint32_t mSdkAddonVersion; - byte_t mRightsId[nca::kRightsIdLen]; - fnd::List mPartitions; - fnd::List mEncAesKeys; - - uint64_t blockNumToSize(uint32_t block_num) const; - uint32_t sizeToBlockNum(uint64_t real_size) const; - }; -} -} \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/NroHeader.h b/lib/libhac/include/nn/hac/NroHeader.h index 7bd33dd..9f8fff1 100644 --- a/lib/libhac/include/nn/hac/NroHeader.h +++ b/lib/libhac/include/nn/hac/NroHeader.h @@ -1,141 +1,141 @@ -#pragma once -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class NroHeader : - public fnd::ISerialisable - { - public: - struct sRoCrt - { - byte_t data[nro::kRoCrtSize]; - - void operator=(const sRoCrt& other) - { - memcpy(data, other.data, nro::kRoCrtSize); - } - - bool operator==(const sRoCrt& other) const - { - return memcmp(data, other.data, nro::kRoCrtSize) == 0; - } - - bool operator!=(const sRoCrt& other) const - { - return !(*this == other); - } - }; - - struct sModuleId - { - byte_t data[nro::kModuleIdSize]; - - void operator=(const sModuleId& other) - { - memcpy(data, other.data, nro::kModuleIdSize); - } - - bool operator==(const sModuleId& other) const - { - return memcmp(data, other.data, nro::kModuleIdSize) == 0; - } - - bool operator!=(const sModuleId& other) const - { - return !(*this == other); - } - }; - - struct sSection - { - uint32_t memory_offset; - uint32_t size; - - void operator=(const sSection& other) - { - memory_offset = other.memory_offset; - size = other.size; - } - - bool operator==(const sSection& other) const - { - return (memory_offset == other.memory_offset) \ - && (size == other.size); - } - - bool operator!=(const sSection& other) const - { - return !(*this == other); - } - }; - - NroHeader(); - NroHeader(const NroHeader& other); - - void operator=(const NroHeader& other); - bool operator==(const NroHeader& other) const; - bool operator!=(const NroHeader& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const sRoCrt& getRoCrt() const; - void setRoCrt(const sRoCrt& ro_crt); - - uint32_t getNroSize() const; - void setNroSize(uint32_t size); - - const sSection& getTextInfo() const; - void setTextInfo(const sSection& info); - - const sSection& getRoInfo() const; - void setRoInfo(const sSection& info); - - const sSection& getDataInfo() const; - void setDataInfo(const sSection& info); - - uint32_t getBssSize() const; - void setBssSize(uint32_t size); - - const sModuleId& getModuleId() const; - void setModuleId(const sModuleId& id); - - const sSection& getRoEmbeddedInfo() const; - void setRoEmbeddedInfo(const sSection& info); - - const sSection& getRoDynStrInfo() const; - void setRoDynStrInfo(const sSection& info); - - const sSection& getRoDynSymInfo() const; - void setRoDynSymInfo(const sSection& info); - private: - const std::string kModuleName = "NRO_HEADER"; - - // binary - fnd::Vec mRawBinary; - - // data - sRoCrt mRoCrt; - uint32_t mNroSize; - sSection mTextInfo; - sSection mRoInfo; - sSection mDataInfo; - uint32_t mBssSize; - sModuleId mModuleId; - sSection mRoEmbeddedInfo; - sSection mRoDynStrInfo; - sSection mRoDynSymInfo; - }; -} +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class NroHeader : + public fnd::IByteModel + { + public: + struct sRoCrt + { + byte_t data[nro::kRoCrtSize]; + + void operator=(const sRoCrt& other) + { + memcpy(data, other.data, nro::kRoCrtSize); + } + + bool operator==(const sRoCrt& other) const + { + return memcmp(data, other.data, nro::kRoCrtSize) == 0; + } + + bool operator!=(const sRoCrt& other) const + { + return !(*this == other); + } + }; + + struct sModuleId + { + byte_t data[nro::kModuleIdSize]; + + void operator=(const sModuleId& other) + { + memcpy(data, other.data, nro::kModuleIdSize); + } + + bool operator==(const sModuleId& other) const + { + return memcmp(data, other.data, nro::kModuleIdSize) == 0; + } + + bool operator!=(const sModuleId& other) const + { + return !(*this == other); + } + }; + + struct sSection + { + uint32_t memory_offset; + uint32_t size; + + void operator=(const sSection& other) + { + memory_offset = other.memory_offset; + size = other.size; + } + + bool operator==(const sSection& other) const + { + return (memory_offset == other.memory_offset) \ + && (size == other.size); + } + + bool operator!=(const sSection& other) const + { + return !(*this == other); + } + }; + + NroHeader(); + NroHeader(const NroHeader& other); + + void operator=(const NroHeader& other); + bool operator==(const NroHeader& other) const; + bool operator!=(const NroHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const sRoCrt& getRoCrt() const; + void setRoCrt(const sRoCrt& ro_crt); + + uint32_t getNroSize() const; + void setNroSize(uint32_t size); + + const sSection& getTextInfo() const; + void setTextInfo(const sSection& info); + + const sSection& getRoInfo() const; + void setRoInfo(const sSection& info); + + const sSection& getDataInfo() const; + void setDataInfo(const sSection& info); + + uint32_t getBssSize() const; + void setBssSize(uint32_t size); + + const sModuleId& getModuleId() const; + void setModuleId(const sModuleId& id); + + const sSection& getRoEmbeddedInfo() const; + void setRoEmbeddedInfo(const sSection& info); + + const sSection& getRoDynStrInfo() const; + void setRoDynStrInfo(const sSection& info); + + const sSection& getRoDynSymInfo() const; + void setRoDynSymInfo(const sSection& info); + private: + const std::string kModuleName = "NRO_HEADER"; + + // binary + fnd::Vec mRawBinary; + + // data + sRoCrt mRoCrt; + uint32_t mNroSize; + sSection mTextInfo; + sSection mRoInfo; + sSection mDataInfo; + uint32_t mBssSize; + sModuleId mModuleId; + sSection mRoEmbeddedInfo; + sSection mRoDynStrInfo; + sSection mRoDynSymInfo; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/NsoHeader.h b/lib/libhac/include/nn/hac/NsoHeader.h index 8fb1c6b..5fc4706 100644 --- a/lib/libhac/include/nn/hac/NsoHeader.h +++ b/lib/libhac/include/nn/hac/NsoHeader.h @@ -1,149 +1,149 @@ -#pragma once -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class NsoHeader : - public fnd::ISerialisable - { - public: - struct sModuleId - { - byte_t data[nso::kModuleIdSize]; - - void operator=(const sModuleId& other) - { - memcpy(data, other.data, nso::kModuleIdSize); - } - - bool operator==(const sModuleId& other) const - { - return memcmp(data, other.data, nso::kModuleIdSize) == 0; - } - - bool operator!=(const sModuleId& other) const - { - return !(*this == other); - } - }; - - struct sLayout - { - uint32_t offset; - uint32_t size; - - void operator=(const sLayout& other) - { - offset = other.offset; - size = other.size; - } - - bool operator==(const sLayout& other) const - { - return (offset == other.offset) \ - && (size == other.size); - } - - bool operator!=(const sLayout& other) const - { - return !(*this == other); - } - }; - - struct sCodeSegment - { - sLayout file_layout; - sLayout memory_layout; - bool is_compressed; - bool is_hashed; - fnd::sha::sSha256Hash hash; - - void operator=(const sCodeSegment& other) - { - file_layout = other.file_layout; - memory_layout = other.memory_layout; - is_compressed = other.is_compressed; - is_hashed = other.is_hashed; - hash = other.hash; - } - - bool operator==(const sCodeSegment& other) const - { - return (file_layout == other.file_layout) \ - && (memory_layout == other.memory_layout) \ - && (is_compressed == other.is_compressed) \ - && (is_hashed == other.is_hashed) \ - && (hash == other.hash); - } - - bool operator!=(const sCodeSegment& other) const - { - return !(*this == other); - } - }; - - NsoHeader(); - NsoHeader(const NsoHeader& other); - - void operator=(const NsoHeader& other); - bool operator==(const NsoHeader& other) const; - bool operator!=(const NsoHeader& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const sModuleId& getModuleId() const; - void setModuleId(const sModuleId& id); - - uint32_t getBssSize() const; - void setBssSize(uint32_t size); - - const sCodeSegment& getTextSegmentInfo() const; - void setTextSegmentInfo(const sCodeSegment& info); - - const sCodeSegment& getRoSegmentInfo() const; - void setRoSegmentInfo(const sCodeSegment& info); - - const sCodeSegment& getDataSegmentInfo() const; - void setDataSegmentInfo(const sCodeSegment& info); - - const sLayout& getModuleNameInfo() const; - void setModuleNameInfo(const sLayout& info); - - const sLayout& getRoEmbeddedInfo() const; - void setRoEmbeddedInfo(const sLayout& info); - - const sLayout& getRoDynStrInfo() const; - void setRoDynStrInfo(const sLayout& info); - - const sLayout& getRoDynSymInfo() const; - void setRoDynSymInfo(const sLayout& info); - private: - const std::string kModuleName = "NSO_HEADER"; - - // binary - fnd::Vec mRawBinary; - - // data - sModuleId mModuleId; - uint32_t mBssSize; - sCodeSegment mTextSegmentInfo; - sCodeSegment mRoSegmentInfo; - sCodeSegment mDataSegmentInfo; - sLayout mModuleNameInfo; - sLayout mRoEmbeddedInfo; - sLayout mRoDynStrInfo; - sLayout mRoDynSymInfo; - }; -} +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class NsoHeader : + public fnd::IByteModel + { + public: + struct sModuleId + { + byte_t data[nso::kModuleIdSize]; + + void operator=(const sModuleId& other) + { + memcpy(data, other.data, nso::kModuleIdSize); + } + + bool operator==(const sModuleId& other) const + { + return memcmp(data, other.data, nso::kModuleIdSize) == 0; + } + + bool operator!=(const sModuleId& other) const + { + return !(*this == other); + } + }; + + struct sLayout + { + uint32_t offset; + uint32_t size; + + void operator=(const sLayout& other) + { + offset = other.offset; + size = other.size; + } + + bool operator==(const sLayout& other) const + { + return (offset == other.offset) \ + && (size == other.size); + } + + bool operator!=(const sLayout& other) const + { + return !(*this == other); + } + }; + + struct sCodeSegment + { + sLayout file_layout; + sLayout memory_layout; + bool is_compressed; + bool is_hashed; + fnd::sha::sSha256Hash hash; + + void operator=(const sCodeSegment& other) + { + file_layout = other.file_layout; + memory_layout = other.memory_layout; + is_compressed = other.is_compressed; + is_hashed = other.is_hashed; + hash = other.hash; + } + + bool operator==(const sCodeSegment& other) const + { + return (file_layout == other.file_layout) \ + && (memory_layout == other.memory_layout) \ + && (is_compressed == other.is_compressed) \ + && (is_hashed == other.is_hashed) \ + && (hash == other.hash); + } + + bool operator!=(const sCodeSegment& other) const + { + return !(*this == other); + } + }; + + NsoHeader(); + NsoHeader(const NsoHeader& other); + + void operator=(const NsoHeader& other); + bool operator==(const NsoHeader& other) const; + bool operator!=(const NsoHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const sModuleId& getModuleId() const; + void setModuleId(const sModuleId& id); + + uint32_t getBssSize() const; + void setBssSize(uint32_t size); + + const sCodeSegment& getTextSegmentInfo() const; + void setTextSegmentInfo(const sCodeSegment& info); + + const sCodeSegment& getRoSegmentInfo() const; + void setRoSegmentInfo(const sCodeSegment& info); + + const sCodeSegment& getDataSegmentInfo() const; + void setDataSegmentInfo(const sCodeSegment& info); + + const sLayout& getModuleNameInfo() const; + void setModuleNameInfo(const sLayout& info); + + const sLayout& getRoEmbeddedInfo() const; + void setRoEmbeddedInfo(const sLayout& info); + + const sLayout& getRoDynStrInfo() const; + void setRoDynStrInfo(const sLayout& info); + + const sLayout& getRoDynSymInfo() const; + void setRoDynSymInfo(const sLayout& info); + private: + const std::string kModuleName = "NSO_HEADER"; + + // binary + fnd::Vec mRawBinary; + + // data + sModuleId mModuleId; + uint32_t mBssSize; + sCodeSegment mTextSegmentInfo; + sCodeSegment mRoSegmentInfo; + sCodeSegment mDataSegmentInfo; + sLayout mModuleNameInfo; + sLayout mRoEmbeddedInfo; + sLayout mRoDynStrInfo; + sLayout mRoDynSymInfo; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/PfsHeader.h b/lib/libhac/include/nn/hac/PartitionFsHeader.h similarity index 76% rename from lib/libhac/include/nn/hac/PfsHeader.h rename to lib/libhac/include/nn/hac/PartitionFsHeader.h index 828e218..7c33f6d 100644 --- a/lib/libhac/include/nn/hac/PfsHeader.h +++ b/lib/libhac/include/nn/hac/PartitionFsHeader.h @@ -1,100 +1,100 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class PfsHeader : - public fnd::ISerialisable - { - public: - enum FsType - { - TYPE_PFS0, - TYPE_HFS0 - }; - - struct sFile - { - std::string name; - size_t offset; - size_t size; - size_t hash_protected_size; - fnd::sha::sSha256Hash hash; - - sFile& operator=(const sFile& other) - { - name = other.name; - offset = other.offset; - size = other.size; - hash_protected_size = other.hash_protected_size; - hash = other.hash; - return *this; - } - - bool operator==(const sFile& other) const - { - return (name == other.name) \ - && (offset == other.offset) \ - && (size == other.size) \ - && (hash_protected_size == other.hash_protected_size) \ - && (hash == other.hash); - } - - bool operator!=(const sFile& other) const - { - return !operator==(other); - } - - bool operator==(const std::string& other) const - { - return (name == other); - } - - bool operator!=(const std::string& other) const - { - return !operator==(other); - } - }; - - PfsHeader(); - PfsHeader(const PfsHeader& other); - - void operator=(const PfsHeader& other); - bool operator==(const PfsHeader& other) const; - bool operator!=(const PfsHeader& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - FsType getFsType() const; - void setFsType(FsType type); - const fnd::List& getFileList() const; - void addFile(const std::string& name, size_t size); - void addFile(const std::string& name, size_t size, size_t hash_protected_size, const fnd::sha::sSha256Hash& hash); - - private: - const std::string kModuleName = "PFS_HEADER"; - - // binary blob - fnd::Vec mRawBinary; - - // variables - FsType mFsType; - fnd::List mFileList; - - size_t getFileEntrySize(FsType fs_type); - void calculateOffsets(size_t data_offset); - }; -} +#pragma once +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class PartitionFsHeader : + public fnd::IByteModel + { + public: + enum FsType + { + TYPE_PFS0, + TYPE_HFS0 + }; + + struct sFile + { + std::string name; + size_t offset; + size_t size; + size_t hash_protected_size; + fnd::sha::sSha256Hash hash; + + sFile& operator=(const sFile& other) + { + name = other.name; + offset = other.offset; + size = other.size; + hash_protected_size = other.hash_protected_size; + hash = other.hash; + return *this; + } + + bool operator==(const sFile& other) const + { + return (name == other.name) \ + && (offset == other.offset) \ + && (size == other.size) \ + && (hash_protected_size == other.hash_protected_size) \ + && (hash == other.hash); + } + + bool operator!=(const sFile& other) const + { + return !operator==(other); + } + + bool operator==(const std::string& other) const + { + return (name == other); + } + + bool operator!=(const std::string& other) const + { + return !operator==(other); + } + }; + + PartitionFsHeader(); + PartitionFsHeader(const PartitionFsHeader& other); + + void operator=(const PartitionFsHeader& other); + bool operator==(const PartitionFsHeader& other) const; + bool operator!=(const PartitionFsHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + FsType getFsType() const; + void setFsType(FsType type); + const fnd::List& getFileList() const; + void addFile(const std::string& name, size_t size); + void addFile(const std::string& name, size_t size, size_t hash_protected_size, const fnd::sha::sSha256Hash& hash); + + private: + const std::string kModuleName = "PARTITIONFS_HEADER"; + + // binary blob + fnd::Vec mRawBinary; + + // variables + FsType mFsType; + fnd::List mFileList; + + size_t getFileEntrySize(FsType fs_type); + void calculateOffsets(size_t data_offset); + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/PatchMetaExtendedHeader.h b/lib/libhac/include/nn/hac/PatchMetaExtendedHeader.h new file mode 100644 index 0000000..da1aa9b --- /dev/null +++ b/lib/libhac/include/nn/hac/PatchMetaExtendedHeader.h @@ -0,0 +1,51 @@ +#pragma once +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class PatchMetaExtendedHeader : + public fnd::IByteModel + { + public: + PatchMetaExtendedHeader(); + PatchMetaExtendedHeader(const PatchMetaExtendedHeader& other); + + void operator=(const PatchMetaExtendedHeader& other); + bool operator==(const PatchMetaExtendedHeader& other) const; + bool operator!=(const PatchMetaExtendedHeader& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + uint64_t getApplicationId() const; + void setApplicationId(uint64_t application_id); + + uint32_t getRequiredSystemVersion() const; + void setRequiredSystemVersion(uint32_t sys_ver); + + uint32_t getExtendedDataSize() const; + void setExtendedDataSize(uint32_t size); + + private: + const std::string kModuleName = "PATCH_META_EXTENDED_HEADER"; + + // binary blob + fnd::Vec mRawBinary; + + // variables + uint64_t mApplicationId; + uint32_t mRequiredSystemVersion; + uint32_t mExtendedDataSize; + }; +} +} diff --git a/lib/libhac/include/nn/hac/ServiceAccessControl.h b/lib/libhac/include/nn/hac/ServiceAccessControl.h new file mode 100644 index 0000000..e808276 --- /dev/null +++ b/lib/libhac/include/nn/hac/ServiceAccessControl.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class ServiceAccessControl : + public fnd::IByteModel + { + public: + ServiceAccessControl(); + ServiceAccessControl(const ServiceAccessControl& other); + + void operator=(const ServiceAccessControl& other); + bool operator==(const ServiceAccessControl& other) const; + bool operator!=(const ServiceAccessControl& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + const fnd::List& getServiceList() const; + void setServiceList(const fnd::List& list); + private: + const std::string kModuleName = "SERVICE_ACCESS_CONTROL"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + fnd::List mServices; + }; +} +} diff --git a/lib/libhac/include/nn/hac/ServiceAccessControlBinary.h b/lib/libhac/include/nn/hac/ServiceAccessControlBinary.h deleted file mode 100644 index 8c63d9c..0000000 --- a/lib/libhac/include/nn/hac/ServiceAccessControlBinary.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class ServiceAccessControlBinary : - public fnd::ISerialisable - { - public: - ServiceAccessControlBinary(); - ServiceAccessControlBinary(const ServiceAccessControlBinary& other); - - void operator=(const ServiceAccessControlBinary& other); - bool operator==(const ServiceAccessControlBinary& other) const; - bool operator!=(const ServiceAccessControlBinary& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - const fnd::List& getServiceList() const; - void addService(const ServiceAccessControlEntry& service); - private: - const std::string kModuleName = "SERVICE_ACCESS_CONTROL_BINARY"; - - // raw binary - fnd::Vec mRawBinary; - - // variables - fnd::List mServices; - }; -} -} diff --git a/lib/libhac/include/nn/hac/ServiceAccessControlEntry.h b/lib/libhac/include/nn/hac/ServiceAccessControlEntry.h index 72fd1be..441682e 100644 --- a/lib/libhac/include/nn/hac/ServiceAccessControlEntry.h +++ b/lib/libhac/include/nn/hac/ServiceAccessControlEntry.h @@ -1,51 +1,51 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - class ServiceAccessControlEntry : - public fnd::ISerialisable - { - public: - ServiceAccessControlEntry(); - ServiceAccessControlEntry(const std::string& name, bool isServer); - ServiceAccessControlEntry(const ServiceAccessControlEntry& other); - - void operator=(const ServiceAccessControlEntry& other); - bool operator==(const ServiceAccessControlEntry& other) const; - bool operator!=(const ServiceAccessControlEntry& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* bytes, size_t len); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - bool isServer() const; - void setIsServer(bool isServer); - const std::string& getName() const; - void setName(const std::string& name); - private: - const std::string kModuleName = "SERVICE_ACCESS_CONTROL_ENTRY"; - static const size_t kMaxServiceNameLen = 8; - - enum ServiceAccessControlEntryFlag - { - SAC_IS_SERVER = _BIT(7), - SAC_NAME_LEN_MASK = _BIT(7) - 1 - }; - - // raw binary - fnd::Vec mRawBinary; - - // variables - bool mIsServer; - std::string mName; - }; -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + class ServiceAccessControlEntry : + public fnd::IByteModel + { + public: + ServiceAccessControlEntry(); + ServiceAccessControlEntry(const std::string& name, bool isServer); + ServiceAccessControlEntry(const ServiceAccessControlEntry& other); + + void operator=(const ServiceAccessControlEntry& other); + bool operator==(const ServiceAccessControlEntry& other) const; + bool operator!=(const ServiceAccessControlEntry& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* bytes, size_t len); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + bool isServer() const; + void setIsServer(bool isServer); + const std::string& getName() const; + void setName(const std::string& name); + private: + const std::string kModuleName = "SERVICE_ACCESS_CONTROL_ENTRY"; + static const size_t kMaxServiceNameLen = 8; + + enum ServiceAccessControlEntryFlag + { + SAC_IS_SERVER = _BIT(7), + SAC_NAME_LEN_MASK = _BIT(7) - 1 + }; + + // raw binary + fnd::Vec mRawBinary; + + // variables + bool mIsServer; + std::string mName; + }; +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/aci.h b/lib/libhac/include/nn/hac/define/aci.h similarity index 92% rename from lib/libhac/include/nn/hac/aci.h rename to lib/libhac/include/nn/hac/define/aci.h index 55742e1..56bb2d3 100644 --- a/lib/libhac/include/nn/hac/aci.h +++ b/lib/libhac/include/nn/hac/define/aci.h @@ -1,56 +1,56 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - namespace aci - { - static const uint32_t kAciStructMagic = _MAKE_STRUCT_MAGIC_U32("ACI0"); - static const uint32_t kAciDescStructMagic = _MAKE_STRUCT_MAGIC_U32("ACID"); - static const size_t kSectionAlignSize = 0x10; - - enum Flag - { - FLAG_PRODUCTION, - FLAG_UNQUALIFIED_APPROVAL - }; - } -#pragma pack(push,1) - struct sAciSection - { - le_uint32_t offset; - le_uint32_t size; - }; - - struct sAciHeader - { - le_uint32_t st_magic; - byte_t reserved_00[0xC]; - le_uint64_t program_id; - byte_t reserved_01[0x8]; - sAciSection fac; - sAciSection sac; - sAciSection kc; - }; - - struct sAciDescHeader - { - byte_t signature[fnd::rsa::kRsa2048Size]; - byte_t nca_rsa_signature2_modulus[fnd::rsa::kRsa2048Size]; - le_uint32_t st_magic; - le_uint32_t signed_size; - byte_t reserved_00[0x4]; - le_uint32_t flags; - le_uint64_t program_id_min; - le_uint64_t program_id_max; - sAciSection fac; - sAciSection sac; - sAciSection kc; - }; -#pragma pack(pop) -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + namespace aci + { + static const uint32_t kAciStructMagic = _MAKE_STRUCT_MAGIC_U32("ACI0"); + static const uint32_t kAciDescStructMagic = _MAKE_STRUCT_MAGIC_U32("ACID"); + static const size_t kSectionAlignSize = 0x10; + + enum Flag + { + FLAG_PRODUCTION, + FLAG_UNQUALIFIED_APPROVAL + }; + } +#pragma pack(push,1) + struct sAciSection + { + le_uint32_t offset; + le_uint32_t size; + }; + + struct sAciHeader + { + le_uint32_t st_magic; + byte_t reserved_00[0xC]; + le_uint64_t program_id; + byte_t reserved_01[0x8]; + sAciSection fac; + sAciSection sac; + sAciSection kc; + }; + + struct sAciDescHeader + { + byte_t signature[fnd::rsa::kRsa2048Size]; + byte_t nca_rsa_signature2_modulus[fnd::rsa::kRsa2048Size]; + le_uint32_t st_magic; + le_uint32_t signed_size; + byte_t reserved_00[0x4]; + le_uint32_t flags; + le_uint64_t program_id_min; + le_uint64_t program_id_max; + sAciSection fac; + sAciSection sac; + sAciSection kc; + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/cnmt.h b/lib/libhac/include/nn/hac/define/cnmt.h similarity index 67% rename from lib/libhac/include/nn/hac/cnmt.h rename to lib/libhac/include/nn/hac/define/cnmt.h index 81871c0..6dc9316 100644 --- a/lib/libhac/include/nn/hac/cnmt.h +++ b/lib/libhac/include/nn/hac/define/cnmt.h @@ -1,138 +1,181 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - namespace cnmt - { - enum ContentType - { - TYPE_META = 0, - TYPE_PROGRAM, - TYPE_DATA, - TYPE_CONTROL, - TYPE_HTML_DOCUMENT, - TYPE_LEGAL_INFORMATION, - TYPE_DELTA_FRAGMENT - }; - - enum ContentMetaType - { - METATYPE_SYSTEM_PROGRAM = 1, - METATYPE_SYSTEM_DATA, - METATYPE_SYSTEM_UPDATE, - METATYPE_BOOT_IMAGE_PACKAGE, - METATYPE_BOOT_IMAGE_PACKAGE_SAFE, - - METATYPE_APPLICATION = 0x80, - METATYPE_PATCH, // can have extended data - METATYPE_ADD_ON_CONTENT, - METATYPE_DELTA // can have extended data - }; - - enum UpdateType - { - UPDATETYPE_APPLY_AS_DELTA, - UPDATETYPE_OVERWRITE, - UPDATETYPE_CREATE - }; - - enum ContentMetaAttribute - { - ATTRIBUTE_INCLUDES_EX_FAT_DRIVER, - ATTRIBUTE_REBOOTLESS - }; - - static const uint32_t kRequiredSystemVersion = 335544320; - static const uint32_t kDefaultVersion = 335545344; - static const size_t kContentIdLen = 0x10; - static const size_t kDigestLen = 0x20; - } - - -#pragma pack(push,1) - /* - struct sContentMeta - { - sContentMetaHeader hdr; - byte_t exhdr[]; // optional - sContentInfo info[]; - sContentMetaInfo meta[]; - byte_t extdata[]; - byte_t digest[32] - }; - */ - - struct sContentMetaHeader - { - le_uint64_t id; - le_uint32_t version; - byte_t type; - byte_t reserved_0; - le_uint16_t exhdr_size; - le_uint16_t content_count; - le_uint16_t content_meta_count; - byte_t attributes; - byte_t reserved_1[3]; - le_uint32_t required_download_system_version; - byte_t reserved_2[4]; - }; - - struct sContentInfo - { - fnd::sha::sSha256Hash content_hash; - byte_t content_id[cnmt::kContentIdLen]; - le_uint32_t size_lower; - le_uint16_t size_higher; - byte_t content_type; - byte_t id_offset; - }; - - struct sContentMetaInfo - { - le_uint64_t id; - le_uint32_t version; - byte_t type; - byte_t attributes; - byte_t reserved[2]; - }; - - struct sApplicationMetaExtendedHeader - { - le_uint64_t patch_id; - le_uint32_t required_system_version; - byte_t reserved[4]; - }; - - struct sPatchMetaExtendedHeader - { - le_uint64_t application_id; - le_uint32_t required_system_version; - le_uint32_t extended_data_size; - byte_t reserved[8]; - }; - - struct sAddOnContentMetaExtendedHeader - { - le_uint64_t application_id; - le_uint32_t required_application_version; - byte_t reserved[4]; - }; - - struct sDeltaMetaExtendedHeader - { - le_uint64_t application_id; - le_uint32_t extended_data_size; - byte_t reserved[4]; - }; - - struct sDigest - { - byte_t data[cnmt::kDigestLen]; - }; -#pragma pack(pop) -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + namespace cnmt + { + enum ContentType + { + TYPE_META = 0, + TYPE_PROGRAM, + TYPE_DATA, + TYPE_CONTROL, + TYPE_HTML_DOCUMENT, + TYPE_LEGAL_INFORMATION, + TYPE_DELTA_FRAGMENT + }; + + enum ContentMetaType + { + METATYPE_SYSTEM_PROGRAM = 1, + METATYPE_SYSTEM_DATA, + METATYPE_SYSTEM_UPDATE, + METATYPE_BOOT_IMAGE_PACKAGE, + METATYPE_BOOT_IMAGE_PACKAGE_SAFE, + + METATYPE_APPLICATION = 0x80, + METATYPE_PATCH, // can have extended data + METATYPE_ADD_ON_CONTENT, + METATYPE_DELTA // can have extended data + }; + + enum UpdateType + { + UPDATETYPE_APPLY_AS_DELTA, + UPDATETYPE_OVERWRITE, + UPDATETYPE_CREATE + }; + + enum ContentMetaAttribute + { + ATTRIBUTE_INCLUDES_EX_FAT_DRIVER, + ATTRIBUTE_REBOOTLESS + }; + + static const size_t kContentIdLen = 0x10; + static const size_t kDigestLen = 0x20; + + struct sContentId + { + byte_t data[kContentIdLen]; + + void set(const byte_t content_id[kContentIdLen]) + { + memcpy(this->data, content_id, kContentIdLen); + } + + void operator=(const sContentId& other) + { + set(other.data); + } + + bool operator==(const sContentId& other) const + { + return memcmp(this->data, other.data, kContentIdLen) == 0; + } + + bool operator!=(const sContentId& other) const + { + return !(*this == other); + } + }; + + struct sDigest + { + byte_t data[kDigestLen]; + + void set(const byte_t digest[kDigestLen]) + { + memcpy(this->data, digest, kDigestLen); + } + + void operator=(const sDigest& other) + { + set(other.data); + } + + bool operator==(const sDigest& other) const + { + return memcmp(this->data, other.data, kDigestLen) == 0; + } + + bool operator!=(const sDigest& other) const + { + return !(*this == other); + } + }; + } + + +#pragma pack(push,1) + /* + struct sContentMeta + { + sContentMetaHeader hdr; + byte_t exhdr[]; // optional + sContentInfo info[]; + sContentMetaInfo meta[]; + byte_t extdata[]; + byte_t digest[32] + }; + */ + + struct sContentMetaHeader + { + le_uint64_t id; + le_uint32_t version; + byte_t type; + byte_t reserved_0; + le_uint16_t exhdr_size; + le_uint16_t content_count; + le_uint16_t content_meta_count; + byte_t attributes; + byte_t reserved_1[3]; + le_uint32_t required_download_system_version; + byte_t reserved_2[4]; + }; + + struct sContentInfo + { + fnd::sha::sSha256Hash content_hash; + cnmt::sContentId content_id; + le_uint32_t size_lower; + le_uint16_t size_higher; + byte_t content_type; + byte_t id_offset; + }; + + struct sContentMetaInfo + { + le_uint64_t id; + le_uint32_t version; + byte_t type; + byte_t attributes; + byte_t reserved[2]; + }; + + struct sApplicationMetaExtendedHeader + { + le_uint64_t patch_id; + le_uint32_t required_system_version; + byte_t reserved[4]; + }; + + struct sPatchMetaExtendedHeader + { + le_uint64_t application_id; + le_uint32_t required_system_version; + le_uint32_t extended_data_size; + byte_t reserved[8]; + }; + + struct sAddOnContentMetaExtendedHeader + { + le_uint64_t application_id; + le_uint32_t required_application_version; + byte_t reserved[4]; + }; + + struct sDeltaMetaExtendedHeader + { + le_uint64_t application_id; + le_uint32_t extended_data_size; + byte_t reserved[4]; + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/delta.h b/lib/libhac/include/nn/hac/define/delta.h similarity index 87% rename from lib/libhac/include/nn/hac/delta.h rename to lib/libhac/include/nn/hac/define/delta.h index 0b17d08..b0d4d2c 100644 --- a/lib/libhac/include/nn/hac/delta.h +++ b/lib/libhac/include/nn/hac/define/delta.h @@ -1,26 +1,26 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - namespace delta - { - static const uint32_t kDeltaStructMagic = _MAKE_STRUCT_MAGIC_U32("NDV0"); - } -#pragma pack(push,1) - struct sDeltaHeader - { - le_uint32_t st_magic; - byte_t reserved_00[4]; - le_uint64_t source_size; - le_uint64_t destination_size; - le_uint64_t header_size; - le_uint64_t body_size; - byte_t reserved_01[0x18]; - }; -#pragma pack(pop) -} -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + namespace delta + { + static const uint32_t kDeltaStructMagic = _MAKE_STRUCT_MAGIC_U32("NDV0"); + } +#pragma pack(push,1) + struct sDeltaHeader + { + le_uint32_t st_magic; + byte_t reserved_00[4]; + le_uint64_t source_size; + le_uint64_t destination_size; + le_uint64_t header_size; + le_uint64_t body_size; + byte_t reserved_01[0x18]; + }; +#pragma pack(pop) +} +} diff --git a/lib/libhac/include/nn/hac/fac.h b/lib/libhac/include/nn/hac/define/fac.h similarity index 95% rename from lib/libhac/include/nn/hac/fac.h rename to lib/libhac/include/nn/hac/define/fac.h index 1b1714e..80bc206 100644 --- a/lib/libhac/include/nn/hac/fac.h +++ b/lib/libhac/include/nn/hac/define/fac.h @@ -1,60 +1,60 @@ -#pragma once -#include - -namespace nn -{ -namespace hac -{ - namespace fac - { - static const uint32_t kFacFormatVersion = 1; - static const size_t kSectionAlignSize = 4; - - enum FsAccessFlag - { - FSA_APPLICATION_INFO, - FSA_BOOT_MODE_CONTROL, - FSA_CALIBRATION, - FSA_SYSTEM_SAVE_DATA, - FSA_GAME_CARD, - FSA_SAVE_DATA_BACKUP, - FSA_SAVE_DATA_MANAGEMENT, - FSA_BIS_ALL_RAW, - FSA_GAME_CARD_RAW, - FSA_GAME_CARD_PRIVATE, - FSA_SET_TIME, - FSA_CONTENT_MANAGER, - FSA_IMAGE_MANAGER, - FSA_CREATE_SAVE_DATA, - FSA_SYSTEM_SAVE_DATA_MANAGEMENT, - FSA_BIS_FILE_SYSTEM, - FSA_SYSTEM_UPDATE, - FSA_SAVE_DATA_META, - FSA_DEVICE_SAVE_CONTROL, - FSA_SETTINGS_CONTROL, - FSA_DEBUG = 62, - FSA_FULL_PERMISSION = 63, - }; - - enum SaveDataOwnerIdAccessType - { - SDO_READ = 1, - SDO_WRITE, - SDO_READWRITE - }; - } - -#pragma pack(push,1) - struct sFacHeader - { - le_uint32_t version; // default 1 - le_uint64_t fac_flags; - struct sFacSection - { - le_uint32_t offset; - le_uint32_t size; - } content_owner_ids, save_data_owner_ids; // the data for these follow later in binary. start/end relative to base of FacData instance - }; -#pragma pack(pop) -} +#pragma once +#include + +namespace nn +{ +namespace hac +{ + namespace fac + { + static const uint32_t kFacFormatVersion = 1; + static const size_t kSectionAlignSize = 4; + + enum FsAccessFlag + { + FSA_APPLICATION_INFO, + FSA_BOOT_MODE_CONTROL, + FSA_CALIBRATION, + FSA_SYSTEM_SAVE_DATA, + FSA_GAME_CARD, + FSA_SAVE_DATA_BACKUP, + FSA_SAVE_DATA_MANAGEMENT, + FSA_BIS_ALL_RAW, + FSA_GAME_CARD_RAW, + FSA_GAME_CARD_PRIVATE, + FSA_SET_TIME, + FSA_CONTENT_MANAGER, + FSA_IMAGE_MANAGER, + FSA_CREATE_SAVE_DATA, + FSA_SYSTEM_SAVE_DATA_MANAGEMENT, + FSA_BIS_FILE_SYSTEM, + FSA_SYSTEM_UPDATE, + FSA_SAVE_DATA_META, + FSA_DEVICE_SAVE_CONTROL, + FSA_SETTINGS_CONTROL, + FSA_DEBUG = 62, + FSA_FULL_PERMISSION = 63, + }; + + enum SaveDataOwnerIdAccessType + { + SDO_READ = 1, + SDO_WRITE, + SDO_READWRITE + }; + } + +#pragma pack(push,1) + struct sFacHeader + { + le_uint32_t version; // default 1 + le_uint64_t fac_flags; + struct sFacSection + { + le_uint32_t offset; + le_uint32_t size; + } content_owner_ids, save_data_owner_ids; // the data for these follow later in binary. start/end relative to base of FacData instance + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/xci.h b/lib/libhac/include/nn/hac/define/gc.h similarity index 85% rename from lib/libhac/include/nn/hac/xci.h rename to lib/libhac/include/nn/hac/define/gc.h index a995fa4..4c3098b 100644 --- a/lib/libhac/include/nn/hac/xci.h +++ b/lib/libhac/include/nn/hac/define/gc.h @@ -1,133 +1,133 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - namespace xci - { - static const uint32_t kXciStructMagic = _MAKE_STRUCT_MAGIC_U32("HEAD"); - static const uint32_t kHeaderEncOffset = 0x90; - static const uint32_t kHeaderEncSize = 0x70; - static const uint32_t kPageSize = 0x200; - static const uint32_t kUppHashLen = 8; - /* - static const uint32_t kCardKeyAreaPageCount = 8; - static const uint32_t kCardHeaderPageCount = 1; - static const uint32_t kReservedAreaPageCount = 55; - static const uint32_t kCertAreaStartPageAddress = kCardHeaderPageCount + kReservedAreaPageCount + kCardKeyAreaPageCount; - static const uint32_t kCertAreaPageCount = 64; - static const uint32_t kNormalAreaStartPageAddress = kReservedAreaPageCount + kCertAreaPageCount + kCardHeaderPageCount + kCardKeyAreaPageCount; - */ - - const std::string kUpdatePartitionStr = "update"; - const std::string kLogoPartitionStr = "logo"; - const std::string kNormalPartitionStr = "normal"; - const std::string kSecurePartitionStr = "secure"; - - enum KekIndex - { - KEK_XCIE, - KEK_XCIR - }; - - enum RomSize - { - ROM_SIZE_1GB = 0xFA, - ROM_SIZE_2GB = 0xF8, - ROM_SIZE_4GB = 0xF0, - ROM_SIZE_8GB = 0xE0, - ROM_SIZE_16GB = 0xE1, - ROM_SIZE_32GB = 0xE2 - }; - - enum HeaderFlags - { - FLAG_AUTOBOOT, - FLAG_HISTORY_ERASE, - FLAG_REPAIR_TOOL - }; - - enum FwVersionIndex - { - FWVER_MINOR, - FWVER_MAJOR - }; - - enum CardClockRate - { - CLOCK_RATE_25 = 10551312, - CLOCK_RATE_50 = 10551313, - }; - } - -#pragma pack(push,1) - struct sXciHeader - { - le_uint32_t st_magic; - le_uint32_t rom_area_start_page; - le_uint32_t backup_area_start_page; - byte_t key_flag; - byte_t rom_size; - byte_t card_header_version; - byte_t flags; - le_uint64_t package_id; - le_uint32_t valid_data_end_page; - byte_t reserved_00[4]; - fnd::aes::sAesIvCtr aescbc_iv; - le_uint64_t partition_fs_header_address; - le_uint64_t partition_fs_header_size; - fnd::sha::sSha256Hash partition_fs_header_hash; - fnd::sha::sSha256Hash initial_data_hash; - le_uint32_t sel_sec; - le_uint32_t sel_t1_key; - le_uint32_t sel_key; - le_uint32_t lim_area; - // START ENCRYPTION - le_uint32_t fw_version[2]; - le_uint32_t acc_ctrl_1; - le_uint32_t wait_1_time_read; - le_uint32_t wait_2_time_read; - le_uint32_t wait_1_time_write; - le_uint32_t wait_2_time_write; - le_uint32_t fw_mode; - le_uint32_t upp_version; - byte_t reserved_01[0x4]; - byte_t upp_hash[xci::kUppHashLen]; - le_uint64_t upp_id; - byte_t reserved_02[0x38]; - // END ENCRYPTION - }; - - struct sXciHeaderPage - { - byte_t signature[fnd::rsa::kRsa2048Size]; - sXciHeader header; - }; // sizeof() = 512 (1 page) - - struct sInitialData - { - byte_t key_source[16]; // { package_id[8], zeros[8]} - byte_t title_key_enc[16]; - byte_t ccm_mac[16]; - byte_t ccm_nonce[12]; - byte_t reserved[0x1c4]; - }; // sizeof() = 512 (1 page) - - struct sKeyDataArea - { - sInitialData initial_data; // AES128-CCM encrypted {titlekey[16]} - byte_t encrypted_00[xci::kPageSize * 6]; // AES128-CTR encrypted {titlekey[16]} - byte_t encrypted_00_aesctr_data[fnd::rsa::kRsa2048Size]; // RSA2048-OAEP-SHA256 encrypted AES-CTR data used for encrypted_00 {key[16],iv[16]} - byte_t reserved[xci::kPageSize - fnd::rsa::kRsa2048Size]; - }; // sizeof() = 512*8 (8 pages) - -#pragma pack(pop) -} +#pragma once +#include +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + namespace gc + { + static const uint32_t kGcHeaderStructMagic = _MAKE_STRUCT_MAGIC_U32("HEAD"); + static const uint32_t kHeaderEncOffset = 0x90; + static const uint32_t kHeaderEncSize = 0x70; + static const uint32_t kPageSize = 0x200; + static const uint32_t kUppHashLen = 8; + /* + static const uint32_t kCardKeyAreaPageCount = 8; + static const uint32_t kCardHeaderPageCount = 1; + static const uint32_t kReservedAreaPageCount = 55; + static const uint32_t kCertAreaStartPageAddress = kCardHeaderPageCount + kReservedAreaPageCount + kCardKeyAreaPageCount; + static const uint32_t kCertAreaPageCount = 64; + static const uint32_t kNormalAreaStartPageAddress = kReservedAreaPageCount + kCertAreaPageCount + kCardHeaderPageCount + kCardKeyAreaPageCount; + */ + + const std::string kUpdatePartitionStr = "update"; + const std::string kLogoPartitionStr = "logo"; + const std::string kNormalPartitionStr = "normal"; + const std::string kSecurePartitionStr = "secure"; + + enum KekIndex + { + KEK_XCIE, + KEK_XCIR + }; + + enum RomSize + { + ROM_SIZE_1GB = 0xFA, + ROM_SIZE_2GB = 0xF8, + ROM_SIZE_4GB = 0xF0, + ROM_SIZE_8GB = 0xE0, + ROM_SIZE_16GB = 0xE1, + ROM_SIZE_32GB = 0xE2 + }; + + enum HeaderFlags + { + FLAG_AUTOBOOT, + FLAG_HISTORY_ERASE, + FLAG_REPAIR_TOOL + }; + + enum FwVersionIndex + { + FWVER_MINOR, + FWVER_MAJOR + }; + + enum CardClockRate + { + CLOCK_RATE_25 = 10551312, + CLOCK_RATE_50 = 10551313, + }; + } + +#pragma pack(push,1) + struct sGcHeader + { + le_uint32_t st_magic; + le_uint32_t rom_area_start_page; + le_uint32_t backup_area_start_page; + byte_t key_flag; + byte_t rom_size; + byte_t card_header_version; + byte_t flags; + le_uint64_t package_id; + le_uint32_t valid_data_end_page; + byte_t reserved_00[4]; + fnd::aes::sAesIvCtr aescbc_iv; + le_uint64_t partition_fs_header_address; + le_uint64_t partition_fs_header_size; + fnd::sha::sSha256Hash partition_fs_header_hash; + fnd::sha::sSha256Hash initial_data_hash; + le_uint32_t sel_sec; + le_uint32_t sel_t1_key; + le_uint32_t sel_key; + le_uint32_t lim_area; + // START ENCRYPTION + le_uint32_t fw_version[2]; + le_uint32_t acc_ctrl_1; + le_uint32_t wait_1_time_read; + le_uint32_t wait_2_time_read; + le_uint32_t wait_1_time_write; + le_uint32_t wait_2_time_write; + le_uint32_t fw_mode; + le_uint32_t upp_version; + byte_t reserved_01[0x4]; + byte_t upp_hash[gc::kUppHashLen]; + le_uint64_t upp_id; + byte_t reserved_02[0x38]; + // END ENCRYPTION + }; + + struct sGcHeaderPage + { + byte_t signature[fnd::rsa::kRsa2048Size]; + sGcHeader header; + }; // sizeof() = 512 (1 page) + + struct sInitialData + { + byte_t key_source[16]; // { package_id[8], zeros[8]} + byte_t title_key_enc[16]; + byte_t ccm_mac[16]; + byte_t ccm_nonce[12]; + byte_t reserved[0x1c4]; + }; // sizeof() = 512 (1 page) + + struct sKeyDataArea + { + sInitialData initial_data; // AES128-CCM encrypted {titlekey[16]} + byte_t encrypted_00[gc::kPageSize * 6]; // AES128-CTR encrypted {titlekey[16]} + byte_t encrypted_00_aesctr_data[fnd::rsa::kRsa2048Size]; // RSA2048-OAEP-SHA256 encrypted AES-CTR data used for encrypted_00 {key[16],iv[16]} + byte_t reserved[gc::kPageSize - fnd::rsa::kRsa2048Size]; + }; // sizeof() = 512*8 (8 pages) + +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/hierarchicalintegrity.h b/lib/libhac/include/nn/hac/define/hierarchicalintegrity.h similarity index 90% rename from lib/libhac/include/nn/hac/hierarchicalintegrity.h rename to lib/libhac/include/nn/hac/define/hierarchicalintegrity.h index e662ee2..7e5eaa6 100644 --- a/lib/libhac/include/nn/hac/hierarchicalintegrity.h +++ b/lib/libhac/include/nn/hac/define/hierarchicalintegrity.h @@ -1,35 +1,35 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - namespace hierarchicalintegrity - { - static const uint32_t kStructMagic = _MAKE_STRUCT_MAGIC_U32("IVFC"); - static const uint32_t kRomfsTypeId = 0x20000; - static const size_t kDefaultLayerNum = 6; - static const size_t kHeaderAlignLen = 0x20; - } - -#pragma pack(push,1) - struct sHierarchicalIntegrityHeader - { - le_uint32_t st_magic; - le_uint32_t type_id; - le_uint32_t master_hash_size; - le_uint32_t layer_num; - }; - - struct sHierarchicalIntegrityLayerInfo // sizeof(0x18) - { - le_uint64_t offset; - le_uint64_t size; - le_uint32_t block_size; - byte_t reserved[4]; - }; -#pragma pack(pop) -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + namespace hierarchicalintegrity + { + static const uint32_t kStructMagic = _MAKE_STRUCT_MAGIC_U32("IVFC"); + static const uint32_t kRomfsTypeId = 0x20000; + static const size_t kDefaultLayerNum = 6; + static const size_t kHeaderAlignLen = 0x20; + } + +#pragma pack(push,1) + struct sHierarchicalIntegrityHeader + { + le_uint32_t st_magic; + le_uint32_t type_id; + le_uint32_t master_hash_size; + le_uint32_t layer_num; + }; + + struct sHierarchicalIntegrityLayerInfo // sizeof(0x18) + { + le_uint64_t offset; + le_uint64_t size; + le_uint32_t block_size; + byte_t reserved[4]; + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/hierarchicalsha256.h b/lib/libhac/include/nn/hac/define/hierarchicalsha256.h similarity index 94% rename from lib/libhac/include/nn/hac/hierarchicalsha256.h rename to lib/libhac/include/nn/hac/define/hierarchicalsha256.h index fd424bb..bb720cc 100644 --- a/lib/libhac/include/nn/hac/hierarchicalsha256.h +++ b/lib/libhac/include/nn/hac/define/hierarchicalsha256.h @@ -1,29 +1,29 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - namespace hierarchicalsha256 - { - static const size_t kDefaultLayerNum = 2; - static const size_t kMaxLayerNum = 2; - } - -#pragma pack(push,1) - struct sHierarchicalSha256Header - { - fnd::sha::sSha256Hash master_hash; - le_uint32_t hash_block_size; - le_uint32_t layer_num; - struct sLayer - { - le_uint64_t offset; - le_uint64_t size; - } layer[hierarchicalsha256::kMaxLayerNum]; - }; -#pragma pack(pop) -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + namespace hierarchicalsha256 + { + static const size_t kDefaultLayerNum = 2; + static const size_t kMaxLayerNum = 2; + } + +#pragma pack(push,1) + struct sHierarchicalSha256Header + { + fnd::sha::sSha256Hash master_hash; + le_uint32_t hash_block_size; + le_uint32_t layer_num; + struct sLayer + { + le_uint64_t offset; + le_uint64_t size; + } layer[hierarchicalsha256::kMaxLayerNum]; + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/kc.h b/lib/libhac/include/nn/hac/define/kc.h similarity index 86% rename from lib/libhac/include/nn/hac/kc.h rename to lib/libhac/include/nn/hac/define/kc.h index e15d487..1bf2d73 100644 --- a/lib/libhac/include/nn/hac/kc.h +++ b/lib/libhac/include/nn/hac/define/kc.h @@ -1,27 +1,27 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - namespace kc - { - enum KernelCapId - { - KC_INVALID = 0, - KC_THREAD_INFO = 3, - KC_ENABLE_SYSTEM_CALLS = 4, - KC_MEMORY_MAP = 6, - KC_IO_MEMORY_MAP = 7, - KC_ENABLE_INTERUPTS = 11, - KC_MISC_PARAMS = 13, - KC_KERNEL_VERSION = 14, - KC_HANDLE_TABLE_SIZE = 15, - KC_MISC_FLAGS = 16 - }; - } -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + namespace kc + { + enum KernelCapId + { + KC_INVALID = 0, + KC_THREAD_INFO = 3, + KC_ENABLE_SYSTEM_CALLS = 4, + KC_MEMORY_MAP = 6, + KC_IO_MEMORY_MAP = 7, + KC_ENABLE_INTERUPTS = 11, + KC_MISC_PARAMS = 13, + KC_KERNEL_VERSION = 14, + KC_HANDLE_TABLE_SIZE = 15, + KC_MISC_FLAGS = 16 + }; + } +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/macro.h b/lib/libhac/include/nn/hac/define/macro.h similarity index 98% rename from lib/libhac/include/nn/hac/macro.h rename to lib/libhac/include/nn/hac/define/macro.h index 6e1431f..8e021c3 100644 --- a/lib/libhac/include/nn/hac/macro.h +++ b/lib/libhac/include/nn/hac/define/macro.h @@ -1,5 +1,5 @@ -#pragma once -#include - -#define _MAKE_STRUCT_MAGIC_U32(x) ((uint32_t)(x[3]) << 24 | (uint32_t)(x[2]) << 16 | (uint32_t)(x[1]) << 8 | (uint32_t)(x[0])) -#define _MAKE_STRUCT_MAGIC_U64(x) ((uint64_t)(x[7]) << 56 | (uint64_t)(x[6]) << 48 | (uint64_t)(x[5]) << 40 | (uint64_t)(x[4]) << 32 | (uint64_t)(x[3]) << 24 | (uint64_t)(x[2]) << 16 | (uint64_t)(x[1]) << 8 | (uint64_t)(x[0])) +#pragma once +#include + +#define _MAKE_STRUCT_MAGIC_U32(x) ((uint32_t)(x[3]) << 24 | (uint32_t)(x[2]) << 16 | (uint32_t)(x[1]) << 8 | (uint32_t)(x[0])) +#define _MAKE_STRUCT_MAGIC_U64(x) ((uint64_t)(x[7]) << 56 | (uint64_t)(x[6]) << 48 | (uint64_t)(x[5]) << 40 | (uint64_t)(x[4]) << 32 | (uint64_t)(x[3]) << 24 | (uint64_t)(x[2]) << 16 | (uint64_t)(x[1]) << 8 | (uint64_t)(x[0])) diff --git a/lib/libhac/include/nn/hac/meta.h b/lib/libhac/include/nn/hac/define/meta.h similarity index 92% rename from lib/libhac/include/nn/hac/meta.h rename to lib/libhac/include/nn/hac/define/meta.h index 477a687..ea1c10f 100644 --- a/lib/libhac/include/nn/hac/meta.h +++ b/lib/libhac/include/nn/hac/define/meta.h @@ -1,58 +1,58 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - namespace meta - { - static const uint32_t kMetaStructMagic = _MAKE_STRUCT_MAGIC_U32("META"); - static const size_t kNameMaxLen = 0x10; - static const size_t kProductCodeMaxLen = 0x10; - static const uint32_t kMaxPriority = BIT(6) - 1; - static const size_t kSectionAlignSize = 0x10; - static const uint32_t kDefaultMainThreadStackSize = 4096; - - enum InstructionType - { - INSTR_32BIT, - INSTR_64BIT, - }; - - enum ProcAddrSpaceType - { - ADDR_SPACE_64BIT = 1, - ADDR_SPACE_32BIT, - ADDR_SPACE_32BIT_NO_RESERVED, - }; - } -#pragma pack(push,1) - struct sMetaSection - { - le_uint32_t offset; - le_uint32_t size; - }; - - struct sMetaHeader - { - le_uint32_t st_magic; - byte_t reserved_0[8]; - byte_t flags; - byte_t reserved_1; - byte_t main_thread_priority; - byte_t main_thread_cpu_id; - byte_t reserved_2[8]; - le_uint32_t version; - le_uint32_t main_thread_stack_size; - char name[meta::kNameMaxLen]; // important - char product_code[meta::kProductCodeMaxLen]; // can be empty - byte_t reserved_3[48]; - sMetaSection aci; - sMetaSection acid; - }; - -#pragma pack(pop) -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + namespace meta + { + static const uint32_t kMetaStructMagic = _MAKE_STRUCT_MAGIC_U32("META"); + static const size_t kNameMaxLen = 0x10; + static const size_t kProductCodeMaxLen = 0x10; + static const uint32_t kMaxPriority = BIT(6) - 1; + static const size_t kSectionAlignSize = 0x10; + static const uint32_t kDefaultMainThreadStackSize = 4096; + + enum InstructionType + { + INSTR_32BIT, + INSTR_64BIT, + }; + + enum ProcAddrSpaceType + { + ADDR_SPACE_64BIT = 1, + ADDR_SPACE_32BIT, + ADDR_SPACE_32BIT_NO_RESERVED, + }; + } +#pragma pack(push,1) + struct sMetaSection + { + le_uint32_t offset; + le_uint32_t size; + }; + + struct sMetaHeader + { + le_uint32_t st_magic; + byte_t reserved_0[8]; + byte_t flags; + byte_t reserved_1; + byte_t main_thread_priority; + byte_t main_thread_cpu_id; + byte_t reserved_2[8]; + le_uint32_t version; + le_uint32_t main_thread_stack_size; + char name[meta::kNameMaxLen]; // important + char product_code[meta::kProductCodeMaxLen]; // can be empty + byte_t reserved_3[48]; + sMetaSection aci; + sMetaSection acid; + }; + +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/nacp.h b/lib/libhac/include/nn/hac/define/nacp.h similarity index 95% rename from lib/libhac/include/nn/hac/nacp.h rename to lib/libhac/include/nn/hac/define/nacp.h index 61de162..5d5e933 100644 --- a/lib/libhac/include/nn/hac/nacp.h +++ b/lib/libhac/include/nn/hac/define/nacp.h @@ -1,223 +1,223 @@ -#pragma once -#include - -namespace nn -{ -namespace hac -{ - namespace nacp - { - static const size_t kNameLength = 0x200; - static const size_t kPublisherLength = 0x100; - static const size_t kMaxLanguageCount = 16; - static const size_t kIsbnLength = 37; - static const size_t kRatingAgeCount = 32; - static const size_t kDisplayVersionLength = 16; - static const size_t kApplicationErrorCodeCategoryLength = 8; - static const size_t kLocalCommunicationIdCount = 8; - static const size_t kBcatPassphraseLength = 65; - static const size_t kPlayLogQueryableApplicationIdCount = 16; - static const int8_t kUnusedAgeRating = -1; - - enum AocRegistrationType - { - AOC_AllOnLaunch, - AOC_OnDemand - }; - - enum AttributeFlag - { - ATTR_None, - ATTR_Demo, - ATTR_RetailInteractiveDisplay - }; - - enum CrashReportMode - { - CREP_Deny, - CREP_Allow - }; - - enum DataLossConfirmation - { - DLOSS_None, - DLOSS_Required - }; - - enum Hdcp - { - HDCP_None, - HDCP_Required - }; - - enum Language - { - LANG_AmericanEnglish, - LANG_BritishEnglish, - LANG_Japanese, - LANG_French, - LANG_German, - LANG_LatinAmericanSpanish, - LANG_Spanish, - LANG_Italian, - LANG_Dutch, - LANG_CanadianFrench, - LANG_Portuguese, - LANG_Russian, - LANG_Korean, - LANG_TraditionalChinese, - LANG_SimplifiedChinese - }; - - enum LogoHandling - { - LHND_Auto, - LHND_None - }; - - enum LogoType - { - LOGO_LicensedByNintendo, - LOGO_DistributedByNintendo, - LOGO_Nintendo - }; - - enum Organisation - { - ORGN_CERO, - ORGN_GRACGCRB, - ORGN_GSRMR, - ORGN_ESRB, - ORGN_ClassInd, - ORGN_USK, - ORGN_PEGI, - ORGN_PEGIPortugal, - ORGN_PEGIBBFC, - ORGN_Russian, - ORGN_ACB, - ORGN_OFLC - }; - - enum ParentalControlFlag - { - PC_None, - PC_FreeCommunication - }; - - enum PlayLogPolicy - { - PLP_All, - PLP_LogOnly, - PLP_None - }; - - enum PlayLogQueryCapability - { - PLQC_None, - PLQC_Whitelist, - PLQC_All - }; - - enum RepairFlag - { - REPF_None, - REPF_SuppressGameCardAccess - }; - - enum RuntimeAocInstallMode - { - RTAOC_Deny, - RTAOC_AllowAppend - }; - - enum ScreenshotMode - { - SCRN_Allow, - SCRN_Deny - }; - - enum StartupUserAccount - { - USER_None, - USER_Required, - USER_RequiredWithNetworkServiceAccountAvailable - }; - - enum TouchScreenUsageMode - { - TOUCH_None, - TOUCH_Supported, - TOUCH_Required, - }; - - enum VideoCaptureMode - { - VCAP_Disable, - VCAP_Manual, - VCAP_Enable - }; - } - - -#pragma pack(push,1) - struct sApplicationTitle - { - char name[nacp::kNameLength]; - char publisher[nacp::kPublisherLength]; - }; - - struct sApplicationControlProperty - { - sApplicationTitle title[nacp::kMaxLanguageCount]; - char isbn[nacp::kIsbnLength]; - byte_t startup_user_account; - byte_t touch_screen_usage; - byte_t add_on_content_registration_type; - le_uint32_t attribute_flag; - le_uint32_t supported_language_flag; - le_uint32_t parental_control_flag; - byte_t screenshot; - byte_t video_capture; - byte_t data_loss_confirmation; - byte_t play_log_policy; - le_uint64_t presence_group_id; - int8_t rating_age[nacp::kRatingAgeCount]; - char display_version[nacp::kDisplayVersionLength]; - le_uint64_t add_on_content_base_id; - le_uint64_t save_data_owner_id; - le_uint64_t user_account_save_data_size; - le_uint64_t user_account_save_data_journal_size; - le_uint64_t device_save_data_size; - le_uint64_t device_save_data_journal_size; - le_uint64_t bcat_delivery_cache_storage_size; - char application_error_code_category[nacp::kApplicationErrorCodeCategoryLength]; - le_uint64_t local_communication_id[nacp::kLocalCommunicationIdCount]; - byte_t logo_type; - byte_t logo_handling; - byte_t runtime_add_on_content_install; - byte_t reserved_00[3]; - byte_t crash_report; - byte_t hdcp; - le_uint64_t seed_for_pseudo_device_id; - char bcat_passphrase[nacp::kBcatPassphraseLength]; - byte_t reserved_01; - byte_t reserved_02[6]; //reserved_for_user_account_save_data_operation - le_uint64_t user_account_save_data_size_max; - le_uint64_t user_account_save_data_journal_size_max; - le_uint64_t device_save_data_size_max; - le_uint64_t device_save_data_journal_size_max; - le_uint64_t temporary_storage_size; - le_uint64_t cache_storage_size; - le_uint64_t cache_storage_journal_size; - le_uint64_t cache_storage_data_and_journal_size_max; - le_uint16_t cache_storage_index_max; - byte_t reserved_03[6]; - le_uint64_t play_log_queryable_application_id[nacp::kPlayLogQueryableApplicationIdCount]; - byte_t play_log_query_capability; - byte_t repair_flag; - byte_t program_index; - byte_t reserved_04[0xDED]; - }; -#pragma pack(pop) -} +#pragma once +#include + +namespace nn +{ +namespace hac +{ + namespace nacp + { + static const size_t kNameLength = 0x200; + static const size_t kPublisherLength = 0x100; + static const size_t kMaxLanguageCount = 16; + static const size_t kIsbnLength = 37; + static const size_t kRatingAgeCount = 32; + static const size_t kDisplayVersionLength = 16; + static const size_t kApplicationErrorCodeCategoryLength = 8; + static const size_t kLocalCommunicationIdCount = 8; + static const size_t kBcatPassphraseLength = 65; + static const size_t kPlayLogQueryableApplicationIdCount = 16; + static const int8_t kUnusedAgeRating = -1; + + enum AocRegistrationType + { + AOC_AllOnLaunch, + AOC_OnDemand + }; + + enum AttributeFlag + { + ATTR_None, + ATTR_Demo, + ATTR_RetailInteractiveDisplay + }; + + enum CrashReportMode + { + CREP_Deny, + CREP_Allow + }; + + enum DataLossConfirmation + { + DLOSS_None, + DLOSS_Required + }; + + enum Hdcp + { + HDCP_None, + HDCP_Required + }; + + enum Language + { + LANG_AmericanEnglish, + LANG_BritishEnglish, + LANG_Japanese, + LANG_French, + LANG_German, + LANG_LatinAmericanSpanish, + LANG_Spanish, + LANG_Italian, + LANG_Dutch, + LANG_CanadianFrench, + LANG_Portuguese, + LANG_Russian, + LANG_Korean, + LANG_TraditionalChinese, + LANG_SimplifiedChinese + }; + + enum LogoHandling + { + LHND_Auto, + LHND_None + }; + + enum LogoType + { + LOGO_LicensedByNintendo, + LOGO_DistributedByNintendo, + LOGO_Nintendo + }; + + enum Organisation + { + ORGN_CERO, + ORGN_GRACGCRB, + ORGN_GSRMR, + ORGN_ESRB, + ORGN_ClassInd, + ORGN_USK, + ORGN_PEGI, + ORGN_PEGIPortugal, + ORGN_PEGIBBFC, + ORGN_Russian, + ORGN_ACB, + ORGN_OFLC + }; + + enum ParentalControlFlag + { + PC_None, + PC_FreeCommunication + }; + + enum PlayLogPolicy + { + PLP_All, + PLP_LogOnly, + PLP_None + }; + + enum PlayLogQueryCapability + { + PLQC_None, + PLQC_Whitelist, + PLQC_All + }; + + enum RepairFlag + { + REPF_None, + REPF_SuppressGameCardAccess + }; + + enum RuntimeAocInstallMode + { + RTAOC_Deny, + RTAOC_AllowAppend + }; + + enum ScreenshotMode + { + SCRN_Allow, + SCRN_Deny + }; + + enum StartupUserAccount + { + USER_None, + USER_Required, + USER_RequiredWithNetworkServiceAccountAvailable + }; + + enum TouchScreenUsageMode + { + TOUCH_None, + TOUCH_Supported, + TOUCH_Required, + }; + + enum VideoCaptureMode + { + VCAP_Disable, + VCAP_Manual, + VCAP_Enable + }; + } + + +#pragma pack(push,1) + struct sApplicationTitle + { + char name[nacp::kNameLength]; + char publisher[nacp::kPublisherLength]; + }; + + struct sApplicationControlProperty + { + sApplicationTitle title[nacp::kMaxLanguageCount]; + char isbn[nacp::kIsbnLength]; + byte_t startup_user_account; + byte_t touch_screen_usage; + byte_t add_on_content_registration_type; + le_uint32_t attribute_flag; + le_uint32_t supported_language_flag; + le_uint32_t parental_control_flag; + byte_t screenshot; + byte_t video_capture; + byte_t data_loss_confirmation; + byte_t play_log_policy; + le_uint64_t presence_group_id; + int8_t rating_age[nacp::kRatingAgeCount]; + char display_version[nacp::kDisplayVersionLength]; + le_uint64_t add_on_content_base_id; + le_uint64_t save_data_owner_id; + le_uint64_t user_account_save_data_size; + le_uint64_t user_account_save_data_journal_size; + le_uint64_t device_save_data_size; + le_uint64_t device_save_data_journal_size; + le_uint64_t bcat_delivery_cache_storage_size; + char application_error_code_category[nacp::kApplicationErrorCodeCategoryLength]; + le_uint64_t local_communication_id[nacp::kLocalCommunicationIdCount]; + byte_t logo_type; + byte_t logo_handling; + byte_t runtime_add_on_content_install; + byte_t reserved_00[3]; + byte_t crash_report; + byte_t hdcp; + le_uint64_t seed_for_pseudo_device_id; + char bcat_passphrase[nacp::kBcatPassphraseLength]; + byte_t reserved_01; + byte_t reserved_02[6]; //reserved_for_user_account_save_data_operation + le_uint64_t user_account_save_data_size_max; + le_uint64_t user_account_save_data_journal_size_max; + le_uint64_t device_save_data_size_max; + le_uint64_t device_save_data_journal_size_max; + le_uint64_t temporary_storage_size; + le_uint64_t cache_storage_size; + le_uint64_t cache_storage_journal_size; + le_uint64_t cache_storage_data_and_journal_size_max; + le_uint16_t cache_storage_index_max; + byte_t reserved_03[6]; + le_uint64_t play_log_queryable_application_id[nacp::kPlayLogQueryableApplicationIdCount]; + byte_t play_log_query_capability; + byte_t repair_flag; + byte_t program_index; + byte_t reserved_04[0xDED]; + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/nca.h b/lib/libhac/include/nn/hac/define/nca.h similarity index 73% rename from lib/libhac/include/nn/hac/nca.h rename to lib/libhac/include/nn/hac/define/nca.h index 4dac6f0..95fae55 100644 --- a/lib/libhac/include/nn/hac/nca.h +++ b/lib/libhac/include/nn/hac/define/nca.h @@ -1,137 +1,144 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace nn -{ -namespace hac -{ - namespace nca - { - static const uint32_t kNca2StructMagic = _MAKE_STRUCT_MAGIC_U32("NCA2"); - static const uint32_t kNca3StructMagic = _MAKE_STRUCT_MAGIC_U32("NCA3"); - static const size_t kSectorSize = 0x200; - static const size_t kPartitionNum = 4; - static const size_t kHeaderSectorNum = 6; - static const size_t kHeaderSize = kSectorSize * kHeaderSectorNum; - static const size_t kAesKeyNum = 16; - static const size_t kRightsIdLen = 0x10; - static const size_t kKeyAreaEncryptionKeyNum = 3; - static const size_t kFsHeaderHashSuperblockLen = 0x138; - static const uint16_t kDefaultFsHeaderVersion = 2; - - enum ProgramPartitionId - { - PARTITION_CODE, - PARTITION_DATA, - PARTITION_LOGO, - }; - - enum DistributionType - { - DIST_DOWNLOAD, - DIST_GAME_CARD - }; - - enum ContentType - { - TYPE_PROGRAM, - TYPE_META, - TYPE_CONTROL, - TYPE_MANUAL, - TYPE_DATA, - TYPE_PUBLIC_DATA - }; - - enum KeyBankIndex - { - KEY_AESXTS_0, - KEY_AESXTS_1, - KEY_AESCTR, - KEY_UNUSED_3, - KEY_AESCTR_HW - }; - - enum KeyAreaEncryptionKeyIndex - { - KAEK_IDX_APPLICATION, - KAEK_IDX_OCEAN, - KAEK_IDX_SYSTEM - }; - - enum FormatType - { - FORMAT_ROMFS, - FORMAT_PFS0 - }; - - enum HashType - { - HASH_AUTO, - HASH_NONE, - HASH_HIERARCHICAL_SHA256, - HASH_HIERARCHICAL_INTERGRITY // IVFC - }; - - enum EncryptionType - { - CRYPT_AUTO, - CRYPT_NONE, - CRYPT_AESXTS, - CRYPT_AESCTR, - CRYPT_AESCTREX - }; - } - -#pragma pack(push,1) - struct sNcaHeader - { - le_uint32_t st_magic; - byte_t distribution_type; - byte_t content_type; - byte_t key_generation; - byte_t key_area_encryption_key_index; - le_uint64_t content_size; - le_uint64_t program_id; - le_uint32_t content_index; - le_uint32_t sdk_addon_version; - byte_t key_generation_2; - byte_t reserved_2[0xf]; - byte_t rights_id[nca::kRightsIdLen]; - struct sNcaSection - { - le_uint32_t start; // block units - le_uint32_t end; // block units - byte_t enabled; - byte_t reserved[7]; - } partition[nca::kPartitionNum]; - fnd::sha::sSha256Hash partition_hash[nca::kPartitionNum]; - fnd::aes::sAes128Key enc_aes_key[nca::kAesKeyNum]; - }; - - struct sNcaFsHeader - { - le_uint16_t version; - byte_t format_type; - byte_t hash_type; - byte_t encryption_type; - byte_t reserved_0[3]; - byte_t hash_superblock[nca::kFsHeaderHashSuperblockLen]; - byte_t aes_ctr_upper[8]; - byte_t reserved_1[0xB8]; - }; - - struct sNcaHeaderBlock - { - byte_t signature_main[fnd::rsa::kRsa2048Size]; - byte_t signature_acid[fnd::rsa::kRsa2048Size]; - sNcaHeader header; - sNcaFsHeader fs_header[nn::hac::nca::kPartitionNum]; - }; - -#pragma pack(pop) -} +#pragma once +#include +#include +#include +#include +#include + +namespace nn +{ +namespace hac +{ + namespace nca + { + static const uint32_t kNca2StructMagic = _MAKE_STRUCT_MAGIC_U32("NCA2"); + static const uint32_t kNca3StructMagic = _MAKE_STRUCT_MAGIC_U32("NCA3"); + static const size_t kSectorSize = 0x200; + static const size_t kPartitionNum = 4; + static const size_t kHeaderSectorNum = 6; + static const size_t kHeaderSize = kSectorSize * kHeaderSectorNum; + static const size_t kRightsIdLen = 0x10; + static const size_t kKeyAreaSize = 0x100; + static const size_t kKeyAreaKeyNum = kKeyAreaSize / fnd::aes::kAes128KeySize; + static const size_t kKeyAreaEncryptionKeyNum = 3; + static const size_t kFsHeaderHashSuperblockLen = 0x138; + static const uint16_t kDefaultFsHeaderVersion = 2; + + enum HeaderFormatVersion + { + FORMAT_NCA2 = 2, + FORMAT_NCA3 = 3 + }; + + enum ProgramContentPartitionIndex + { + PARTITION_CODE = 0, + PARTITION_DATA = 1, + PARTITION_LOGO = 2, + }; + + enum DistributionType + { + DIST_DOWNLOAD, + DIST_GAME_CARD + }; + + enum ContentType + { + TYPE_PROGRAM, + TYPE_META, + TYPE_CONTROL, + TYPE_MANUAL, + TYPE_DATA, + TYPE_PUBLIC_DATA + }; + + enum KeyBankIndex + { + KEY_AESXTS_0, + KEY_AESXTS_1, + KEY_AESCTR, + KEY_UNUSED_3, + KEY_AESCTR_HW + }; + + enum KeyAreaEncryptionKeyIndex + { + KAEK_IDX_APPLICATION, + KAEK_IDX_OCEAN, + KAEK_IDX_SYSTEM + }; + + enum FormatType + { + FORMAT_ROMFS, + FORMAT_PFS0 + }; + + enum HashType + { + HASH_AUTO, + HASH_NONE, + HASH_HIERARCHICAL_SHA256, + HASH_HIERARCHICAL_INTERGRITY // IVFC + }; + + enum EncryptionType + { + CRYPT_AUTO, + CRYPT_NONE, + CRYPT_AESXTS, + CRYPT_AESCTR, + CRYPT_AESCTREX + }; + } + +#pragma pack(push,1) + struct sContentArchiveHeader + { + le_uint32_t st_magic; + byte_t distribution_type; + byte_t content_type; + byte_t key_generation; + byte_t key_area_encryption_key_index; + le_uint64_t content_size; + le_uint64_t program_id; + le_uint32_t content_index; + le_uint32_t sdk_addon_version; + byte_t key_generation_2; + byte_t reserved_2[0xf]; + byte_t rights_id[nca::kRightsIdLen]; + struct sPartitionEntry + { + le_uint32_t start_blk; // block units + le_uint32_t end_blk; // block units + byte_t enabled; + byte_t reserved[7]; + } partition_entry[nca::kPartitionNum]; + fnd::sha::sSha256Hash fs_header_hash[nca::kPartitionNum]; + byte_t key_area[nca::kKeyAreaSize]; + }; + + struct sNcaFsHeader + { + le_uint16_t version; + byte_t format_type; + byte_t hash_type; + byte_t encryption_type; + byte_t reserved_0[3]; + byte_t hash_superblock[nca::kFsHeaderHashSuperblockLen]; + byte_t aes_ctr_upper[8]; + byte_t reserved_1[0xB8]; + }; + + struct sContentArchiveHeaderBlock + { + byte_t signature_main[fnd::rsa::kRsa2048Size]; + byte_t signature_acid[fnd::rsa::kRsa2048Size]; + sContentArchiveHeader header; + sNcaFsHeader fs_header[nn::hac::nca::kPartitionNum]; + }; + +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/nro.h b/lib/libhac/include/nn/hac/define/nro.h similarity index 91% rename from lib/libhac/include/nn/hac/nro.h rename to lib/libhac/include/nn/hac/define/nro.h index e46b316..6ab147f 100644 --- a/lib/libhac/include/nn/hac/nro.h +++ b/lib/libhac/include/nn/hac/define/nro.h @@ -1,45 +1,45 @@ -#pragma once -#include -#include - -namespace nn -{ -namespace hac -{ - namespace nro - { - static const uint32_t kNroStructMagic = _MAKE_STRUCT_MAGIC_U32("NRO0"); - static const uint32_t kDefaultFormatVersion = 0; - static const size_t kRoCrtSize = 8; - static const size_t kModuleIdSize = 32; - } - -#pragma pack(push,1) - struct sNroSection - { - le_uint32_t memory_offset; - le_uint32_t size; - }; - - struct sNroHeader - { - byte_t ro_crt[nro::kRoCrtSize]; - byte_t reserved_0[8]; - le_uint32_t st_magic; - le_uint32_t format_version; - le_uint32_t size; - le_uint32_t flags; - sNroSection text; - sNroSection ro; - sNroSection data; - le_uint32_t bss_size; - byte_t reserved_1[4]; - byte_t module_id[nro::kModuleIdSize]; - byte_t reserved_2[8]; - sNroSection embedded; - sNroSection dyn_str; - sNroSection dyn_sym; - }; -#pragma pack(pop) -} +#pragma once +#include +#include + +namespace nn +{ +namespace hac +{ + namespace nro + { + static const uint32_t kNroStructMagic = _MAKE_STRUCT_MAGIC_U32("NRO0"); + static const uint32_t kDefaultFormatVersion = 0; + static const size_t kRoCrtSize = 8; + static const size_t kModuleIdSize = 32; + } + +#pragma pack(push,1) + struct sNroSection + { + le_uint32_t memory_offset; + le_uint32_t size; + }; + + struct sNroHeader + { + byte_t ro_crt[nro::kRoCrtSize]; + byte_t reserved_0[8]; + le_uint32_t st_magic; + le_uint32_t format_version; + le_uint32_t size; + le_uint32_t flags; + sNroSection text; + sNroSection ro; + sNroSection data; + le_uint32_t bss_size; + byte_t reserved_1[4]; + byte_t module_id[nro::kModuleIdSize]; + byte_t reserved_2[8]; + sNroSection embedded; + sNroSection dyn_str; + sNroSection dyn_sym; + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/nrr.h b/lib/libhac/include/nn/hac/define/nrr.h similarity index 91% rename from lib/libhac/include/nn/hac/nrr.h rename to lib/libhac/include/nn/hac/define/nrr.h index 452cc71..275e5f9 100644 --- a/lib/libhac/include/nn/hac/nrr.h +++ b/lib/libhac/include/nn/hac/define/nrr.h @@ -1,39 +1,39 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - namespace nrr - { - static const uint32_t kNrrStructMagic = _MAKE_STRUCT_MAGIC_U32("NRR0"); - } - -#pragma pack(push,1) - struct sNrrCertificate - { - le_uint64_t application_id_mask; - le_uint64_t application_id_pattern; - byte_t nrr_body_modulus[fnd::rsa::kRsa2048Size]; - byte_t nrr_cert_signature[fnd::rsa::kRsa2048Size]; - }; - - struct sNrrHeader - { - le_uint32_t st_magic; - byte_t reserved_0[28]; - sNrrCertificate certificate; - byte_t nrr_body_signature[fnd::rsa::kRsa2048Size]; - le_uint64_t application_id; - le_uint32_t size; - byte_t reserved_1[4]; - le_uint32_t hash_offset; - le_uint32_t hash_count; - byte_t reserved_2[8]; - }; -#pragma pack(pop) -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + namespace nrr + { + static const uint32_t kNrrStructMagic = _MAKE_STRUCT_MAGIC_U32("NRR0"); + } + +#pragma pack(push,1) + struct sNrrCertificate + { + le_uint64_t application_id_mask; + le_uint64_t application_id_pattern; + byte_t nrr_body_modulus[fnd::rsa::kRsa2048Size]; + byte_t nrr_cert_signature[fnd::rsa::kRsa2048Size]; + }; + + struct sNrrHeader + { + le_uint32_t st_magic; + byte_t reserved_0[28]; + sNrrCertificate certificate; + byte_t nrr_body_signature[fnd::rsa::kRsa2048Size]; + le_uint64_t application_id; + le_uint32_t size; + byte_t reserved_1[4]; + le_uint32_t hash_offset; + le_uint32_t hash_count; + byte_t reserved_2[8]; + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/nso.h b/lib/libhac/include/nn/hac/define/nso.h similarity index 92% rename from lib/libhac/include/nn/hac/nso.h rename to lib/libhac/include/nn/hac/define/nso.h index 1b4a10b..8d842a5 100644 --- a/lib/libhac/include/nn/hac/nso.h +++ b/lib/libhac/include/nn/hac/define/nso.h @@ -1,68 +1,68 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - namespace nso - { - static const uint32_t kNsoStructMagic = _MAKE_STRUCT_MAGIC_U32("NSO0"); - static const uint32_t kDefaultFormatVersion = 0; - static const size_t kModuleIdSize = 32; - - enum HeaderFlags - { - FLAG_TEXT_COMPRESS, - FLAG_RO_COMPRESS, - FLAG_DATA_COMPRESS, - FLAG_TEXT_HASH, - FLAG_RO_HASH, - FLAG_DATA_HASH - }; - } - -#pragma pack(push,1) - struct sNsoCodeSegment - { - le_uint32_t file_offset; - le_uint32_t memory_offset; - le_uint32_t size; - }; - - struct sNsoSection - { - le_uint32_t offset; - le_uint32_t size; - }; - - struct sNsoHeader - { - le_uint32_t st_magic; - le_uint32_t format_version; - byte_t reserved_1[4]; - le_uint32_t flags; - sNsoCodeSegment text; - le_uint32_t module_name_offset; - sNsoCodeSegment ro; - le_uint32_t module_name_size; - sNsoCodeSegment data; - le_uint32_t bss_size; - byte_t module_id[nso::kModuleIdSize]; - le_uint32_t text_file_size; - le_uint32_t ro_file_size; - le_uint32_t data_file_size; - byte_t reserved_2[28]; - sNsoSection embedded; - sNsoSection dyn_str; - sNsoSection dyn_sym; - fnd::sha::sSha256Hash text_hash; - fnd::sha::sSha256Hash ro_hash; - fnd::sha::sSha256Hash data_hash; - }; - -#pragma pack(pop) -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + namespace nso + { + static const uint32_t kNsoStructMagic = _MAKE_STRUCT_MAGIC_U32("NSO0"); + static const uint32_t kDefaultFormatVersion = 0; + static const size_t kModuleIdSize = 32; + + enum HeaderFlags + { + FLAG_TEXT_COMPRESS, + FLAG_RO_COMPRESS, + FLAG_DATA_COMPRESS, + FLAG_TEXT_HASH, + FLAG_RO_HASH, + FLAG_DATA_HASH + }; + } + +#pragma pack(push,1) + struct sNsoCodeSegment + { + le_uint32_t file_offset; + le_uint32_t memory_offset; + le_uint32_t size; + }; + + struct sNsoSection + { + le_uint32_t offset; + le_uint32_t size; + }; + + struct sNsoHeader + { + le_uint32_t st_magic; + le_uint32_t format_version; + byte_t reserved_1[4]; + le_uint32_t flags; + sNsoCodeSegment text; + le_uint32_t module_name_offset; + sNsoCodeSegment ro; + le_uint32_t module_name_size; + sNsoCodeSegment data; + le_uint32_t bss_size; + byte_t module_id[nso::kModuleIdSize]; + le_uint32_t text_file_size; + le_uint32_t ro_file_size; + le_uint32_t data_file_size; + byte_t reserved_2[28]; + sNsoSection embedded; + sNsoSection dyn_str; + sNsoSection dyn_sym; + fnd::sha::sSha256Hash text_hash; + fnd::sha::sSha256Hash ro_hash; + fnd::sha::sSha256Hash data_hash; + }; + +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/pfs.h b/lib/libhac/include/nn/hac/define/pfs.h similarity index 91% rename from lib/libhac/include/nn/hac/pfs.h rename to lib/libhac/include/nn/hac/define/pfs.h index 60f12fa..6f78d38 100644 --- a/lib/libhac/include/nn/hac/pfs.h +++ b/lib/libhac/include/nn/hac/define/pfs.h @@ -1,45 +1,45 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace hac -{ - namespace pfs - { - static const uint32_t kPfsStructMagic = _MAKE_STRUCT_MAGIC_U32("PFS0"); - static const uint32_t kHashedPfsStructMagic = _MAKE_STRUCT_MAGIC_U32("HFS0"); - static const size_t kHeaderAlign = 64; - } - -#pragma pack(push,1) - struct sPfsHeader - { - le_uint32_t st_magic; - le_uint32_t file_num; - le_uint32_t name_table_size; - byte_t padding[4]; - }; - - struct sPfsFile - { - le_uint64_t data_offset; - le_uint64_t size; - le_uint32_t name_offset; - byte_t padding[4]; - }; // sizeof(0x18) - - struct sHashedPfsFile - { - le_uint64_t data_offset; - le_uint64_t size; - le_uint32_t name_offset; - le_uint32_t hash_protected_size; - byte_t padding[8]; - fnd::sha::sSha256Hash hash; - }; // sizeof(0x40) -#pragma pack(pop) -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace hac +{ + namespace pfs + { + static const uint32_t kPfsStructMagic = _MAKE_STRUCT_MAGIC_U32("PFS0"); + static const uint32_t kHashedPfsStructMagic = _MAKE_STRUCT_MAGIC_U32("HFS0"); + static const size_t kHeaderAlign = 64; + } + +#pragma pack(push,1) + struct sPfsHeader + { + le_uint32_t st_magic; + le_uint32_t file_num; + le_uint32_t name_table_size; + byte_t padding[4]; + }; + + struct sPfsFile + { + le_uint64_t data_offset; + le_uint64_t size; + le_uint32_t name_offset; + byte_t padding[4]; + }; // sizeof(0x18) + + struct sHashedPfsFile + { + le_uint64_t data_offset; + le_uint64_t size; + le_uint32_t name_offset; + le_uint32_t hash_protected_size; + byte_t padding[8]; + fnd::sha::sSha256Hash hash; + }; // sizeof(0x40) +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/include/nn/hac/romfs.h b/lib/libhac/include/nn/hac/define/romfs.h similarity index 95% rename from lib/libhac/include/nn/hac/romfs.h rename to lib/libhac/include/nn/hac/define/romfs.h index 73d376d..bc346d6 100644 --- a/lib/libhac/include/nn/hac/romfs.h +++ b/lib/libhac/include/nn/hac/define/romfs.h @@ -1,60 +1,60 @@ -#pragma once -#include - -namespace nn -{ -namespace hac -{ - namespace romfs - { - static const uint64_t kRomfsHeaderAlign = 0x200; - static const uint32_t kInvalidAddr = 0xffffffff; - - enum HeaderSectionIndex - { - DIR_HASHMAP_TABLE, - DIR_NODE_TABLE, - FILE_HASHMAP_TABLE, - FILE_NODE_TABLE, - SECTION_NUM - }; - } - -#pragma pack(push,1) - struct sRomfsHeader - { - le_uint64_t header_size; - struct sSection - { - le_uint64_t offset; - le_uint64_t size; - } sections[romfs::SECTION_NUM]; - le_uint64_t data_offset; - }; - - struct sRomfsDirEntry - { - le_uint32_t parent; - le_uint32_t sibling; - le_uint32_t child; - le_uint32_t file; - le_uint32_t hash; - le_uint32_t name_size; - char* name() { return ((char*)(this)) + sizeof(sRomfsDirEntry); } - const char* name() const { return ((char*)(this)) + sizeof(sRomfsDirEntry); } - }; - - struct sRomfsFileEntry - { - le_uint32_t parent; - le_uint32_t sibling; - le_uint64_t offset; - le_uint64_t size; - le_uint32_t hash; - le_uint32_t name_size; - char* name() { return ((char*)(this)) + sizeof(sRomfsFileEntry); } - const char* name() const { return ((char*)(this)) + sizeof(sRomfsFileEntry); } - }; -#pragma pack(pop) -} +#pragma once +#include + +namespace nn +{ +namespace hac +{ + namespace romfs + { + static const uint64_t kRomfsHeaderAlign = 0x200; + static const uint32_t kInvalidAddr = 0xffffffff; + + enum HeaderSectionIndex + { + DIR_HASHMAP_TABLE, + DIR_NODE_TABLE, + FILE_HASHMAP_TABLE, + FILE_NODE_TABLE, + SECTION_NUM + }; + } + +#pragma pack(push,1) + struct sRomfsHeader + { + le_uint64_t header_size; + struct sSection + { + le_uint64_t offset; + le_uint64_t size; + } sections[romfs::SECTION_NUM]; + le_uint64_t data_offset; + }; + + struct sRomfsDirEntry + { + le_uint32_t parent; + le_uint32_t sibling; + le_uint32_t child; + le_uint32_t file; + le_uint32_t hash; + le_uint32_t name_size; + char* name() { return ((char*)(this)) + sizeof(sRomfsDirEntry); } + const char* name() const { return ((char*)(this)) + sizeof(sRomfsDirEntry); } + }; + + struct sRomfsFileEntry + { + le_uint32_t parent; + le_uint32_t sibling; + le_uint64_t offset; + le_uint64_t size; + le_uint32_t hash; + le_uint32_t name_size; + char* name() { return ((char*)(this)) + sizeof(sRomfsFileEntry); } + const char* name() const { return ((char*)(this)) + sizeof(sRomfsFileEntry); } + }; +#pragma pack(pop) +} } \ No newline at end of file diff --git a/lib/libhac/libhac.vcxproj b/lib/libhac/libhac.vcxproj index 7b457ae..483f783 100644 --- a/lib/libhac/libhac.vcxproj +++ b/lib/libhac/libhac.vcxproj @@ -1,228 +1,240 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15.0 - {91BA9E79-8242-4F7D-B997-0DFEC95EA22B} - hac - 10.0.16299.0 - libhac - - - - StaticLibrary - true - v141 - MultiByte - - - StaticLibrary - false - v141 - true - MultiByte - - - StaticLibrary - true - v141 - MultiByte - - - StaticLibrary - false - v141 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - true - ..\libfnd\include;..\libhac\include; - _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - - - Level3 - Disabled - true - ..\libfnd\include;..\libhac\include; - _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - - - Level3 - MaxSpeed - true - true - true - ..\libfnd\include;..\libhac\include; - _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - true - true - - - - - Level3 - MaxSpeed - true - true - true - ..\libfnd\include;..\libhac\include; - _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - true - true - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 15.0 + {91BA9E79-8242-4F7D-B997-0DFEC95EA22B} + hac + 10.0.16299.0 + libhac + + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + false + v141 + true + MultiByte + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + ..\libfnd\include;..\libhac\include; + _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + + + Level3 + Disabled + true + ..\libfnd\include;..\libhac\include; + _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + + + Level3 + MaxSpeed + true + true + true + ..\libfnd\include;..\libhac\include; + _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + ..\libfnd\include;..\libhac\include; + _MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + + + + + \ No newline at end of file diff --git a/lib/libhac/libhac.vcxproj.filters b/lib/libhac/libhac.vcxproj.filters index fcc95c3..39c36cb 100644 --- a/lib/libhac/libhac.vcxproj.filters +++ b/lib/libhac/libhac.vcxproj.filters @@ -1,312 +1,345 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - + + + + + + + + {040358e3-f1c5-4875-b34f-23607459567c} + + + {1c33ce2b-25c4-4857-966c-9dc24daf3f61} + + + {a9fd54c0-9fd8-46a1-978e-fb531bf3ee1c} + + + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files\define + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/lib/libhac/source/AccessControlInfoBinary.cpp b/lib/libhac/source/AccessControlInfo.cpp similarity index 70% rename from lib/libhac/source/AccessControlInfoBinary.cpp rename to lib/libhac/source/AccessControlInfo.cpp index 5a22449..438b648 100644 --- a/lib/libhac/source/AccessControlInfoBinary.cpp +++ b/lib/libhac/source/AccessControlInfo.cpp @@ -1,173 +1,173 @@ -#include - -nn::hac::AccessControlInfoBinary::AccessControlInfoBinary() -{ - clear(); -} - -nn::hac::AccessControlInfoBinary::AccessControlInfoBinary(const AccessControlInfoBinary & other) -{ - *this = other; -} - -void nn::hac::AccessControlInfoBinary::operator=(const AccessControlInfoBinary & other) -{ - mRawBinary = other.mRawBinary; - mProgramId = other.mProgramId; - mFileSystemAccessControl = other.mFileSystemAccessControl; - mServiceAccessControl = other.mServiceAccessControl; - mKernelCapabilities = other.mKernelCapabilities; -} - -bool nn::hac::AccessControlInfoBinary::operator==(const AccessControlInfoBinary & other) const -{ - return (mProgramId == other.mProgramId) \ - && (mFileSystemAccessControl == other.mFileSystemAccessControl) \ - && (mServiceAccessControl == other.mServiceAccessControl) \ - && (mKernelCapabilities == other.mKernelCapabilities); -} - -bool nn::hac::AccessControlInfoBinary::operator!=(const AccessControlInfoBinary & other) const -{ - return !(*this == other); -} - -void nn::hac::AccessControlInfoBinary::toBytes() -{ - // serialise the sections - mFileSystemAccessControl.toBytes(); - mServiceAccessControl.toBytes(); - mKernelCapabilities.toBytes(); - - // determine section layout - struct sLayout { - uint32_t offset, size; - } fac, sac, kc; - - fac.offset = (uint32_t)align(sizeof(sAciHeader), aci::kSectionAlignSize); - fac.size = (uint32_t)mFileSystemAccessControl.getBytes().size(); - sac.offset = (uint32_t)align(fac.offset + fac.size, aci::kSectionAlignSize); - sac.size = (uint32_t)mServiceAccessControl.getBytes().size(); - kc.offset = (uint32_t)align(sac.offset + sac.size, aci::kSectionAlignSize); - kc.size = (uint32_t)mKernelCapabilities.getBytes().size(); - - // get total size - size_t total_size = _MAX(_MAX(fac.offset + fac.size, sac.offset + sac.size), kc.offset + kc.size); - - mRawBinary.alloc(total_size); - sAciHeader* hdr = (sAciHeader*)mRawBinary.data(); - - // set type - hdr->st_magic = aci::kAciStructMagic; - - // set program id - hdr->program_id = mProgramId; - - // set offset/size - hdr->fac.offset = fac.offset; - hdr->fac.size = fac.size; - hdr->sac.offset = sac.offset; - hdr->sac.size = sac.size; - hdr->kc.offset = kc.offset; - hdr->kc.size = kc.size; - - // write data - memcpy(mRawBinary.data() + fac.offset, mFileSystemAccessControl.getBytes().data(), fac.size); - memcpy(mRawBinary.data() + sac.offset, mServiceAccessControl.getBytes().data(), sac.size); - memcpy(mRawBinary.data() + kc.offset, mKernelCapabilities.getBytes().data(), kc.size); -} - -void nn::hac::AccessControlInfoBinary::fromBytes(const byte_t* data, size_t len) -{ - // check size - if (len < sizeof(sAciHeader)) - { - throw fnd::Exception(kModuleName, "AccessControlInfo binary is too small"); - } - - // clear variables - clear(); - - // save a copy of the header - sAciHeader hdr; - memcpy((void*)&hdr, data, sizeof(sAciHeader)); - - // check magic - if (hdr.st_magic.get() != aci::kAciStructMagic) - { - throw fnd::Exception(kModuleName, "AccessControlInfo header corrupt"); - } - - // get total size - size_t total_size = _MAX(_MAX(hdr.fac.offset.get() + hdr.fac.size.get(), hdr.sac.offset.get() + hdr.sac.size.get()), hdr.kc.offset.get() + hdr.kc.size.get()); - - // validate binary size - if (len < total_size) - { - throw fnd::Exception(kModuleName, "AccessControlInfo binary is too small"); - } - - // allocate memory for header - mRawBinary.alloc(total_size); - memcpy(mRawBinary.data(), data, mRawBinary.size()); - - // save variables - mProgramId = hdr.program_id.get(); - mFileSystemAccessControl.fromBytes(mRawBinary.data() + hdr.fac.offset.get(), hdr.fac.size.get()); - mServiceAccessControl.fromBytes(mRawBinary.data() + hdr.sac.offset.get(), hdr.sac.size.get()); - mKernelCapabilities.fromBytes(mRawBinary.data() + hdr.kc.offset.get(), hdr.kc.size.get()); -} - -const fnd::Vec& nn::hac::AccessControlInfoBinary::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::AccessControlInfoBinary::clear() -{ - mRawBinary.clear(); - mProgramId = 0; - mFileSystemAccessControl.clear(); - mServiceAccessControl.clear(); - mKernelCapabilities.clear(); -} - -uint64_t nn::hac::AccessControlInfoBinary::getProgramId() const -{ - return mProgramId; -} - -void nn::hac::AccessControlInfoBinary::setProgramId(uint64_t program_id) -{ - mProgramId = program_id; -} - -const nn::hac::FileSystemAccessControlBinary& nn::hac::AccessControlInfoBinary::getFileSystemAccessControl() const -{ - return mFileSystemAccessControl; -} - -void nn::hac::AccessControlInfoBinary::setFileSystemAccessControl(const nn::hac::FileSystemAccessControlBinary& fac) -{ - mFileSystemAccessControl = fac; -} - -const nn::hac::ServiceAccessControlBinary& nn::hac::AccessControlInfoBinary::getServiceAccessControl() const -{ - return mServiceAccessControl; -} - -void nn::hac::AccessControlInfoBinary::setServiceAccessControl(const nn::hac::ServiceAccessControlBinary& sac) -{ - mServiceAccessControl = sac; -} - -const nn::hac::KernelCapabilityBinary& nn::hac::AccessControlInfoBinary::getKernelCapabilities() const -{ - return mKernelCapabilities; -} - -void nn::hac::AccessControlInfoBinary::setKernelCapabilities(const nn::hac::KernelCapabilityBinary& kc) -{ - mKernelCapabilities = kc; +#include + +nn::hac::AccessControlInfo::AccessControlInfo() +{ + clear(); +} + +nn::hac::AccessControlInfo::AccessControlInfo(const AccessControlInfo & other) +{ + *this = other; +} + +void nn::hac::AccessControlInfo::operator=(const AccessControlInfo & other) +{ + mRawBinary = other.mRawBinary; + mProgramId = other.mProgramId; + mFileSystemAccessControl = other.mFileSystemAccessControl; + mServiceAccessControl = other.mServiceAccessControl; + mKernelCapabilities = other.mKernelCapabilities; +} + +bool nn::hac::AccessControlInfo::operator==(const AccessControlInfo & other) const +{ + return (mProgramId == other.mProgramId) \ + && (mFileSystemAccessControl == other.mFileSystemAccessControl) \ + && (mServiceAccessControl == other.mServiceAccessControl) \ + && (mKernelCapabilities == other.mKernelCapabilities); +} + +bool nn::hac::AccessControlInfo::operator!=(const AccessControlInfo & other) const +{ + return !(*this == other); +} + +void nn::hac::AccessControlInfo::toBytes() +{ + // serialise the sections + mFileSystemAccessControl.toBytes(); + mServiceAccessControl.toBytes(); + mKernelCapabilities.toBytes(); + + // determine section layout + struct sLayout { + uint32_t offset, size; + } fac, sac, kc; + + fac.offset = (uint32_t)align(sizeof(sAciHeader), aci::kSectionAlignSize); + fac.size = (uint32_t)mFileSystemAccessControl.getBytes().size(); + sac.offset = (uint32_t)align(fac.offset + fac.size, aci::kSectionAlignSize); + sac.size = (uint32_t)mServiceAccessControl.getBytes().size(); + kc.offset = (uint32_t)align(sac.offset + sac.size, aci::kSectionAlignSize); + kc.size = (uint32_t)mKernelCapabilities.getBytes().size(); + + // get total size + size_t total_size = _MAX(_MAX(fac.offset + fac.size, sac.offset + sac.size), kc.offset + kc.size); + + mRawBinary.alloc(total_size); + sAciHeader* hdr = (sAciHeader*)mRawBinary.data(); + + // set type + hdr->st_magic = aci::kAciStructMagic; + + // set program id + hdr->program_id = mProgramId; + + // set offset/size + hdr->fac.offset = fac.offset; + hdr->fac.size = fac.size; + hdr->sac.offset = sac.offset; + hdr->sac.size = sac.size; + hdr->kc.offset = kc.offset; + hdr->kc.size = kc.size; + + // write data + memcpy(mRawBinary.data() + fac.offset, mFileSystemAccessControl.getBytes().data(), fac.size); + memcpy(mRawBinary.data() + sac.offset, mServiceAccessControl.getBytes().data(), sac.size); + memcpy(mRawBinary.data() + kc.offset, mKernelCapabilities.getBytes().data(), kc.size); +} + +void nn::hac::AccessControlInfo::fromBytes(const byte_t* data, size_t len) +{ + // check size + if (len < sizeof(sAciHeader)) + { + throw fnd::Exception(kModuleName, "AccessControlInfo binary is too small"); + } + + // clear variables + clear(); + + // save a copy of the header + sAciHeader hdr; + memcpy((void*)&hdr, data, sizeof(sAciHeader)); + + // check magic + if (hdr.st_magic.get() != aci::kAciStructMagic) + { + throw fnd::Exception(kModuleName, "AccessControlInfo header corrupt"); + } + + // get total size + size_t total_size = _MAX(_MAX(hdr.fac.offset.get() + hdr.fac.size.get(), hdr.sac.offset.get() + hdr.sac.size.get()), hdr.kc.offset.get() + hdr.kc.size.get()); + + // validate binary size + if (len < total_size) + { + throw fnd::Exception(kModuleName, "AccessControlInfo binary is too small"); + } + + // allocate memory for header + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + // save variables + mProgramId = hdr.program_id.get(); + mFileSystemAccessControl.fromBytes(mRawBinary.data() + hdr.fac.offset.get(), hdr.fac.size.get()); + mServiceAccessControl.fromBytes(mRawBinary.data() + hdr.sac.offset.get(), hdr.sac.size.get()); + mKernelCapabilities.fromBytes(mRawBinary.data() + hdr.kc.offset.get(), hdr.kc.size.get()); +} + +const fnd::Vec& nn::hac::AccessControlInfo::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::AccessControlInfo::clear() +{ + mRawBinary.clear(); + mProgramId = 0; + mFileSystemAccessControl.clear(); + mServiceAccessControl.clear(); + mKernelCapabilities.clear(); +} + +uint64_t nn::hac::AccessControlInfo::getProgramId() const +{ + return mProgramId; +} + +void nn::hac::AccessControlInfo::setProgramId(uint64_t program_id) +{ + mProgramId = program_id; +} + +const nn::hac::FileSystemAccessControl& nn::hac::AccessControlInfo::getFileSystemAccessControl() const +{ + return mFileSystemAccessControl; +} + +void nn::hac::AccessControlInfo::setFileSystemAccessControl(const nn::hac::FileSystemAccessControl& fac) +{ + mFileSystemAccessControl = fac; +} + +const nn::hac::ServiceAccessControl& nn::hac::AccessControlInfo::getServiceAccessControl() const +{ + return mServiceAccessControl; +} + +void nn::hac::AccessControlInfo::setServiceAccessControl(const nn::hac::ServiceAccessControl& sac) +{ + mServiceAccessControl = sac; +} + +const nn::hac::KernelCapabilityControl& nn::hac::AccessControlInfo::getKernelCapabilities() const +{ + return mKernelCapabilities; +} + +void nn::hac::AccessControlInfo::setKernelCapabilities(const nn::hac::KernelCapabilityControl& kc) +{ + mKernelCapabilities = kc; } \ No newline at end of file diff --git a/lib/libhac/source/AccessControlInfoDescBinary.cpp b/lib/libhac/source/AccessControlInfoDesc.cpp similarity index 64% rename from lib/libhac/source/AccessControlInfoDescBinary.cpp rename to lib/libhac/source/AccessControlInfoDesc.cpp index efd29c4..fa6fff7 100644 --- a/lib/libhac/source/AccessControlInfoDescBinary.cpp +++ b/lib/libhac/source/AccessControlInfoDesc.cpp @@ -1,251 +1,251 @@ -#include - -nn::hac::AccessControlInfoDescBinary::AccessControlInfoDescBinary() -{ - clear(); -} - -nn::hac::AccessControlInfoDescBinary::AccessControlInfoDescBinary(const AccessControlInfoDescBinary & other) -{ - *this = other; -} - -void nn::hac::AccessControlInfoDescBinary::operator=(const AccessControlInfoDescBinary & other) -{ - mRawBinary = other.mRawBinary; - mNcaHeaderSignature2Key = other.mNcaHeaderSignature2Key; - mFlags = other.mFlags; - mProgramIdRestrict = other.mProgramIdRestrict; - mFileSystemAccessControl = other.mFileSystemAccessControl; - mServiceAccessControl = other.mServiceAccessControl; - mKernelCapabilities = other.mKernelCapabilities; -} - -bool nn::hac::AccessControlInfoDescBinary::operator==(const AccessControlInfoDescBinary & other) const -{ - return (mNcaHeaderSignature2Key == other.mNcaHeaderSignature2Key) \ - && (mFlags == other.mFlags) \ - && (mProgramIdRestrict == other.mProgramIdRestrict) \ - && (mFileSystemAccessControl == other.mFileSystemAccessControl) \ - && (mServiceAccessControl == other.mServiceAccessControl) \ - && (mKernelCapabilities == other.mKernelCapabilities); -} - -bool nn::hac::AccessControlInfoDescBinary::operator!=(const AccessControlInfoDescBinary & other) const -{ - return !(*this == other); -} - -void nn::hac::AccessControlInfoDescBinary::toBytes() -{ - // serialise the sections - mFileSystemAccessControl.toBytes(); - mServiceAccessControl.toBytes(); - mKernelCapabilities.toBytes(); - - // determine section layout - struct sLayout { - uint32_t offset, size; - } fac, sac, kc; - - fac.offset = (uint32_t)align(sizeof(sAciDescHeader), aci::kSectionAlignSize); - fac.size = (uint32_t)mFileSystemAccessControl.getBytes().size(); - sac.offset = (uint32_t)align(fac.offset + fac.size, aci::kSectionAlignSize); - sac.size = (uint32_t)mServiceAccessControl.getBytes().size(); - kc.offset = (uint32_t)align(sac.offset + sac.size, aci::kSectionAlignSize); - kc.size = (uint32_t)mKernelCapabilities.getBytes().size(); - - // get total size - size_t total_size = _MAX(_MAX(fac.offset + fac.size, sac.offset + sac.size), kc.offset + kc.size); - - mRawBinary.alloc(total_size); - sAciDescHeader* hdr = (sAciDescHeader*)mRawBinary.data(); - - // set rsa modulus - memcpy(hdr->nca_rsa_signature2_modulus, mNcaHeaderSignature2Key.modulus, fnd::rsa::kRsa2048Size); - - // set type - hdr->st_magic = aci::kAciDescStructMagic; - - // set "acid size" - hdr->signed_size = (uint32_t)(total_size - fnd::rsa::kRsa2048Size); - - // set flags - uint32_t flags = 0; - for (size_t i = 0; i < mFlags.size(); i++) - flags |= _BIT(mFlags[i]); - hdr->flags = flags; - - // set program id restrict settings - hdr->program_id_min = mProgramIdRestrict.min; - hdr->program_id_max = mProgramIdRestrict.max; - - // set offset/size - hdr->fac.offset = fac.offset; - hdr->fac.size = fac.size; - hdr->sac.offset = sac.offset; - hdr->sac.size = sac.size; - hdr->kc.offset = kc.offset; - hdr->kc.size = kc.size; - - // write data - memcpy(mRawBinary.data() + fac.offset, mFileSystemAccessControl.getBytes().data(), fac.size); - memcpy(mRawBinary.data() + sac.offset, mServiceAccessControl.getBytes().data(), sac.size); - memcpy(mRawBinary.data() + kc.offset, mKernelCapabilities.getBytes().data(), kc.size); -} - -void nn::hac::AccessControlInfoDescBinary::fromBytes(const byte_t* data, size_t len) -{ - // check size - if (len < sizeof(sAciDescHeader)) - { - throw fnd::Exception(kModuleName, "AccessControlInfoDesc binary is too small"); - } - - // clear variables - clear(); - - // save a copy of the header - sAciDescHeader hdr; - memcpy((void*)&hdr, data, sizeof(sAciDescHeader)); - - // check magic - if (hdr.st_magic.get() != aci::kAciDescStructMagic) - { - throw fnd::Exception(kModuleName, "AccessControlInfoDesc header corrupt"); - } - - // get total size - size_t total_size = _MAX(_MAX(hdr.fac.offset.get() + hdr.fac.size.get(), hdr.sac.offset.get() + hdr.sac.size.get()), hdr.kc.offset.get() + hdr.kc.size.get()); - - // validate binary size - if (len < total_size) - { - throw fnd::Exception(kModuleName, "AccessControlInfoDesc binary is too small"); - } - - // allocate memory for header - mRawBinary.alloc(total_size); - memcpy(mRawBinary.data(), data, mRawBinary.size()); - - // save variables - memcpy(mNcaHeaderSignature2Key.modulus, hdr.nca_rsa_signature2_modulus, fnd::rsa::kRsa2048Size); - - for (size_t i = 0; i < 32; i++) - { - if (_HAS_BIT(hdr.flags.get(), i)) - mFlags.addElement((aci::Flag)i); - } - - mProgramIdRestrict.min = hdr.program_id_min.get(); - mProgramIdRestrict.max = hdr.program_id_max.get(); - - mFileSystemAccessControl.fromBytes(mRawBinary.data() + hdr.fac.offset.get(), hdr.fac.size.get()); - mServiceAccessControl.fromBytes(mRawBinary.data() + hdr.sac.offset.get(), hdr.sac.size.get()); - mKernelCapabilities.fromBytes(mRawBinary.data() + hdr.kc.offset.get(), hdr.kc.size.get()); -} - -const fnd::Vec& nn::hac::AccessControlInfoDescBinary::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::AccessControlInfoDescBinary::generateSignature(const fnd::rsa::sRsa2048Key& key) -{ - if (mRawBinary.size() == 0) - toBytes(); - - byte_t hash[fnd::sha::kSha256HashLen]; - fnd::sha::Sha256(mRawBinary.data() + fnd::rsa::kRsa2048Size, mRawBinary.size() - fnd::rsa::kRsa2048Size, hash); - - if (fnd::rsa::pss::rsaSign(key, fnd::sha::HASH_SHA256, hash, mRawBinary.data()) != 0) - { - throw fnd::Exception(kModuleName, "Failed to sign Access Control Info Desc"); - } -} - -void nn::hac::AccessControlInfoDescBinary::validateSignature(const fnd::rsa::sRsa2048Key& key) const -{ - if (mRawBinary.size() == 0) - throw fnd::Exception(kModuleName, "No Access Control Info Desc binary exists to verify"); - - byte_t hash[fnd::sha::kSha256HashLen]; - fnd::sha::Sha256(mRawBinary.data() + fnd::rsa::kRsa2048Size, mRawBinary.size() - fnd::rsa::kRsa2048Size, hash); - - if (fnd::rsa::pss::rsaVerify(key, fnd::sha::HASH_SHA256, hash, mRawBinary.data()) != 0) - { - throw fnd::Exception(kModuleName, "Failed to verify Access Control Info Desc"); - } -} - -void nn::hac::AccessControlInfoDescBinary::clear() -{ - mRawBinary.clear(); - memset((void*)&mNcaHeaderSignature2Key, 0, sizeof(mNcaHeaderSignature2Key)); - mFlags.clear(); - mProgramIdRestrict.min = 0; - mProgramIdRestrict.max = 0; - mFileSystemAccessControl.clear(); - mServiceAccessControl.clear(); - mKernelCapabilities.clear(); -} - -const fnd::rsa::sRsa2048Key& nn::hac::AccessControlInfoDescBinary::getNcaHeaderSignature2Key() const -{ - return mNcaHeaderSignature2Key; -} - -void nn::hac::AccessControlInfoDescBinary::setNcaHeaderSignature2Key(const fnd::rsa::sRsa2048Key& key) -{ - mNcaHeaderSignature2Key = key; -} - -const fnd::List& nn::hac::AccessControlInfoDescBinary::getFlagList() const -{ - return mFlags; -} - -void nn::hac::AccessControlInfoDescBinary::setFlagList(const fnd::List& flags) -{ - mFlags = flags; -} - -const nn::hac::AccessControlInfoDescBinary::sProgramIdRestrict& nn::hac::AccessControlInfoDescBinary::getProgramIdRestrict() const -{ - return mProgramIdRestrict; -} - -void nn::hac::AccessControlInfoDescBinary::setProgramIdRestrict(const sProgramIdRestrict& pid_restrict) -{ - mProgramIdRestrict = pid_restrict; -} - -const nn::hac::FileSystemAccessControlBinary& nn::hac::AccessControlInfoDescBinary::getFileSystemAccessControl() const -{ - return mFileSystemAccessControl; -} - -void nn::hac::AccessControlInfoDescBinary::setFileSystemAccessControl(const nn::hac::FileSystemAccessControlBinary& fac) -{ - mFileSystemAccessControl = fac; -} - -const nn::hac::ServiceAccessControlBinary& nn::hac::AccessControlInfoDescBinary::getServiceAccessControl() const -{ - return mServiceAccessControl; -} - -void nn::hac::AccessControlInfoDescBinary::setServiceAccessControl(const nn::hac::ServiceAccessControlBinary& sac) -{ - mServiceAccessControl = sac; -} - -const nn::hac::KernelCapabilityBinary& nn::hac::AccessControlInfoDescBinary::getKernelCapabilities() const -{ - return mKernelCapabilities; -} - -void nn::hac::AccessControlInfoDescBinary::setKernelCapabilities(const nn::hac::KernelCapabilityBinary& kc) -{ - mKernelCapabilities = kc; +#include + +nn::hac::AccessControlInfoDesc::AccessControlInfoDesc() +{ + clear(); +} + +nn::hac::AccessControlInfoDesc::AccessControlInfoDesc(const AccessControlInfoDesc & other) +{ + *this = other; +} + +void nn::hac::AccessControlInfoDesc::operator=(const AccessControlInfoDesc & other) +{ + mRawBinary = other.mRawBinary; + mContentArchiveHeaderSignature2Key = other.mContentArchiveHeaderSignature2Key; + mFlags = other.mFlags; + mProgramIdRestrict = other.mProgramIdRestrict; + mFileSystemAccessControl = other.mFileSystemAccessControl; + mServiceAccessControl = other.mServiceAccessControl; + mKernelCapabilities = other.mKernelCapabilities; +} + +bool nn::hac::AccessControlInfoDesc::operator==(const AccessControlInfoDesc & other) const +{ + return (mContentArchiveHeaderSignature2Key == other.mContentArchiveHeaderSignature2Key) \ + && (mFlags == other.mFlags) \ + && (mProgramIdRestrict == other.mProgramIdRestrict) \ + && (mFileSystemAccessControl == other.mFileSystemAccessControl) \ + && (mServiceAccessControl == other.mServiceAccessControl) \ + && (mKernelCapabilities == other.mKernelCapabilities); +} + +bool nn::hac::AccessControlInfoDesc::operator!=(const AccessControlInfoDesc & other) const +{ + return !(*this == other); +} + +void nn::hac::AccessControlInfoDesc::toBytes() +{ + // serialise the sections + mFileSystemAccessControl.toBytes(); + mServiceAccessControl.toBytes(); + mKernelCapabilities.toBytes(); + + // determine section layout + struct sLayout { + uint32_t offset, size; + } fac, sac, kc; + + fac.offset = (uint32_t)align(sizeof(sAciDescHeader), aci::kSectionAlignSize); + fac.size = (uint32_t)mFileSystemAccessControl.getBytes().size(); + sac.offset = (uint32_t)align(fac.offset + fac.size, aci::kSectionAlignSize); + sac.size = (uint32_t)mServiceAccessControl.getBytes().size(); + kc.offset = (uint32_t)align(sac.offset + sac.size, aci::kSectionAlignSize); + kc.size = (uint32_t)mKernelCapabilities.getBytes().size(); + + // get total size + size_t total_size = _MAX(_MAX(fac.offset + fac.size, sac.offset + sac.size), kc.offset + kc.size); + + mRawBinary.alloc(total_size); + sAciDescHeader* hdr = (sAciDescHeader*)mRawBinary.data(); + + // set rsa modulus + memcpy(hdr->nca_rsa_signature2_modulus, mContentArchiveHeaderSignature2Key.modulus, fnd::rsa::kRsa2048Size); + + // set type + hdr->st_magic = aci::kAciDescStructMagic; + + // set "acid size" + hdr->signed_size = (uint32_t)(total_size - fnd::rsa::kRsa2048Size); + + // set flags + uint32_t flags = 0; + for (size_t i = 0; i < mFlags.size(); i++) + flags |= _BIT(mFlags[i]); + hdr->flags = flags; + + // set program id restrict settings + hdr->program_id_min = mProgramIdRestrict.min; + hdr->program_id_max = mProgramIdRestrict.max; + + // set offset/size + hdr->fac.offset = fac.offset; + hdr->fac.size = fac.size; + hdr->sac.offset = sac.offset; + hdr->sac.size = sac.size; + hdr->kc.offset = kc.offset; + hdr->kc.size = kc.size; + + // write data + memcpy(mRawBinary.data() + fac.offset, mFileSystemAccessControl.getBytes().data(), fac.size); + memcpy(mRawBinary.data() + sac.offset, mServiceAccessControl.getBytes().data(), sac.size); + memcpy(mRawBinary.data() + kc.offset, mKernelCapabilities.getBytes().data(), kc.size); +} + +void nn::hac::AccessControlInfoDesc::fromBytes(const byte_t* data, size_t len) +{ + // check size + if (len < sizeof(sAciDescHeader)) + { + throw fnd::Exception(kModuleName, "AccessControlInfoDesc binary is too small"); + } + + // clear variables + clear(); + + // save a copy of the header + sAciDescHeader hdr; + memcpy((void*)&hdr, data, sizeof(sAciDescHeader)); + + // check magic + if (hdr.st_magic.get() != aci::kAciDescStructMagic) + { + throw fnd::Exception(kModuleName, "AccessControlInfoDesc header corrupt"); + } + + // get total size + size_t total_size = _MAX(_MAX(hdr.fac.offset.get() + hdr.fac.size.get(), hdr.sac.offset.get() + hdr.sac.size.get()), hdr.kc.offset.get() + hdr.kc.size.get()); + + // validate binary size + if (len < total_size) + { + throw fnd::Exception(kModuleName, "AccessControlInfoDesc binary is too small"); + } + + // allocate memory for header + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + // save variables + memcpy(mContentArchiveHeaderSignature2Key.modulus, hdr.nca_rsa_signature2_modulus, fnd::rsa::kRsa2048Size); + + for (size_t i = 0; i < 32; i++) + { + if (_HAS_BIT(hdr.flags.get(), i)) + mFlags.addElement((aci::Flag)i); + } + + mProgramIdRestrict.min = hdr.program_id_min.get(); + mProgramIdRestrict.max = hdr.program_id_max.get(); + + mFileSystemAccessControl.fromBytes(mRawBinary.data() + hdr.fac.offset.get(), hdr.fac.size.get()); + mServiceAccessControl.fromBytes(mRawBinary.data() + hdr.sac.offset.get(), hdr.sac.size.get()); + mKernelCapabilities.fromBytes(mRawBinary.data() + hdr.kc.offset.get(), hdr.kc.size.get()); +} + +const fnd::Vec& nn::hac::AccessControlInfoDesc::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::AccessControlInfoDesc::generateSignature(const fnd::rsa::sRsa2048Key& key) +{ + if (mRawBinary.size() == 0) + toBytes(); + + byte_t hash[fnd::sha::kSha256HashLen]; + fnd::sha::Sha256(mRawBinary.data() + fnd::rsa::kRsa2048Size, mRawBinary.size() - fnd::rsa::kRsa2048Size, hash); + + if (fnd::rsa::pss::rsaSign(key, fnd::sha::HASH_SHA256, hash, mRawBinary.data()) != 0) + { + throw fnd::Exception(kModuleName, "Failed to sign Access Control Info Desc"); + } +} + +void nn::hac::AccessControlInfoDesc::validateSignature(const fnd::rsa::sRsa2048Key& key) const +{ + if (mRawBinary.size() == 0) + throw fnd::Exception(kModuleName, "No Access Control Info Desc binary exists to verify"); + + byte_t hash[fnd::sha::kSha256HashLen]; + fnd::sha::Sha256(mRawBinary.data() + fnd::rsa::kRsa2048Size, mRawBinary.size() - fnd::rsa::kRsa2048Size, hash); + + if (fnd::rsa::pss::rsaVerify(key, fnd::sha::HASH_SHA256, hash, mRawBinary.data()) != 0) + { + throw fnd::Exception(kModuleName, "Failed to verify Access Control Info Desc"); + } +} + +void nn::hac::AccessControlInfoDesc::clear() +{ + mRawBinary.clear(); + memset((void*)&mContentArchiveHeaderSignature2Key, 0, sizeof(mContentArchiveHeaderSignature2Key)); + mFlags.clear(); + mProgramIdRestrict.min = 0; + mProgramIdRestrict.max = 0; + mFileSystemAccessControl.clear(); + mServiceAccessControl.clear(); + mKernelCapabilities.clear(); +} + +const fnd::rsa::sRsa2048Key& nn::hac::AccessControlInfoDesc::getContentArchiveHeaderSignature2Key() const +{ + return mContentArchiveHeaderSignature2Key; +} + +void nn::hac::AccessControlInfoDesc::setContentArchiveHeaderSignature2Key(const fnd::rsa::sRsa2048Key& key) +{ + mContentArchiveHeaderSignature2Key = key; +} + +const fnd::List& nn::hac::AccessControlInfoDesc::getFlagList() const +{ + return mFlags; +} + +void nn::hac::AccessControlInfoDesc::setFlagList(const fnd::List& flags) +{ + mFlags = flags; +} + +const nn::hac::AccessControlInfoDesc::sProgramIdRestrict& nn::hac::AccessControlInfoDesc::getProgramIdRestrict() const +{ + return mProgramIdRestrict; +} + +void nn::hac::AccessControlInfoDesc::setProgramIdRestrict(const sProgramIdRestrict& pid_restrict) +{ + mProgramIdRestrict = pid_restrict; +} + +const nn::hac::FileSystemAccessControl& nn::hac::AccessControlInfoDesc::getFileSystemAccessControl() const +{ + return mFileSystemAccessControl; +} + +void nn::hac::AccessControlInfoDesc::setFileSystemAccessControl(const nn::hac::FileSystemAccessControl& fac) +{ + mFileSystemAccessControl = fac; +} + +const nn::hac::ServiceAccessControl& nn::hac::AccessControlInfoDesc::getServiceAccessControl() const +{ + return mServiceAccessControl; +} + +void nn::hac::AccessControlInfoDesc::setServiceAccessControl(const nn::hac::ServiceAccessControl& sac) +{ + mServiceAccessControl = sac; +} + +const nn::hac::KernelCapabilityControl& nn::hac::AccessControlInfoDesc::getKernelCapabilities() const +{ + return mKernelCapabilities; +} + +void nn::hac::AccessControlInfoDesc::setKernelCapabilities(const nn::hac::KernelCapabilityControl& kc) +{ + mKernelCapabilities = kc; } \ No newline at end of file diff --git a/lib/libhac/source/AddOnContentMetaExtendedHeader.cpp b/lib/libhac/source/AddOnContentMetaExtendedHeader.cpp new file mode 100644 index 0000000..8d3f640 --- /dev/null +++ b/lib/libhac/source/AddOnContentMetaExtendedHeader.cpp @@ -0,0 +1,84 @@ +#include + +nn::hac::AddOnContentMetaExtendedHeader::AddOnContentMetaExtendedHeader() +{ + clear(); +} + +nn::hac::AddOnContentMetaExtendedHeader::AddOnContentMetaExtendedHeader(const AddOnContentMetaExtendedHeader& other) +{ + *this = other; +} + +void nn::hac::AddOnContentMetaExtendedHeader::operator=(const AddOnContentMetaExtendedHeader& other) +{ + clear(); + mRawBinary = other.mRawBinary; + mApplicationId = other.mApplicationId; + mRequiredApplicationVersion = other.mRequiredApplicationVersion; +} + +bool nn::hac::AddOnContentMetaExtendedHeader::operator==(const AddOnContentMetaExtendedHeader& other) const +{ + return (mApplicationId == other.mApplicationId) \ + && (mRequiredApplicationVersion == other.mRequiredApplicationVersion); +} + +bool nn::hac::AddOnContentMetaExtendedHeader::operator!=(const AddOnContentMetaExtendedHeader& other) const +{ + return !(*this == other); +} + +void nn::hac::AddOnContentMetaExtendedHeader::toBytes() +{ + mRawBinary.alloc(sizeof(sAddOnContentMetaExtendedHeader)); + sAddOnContentMetaExtendedHeader* info = (sAddOnContentMetaExtendedHeader*)mRawBinary.data(); + + info->application_id = mApplicationId; + info->required_application_version = mRequiredApplicationVersion; +} + +void nn::hac::AddOnContentMetaExtendedHeader::fromBytes(const byte_t* bytes, size_t len) +{ + if (len < sizeof(sAddOnContentMetaExtendedHeader)) + { + throw fnd::Exception(kModuleName, "AddOnContentMetaExtendedHeader too small"); + } + + const sAddOnContentMetaExtendedHeader* info = (const sAddOnContentMetaExtendedHeader*)bytes; + + mApplicationId = info->application_id.get(); + mRequiredApplicationVersion = info->required_application_version.get(); +} + +const fnd::Vec& nn::hac::AddOnContentMetaExtendedHeader::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::AddOnContentMetaExtendedHeader::clear() +{ + mRawBinary.clear(); + mApplicationId = 0; + mRequiredApplicationVersion = 0; +} + +uint64_t nn::hac::AddOnContentMetaExtendedHeader::getApplicationId() const +{ + return mApplicationId; +} + +void nn::hac::AddOnContentMetaExtendedHeader::setApplicationId(uint64_t application_id) +{ + mApplicationId = application_id; +} + +uint32_t nn::hac::AddOnContentMetaExtendedHeader::getRequiredApplicationVersion() const +{ + return mRequiredApplicationVersion; +} + +void nn::hac::AddOnContentMetaExtendedHeader::setRequiredApplicationVersion(uint32_t sys_ver) +{ + mRequiredApplicationVersion = sys_ver; +} \ No newline at end of file diff --git a/lib/libhac/source/ApplicationControlPropertyBinary.cpp b/lib/libhac/source/ApplicationControlProperty.cpp similarity index 68% rename from lib/libhac/source/ApplicationControlPropertyBinary.cpp rename to lib/libhac/source/ApplicationControlProperty.cpp index e8bd9c3..8e58271 100644 --- a/lib/libhac/source/ApplicationControlPropertyBinary.cpp +++ b/lib/libhac/source/ApplicationControlProperty.cpp @@ -1,716 +1,716 @@ -#include -#include - -nn::hac::ApplicationControlPropertyBinary::ApplicationControlPropertyBinary() -{ - clear(); -} - -nn::hac::ApplicationControlPropertyBinary::ApplicationControlPropertyBinary(const ApplicationControlPropertyBinary& other) -{ - *this = other; -} - -void nn::hac::ApplicationControlPropertyBinary::operator=(const ApplicationControlPropertyBinary& other) -{ - clear(); - mTitle = other.mTitle; - mIsbn = other.mIsbn; - mStartupUserAccount = other.mStartupUserAccount; - mTouchScreenUsageMode = other.mTouchScreenUsageMode; - mAocRegistrationType = other.mAocRegistrationType; - mAttributeFlag = other.mAttributeFlag; - mSupportedLanguages = other.mSupportedLanguages; - mParentalControlFlag = other.mParentalControlFlag; - mScreenshotMode = other.mScreenshotMode; - mVideoCaptureMode = other.mVideoCaptureMode; - mDataLossConfirmation = other.mDataLossConfirmation; - mPlayLogPolicy = other.mPlayLogPolicy; - mPresenceGroupId = other.mPresenceGroupId; - mRatingAge = other.mRatingAge; - mDisplayVersion = other.mDisplayVersion; - mAocBaseId = other.mAocBaseId; - mSaveDatawOwnerId = other.mSaveDatawOwnerId; - mUserAccountSaveDataSize = other.mUserAccountSaveDataSize; - mDeviceSaveDataSize = other.mDeviceSaveDataSize; - mBcatDeliveryCacheStorageSize = other.mBcatDeliveryCacheStorageSize; - mApplicationErrorCodeCategory = other.mApplicationErrorCodeCategory; - mLocalCommunicationId = other.mLocalCommunicationId; - mLogoType = other.mLogoType; - mLogoHandling = other.mLogoHandling; - mRuntimeAocInstallMode = other.mRuntimeAocInstallMode; - mCrashReportMode = other.mCrashReportMode; - mHdcp = other.mHdcp; - mSeedForPsuedoDeviceId = other.mSeedForPsuedoDeviceId; - mBcatPassphase = other.mBcatPassphase; - mUserAccountSaveDataMax = other.mUserAccountSaveDataMax; - mDeviceSaveDataMax = other.mDeviceSaveDataMax; - mTemporaryStorageSize = other.mTemporaryStorageSize; - mCacheStorageSize = other.mCacheStorageSize; - mCacheStorageDataAndJournalSizeMax = other.mCacheStorageDataAndJournalSizeMax; - mCacheStorageIndexMax = other.mCacheStorageIndexMax; - mPlayLogQueryableApplicationId = other.mPlayLogQueryableApplicationId; - mPlayLogQueryCapability = other.mPlayLogQueryCapability; - mRepairFlag = other.mRepairFlag; - mProgramIndex = other.mProgramIndex; -} - -bool nn::hac::ApplicationControlPropertyBinary::operator==(const ApplicationControlPropertyBinary& other) const -{ - return (mTitle == other.mTitle) \ - && (mIsbn == other.mIsbn) \ - && (mStartupUserAccount == other.mStartupUserAccount) \ - && (mTouchScreenUsageMode == other.mTouchScreenUsageMode) \ - && (mAocRegistrationType == other.mAocRegistrationType) \ - && (mAttributeFlag == other.mAttributeFlag) \ - && (mSupportedLanguages == other.mSupportedLanguages) \ - && (mParentalControlFlag == other.mParentalControlFlag) \ - && (mScreenshotMode == other.mScreenshotMode) \ - && (mVideoCaptureMode == other.mVideoCaptureMode) \ - && (mDataLossConfirmation == other.mDataLossConfirmation) \ - && (mPlayLogPolicy == other.mPlayLogPolicy) \ - && (mPresenceGroupId == other.mPresenceGroupId) \ - && (mRatingAge == other.mRatingAge) \ - && (mDisplayVersion == other.mDisplayVersion) \ - && (mAocBaseId == other.mAocBaseId) \ - && (mSaveDatawOwnerId == other.mSaveDatawOwnerId) \ - && (mUserAccountSaveDataSize == other.mUserAccountSaveDataSize) \ - && (mDeviceSaveDataSize == other.mDeviceSaveDataSize) \ - && (mBcatDeliveryCacheStorageSize == other.mBcatDeliveryCacheStorageSize) \ - && (mApplicationErrorCodeCategory == other.mApplicationErrorCodeCategory) \ - && (mLocalCommunicationId == other.mLocalCommunicationId) \ - && (mLogoType == other.mLogoType) \ - && (mLogoHandling == other.mLogoHandling) \ - && (mRuntimeAocInstallMode == other.mRuntimeAocInstallMode) \ - && (mCrashReportMode == other.mCrashReportMode) \ - && (mHdcp == other.mHdcp) \ - && (mSeedForPsuedoDeviceId == other.mSeedForPsuedoDeviceId) \ - && (mBcatPassphase == other.mBcatPassphase) \ - && (mUserAccountSaveDataMax == other.mUserAccountSaveDataMax) \ - && (mDeviceSaveDataMax == other.mDeviceSaveDataMax) \ - && (mTemporaryStorageSize == other.mTemporaryStorageSize) \ - && (mCacheStorageSize == other.mCacheStorageSize) \ - && (mCacheStorageDataAndJournalSizeMax == other.mCacheStorageDataAndJournalSizeMax) \ - && (mCacheStorageIndexMax == other.mCacheStorageIndexMax) \ - && (mPlayLogQueryableApplicationId == other.mPlayLogQueryableApplicationId) \ - && (mPlayLogQueryCapability == other.mPlayLogQueryCapability) \ - && (mRepairFlag == other.mRepairFlag) \ - && (mProgramIndex == other.mProgramIndex); -} - -bool nn::hac::ApplicationControlPropertyBinary::operator!=(const ApplicationControlPropertyBinary& other) const -{ - return !(*this == other); -} - -void nn::hac::ApplicationControlPropertyBinary::toBytes() -{ - mRawBinary.alloc(sizeof(nn::hac::sApplicationControlProperty)); - - sApplicationControlProperty* data = (sApplicationControlProperty*)mRawBinary.data(); - - // strings - for (size_t i = 0; i < mTitle.size(); i++) - { - strncpy(data->title[mTitle[i].language].name, mTitle[i].name.c_str(), nacp::kNameLength); - strncpy(data->title[mTitle[i].language].publisher, mTitle[i].publisher.c_str(), nacp::kPublisherLength); - } - - uint32_t supported_langs = 0; - for (size_t i = 0; i < mSupportedLanguages.size(); i++) - { - supported_langs |= _BIT(mSupportedLanguages[i]); - } - data->supported_language_flag = supported_langs; - - strncpy(data->isbn, mIsbn.c_str(), nacp::kIsbnLength); - strncpy(data->display_version, mDisplayVersion.c_str(), nacp::kDisplayVersionLength); - strncpy(data->application_error_code_category, mApplicationErrorCodeCategory.c_str(), nacp::kApplicationErrorCodeCategoryLength); - strncpy(data->bcat_passphrase, mBcatPassphase.c_str(), nacp::kBcatPassphraseLength); - - // enum type casts - data->startup_user_account = mStartupUserAccount; - data->touch_screen_usage = mTouchScreenUsageMode; - data->add_on_content_registration_type = mAocRegistrationType; - data->attribute_flag = mAttributeFlag; - data->parental_control_flag = mParentalControlFlag; - data->screenshot = mScreenshotMode; - data->video_capture = mVideoCaptureMode; - data->data_loss_confirmation = mDataLossConfirmation; - data->play_log_policy = mPlayLogPolicy; - data->logo_type = mLogoType; - data->logo_handling = mLogoHandling; - data->runtime_add_on_content_install = mRuntimeAocInstallMode; - data->crash_report = mCrashReportMode; - data->hdcp = mHdcp; - data->play_log_query_capability = mPlayLogQueryCapability; - data->repair_flag = mRepairFlag; - - // misc params - data->presence_group_id = mPresenceGroupId; - memset(data->rating_age, nacp::kUnusedAgeRating, nacp::kRatingAgeCount); // clear ratings - for (size_t i = 0; i < mRatingAge.size(); i++) - { - data->rating_age[mRatingAge[i].organisation] = mRatingAge[i].age; - } - data->add_on_content_base_id = mAocBaseId; - data->save_data_owner_id = mSaveDatawOwnerId; - for (size_t i = 0; i < mLocalCommunicationId.size() && i < nacp::kLocalCommunicationIdCount; i++) - { - data->local_communication_id[i] = mLocalCommunicationId[i]; - } - data->seed_for_pseudo_device_id = mSeedForPsuedoDeviceId; - for (size_t i = 0; i < mPlayLogQueryableApplicationId.size() && i < nacp::kPlayLogQueryableApplicationIdCount; i++) - { - data->play_log_queryable_application_id[i] = mPlayLogQueryableApplicationId[i]; - } - data->cache_storage_index_max = mCacheStorageIndexMax; - data->program_index = mProgramIndex; - - // sizes - data->user_account_save_data_size = mUserAccountSaveDataSize.size; - data->user_account_save_data_journal_size = mUserAccountSaveDataSize.journal_size; - data->device_save_data_size = mDeviceSaveDataSize.size; - data->device_save_data_journal_size = mDeviceSaveDataSize.journal_size; - data->bcat_delivery_cache_storage_size = mBcatDeliveryCacheStorageSize; - data->user_account_save_data_size_max = mUserAccountSaveDataMax.size; - data->user_account_save_data_journal_size_max = mUserAccountSaveDataMax.journal_size; - data->device_save_data_size_max = mDeviceSaveDataMax.size; - data->device_save_data_journal_size_max = mDeviceSaveDataMax.journal_size; - data->temporary_storage_size = mTemporaryStorageSize; - data->cache_storage_size = mCacheStorageSize.size; - data->cache_storage_journal_size = mCacheStorageSize.journal_size; - data->cache_storage_data_and_journal_size_max = mCacheStorageDataAndJournalSizeMax; -} - -void nn::hac::ApplicationControlPropertyBinary::fromBytes(const byte_t* bytes, size_t len) -{ - if (len < sizeof(nn::hac::sApplicationControlProperty)) - { - throw fnd::Exception(kModuleName, "NACP too small"); - } - - clear(); - - mRawBinary.alloc(sizeof(nn::hac::sApplicationControlProperty)); - memcpy(mRawBinary.data(), bytes, mRawBinary.size()); - - const sApplicationControlProperty* data = (const sApplicationControlProperty*)mRawBinary.data(); - - // strings - for (size_t i = 0; i < nacp::kMaxLanguageCount; i++) - { - if (_HAS_BIT(data->supported_language_flag.get(), i)) - { - mSupportedLanguages.addElement((nacp::Language)i); - } - if (data->title[i].name[0] != '\0' && data->title[i].publisher[0] != '\0') - { - mTitle.addElement({ (nacp::Language)i, std::string(data->title[i].name, _MIN(strlen(data->title[i].name), nacp::kNameLength)), std::string(data->title[i].publisher, _MIN(strlen(data->title[i].publisher), nacp::kPublisherLength)) }); - } - } - - if (data->isbn[0] != 0) - mIsbn = std::string(data->isbn, _MIN(strlen(data->isbn), nacp::kIsbnLength)); - if (data->display_version[0] != 0) - mDisplayVersion = std::string(data->display_version, _MIN(strlen(data->display_version), nacp::kDisplayVersionLength)); - if (data->application_error_code_category[0] != 0) - mApplicationErrorCodeCategory = std::string(data->application_error_code_category, _MIN(strlen(data->application_error_code_category), nacp::kApplicationErrorCodeCategoryLength)); - if (data->bcat_passphrase[0] != 0) - mBcatPassphase = std::string(data->bcat_passphrase, _MIN(strlen(data->bcat_passphrase), nacp::kBcatPassphraseLength)); - - // enum type casts - mStartupUserAccount = (nacp::StartupUserAccount)data->startup_user_account; - mTouchScreenUsageMode = (nacp::TouchScreenUsageMode)data->touch_screen_usage; - mAocRegistrationType = (nacp::AocRegistrationType)data->add_on_content_registration_type; - mAttributeFlag = (nacp::AttributeFlag)data->attribute_flag.get(); - mParentalControlFlag = (nacp::ParentalControlFlag)data->parental_control_flag.get(); - mScreenshotMode = (nacp::ScreenshotMode)data->screenshot; - mVideoCaptureMode = (nacp::VideoCaptureMode)data->video_capture; - mDataLossConfirmation = (nacp::DataLossConfirmation)data->data_loss_confirmation; - mPlayLogPolicy = (nacp::PlayLogPolicy)data->play_log_policy; - mLogoType = (nacp::LogoType)data->logo_type; - mLogoHandling = (nacp::LogoHandling)data->logo_handling; - mRuntimeAocInstallMode = (nacp::RuntimeAocInstallMode)data->runtime_add_on_content_install; - mCrashReportMode = (nacp::CrashReportMode)data->crash_report; - mHdcp = (nacp::Hdcp)data->hdcp; - mPlayLogQueryCapability = (nacp::PlayLogQueryCapability)data->play_log_query_capability; - mRepairFlag = (nacp::RepairFlag)data->repair_flag; - - // misc params - mPresenceGroupId = data->presence_group_id.get(); - for (size_t i = 0; i < nacp::kRatingAgeCount; i++) - { - if (data->rating_age[i] != nacp::kUnusedAgeRating) - mRatingAge.addElement({(nacp::Organisation)i, data->rating_age[i]}); - } - mAocBaseId = data->add_on_content_base_id.get(); - mSaveDatawOwnerId = data->save_data_owner_id.get(); - for (size_t i = 0; i < nacp::kLocalCommunicationIdCount; i++) - { - if (data->local_communication_id[i].get() != 0) - mLocalCommunicationId.addElement(data->local_communication_id[i].get()); - } - mSeedForPsuedoDeviceId = data->seed_for_pseudo_device_id.get(); - for (size_t i = 0; i < nacp::kPlayLogQueryableApplicationIdCount; i++) - { - if (data->play_log_queryable_application_id[i].get() != 0) - mPlayLogQueryableApplicationId.addElement(data->play_log_queryable_application_id[i].get()); - } - mCacheStorageIndexMax = data->cache_storage_index_max.get(); - mProgramIndex = data->program_index; - - // sizes - mUserAccountSaveDataSize.size = (int64_t)data->user_account_save_data_size.get(); - mUserAccountSaveDataSize.journal_size = (int64_t)data->user_account_save_data_journal_size.get(); - mDeviceSaveDataSize.size = (int64_t)data->device_save_data_size.get(); - mDeviceSaveDataSize.journal_size = (int64_t)data->device_save_data_journal_size.get(); - mBcatDeliveryCacheStorageSize = (int64_t)data->bcat_delivery_cache_storage_size.get(); - mUserAccountSaveDataMax.size = (int64_t)data->user_account_save_data_size_max.get(); - mUserAccountSaveDataMax.journal_size = (int64_t)data->user_account_save_data_journal_size_max.get(); - mDeviceSaveDataMax.size = (int64_t)data->device_save_data_size_max.get(); - mDeviceSaveDataMax.journal_size = (int64_t)data->device_save_data_journal_size_max.get(); - mTemporaryStorageSize = (int64_t)data->temporary_storage_size.get(); - mCacheStorageSize.size = (int64_t)data->cache_storage_size.get(); - mCacheStorageSize.journal_size = (int64_t)data->cache_storage_journal_size.get(); - mCacheStorageDataAndJournalSizeMax = (int64_t)data->cache_storage_data_and_journal_size_max.get(); -} - -const fnd::Vec& nn::hac::ApplicationControlPropertyBinary::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::ApplicationControlPropertyBinary::clear() -{ - mRawBinary.clear(); - mTitle.clear(); - mIsbn.clear(); - mStartupUserAccount = nacp::USER_None; - mTouchScreenUsageMode = nacp::TOUCH_None; - mAocRegistrationType = nacp::AOC_AllOnLaunch; - mAttributeFlag = nacp::ATTR_None; - mSupportedLanguages.clear(); - mParentalControlFlag = nacp::PC_None; - mScreenshotMode = nacp::SCRN_Allow; - mVideoCaptureMode = nacp::VCAP_Disable; - mDataLossConfirmation = nacp::DLOSS_None; - mPlayLogPolicy = nacp::PLP_All; - mPresenceGroupId = 0; - mRatingAge.clear(); - mDisplayVersion.clear(); - mAocBaseId = 0; - mSaveDatawOwnerId = 0; - mUserAccountSaveDataSize = {0, 0}; - mDeviceSaveDataSize = {0, 0}; - mBcatDeliveryCacheStorageSize = 0; - mApplicationErrorCodeCategory.clear(); - mLocalCommunicationId.clear(); - mLogoType = nacp::LOGO_Nintendo; - mLogoHandling = nacp::LHND_Auto; - mRuntimeAocInstallMode = nacp::RTAOC_Deny; - mCrashReportMode = nacp::CREP_Deny; - mHdcp = nacp::HDCP_None; - mSeedForPsuedoDeviceId = 0; - mBcatPassphase.clear(); - mUserAccountSaveDataMax; - mDeviceSaveDataMax = {0, 0}; - mTemporaryStorageSize = 0; - mCacheStorageSize = {0, 0}; - mCacheStorageDataAndJournalSizeMax = 0; - mCacheStorageIndexMax = 0; - mPlayLogQueryableApplicationId.clear(); - mPlayLogQueryCapability = nacp::PLQC_None; - mRepairFlag = nacp::REPF_None; - mProgramIndex = 0; -} - -const fnd::List& nn::hac::ApplicationControlPropertyBinary::getTitle() const -{ - return mTitle; -} - -void nn::hac::ApplicationControlPropertyBinary::setTitle(const fnd::List& title) -{ - mTitle = title; -} - -const std::string& nn::hac::ApplicationControlPropertyBinary::getIsbn() const -{ - return mIsbn; -} - -void nn::hac::ApplicationControlPropertyBinary::setIsbn(const std::string& isbn) -{ - mIsbn = isbn; -} - -nn::hac::nacp::StartupUserAccount nn::hac::ApplicationControlPropertyBinary::getStartupUserAccount() const -{ - return mStartupUserAccount; -} - -void nn::hac::ApplicationControlPropertyBinary::setStartupUserAccount(nacp::StartupUserAccount var) -{ - mStartupUserAccount = var; -} - -nn::hac::nacp::TouchScreenUsageMode nn::hac::ApplicationControlPropertyBinary::getTouchScreenUsageMode() const -{ - return mTouchScreenUsageMode; -} - -void nn::hac::ApplicationControlPropertyBinary::setTouchScreenUsageMode(nacp::TouchScreenUsageMode var) -{ - mTouchScreenUsageMode = var; -} - -nn::hac::nacp::AocRegistrationType nn::hac::ApplicationControlPropertyBinary::getAocRegistrationType() const -{ - return mAocRegistrationType; -} - -void nn::hac::ApplicationControlPropertyBinary::setAocRegistrationType(nacp::AocRegistrationType var) -{ - mAocRegistrationType = var; -} - -nn::hac::nacp::AttributeFlag nn::hac::ApplicationControlPropertyBinary::getAttributeFlag() const -{ - return mAttributeFlag; -} - -void nn::hac::ApplicationControlPropertyBinary::setAttributeFlag(nacp::AttributeFlag var) -{ - mAttributeFlag = var; -} - -const fnd::List& nn::hac::ApplicationControlPropertyBinary::getSupportedLanguages() const -{ - return mSupportedLanguages; -} - -void nn::hac::ApplicationControlPropertyBinary::setSupportedLanguages(const fnd::List& var) -{ - mSupportedLanguages = var; -} - -nn::hac::nacp::ParentalControlFlag nn::hac::ApplicationControlPropertyBinary::getParentalControlFlag() const -{ - return mParentalControlFlag; -} - -void nn::hac::ApplicationControlPropertyBinary::setParentalControlFlag(nacp::ParentalControlFlag var) -{ - mParentalControlFlag = var; -} - -nn::hac::nacp::ScreenshotMode nn::hac::ApplicationControlPropertyBinary::getScreenshotMode() const -{ - return mScreenshotMode; -} - -void nn::hac::ApplicationControlPropertyBinary::setScreenshotMode(nacp::ScreenshotMode var) -{ - mScreenshotMode = var; -} - -nn::hac::nacp::VideoCaptureMode nn::hac::ApplicationControlPropertyBinary::getVideoCaptureMode() const -{ - return mVideoCaptureMode; -} - -void nn::hac::ApplicationControlPropertyBinary::setVideoCaptureMode(nacp::VideoCaptureMode var) -{ - mVideoCaptureMode = var; -} - -nn::hac::nacp::DataLossConfirmation nn::hac::ApplicationControlPropertyBinary::getDataLossConfirmation() const -{ - return mDataLossConfirmation; -} - -void nn::hac::ApplicationControlPropertyBinary::setDataLossConfirmation(nacp::DataLossConfirmation var) -{ - mDataLossConfirmation = var; -} - -nn::hac::nacp::PlayLogPolicy nn::hac::ApplicationControlPropertyBinary::getPlayLogPolicy() const -{ - return mPlayLogPolicy; -} - -void nn::hac::ApplicationControlPropertyBinary::setPlayLogPolicy(nacp::PlayLogPolicy var) -{ - mPlayLogPolicy = var; -} - -uint64_t nn::hac::ApplicationControlPropertyBinary::getPresenceGroupId() const -{ - return mPresenceGroupId; -} - -void nn::hac::ApplicationControlPropertyBinary::setPresenceGroupId(uint64_t var) -{ - mPresenceGroupId = var; -} - -const fnd::List& nn::hac::ApplicationControlPropertyBinary::getRatingAge() const -{ - return mRatingAge; -} - -void nn::hac::ApplicationControlPropertyBinary::setRatingAge(const fnd::List& var) -{ - mRatingAge = var; -} - -const std::string& nn::hac::ApplicationControlPropertyBinary::getDisplayVersion() const -{ - return mDisplayVersion; -} - -void nn::hac::ApplicationControlPropertyBinary::setDisplayVersion(const std::string& var) -{ - mDisplayVersion = var; -} - -uint64_t nn::hac::ApplicationControlPropertyBinary::getAocBaseId() const -{ - return mAocBaseId; -} - -void nn::hac::ApplicationControlPropertyBinary::setAocBaseId(uint64_t var) -{ - mAocBaseId = var; -} - -uint64_t nn::hac::ApplicationControlPropertyBinary::getSaveDatawOwnerId() const -{ - return mSaveDatawOwnerId; -} - -void nn::hac::ApplicationControlPropertyBinary::setSaveDatawOwnerId(uint64_t var) -{ - mSaveDatawOwnerId = var; -} - -const nn::hac::ApplicationControlPropertyBinary::sStorageSize& nn::hac::ApplicationControlPropertyBinary::getUserAccountSaveDataSize() const -{ - return mUserAccountSaveDataSize; -} - -void nn::hac::ApplicationControlPropertyBinary::setUserAccountSaveDataSize(const sStorageSize& var) -{ - mUserAccountSaveDataSize = var; -} - -const nn::hac::ApplicationControlPropertyBinary::sStorageSize& nn::hac::ApplicationControlPropertyBinary::getDeviceSaveDataSize() const -{ - return mDeviceSaveDataSize; -} - -void nn::hac::ApplicationControlPropertyBinary::setDeviceSaveDataSize(const sStorageSize& var) -{ - mDeviceSaveDataSize = var; -} - -int64_t nn::hac::ApplicationControlPropertyBinary::getBcatDeliveryCacheStorageSize() const -{ - return mBcatDeliveryCacheStorageSize; -} - -void nn::hac::ApplicationControlPropertyBinary::setBcatDeliveryCacheStorageSize(int64_t var) -{ - mBcatDeliveryCacheStorageSize = var; -} - -const std::string& nn::hac::ApplicationControlPropertyBinary::getApplicationErrorCodeCategory() const -{ - return mApplicationErrorCodeCategory; -} - -void nn::hac::ApplicationControlPropertyBinary::setApplicationErrorCodeCategory(const std::string& var) -{ - mApplicationErrorCodeCategory = var; -} - -const fnd::List& nn::hac::ApplicationControlPropertyBinary::getLocalCommunicationId() const -{ - return mLocalCommunicationId; -} - -void nn::hac::ApplicationControlPropertyBinary::setLocalCommunicationId(const fnd::List& var) -{ - mLocalCommunicationId = var; -} - -nn::hac::nacp::LogoType nn::hac::ApplicationControlPropertyBinary::getLogoType() const -{ - return mLogoType; -} - -void nn::hac::ApplicationControlPropertyBinary::setLogoType(nacp::LogoType var) -{ - mLogoType = var; -} - -nn::hac::nacp::LogoHandling nn::hac::ApplicationControlPropertyBinary::getLogoHandling() const -{ - return mLogoHandling; -} - -void nn::hac::ApplicationControlPropertyBinary::setLogoHandling(nacp::LogoHandling var) -{ - mLogoHandling = var; -} - -nn::hac::nacp::RuntimeAocInstallMode nn::hac::ApplicationControlPropertyBinary::getRuntimeAocInstallMode() const -{ - return mRuntimeAocInstallMode; -} - -void nn::hac::ApplicationControlPropertyBinary::setRuntimeAocInstallMode(nacp::RuntimeAocInstallMode var) -{ - mRuntimeAocInstallMode = var; -} - -nn::hac::nacp::CrashReportMode nn::hac::ApplicationControlPropertyBinary::getCrashReportMode() const -{ - return mCrashReportMode; -} - -void nn::hac::ApplicationControlPropertyBinary::setCrashReportMode(nacp::CrashReportMode var) -{ - mCrashReportMode = var; -} - -nn::hac::nacp::Hdcp nn::hac::ApplicationControlPropertyBinary::getHdcp() const -{ - return mHdcp; -} - -void nn::hac::ApplicationControlPropertyBinary::setHdcp(nacp::Hdcp var) -{ - mHdcp = var; -} - -uint64_t nn::hac::ApplicationControlPropertyBinary::getSeedForPsuedoDeviceId() const -{ - return mSeedForPsuedoDeviceId; -} - -void nn::hac::ApplicationControlPropertyBinary::setSeedForPsuedoDeviceId(uint64_t var) -{ - mSeedForPsuedoDeviceId = var; -} - -const std::string& nn::hac::ApplicationControlPropertyBinary::getBcatPassphase() const -{ - return mBcatPassphase; -} - -void nn::hac::ApplicationControlPropertyBinary::setBcatPassphase(const std::string& var) -{ - mBcatPassphase = var; -} - -const nn::hac::ApplicationControlPropertyBinary::sStorageSize& nn::hac::ApplicationControlPropertyBinary::getUserAccountSaveDataMax() const -{ - return mUserAccountSaveDataMax; -} - -void nn::hac::ApplicationControlPropertyBinary::setUserAccountSaveDataMax(const sStorageSize& var) -{ - mUserAccountSaveDataMax = var; -} - -const nn::hac::ApplicationControlPropertyBinary::sStorageSize& nn::hac::ApplicationControlPropertyBinary::getDeviceSaveDataMax() const -{ - return mDeviceSaveDataMax; -} - -void nn::hac::ApplicationControlPropertyBinary::setDeviceSaveDataMax(const sStorageSize& var) -{ - mDeviceSaveDataMax = var; -} - -int64_t nn::hac::ApplicationControlPropertyBinary::getTemporaryStorageSize() const -{ - return mTemporaryStorageSize; -} - -void nn::hac::ApplicationControlPropertyBinary::setTemporaryStorageSize(int64_t var) -{ - mTemporaryStorageSize = var; -} - -const nn::hac::ApplicationControlPropertyBinary::sStorageSize& nn::hac::ApplicationControlPropertyBinary::getCacheStorageSize() const -{ - return mCacheStorageSize; -} - -void nn::hac::ApplicationControlPropertyBinary::setCacheStorageSize(const sStorageSize& var) -{ - mCacheStorageSize = var; -} - -int64_t nn::hac::ApplicationControlPropertyBinary::getCacheStorageDataAndJournalSizeMax() const -{ - return mCacheStorageDataAndJournalSizeMax; -} - -void nn::hac::ApplicationControlPropertyBinary::setCacheStorageDataAndJournalSizeMax(int64_t var) -{ - mCacheStorageDataAndJournalSizeMax = var; -} - -uint16_t nn::hac::ApplicationControlPropertyBinary::getCacheStorageIndexMax() const -{ - return mCacheStorageIndexMax; -} - -void nn::hac::ApplicationControlPropertyBinary::setCacheStorageIndexMax(uint16_t var) -{ - mCacheStorageIndexMax = var; -} - -const fnd::List& nn::hac::ApplicationControlPropertyBinary::getPlayLogQueryableApplicationId() const -{ - return mPlayLogQueryableApplicationId; -} - -void nn::hac::ApplicationControlPropertyBinary::setPlayLogQueryableApplicationId(const fnd::List& var) -{ - mPlayLogQueryableApplicationId = var; -} - -nn::hac::nacp::PlayLogQueryCapability nn::hac::ApplicationControlPropertyBinary::getPlayLogQueryCapability() const -{ - return mPlayLogQueryCapability; -} - -void nn::hac::ApplicationControlPropertyBinary::setPlayLogQueryCapability(nacp::PlayLogQueryCapability var) -{ - mPlayLogQueryCapability = var; -} - -nn::hac::nacp::RepairFlag nn::hac::ApplicationControlPropertyBinary::getRepairFlag() const -{ - return mRepairFlag; -} - -void nn::hac::ApplicationControlPropertyBinary::setRepairFlag(nacp::RepairFlag var) -{ - mRepairFlag = var; -} - -byte_t nn::hac::ApplicationControlPropertyBinary::getProgramIndex() const -{ - return mProgramIndex; -} - -void nn::hac::ApplicationControlPropertyBinary::setProgramIndex(byte_t var) -{ - mProgramIndex = var; +#include +#include + +nn::hac::ApplicationControlProperty::ApplicationControlProperty() +{ + clear(); +} + +nn::hac::ApplicationControlProperty::ApplicationControlProperty(const ApplicationControlProperty& other) +{ + *this = other; +} + +void nn::hac::ApplicationControlProperty::operator=(const ApplicationControlProperty& other) +{ + clear(); + mTitle = other.mTitle; + mIsbn = other.mIsbn; + mStartupUserAccount = other.mStartupUserAccount; + mTouchScreenUsageMode = other.mTouchScreenUsageMode; + mAocRegistrationType = other.mAocRegistrationType; + mAttributeFlag = other.mAttributeFlag; + mSupportedLanguages = other.mSupportedLanguages; + mParentalControlFlag = other.mParentalControlFlag; + mScreenshotMode = other.mScreenshotMode; + mVideoCaptureMode = other.mVideoCaptureMode; + mDataLossConfirmation = other.mDataLossConfirmation; + mPlayLogPolicy = other.mPlayLogPolicy; + mPresenceGroupId = other.mPresenceGroupId; + mRatingAge = other.mRatingAge; + mDisplayVersion = other.mDisplayVersion; + mAocBaseId = other.mAocBaseId; + mSaveDatawOwnerId = other.mSaveDatawOwnerId; + mUserAccountSaveDataSize = other.mUserAccountSaveDataSize; + mDeviceSaveDataSize = other.mDeviceSaveDataSize; + mBcatDeliveryCacheStorageSize = other.mBcatDeliveryCacheStorageSize; + mApplicationErrorCodeCategory = other.mApplicationErrorCodeCategory; + mLocalCommunicationId = other.mLocalCommunicationId; + mLogoType = other.mLogoType; + mLogoHandling = other.mLogoHandling; + mRuntimeAocInstallMode = other.mRuntimeAocInstallMode; + mCrashReportMode = other.mCrashReportMode; + mHdcp = other.mHdcp; + mSeedForPsuedoDeviceId = other.mSeedForPsuedoDeviceId; + mBcatPassphase = other.mBcatPassphase; + mUserAccountSaveDataMax = other.mUserAccountSaveDataMax; + mDeviceSaveDataMax = other.mDeviceSaveDataMax; + mTemporaryStorageSize = other.mTemporaryStorageSize; + mCacheStorageSize = other.mCacheStorageSize; + mCacheStorageDataAndJournalSizeMax = other.mCacheStorageDataAndJournalSizeMax; + mCacheStorageIndexMax = other.mCacheStorageIndexMax; + mPlayLogQueryableApplicationId = other.mPlayLogQueryableApplicationId; + mPlayLogQueryCapability = other.mPlayLogQueryCapability; + mRepairFlag = other.mRepairFlag; + mProgramIndex = other.mProgramIndex; +} + +bool nn::hac::ApplicationControlProperty::operator==(const ApplicationControlProperty& other) const +{ + return (mTitle == other.mTitle) \ + && (mIsbn == other.mIsbn) \ + && (mStartupUserAccount == other.mStartupUserAccount) \ + && (mTouchScreenUsageMode == other.mTouchScreenUsageMode) \ + && (mAocRegistrationType == other.mAocRegistrationType) \ + && (mAttributeFlag == other.mAttributeFlag) \ + && (mSupportedLanguages == other.mSupportedLanguages) \ + && (mParentalControlFlag == other.mParentalControlFlag) \ + && (mScreenshotMode == other.mScreenshotMode) \ + && (mVideoCaptureMode == other.mVideoCaptureMode) \ + && (mDataLossConfirmation == other.mDataLossConfirmation) \ + && (mPlayLogPolicy == other.mPlayLogPolicy) \ + && (mPresenceGroupId == other.mPresenceGroupId) \ + && (mRatingAge == other.mRatingAge) \ + && (mDisplayVersion == other.mDisplayVersion) \ + && (mAocBaseId == other.mAocBaseId) \ + && (mSaveDatawOwnerId == other.mSaveDatawOwnerId) \ + && (mUserAccountSaveDataSize == other.mUserAccountSaveDataSize) \ + && (mDeviceSaveDataSize == other.mDeviceSaveDataSize) \ + && (mBcatDeliveryCacheStorageSize == other.mBcatDeliveryCacheStorageSize) \ + && (mApplicationErrorCodeCategory == other.mApplicationErrorCodeCategory) \ + && (mLocalCommunicationId == other.mLocalCommunicationId) \ + && (mLogoType == other.mLogoType) \ + && (mLogoHandling == other.mLogoHandling) \ + && (mRuntimeAocInstallMode == other.mRuntimeAocInstallMode) \ + && (mCrashReportMode == other.mCrashReportMode) \ + && (mHdcp == other.mHdcp) \ + && (mSeedForPsuedoDeviceId == other.mSeedForPsuedoDeviceId) \ + && (mBcatPassphase == other.mBcatPassphase) \ + && (mUserAccountSaveDataMax == other.mUserAccountSaveDataMax) \ + && (mDeviceSaveDataMax == other.mDeviceSaveDataMax) \ + && (mTemporaryStorageSize == other.mTemporaryStorageSize) \ + && (mCacheStorageSize == other.mCacheStorageSize) \ + && (mCacheStorageDataAndJournalSizeMax == other.mCacheStorageDataAndJournalSizeMax) \ + && (mCacheStorageIndexMax == other.mCacheStorageIndexMax) \ + && (mPlayLogQueryableApplicationId == other.mPlayLogQueryableApplicationId) \ + && (mPlayLogQueryCapability == other.mPlayLogQueryCapability) \ + && (mRepairFlag == other.mRepairFlag) \ + && (mProgramIndex == other.mProgramIndex); +} + +bool nn::hac::ApplicationControlProperty::operator!=(const ApplicationControlProperty& other) const +{ + return !(*this == other); +} + +void nn::hac::ApplicationControlProperty::toBytes() +{ + mRawBinary.alloc(sizeof(nn::hac::sApplicationControlProperty)); + + sApplicationControlProperty* data = (sApplicationControlProperty*)mRawBinary.data(); + + // strings + for (size_t i = 0; i < mTitle.size(); i++) + { + strncpy(data->title[mTitle[i].language].name, mTitle[i].name.c_str(), nacp::kNameLength); + strncpy(data->title[mTitle[i].language].publisher, mTitle[i].publisher.c_str(), nacp::kPublisherLength); + } + + uint32_t supported_langs = 0; + for (size_t i = 0; i < mSupportedLanguages.size(); i++) + { + supported_langs |= _BIT(mSupportedLanguages[i]); + } + data->supported_language_flag = supported_langs; + + strncpy(data->isbn, mIsbn.c_str(), nacp::kIsbnLength); + strncpy(data->display_version, mDisplayVersion.c_str(), nacp::kDisplayVersionLength); + strncpy(data->application_error_code_category, mApplicationErrorCodeCategory.c_str(), nacp::kApplicationErrorCodeCategoryLength); + strncpy(data->bcat_passphrase, mBcatPassphase.c_str(), nacp::kBcatPassphraseLength); + + // enum type casts + data->startup_user_account = mStartupUserAccount; + data->touch_screen_usage = mTouchScreenUsageMode; + data->add_on_content_registration_type = mAocRegistrationType; + data->attribute_flag = mAttributeFlag; + data->parental_control_flag = mParentalControlFlag; + data->screenshot = mScreenshotMode; + data->video_capture = mVideoCaptureMode; + data->data_loss_confirmation = mDataLossConfirmation; + data->play_log_policy = mPlayLogPolicy; + data->logo_type = mLogoType; + data->logo_handling = mLogoHandling; + data->runtime_add_on_content_install = mRuntimeAocInstallMode; + data->crash_report = mCrashReportMode; + data->hdcp = mHdcp; + data->play_log_query_capability = mPlayLogQueryCapability; + data->repair_flag = mRepairFlag; + + // misc params + data->presence_group_id = mPresenceGroupId; + memset(data->rating_age, nacp::kUnusedAgeRating, nacp::kRatingAgeCount); // clear ratings + for (size_t i = 0; i < mRatingAge.size(); i++) + { + data->rating_age[mRatingAge[i].organisation] = mRatingAge[i].age; + } + data->add_on_content_base_id = mAocBaseId; + data->save_data_owner_id = mSaveDatawOwnerId; + for (size_t i = 0; i < mLocalCommunicationId.size() && i < nacp::kLocalCommunicationIdCount; i++) + { + data->local_communication_id[i] = mLocalCommunicationId[i]; + } + data->seed_for_pseudo_device_id = mSeedForPsuedoDeviceId; + for (size_t i = 0; i < mPlayLogQueryableApplicationId.size() && i < nacp::kPlayLogQueryableApplicationIdCount; i++) + { + data->play_log_queryable_application_id[i] = mPlayLogQueryableApplicationId[i]; + } + data->cache_storage_index_max = mCacheStorageIndexMax; + data->program_index = mProgramIndex; + + // sizes + data->user_account_save_data_size = mUserAccountSaveDataSize.size; + data->user_account_save_data_journal_size = mUserAccountSaveDataSize.journal_size; + data->device_save_data_size = mDeviceSaveDataSize.size; + data->device_save_data_journal_size = mDeviceSaveDataSize.journal_size; + data->bcat_delivery_cache_storage_size = mBcatDeliveryCacheStorageSize; + data->user_account_save_data_size_max = mUserAccountSaveDataMax.size; + data->user_account_save_data_journal_size_max = mUserAccountSaveDataMax.journal_size; + data->device_save_data_size_max = mDeviceSaveDataMax.size; + data->device_save_data_journal_size_max = mDeviceSaveDataMax.journal_size; + data->temporary_storage_size = mTemporaryStorageSize; + data->cache_storage_size = mCacheStorageSize.size; + data->cache_storage_journal_size = mCacheStorageSize.journal_size; + data->cache_storage_data_and_journal_size_max = mCacheStorageDataAndJournalSizeMax; +} + +void nn::hac::ApplicationControlProperty::fromBytes(const byte_t* bytes, size_t len) +{ + if (len < sizeof(nn::hac::sApplicationControlProperty)) + { + throw fnd::Exception(kModuleName, "NACP too small"); + } + + clear(); + + mRawBinary.alloc(sizeof(nn::hac::sApplicationControlProperty)); + memcpy(mRawBinary.data(), bytes, mRawBinary.size()); + + const sApplicationControlProperty* data = (const sApplicationControlProperty*)mRawBinary.data(); + + // strings + for (size_t i = 0; i < nacp::kMaxLanguageCount; i++) + { + if (_HAS_BIT(data->supported_language_flag.get(), i)) + { + mSupportedLanguages.addElement((nacp::Language)i); + } + if (data->title[i].name[0] != '\0' && data->title[i].publisher[0] != '\0') + { + mTitle.addElement({ (nacp::Language)i, std::string(data->title[i].name, _MIN(strlen(data->title[i].name), nacp::kNameLength)), std::string(data->title[i].publisher, _MIN(strlen(data->title[i].publisher), nacp::kPublisherLength)) }); + } + } + + if (data->isbn[0] != 0) + mIsbn = std::string(data->isbn, _MIN(strlen(data->isbn), nacp::kIsbnLength)); + if (data->display_version[0] != 0) + mDisplayVersion = std::string(data->display_version, _MIN(strlen(data->display_version), nacp::kDisplayVersionLength)); + if (data->application_error_code_category[0] != 0) + mApplicationErrorCodeCategory = std::string(data->application_error_code_category, _MIN(strlen(data->application_error_code_category), nacp::kApplicationErrorCodeCategoryLength)); + if (data->bcat_passphrase[0] != 0) + mBcatPassphase = std::string(data->bcat_passphrase, _MIN(strlen(data->bcat_passphrase), nacp::kBcatPassphraseLength)); + + // enum type casts + mStartupUserAccount = (nacp::StartupUserAccount)data->startup_user_account; + mTouchScreenUsageMode = (nacp::TouchScreenUsageMode)data->touch_screen_usage; + mAocRegistrationType = (nacp::AocRegistrationType)data->add_on_content_registration_type; + mAttributeFlag = (nacp::AttributeFlag)data->attribute_flag.get(); + mParentalControlFlag = (nacp::ParentalControlFlag)data->parental_control_flag.get(); + mScreenshotMode = (nacp::ScreenshotMode)data->screenshot; + mVideoCaptureMode = (nacp::VideoCaptureMode)data->video_capture; + mDataLossConfirmation = (nacp::DataLossConfirmation)data->data_loss_confirmation; + mPlayLogPolicy = (nacp::PlayLogPolicy)data->play_log_policy; + mLogoType = (nacp::LogoType)data->logo_type; + mLogoHandling = (nacp::LogoHandling)data->logo_handling; + mRuntimeAocInstallMode = (nacp::RuntimeAocInstallMode)data->runtime_add_on_content_install; + mCrashReportMode = (nacp::CrashReportMode)data->crash_report; + mHdcp = (nacp::Hdcp)data->hdcp; + mPlayLogQueryCapability = (nacp::PlayLogQueryCapability)data->play_log_query_capability; + mRepairFlag = (nacp::RepairFlag)data->repair_flag; + + // misc params + mPresenceGroupId = data->presence_group_id.get(); + for (size_t i = 0; i < nacp::kRatingAgeCount; i++) + { + if (data->rating_age[i] != nacp::kUnusedAgeRating) + mRatingAge.addElement({(nacp::Organisation)i, data->rating_age[i]}); + } + mAocBaseId = data->add_on_content_base_id.get(); + mSaveDatawOwnerId = data->save_data_owner_id.get(); + for (size_t i = 0; i < nacp::kLocalCommunicationIdCount; i++) + { + if (data->local_communication_id[i].get() != 0) + mLocalCommunicationId.addElement(data->local_communication_id[i].get()); + } + mSeedForPsuedoDeviceId = data->seed_for_pseudo_device_id.get(); + for (size_t i = 0; i < nacp::kPlayLogQueryableApplicationIdCount; i++) + { + if (data->play_log_queryable_application_id[i].get() != 0) + mPlayLogQueryableApplicationId.addElement(data->play_log_queryable_application_id[i].get()); + } + mCacheStorageIndexMax = data->cache_storage_index_max.get(); + mProgramIndex = data->program_index; + + // sizes + mUserAccountSaveDataSize.size = (int64_t)data->user_account_save_data_size.get(); + mUserAccountSaveDataSize.journal_size = (int64_t)data->user_account_save_data_journal_size.get(); + mDeviceSaveDataSize.size = (int64_t)data->device_save_data_size.get(); + mDeviceSaveDataSize.journal_size = (int64_t)data->device_save_data_journal_size.get(); + mBcatDeliveryCacheStorageSize = (int64_t)data->bcat_delivery_cache_storage_size.get(); + mUserAccountSaveDataMax.size = (int64_t)data->user_account_save_data_size_max.get(); + mUserAccountSaveDataMax.journal_size = (int64_t)data->user_account_save_data_journal_size_max.get(); + mDeviceSaveDataMax.size = (int64_t)data->device_save_data_size_max.get(); + mDeviceSaveDataMax.journal_size = (int64_t)data->device_save_data_journal_size_max.get(); + mTemporaryStorageSize = (int64_t)data->temporary_storage_size.get(); + mCacheStorageSize.size = (int64_t)data->cache_storage_size.get(); + mCacheStorageSize.journal_size = (int64_t)data->cache_storage_journal_size.get(); + mCacheStorageDataAndJournalSizeMax = (int64_t)data->cache_storage_data_and_journal_size_max.get(); +} + +const fnd::Vec& nn::hac::ApplicationControlProperty::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::ApplicationControlProperty::clear() +{ + mRawBinary.clear(); + mTitle.clear(); + mIsbn.clear(); + mStartupUserAccount = nacp::USER_None; + mTouchScreenUsageMode = nacp::TOUCH_None; + mAocRegistrationType = nacp::AOC_AllOnLaunch; + mAttributeFlag = nacp::ATTR_None; + mSupportedLanguages.clear(); + mParentalControlFlag = nacp::PC_None; + mScreenshotMode = nacp::SCRN_Allow; + mVideoCaptureMode = nacp::VCAP_Disable; + mDataLossConfirmation = nacp::DLOSS_None; + mPlayLogPolicy = nacp::PLP_All; + mPresenceGroupId = 0; + mRatingAge.clear(); + mDisplayVersion.clear(); + mAocBaseId = 0; + mSaveDatawOwnerId = 0; + mUserAccountSaveDataSize = {0, 0}; + mDeviceSaveDataSize = {0, 0}; + mBcatDeliveryCacheStorageSize = 0; + mApplicationErrorCodeCategory.clear(); + mLocalCommunicationId.clear(); + mLogoType = nacp::LOGO_Nintendo; + mLogoHandling = nacp::LHND_Auto; + mRuntimeAocInstallMode = nacp::RTAOC_Deny; + mCrashReportMode = nacp::CREP_Deny; + mHdcp = nacp::HDCP_None; + mSeedForPsuedoDeviceId = 0; + mBcatPassphase.clear(); + mUserAccountSaveDataMax; + mDeviceSaveDataMax = {0, 0}; + mTemporaryStorageSize = 0; + mCacheStorageSize = {0, 0}; + mCacheStorageDataAndJournalSizeMax = 0; + mCacheStorageIndexMax = 0; + mPlayLogQueryableApplicationId.clear(); + mPlayLogQueryCapability = nacp::PLQC_None; + mRepairFlag = nacp::REPF_None; + mProgramIndex = 0; +} + +const fnd::List& nn::hac::ApplicationControlProperty::getTitle() const +{ + return mTitle; +} + +void nn::hac::ApplicationControlProperty::setTitle(const fnd::List& title) +{ + mTitle = title; +} + +const std::string& nn::hac::ApplicationControlProperty::getIsbn() const +{ + return mIsbn; +} + +void nn::hac::ApplicationControlProperty::setIsbn(const std::string& isbn) +{ + mIsbn = isbn; +} + +nn::hac::nacp::StartupUserAccount nn::hac::ApplicationControlProperty::getStartupUserAccount() const +{ + return mStartupUserAccount; +} + +void nn::hac::ApplicationControlProperty::setStartupUserAccount(nacp::StartupUserAccount var) +{ + mStartupUserAccount = var; +} + +nn::hac::nacp::TouchScreenUsageMode nn::hac::ApplicationControlProperty::getTouchScreenUsageMode() const +{ + return mTouchScreenUsageMode; +} + +void nn::hac::ApplicationControlProperty::setTouchScreenUsageMode(nacp::TouchScreenUsageMode var) +{ + mTouchScreenUsageMode = var; +} + +nn::hac::nacp::AocRegistrationType nn::hac::ApplicationControlProperty::getAocRegistrationType() const +{ + return mAocRegistrationType; +} + +void nn::hac::ApplicationControlProperty::setAocRegistrationType(nacp::AocRegistrationType var) +{ + mAocRegistrationType = var; +} + +nn::hac::nacp::AttributeFlag nn::hac::ApplicationControlProperty::getAttributeFlag() const +{ + return mAttributeFlag; +} + +void nn::hac::ApplicationControlProperty::setAttributeFlag(nacp::AttributeFlag var) +{ + mAttributeFlag = var; +} + +const fnd::List& nn::hac::ApplicationControlProperty::getSupportedLanguages() const +{ + return mSupportedLanguages; +} + +void nn::hac::ApplicationControlProperty::setSupportedLanguages(const fnd::List& var) +{ + mSupportedLanguages = var; +} + +nn::hac::nacp::ParentalControlFlag nn::hac::ApplicationControlProperty::getParentalControlFlag() const +{ + return mParentalControlFlag; +} + +void nn::hac::ApplicationControlProperty::setParentalControlFlag(nacp::ParentalControlFlag var) +{ + mParentalControlFlag = var; +} + +nn::hac::nacp::ScreenshotMode nn::hac::ApplicationControlProperty::getScreenshotMode() const +{ + return mScreenshotMode; +} + +void nn::hac::ApplicationControlProperty::setScreenshotMode(nacp::ScreenshotMode var) +{ + mScreenshotMode = var; +} + +nn::hac::nacp::VideoCaptureMode nn::hac::ApplicationControlProperty::getVideoCaptureMode() const +{ + return mVideoCaptureMode; +} + +void nn::hac::ApplicationControlProperty::setVideoCaptureMode(nacp::VideoCaptureMode var) +{ + mVideoCaptureMode = var; +} + +nn::hac::nacp::DataLossConfirmation nn::hac::ApplicationControlProperty::getDataLossConfirmation() const +{ + return mDataLossConfirmation; +} + +void nn::hac::ApplicationControlProperty::setDataLossConfirmation(nacp::DataLossConfirmation var) +{ + mDataLossConfirmation = var; +} + +nn::hac::nacp::PlayLogPolicy nn::hac::ApplicationControlProperty::getPlayLogPolicy() const +{ + return mPlayLogPolicy; +} + +void nn::hac::ApplicationControlProperty::setPlayLogPolicy(nacp::PlayLogPolicy var) +{ + mPlayLogPolicy = var; +} + +uint64_t nn::hac::ApplicationControlProperty::getPresenceGroupId() const +{ + return mPresenceGroupId; +} + +void nn::hac::ApplicationControlProperty::setPresenceGroupId(uint64_t var) +{ + mPresenceGroupId = var; +} + +const fnd::List& nn::hac::ApplicationControlProperty::getRatingAge() const +{ + return mRatingAge; +} + +void nn::hac::ApplicationControlProperty::setRatingAge(const fnd::List& var) +{ + mRatingAge = var; +} + +const std::string& nn::hac::ApplicationControlProperty::getDisplayVersion() const +{ + return mDisplayVersion; +} + +void nn::hac::ApplicationControlProperty::setDisplayVersion(const std::string& var) +{ + mDisplayVersion = var; +} + +uint64_t nn::hac::ApplicationControlProperty::getAocBaseId() const +{ + return mAocBaseId; +} + +void nn::hac::ApplicationControlProperty::setAocBaseId(uint64_t var) +{ + mAocBaseId = var; +} + +uint64_t nn::hac::ApplicationControlProperty::getSaveDatawOwnerId() const +{ + return mSaveDatawOwnerId; +} + +void nn::hac::ApplicationControlProperty::setSaveDatawOwnerId(uint64_t var) +{ + mSaveDatawOwnerId = var; +} + +const nn::hac::ApplicationControlProperty::sStorageSize& nn::hac::ApplicationControlProperty::getUserAccountSaveDataSize() const +{ + return mUserAccountSaveDataSize; +} + +void nn::hac::ApplicationControlProperty::setUserAccountSaveDataSize(const sStorageSize& var) +{ + mUserAccountSaveDataSize = var; +} + +const nn::hac::ApplicationControlProperty::sStorageSize& nn::hac::ApplicationControlProperty::getDeviceSaveDataSize() const +{ + return mDeviceSaveDataSize; +} + +void nn::hac::ApplicationControlProperty::setDeviceSaveDataSize(const sStorageSize& var) +{ + mDeviceSaveDataSize = var; +} + +int64_t nn::hac::ApplicationControlProperty::getBcatDeliveryCacheStorageSize() const +{ + return mBcatDeliveryCacheStorageSize; +} + +void nn::hac::ApplicationControlProperty::setBcatDeliveryCacheStorageSize(int64_t var) +{ + mBcatDeliveryCacheStorageSize = var; +} + +const std::string& nn::hac::ApplicationControlProperty::getApplicationErrorCodeCategory() const +{ + return mApplicationErrorCodeCategory; +} + +void nn::hac::ApplicationControlProperty::setApplicationErrorCodeCategory(const std::string& var) +{ + mApplicationErrorCodeCategory = var; +} + +const fnd::List& nn::hac::ApplicationControlProperty::getLocalCommunicationId() const +{ + return mLocalCommunicationId; +} + +void nn::hac::ApplicationControlProperty::setLocalCommunicationId(const fnd::List& var) +{ + mLocalCommunicationId = var; +} + +nn::hac::nacp::LogoType nn::hac::ApplicationControlProperty::getLogoType() const +{ + return mLogoType; +} + +void nn::hac::ApplicationControlProperty::setLogoType(nacp::LogoType var) +{ + mLogoType = var; +} + +nn::hac::nacp::LogoHandling nn::hac::ApplicationControlProperty::getLogoHandling() const +{ + return mLogoHandling; +} + +void nn::hac::ApplicationControlProperty::setLogoHandling(nacp::LogoHandling var) +{ + mLogoHandling = var; +} + +nn::hac::nacp::RuntimeAocInstallMode nn::hac::ApplicationControlProperty::getRuntimeAocInstallMode() const +{ + return mRuntimeAocInstallMode; +} + +void nn::hac::ApplicationControlProperty::setRuntimeAocInstallMode(nacp::RuntimeAocInstallMode var) +{ + mRuntimeAocInstallMode = var; +} + +nn::hac::nacp::CrashReportMode nn::hac::ApplicationControlProperty::getCrashReportMode() const +{ + return mCrashReportMode; +} + +void nn::hac::ApplicationControlProperty::setCrashReportMode(nacp::CrashReportMode var) +{ + mCrashReportMode = var; +} + +nn::hac::nacp::Hdcp nn::hac::ApplicationControlProperty::getHdcp() const +{ + return mHdcp; +} + +void nn::hac::ApplicationControlProperty::setHdcp(nacp::Hdcp var) +{ + mHdcp = var; +} + +uint64_t nn::hac::ApplicationControlProperty::getSeedForPsuedoDeviceId() const +{ + return mSeedForPsuedoDeviceId; +} + +void nn::hac::ApplicationControlProperty::setSeedForPsuedoDeviceId(uint64_t var) +{ + mSeedForPsuedoDeviceId = var; +} + +const std::string& nn::hac::ApplicationControlProperty::getBcatPassphase() const +{ + return mBcatPassphase; +} + +void nn::hac::ApplicationControlProperty::setBcatPassphase(const std::string& var) +{ + mBcatPassphase = var; +} + +const nn::hac::ApplicationControlProperty::sStorageSize& nn::hac::ApplicationControlProperty::getUserAccountSaveDataMax() const +{ + return mUserAccountSaveDataMax; +} + +void nn::hac::ApplicationControlProperty::setUserAccountSaveDataMax(const sStorageSize& var) +{ + mUserAccountSaveDataMax = var; +} + +const nn::hac::ApplicationControlProperty::sStorageSize& nn::hac::ApplicationControlProperty::getDeviceSaveDataMax() const +{ + return mDeviceSaveDataMax; +} + +void nn::hac::ApplicationControlProperty::setDeviceSaveDataMax(const sStorageSize& var) +{ + mDeviceSaveDataMax = var; +} + +int64_t nn::hac::ApplicationControlProperty::getTemporaryStorageSize() const +{ + return mTemporaryStorageSize; +} + +void nn::hac::ApplicationControlProperty::setTemporaryStorageSize(int64_t var) +{ + mTemporaryStorageSize = var; +} + +const nn::hac::ApplicationControlProperty::sStorageSize& nn::hac::ApplicationControlProperty::getCacheStorageSize() const +{ + return mCacheStorageSize; +} + +void nn::hac::ApplicationControlProperty::setCacheStorageSize(const sStorageSize& var) +{ + mCacheStorageSize = var; +} + +int64_t nn::hac::ApplicationControlProperty::getCacheStorageDataAndJournalSizeMax() const +{ + return mCacheStorageDataAndJournalSizeMax; +} + +void nn::hac::ApplicationControlProperty::setCacheStorageDataAndJournalSizeMax(int64_t var) +{ + mCacheStorageDataAndJournalSizeMax = var; +} + +uint16_t nn::hac::ApplicationControlProperty::getCacheStorageIndexMax() const +{ + return mCacheStorageIndexMax; +} + +void nn::hac::ApplicationControlProperty::setCacheStorageIndexMax(uint16_t var) +{ + mCacheStorageIndexMax = var; +} + +const fnd::List& nn::hac::ApplicationControlProperty::getPlayLogQueryableApplicationId() const +{ + return mPlayLogQueryableApplicationId; +} + +void nn::hac::ApplicationControlProperty::setPlayLogQueryableApplicationId(const fnd::List& var) +{ + mPlayLogQueryableApplicationId = var; +} + +nn::hac::nacp::PlayLogQueryCapability nn::hac::ApplicationControlProperty::getPlayLogQueryCapability() const +{ + return mPlayLogQueryCapability; +} + +void nn::hac::ApplicationControlProperty::setPlayLogQueryCapability(nacp::PlayLogQueryCapability var) +{ + mPlayLogQueryCapability = var; +} + +nn::hac::nacp::RepairFlag nn::hac::ApplicationControlProperty::getRepairFlag() const +{ + return mRepairFlag; +} + +void nn::hac::ApplicationControlProperty::setRepairFlag(nacp::RepairFlag var) +{ + mRepairFlag = var; +} + +byte_t nn::hac::ApplicationControlProperty::getProgramIndex() const +{ + return mProgramIndex; +} + +void nn::hac::ApplicationControlProperty::setProgramIndex(byte_t var) +{ + mProgramIndex = var; } \ No newline at end of file diff --git a/lib/libhac/source/ApplicationMetaExtendedHeader.cpp b/lib/libhac/source/ApplicationMetaExtendedHeader.cpp new file mode 100644 index 0000000..c037cd9 --- /dev/null +++ b/lib/libhac/source/ApplicationMetaExtendedHeader.cpp @@ -0,0 +1,84 @@ +#include + +nn::hac::ApplicationMetaExtendedHeader::ApplicationMetaExtendedHeader() +{ + clear(); +} + +nn::hac::ApplicationMetaExtendedHeader::ApplicationMetaExtendedHeader(const ApplicationMetaExtendedHeader& other) +{ + *this = other; +} + +void nn::hac::ApplicationMetaExtendedHeader::operator=(const ApplicationMetaExtendedHeader& other) +{ + clear(); + mRawBinary = other.mRawBinary; + mPatchId = other.mPatchId; + mRequiredSystemVersion = other.mRequiredSystemVersion; +} + +bool nn::hac::ApplicationMetaExtendedHeader::operator==(const ApplicationMetaExtendedHeader& other) const +{ + return (mPatchId == other.mPatchId) \ + && (mRequiredSystemVersion == other.mRequiredSystemVersion); +} + +bool nn::hac::ApplicationMetaExtendedHeader::operator!=(const ApplicationMetaExtendedHeader& other) const +{ + return !(*this == other); +} + +void nn::hac::ApplicationMetaExtendedHeader::toBytes() +{ + mRawBinary.alloc(sizeof(sApplicationMetaExtendedHeader)); + sApplicationMetaExtendedHeader* info = (sApplicationMetaExtendedHeader*)mRawBinary.data(); + + info->patch_id = mPatchId; + info->required_system_version = mRequiredSystemVersion; +} + +void nn::hac::ApplicationMetaExtendedHeader::fromBytes(const byte_t* bytes, size_t len) +{ + if (len < sizeof(sApplicationMetaExtendedHeader)) + { + throw fnd::Exception(kModuleName, "ApplicationMetaExtendedHeader too small"); + } + + const sApplicationMetaExtendedHeader* info = (const sApplicationMetaExtendedHeader*)bytes; + + mPatchId = info->patch_id.get(); + mRequiredSystemVersion = info->required_system_version.get(); +} + +const fnd::Vec& nn::hac::ApplicationMetaExtendedHeader::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::ApplicationMetaExtendedHeader::clear() +{ + mRawBinary.clear(); + mPatchId = 0; + mRequiredSystemVersion = 0; +} + +uint64_t nn::hac::ApplicationMetaExtendedHeader::getPatchId() const +{ + return mPatchId; +} + +void nn::hac::ApplicationMetaExtendedHeader::setPatchId(uint64_t application_id) +{ + mPatchId = application_id; +} + +uint32_t nn::hac::ApplicationMetaExtendedHeader::getRequiredSystemVersion() const +{ + return mRequiredSystemVersion; +} + +void nn::hac::ApplicationMetaExtendedHeader::setRequiredSystemVersion(uint32_t sys_ver) +{ + mRequiredSystemVersion = sys_ver; +} \ No newline at end of file diff --git a/lib/libhac/source/ContentArchiveHeader.cpp b/lib/libhac/source/ContentArchiveHeader.cpp new file mode 100644 index 0000000..e5d51b4 --- /dev/null +++ b/lib/libhac/source/ContentArchiveHeader.cpp @@ -0,0 +1,334 @@ +#include + +nn::hac::ContentArchiveHeader::ContentArchiveHeader() +{ + mRightsId.alloc(nca::kRightsIdLen); + mKeyArea.alloc(nca::kKeyAreaSize); + clear(); +} + +nn::hac::ContentArchiveHeader::ContentArchiveHeader(const ContentArchiveHeader & other) : + ContentArchiveHeader() +{ + *this = other; +} + +bool nn::hac::ContentArchiveHeader::operator==(const ContentArchiveHeader & other) const +{ + return (mFormatVersion == other.mFormatVersion) \ + && (mDistributionType == other.mDistributionType) \ + && (mContentType == other.mContentType) \ + && (mKeyGeneration == other.mKeyGeneration) \ + && (mKaekIndex == other.mKaekIndex) \ + && (mContentSize == other.mContentSize) \ + && (mProgramId == other.mProgramId) \ + && (mContentIndex == other.mContentIndex) \ + && (mSdkAddonVersion == other.mSdkAddonVersion) \ + && (mRightsId == other.mRightsId) \ + && (mPartitionEntryList == other.mPartitionEntryList) \ + && (mKeyArea == other.mKeyArea); +} + +bool nn::hac::ContentArchiveHeader::operator!=(const ContentArchiveHeader & other) const +{ + return !(*this == other); +} + +void nn::hac::ContentArchiveHeader::operator=(const ContentArchiveHeader & other) +{ + mRawBinary = other.mRawBinary; + mDistributionType = other.mDistributionType; + mContentType = other.mContentType; + mKeyGeneration = other.mKeyGeneration; + mKaekIndex = other.mKaekIndex; + mContentSize = other.mContentSize; + mProgramId = other.mProgramId; + mContentIndex = other.mContentIndex; + mSdkAddonVersion = other.mSdkAddonVersion; + mRightsId = other.mRightsId; + mPartitionEntryList = other.mPartitionEntryList; + mKeyArea = other.mKeyArea; +} + +void nn::hac::ContentArchiveHeader::toBytes() +{ + mRawBinary.alloc(sizeof(sContentArchiveHeader)); + sContentArchiveHeader* hdr = (sContentArchiveHeader*)mRawBinary.data(); + + // set header magic + switch(mFormatVersion) + { + case (nca::FORMAT_NCA2): + hdr->st_magic = nca::kNca2StructMagic; + break; + case (nca::FORMAT_NCA3): + hdr->st_magic = nca::kNca3StructMagic; + break; + default: + throw fnd::Exception(kModuleName, "Unsupported format version"); + } + + // set variables + hdr->distribution_type = mDistributionType; + hdr->content_type = mContentType; + if (mKeyGeneration > 2) + { + hdr->key_generation = 2; + hdr->key_generation_2 = mKeyGeneration; + } + else + { + hdr->key_generation = mKeyGeneration; + hdr->key_generation_2 = 0; + } + hdr->key_area_encryption_key_index = mKaekIndex; + hdr->content_size = mContentSize; + hdr->program_id = mProgramId; + hdr->content_index = mContentIndex; + hdr->sdk_addon_version = mSdkAddonVersion; + memcpy(hdr->rights_id, mRightsId.data(), nca::kRightsIdLen); + memcpy(hdr->key_area, mKeyArea.data(), nca::kKeyAreaSize); + + for (size_t i = 0; i < mPartitionEntryList.size(); i++) + { + byte_t index = mPartitionEntryList[i].header_index; + + if (index >= nca::kPartitionNum) continue; + + hdr->partition_entry[index].start_blk = sizeToBlockNum(mPartitionEntryList[index].offset); + hdr->partition_entry[index].end_blk = (sizeToBlockNum(mPartitionEntryList[index].offset) + sizeToBlockNum(mPartitionEntryList[index].size)); + hdr->partition_entry[index].enabled = true; + hdr->fs_header_hash[index] = mPartitionEntryList[i].fs_header_hash; + } +} + +void nn::hac::ContentArchiveHeader::fromBytes(const byte_t * data, size_t len) +{ + if (len < sizeof(sContentArchiveHeader)) + { + throw fnd::Exception(kModuleName, "ContentArchive header size is too small"); + } + + clear(); + + mRawBinary.alloc(sizeof(sContentArchiveHeader)); + memcpy(mRawBinary.data(), data, sizeof(sContentArchiveHeader)); + + sContentArchiveHeader* hdr = (sContentArchiveHeader*)mRawBinary.data(); + + // check magic + switch(hdr->st_magic.get()) + { + case (nca::kNca2StructMagic) : + mFormatVersion = nca::FORMAT_NCA2; + break; + case (nca::kNca3StructMagic) : + mFormatVersion = nca::FORMAT_NCA3; + break; + throw fnd::Exception(kModuleName, "ContentArchive header corrupt (unrecognised header magic)."); + } + + // variables + mDistributionType = (nca::DistributionType)hdr->distribution_type; + mContentType = (nca::ContentType)hdr->content_type; + mKeyGeneration = _MAX(hdr->key_generation, hdr->key_generation_2); + mKaekIndex = hdr->key_area_encryption_key_index; + mContentSize = *hdr->content_size; + mProgramId = *hdr->program_id; + mContentIndex = *hdr->content_index; + mSdkAddonVersion = *hdr->sdk_addon_version; + memcpy(mRightsId.data(), hdr->rights_id, nca::kRightsIdLen); + memcpy(mKeyArea.data(), hdr->key_area, nca::kKeyAreaSize); + + for (size_t i = 0; i < nca::kPartitionNum; i++) + { + if (hdr->partition_entry[i].enabled) + { + mPartitionEntryList.addElement({(byte_t)i, blockNumToSize(hdr->partition_entry[i].start_blk.get()), blockNumToSize(hdr->partition_entry[i].end_blk.get() - hdr->partition_entry[i].start_blk.get()), hdr->fs_header_hash[i] }); + } + } +} + +const fnd::Vec& nn::hac::ContentArchiveHeader::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::ContentArchiveHeader::clear() +{ + mFormatVersion = nca::FORMAT_NCA3; + mDistributionType = nca::DIST_DOWNLOAD; + mContentType = nca::TYPE_PROGRAM; + mKeyGeneration = 0; + mKaekIndex = 0; + mContentSize = 0; + mProgramId = 0; + mContentIndex = 0; + mSdkAddonVersion = 0; + memset(mRightsId.data(), 0, mRightsId.size()); + mPartitionEntryList.clear(); + memset(mKeyArea.data(), 0, mKeyArea.size()); +} + +byte_t nn::hac::ContentArchiveHeader::getFormatVersion() const +{ + return mFormatVersion; +} + +void nn::hac::ContentArchiveHeader::setFormatVersion(byte_t version) +{ + mFormatVersion = version; +} + +nn::hac::nca::DistributionType nn::hac::ContentArchiveHeader::getDistributionType() const +{ + return mDistributionType; +} + +void nn::hac::ContentArchiveHeader::setDistributionType(nca::DistributionType type) +{ + mDistributionType = type; +} + +nn::hac::nca::ContentType nn::hac::ContentArchiveHeader::getContentType() const +{ + return mContentType; +} + +void nn::hac::ContentArchiveHeader::setContentType(nca::ContentType type) +{ + mContentType = type; +} + +byte_t nn::hac::ContentArchiveHeader::getKeyGeneration() const +{ + return mKeyGeneration; +} + +void nn::hac::ContentArchiveHeader::setKeyGeneration(byte_t gen) +{ + mKeyGeneration = gen; +} + +byte_t nn::hac::ContentArchiveHeader::getKeyAreaEncryptionKeyIndex() const +{ + return mKaekIndex; +} + +void nn::hac::ContentArchiveHeader::setKeyAreaEncryptionKeyIndex(byte_t index) +{ + mKaekIndex = index; +} + +uint64_t nn::hac::ContentArchiveHeader::getContentSize() const +{ + return mContentSize; +} + +void nn::hac::ContentArchiveHeader::setContentSize(uint64_t size) +{ + mContentSize = size; +} + +uint64_t nn::hac::ContentArchiveHeader::getProgramId() const +{ + return mProgramId; +} + +void nn::hac::ContentArchiveHeader::setProgramId(uint64_t program_id) +{ + mProgramId = program_id; +} + +uint32_t nn::hac::ContentArchiveHeader::getContentIndex() const +{ + return mContentIndex; +} + +void nn::hac::ContentArchiveHeader::setContentIndex(uint32_t index) +{ + mContentIndex = index; +} + +uint32_t nn::hac::ContentArchiveHeader::getSdkAddonVersion() const +{ + return mSdkAddonVersion; +} + +void nn::hac::ContentArchiveHeader::setSdkAddonVersion(uint32_t version) +{ + mSdkAddonVersion = version; +} + +bool nn::hac::ContentArchiveHeader::hasRightsId() const +{ + bool rightsIdIsSet = false; + + for (size_t i = 0; i < nca::kRightsIdLen; i++) + { + if (mRightsId[i] != 0) + rightsIdIsSet = true; + } + + return rightsIdIsSet; +} + +const byte_t* nn::hac::ContentArchiveHeader::getRightsId() const +{ + return mRightsId.data(); +} + +void nn::hac::ContentArchiveHeader::setRightsId(const byte_t* rights_id) +{ + memcpy(mRightsId.data(), rights_id, nca::kRightsIdLen); +} + +const fnd::List& nn::hac::ContentArchiveHeader::getPartitionEntryList() const +{ + return mPartitionEntryList; +} + +void nn::hac::ContentArchiveHeader::setPartitionEntryList(const fnd::List& partition_entry_list) +{ + mPartitionEntryList = partition_entry_list; + + // sanity check the list + if (mPartitionEntryList.size() >= nca::kPartitionNum) + { + throw fnd::Exception(kModuleName, "Too many partitions"); + } + for (size_t i = 0; i < mPartitionEntryList.size(); i++) + { + if (mPartitionEntryList[i].header_index >= nca::kPartitionNum) + { + throw fnd::Exception(kModuleName, "Illegal partition index"); + } + for (size_t j = i+1; j < mPartitionEntryList.size(); j++) + { + if (mPartitionEntryList[i].header_index == mPartitionEntryList[j].header_index) + { + throw fnd::Exception(kModuleName, "Duplicated partition index"); + } + } + } +} + +const byte_t* nn::hac::ContentArchiveHeader::getKeyArea() const +{ + return mKeyArea.data(); +} + +void nn::hac::ContentArchiveHeader::setKeyArea(const byte_t* key_area) +{ + memcpy(mKeyArea.data(), key_area, nca::kKeyAreaSize); +} + +uint64_t nn::hac::ContentArchiveHeader::blockNumToSize(uint32_t block_num) const +{ + return block_num * nca::kSectorSize; +} + +uint32_t nn::hac::ContentArchiveHeader::sizeToBlockNum(uint64_t real_size) const +{ + return (uint32_t)(align(real_size, nca::kSectorSize) / nca::kSectorSize); +} \ No newline at end of file diff --git a/lib/libhac/source/NcaUtils.cpp b/lib/libhac/source/ContentArchiveUtils.cpp similarity index 65% rename from lib/libhac/source/NcaUtils.cpp rename to lib/libhac/source/ContentArchiveUtils.cpp index 9b71878..284bca6 100644 --- a/lib/libhac/source/NcaUtils.cpp +++ b/lib/libhac/source/ContentArchiveUtils.cpp @@ -1,58 +1,58 @@ -#include - -void nn::hac::NcaUtils::decryptNcaHeader(const byte_t* src, byte_t* dst, const fnd::aes::sAesXts128Key& key) -{ - byte_t tweak[fnd::aes::kAesBlockSize]; - - // decrypt main header - byte_t raw_hdr[nn::hac::nca::kSectorSize]; - fnd::aes::AesXtsMakeTweak(tweak, 1); - fnd::aes::AesXtsDecryptSector(src + sectorToOffset(1), nn::hac::nca::kSectorSize, key.key[0], key.key[1], tweak, raw_hdr); - - bool useNca2SectorIndex = ((nn::hac::sNcaHeader*)(raw_hdr))->st_magic.get() == nn::hac::nca::kNca2StructMagic; - - // decrypt whole header - for (size_t i = 0; i < nn::hac::nca::kHeaderSectorNum; i++) - { - fnd::aes::AesXtsMakeTweak(tweak, (i > 1 && useNca2SectorIndex)? 0 : i); - fnd::aes::AesXtsDecryptSector(src + sectorToOffset(i), nn::hac::nca::kSectorSize, key.key[0], key.key[1], tweak, dst + sectorToOffset(i)); - } -} - -byte_t nn::hac::NcaUtils::getMasterKeyRevisionFromKeyGeneration(byte_t key_generation) -{ - byte_t masterkey_rev; - - switch (key_generation) - { - case(0): - case(1): - masterkey_rev = 0; - break; - case(2): - masterkey_rev = 1; - break; - case(3): - masterkey_rev = 2; - break; - case(4): - masterkey_rev = 3; - break; - case(5): - masterkey_rev = 4; - break; - default: - masterkey_rev = key_generation - 1; - } - - return masterkey_rev; -} - -void nn::hac::NcaUtils::getNcaPartitionAesCtr(const nn::hac::sNcaFsHeader* hdr, byte_t* ctr) -{ - for (size_t i = 0; i < 8; i++) - { - ctr[7-i] = hdr->aes_ctr_upper[i]; - ctr[15-i] = 0; - } +#include + +void nn::hac::ContentArchiveUtils::decryptContentArchiveHeader(const byte_t* src, byte_t* dst, const fnd::aes::sAesXts128Key& key) +{ + byte_t tweak[fnd::aes::kAesBlockSize]; + + // decrypt main header + byte_t raw_hdr[nn::hac::nca::kSectorSize]; + fnd::aes::AesXtsMakeTweak(tweak, 1); + fnd::aes::AesXtsDecryptSector(src + sectorToOffset(1), nn::hac::nca::kSectorSize, key.key[0], key.key[1], tweak, raw_hdr); + + bool useNca2SectorIndex = ((nn::hac::sContentArchiveHeader*)(raw_hdr))->st_magic.get() == nn::hac::nca::kNca2StructMagic; + + // decrypt whole header + for (size_t i = 0; i < nn::hac::nca::kHeaderSectorNum; i++) + { + fnd::aes::AesXtsMakeTweak(tweak, (i > 1 && useNca2SectorIndex)? 0 : i); + fnd::aes::AesXtsDecryptSector(src + sectorToOffset(i), nn::hac::nca::kSectorSize, key.key[0], key.key[1], tweak, dst + sectorToOffset(i)); + } +} + +byte_t nn::hac::ContentArchiveUtils::getMasterKeyRevisionFromKeyGeneration(byte_t key_generation) +{ + byte_t masterkey_rev; + + switch (key_generation) + { + case(0): + case(1): + masterkey_rev = 0; + break; + case(2): + masterkey_rev = 1; + break; + case(3): + masterkey_rev = 2; + break; + case(4): + masterkey_rev = 3; + break; + case(5): + masterkey_rev = 4; + break; + default: + masterkey_rev = key_generation - 1; + } + + return masterkey_rev; +} + +void nn::hac::ContentArchiveUtils::getNcaPartitionAesCtr(const nn::hac::sNcaFsHeader* hdr, byte_t* ctr) +{ + for (size_t i = 0; i < 8; i++) + { + ctr[7-i] = hdr->aes_ctr_upper[i]; + ctr[15-i] = 0; + } } \ No newline at end of file diff --git a/lib/libhac/source/ContentInfo.cpp b/lib/libhac/source/ContentInfo.cpp new file mode 100644 index 0000000..43902ea --- /dev/null +++ b/lib/libhac/source/ContentInfo.cpp @@ -0,0 +1,123 @@ +#include + +nn::hac::ContentInfo::ContentInfo() +{ + clear(); +} + +nn::hac::ContentInfo::ContentInfo(const ContentInfo& other) +{ + *this = other; +} + +void nn::hac::ContentInfo::operator=(const ContentInfo& other) +{ + clear(); + mRawBinary = other.mRawBinary; + mHash = other.mHash; + mContentId = other.mContentId; + mSize = other.mSize; + mType = other.mType; +} + +bool nn::hac::ContentInfo::operator==(const ContentInfo& other) const +{ + return (mHash == other.mHash) \ + && (mContentId == other.mContentId) \ + && (mSize == other.mSize) \ + && (mType == other.mType); +} + +bool nn::hac::ContentInfo::operator!=(const ContentInfo& other) const +{ + return !(*this == other); +} + +void nn::hac::ContentInfo::toBytes() +{ + mRawBinary.alloc(sizeof(sContentInfo)); + sContentInfo* info = (sContentInfo*)mRawBinary.data(); + + info->content_hash = mHash; + info->content_id = mContentId; + info->size_lower = mSize & (uint32_t)(-1); + info->size_higher = (mSize >> 32) & (uint16_t)(-1); + info->content_type = mType; + info->id_offset = mIdOffset; +} + +void nn::hac::ContentInfo::fromBytes(const byte_t* bytes, size_t len) +{ + if (len < sizeof(sContentInfo)) + { + throw fnd::Exception(kModuleName, "ContentInfo too small"); + } + + const sContentInfo* info = (const sContentInfo*)bytes; + + mHash = info->content_hash; + mContentId = info->content_id; + mSize = (uint64_t)(info->size_lower.get()) | (uint64_t)(info->size_higher.get()) << 32; + mType = (cnmt::ContentType)info->content_type; + mIdOffset = info->id_offset; +} + +const fnd::Vec& nn::hac::ContentInfo::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::ContentInfo::clear() +{ + mRawBinary.clear(); +} + +const fnd::sha::sSha256Hash& nn::hac::ContentInfo::getContentHash() const +{ + return mHash; +} + +void nn::hac::ContentInfo::setContentHash(const fnd::sha::sSha256Hash& hash) +{ + mHash = hash; +} + +const nn::hac::cnmt::sContentId& nn::hac::ContentInfo::getContentId() const +{ + return mContentId; +} + +void nn::hac::ContentInfo::setContentId(const cnmt::sContentId& content_id) +{ + mContentId = content_id; +} + +size_t nn::hac::ContentInfo::getContentSize() const +{ + return mSize; +} + +void nn::hac::ContentInfo::setContentSize(size_t size) +{ + mSize = size; +} + +nn::hac::cnmt::ContentType nn::hac::ContentInfo::getContentType() const +{ + return mType; +} + +void nn::hac::ContentInfo::setContentType(cnmt::ContentType type) +{ + mType = type; +} + +byte_t nn::hac::ContentInfo::getIdOffset() const +{ + return mIdOffset; +} + +void nn::hac::ContentInfo::setIdOffset(byte_t id_offset) +{ + mIdOffset = id_offset; +} \ No newline at end of file diff --git a/lib/libhac/source/ContentMetaBinary.cpp b/lib/libhac/source/ContentMeta.cpp similarity index 54% rename from lib/libhac/source/ContentMetaBinary.cpp rename to lib/libhac/source/ContentMeta.cpp index 7ebd628..3c181de 100644 --- a/lib/libhac/source/ContentMetaBinary.cpp +++ b/lib/libhac/source/ContentMeta.cpp @@ -1,380 +1,368 @@ -#include - -nn::hac::ContentMetaBinary::ContentMetaBinary() -{ - clear(); -} - -nn::hac::ContentMetaBinary::ContentMetaBinary(const ContentMetaBinary & other) -{ - *this = other; -} - -void nn::hac::ContentMetaBinary::operator=(const ContentMetaBinary& other) -{ - if (other.getBytes().size() > 0) - { - fromBytes(other.getBytes().data(), other.getBytes().size()); - } - else - { - clear(); - mTitleId = other.mTitleId; - mTitleVersion = other.mTitleVersion; - mType = other.mType; - mAttributes = other.mAttributes; - mRequiredDownloadSystemVersion = other.mRequiredDownloadSystemVersion; - mExtendedHeader = other.mExtendedHeader; - mApplicationMetaExtendedHeader = other.mApplicationMetaExtendedHeader; - mPatchMetaExtendedHeader = other.mPatchMetaExtendedHeader; - mAddOnContentMetaExtendedHeader = other.mAddOnContentMetaExtendedHeader; - mDeltaMetaExtendedHeader = other.mDeltaMetaExtendedHeader; - mContentInfo = other.mContentInfo; - mContentMetaInfo = other.mContentMetaInfo; - mExtendedData = other.mExtendedData; - memcpy(mDigest.data, other.mDigest.data, cnmt::kDigestLen); - } -} - -bool nn::hac::ContentMetaBinary::operator==(const ContentMetaBinary& other) const -{ - return (mTitleId == other.mTitleId) \ - && (mTitleVersion == other.mTitleVersion) \ - && (mType == other.mType) \ - && (mAttributes == other.mAttributes) \ - && (mRequiredDownloadSystemVersion == other.mRequiredDownloadSystemVersion) \ - && (mExtendedHeader == other.mExtendedHeader) \ - && (mApplicationMetaExtendedHeader == other.mApplicationMetaExtendedHeader) \ - && (mPatchMetaExtendedHeader == other.mPatchMetaExtendedHeader) \ - && (mAddOnContentMetaExtendedHeader == other.mAddOnContentMetaExtendedHeader) \ - && (mDeltaMetaExtendedHeader == other.mDeltaMetaExtendedHeader) \ - && (mContentInfo == other.mContentInfo) \ - && (mContentMetaInfo == other.mContentMetaInfo) \ - && (mExtendedData == other.mExtendedData) \ - && (memcmp(mDigest.data, other.mDigest.data, cnmt::kDigestLen) == 0); -} - -bool nn::hac::ContentMetaBinary::operator!=(const ContentMetaBinary& other) const -{ - return !(*this == other); -} - -void nn::hac::ContentMetaBinary::toBytes() -{ - throw fnd::Exception(kModuleName, "exportBinary() not implemented"); -} - -void nn::hac::ContentMetaBinary::fromBytes(const byte_t* data, size_t len) -{ - // clear member variables - clear(); - - // validate layout - validateBinary(data, len); - - // get pointer to header structure - const sContentMetaHeader* hdr = (const sContentMetaHeader*)data; - - mTitleId = hdr->id.get(); - mTitleVersion = hdr->version.get(); - mType = (cnmt::ContentMetaType)hdr->type; - mAttributes = hdr->attributes; - mRequiredDownloadSystemVersion = hdr->required_download_system_version.get(); - size_t exdata_size = 0; - - // save exheader - if (hdr->exhdr_size.get() > 0) - { - mExtendedHeader.alloc(hdr->exhdr_size.get()); - memcpy(mExtendedHeader.data(), data + getExtendedHeaderOffset(), hdr->exhdr_size.get()); - - switch (mType) - { - case (cnmt::METATYPE_APPLICATION): - mApplicationMetaExtendedHeader.patch_id = ((sApplicationMetaExtendedHeader*)mExtendedHeader.data())->patch_id.get(); - mApplicationMetaExtendedHeader.required_system_version = ((sApplicationMetaExtendedHeader*)mExtendedHeader.data())->required_system_version.get(); - break; - case (cnmt::METATYPE_PATCH): - mPatchMetaExtendedHeader.application_id = ((sPatchMetaExtendedHeader*)mExtendedHeader.data())->application_id.get(); - mPatchMetaExtendedHeader.required_system_version = ((sPatchMetaExtendedHeader*)mExtendedHeader.data())->required_system_version.get(); - break; - case (cnmt::METATYPE_ADD_ON_CONTENT): - mAddOnContentMetaExtendedHeader.application_id = ((sAddOnContentMetaExtendedHeader*)mExtendedHeader.data())->application_id.get(); - mAddOnContentMetaExtendedHeader.required_application_version = ((sAddOnContentMetaExtendedHeader*)mExtendedHeader.data())->required_application_version.get(); - break; - case (cnmt::METATYPE_DELTA): - mDeltaMetaExtendedHeader.application_id = ((sDeltaMetaExtendedHeader*)mExtendedHeader.data())->application_id.get(); - break; - default: - break; - } - - exdata_size = getExtendedDataSize(mType, mExtendedHeader.data()); - } - - // save content info - if (hdr->content_count.get() > 0) - { - const sContentInfo* info = (const sContentInfo*)(data + getContentInfoOffset(hdr->exhdr_size.get())); - ContentInfo cinfo; - for (size_t i = 0; i < hdr->content_count.get(); i++) - { - cinfo.hash = info[i].content_hash; - memcpy(cinfo.nca_id, info[i].content_id, cnmt::kContentIdLen); - cinfo.size = (uint64_t)(info[i].size_lower.get()) | (uint64_t)(info[i].size_higher.get()) << 32; - cinfo.type = (cnmt::ContentType)info[i].content_type; - mContentInfo.addElement(cinfo); - } - } - - // save content meta info - if (hdr->content_meta_count.get() > 0) - { - const sContentMetaInfo* info = (const sContentMetaInfo*)(data + getContentMetaInfoOffset(hdr->exhdr_size.get(), hdr->content_count.get())); - ContentMetaInfo cmeta; - for (size_t i = 0; i < hdr->content_meta_count.get(); i++) - { - cmeta.id = info[i].id.get(); - cmeta.version = info[i].version.get(); - cmeta.type = (cnmt::ContentMetaType)info[i].type; - cmeta.attributes = info[i].attributes; - mContentMetaInfo.addElement(cmeta); - } - } - - // save exdata - if (exdata_size > 0) - { - mExtendedData.alloc(exdata_size); - memcpy(mExtendedData.data(), data + getExtendedDataOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get()), exdata_size); - } - - // save digest - memcpy(mDigest.data, data + getDigestOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), exdata_size), cnmt::kDigestLen); -} - -const fnd::Vec& nn::hac::ContentMetaBinary::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::ContentMetaBinary::clear() -{ - mRawBinary.clear(); - mTitleId = 0; - mTitleVersion = 0; - mType = cnmt::METATYPE_SYSTEM_PROGRAM; - mAttributes = 0; - mRequiredDownloadSystemVersion = 0; - mExtendedHeader.clear(); - memset(&mApplicationMetaExtendedHeader, 0, sizeof(mApplicationMetaExtendedHeader)); - memset(&mPatchMetaExtendedHeader, 0, sizeof(mPatchMetaExtendedHeader)); - memset(&mAddOnContentMetaExtendedHeader, 0, sizeof(mAddOnContentMetaExtendedHeader)); - memset(&mDeltaMetaExtendedHeader, 0, sizeof(mDeltaMetaExtendedHeader)); - mContentInfo.clear(); - mContentMetaInfo.clear(); - mExtendedData.clear(); - memset(mDigest.data, 0, cnmt::kDigestLen); -} - -uint64_t nn::hac::ContentMetaBinary::getTitleId() const -{ - return mTitleId; -} - -void nn::hac::ContentMetaBinary::setTitleId(uint64_t title_id) -{ - mTitleId = title_id; -} - -uint32_t nn::hac::ContentMetaBinary::getTitleVersion() const -{ - return mTitleVersion; -} - -void nn::hac::ContentMetaBinary::setTitleVersion(uint32_t version) -{ - mTitleVersion = version; -} - -nn::hac::cnmt::ContentMetaType nn::hac::ContentMetaBinary::getType() const -{ - return mType; -} - -void nn::hac::ContentMetaBinary::setType(cnmt::ContentMetaType type) -{ - mType = type; -} - -byte_t nn::hac::ContentMetaBinary::getAttributes() const -{ - return mAttributes; -} - -void nn::hac::ContentMetaBinary::setAttributes(byte_t attributes) -{ - mAttributes = attributes; -} - -uint32_t nn::hac::ContentMetaBinary::getRequiredDownloadSystemVersion() const -{ - return mRequiredDownloadSystemVersion; -} - -void nn::hac::ContentMetaBinary::setRequiredDownloadSystemVersion(uint32_t version) -{ - mRequiredDownloadSystemVersion = version; -} - -const nn::hac::ContentMetaBinary::ApplicationMetaExtendedHeader& nn::hac::ContentMetaBinary::getApplicationMetaExtendedHeader() const -{ - return mApplicationMetaExtendedHeader; -} - -void nn::hac::ContentMetaBinary::setApplicationMetaExtendedHeader(const ApplicationMetaExtendedHeader& exhdr) -{ - mApplicationMetaExtendedHeader = exhdr; -} - -const nn::hac::ContentMetaBinary::PatchMetaExtendedHeader& nn::hac::ContentMetaBinary::getPatchMetaExtendedHeader() const -{ - return mPatchMetaExtendedHeader; -} - -void nn::hac::ContentMetaBinary::setPatchMetaExtendedHeader(const PatchMetaExtendedHeader& exhdr) -{ - mPatchMetaExtendedHeader = exhdr; -} - -const nn::hac::ContentMetaBinary::AddOnContentMetaExtendedHeader& nn::hac::ContentMetaBinary::getAddOnContentMetaExtendedHeader() const -{ - return mAddOnContentMetaExtendedHeader; -} - -void nn::hac::ContentMetaBinary::setAddOnContentMetaExtendedHeader(const AddOnContentMetaExtendedHeader& exhdr) -{ - mAddOnContentMetaExtendedHeader = exhdr; -} - -const nn::hac::ContentMetaBinary::DeltaMetaExtendedHeader& nn::hac::ContentMetaBinary::getDeltaMetaExtendedHeader() const -{ - return mDeltaMetaExtendedHeader; -} - -void nn::hac::ContentMetaBinary::setDeltaMetaExtendedHeader(const DeltaMetaExtendedHeader& exhdr) -{ - mDeltaMetaExtendedHeader = exhdr; -} - -const fnd::List& nn::hac::ContentMetaBinary::getContentInfo() const -{ - return mContentInfo; -} - -void nn::hac::ContentMetaBinary::setContentInfo(const fnd::List& info) -{ - mContentInfo = info; -} - -const fnd::List& nn::hac::ContentMetaBinary::getContentMetaInfo() const -{ - return mContentMetaInfo; -} - -void nn::hac::ContentMetaBinary::setContentMetaInfo(const fnd::List& info) -{ - mContentMetaInfo = info; -} - -const fnd::Vec & nn::hac::ContentMetaBinary::getExtendedData() const -{ - return mExtendedData; -} - -void nn::hac::ContentMetaBinary::setExtendedData(const fnd::Vec & data) -{ - mExtendedData = data; -} - -const nn::hac::sDigest & nn::hac::ContentMetaBinary::getDigest() const -{ - return mDigest; -} - -void nn::hac::ContentMetaBinary::setDigest(const nn::hac::sDigest & digest) -{ - - memcpy(mDigest.data, digest.data, cnmt::kDigestLen); -} - -bool nn::hac::ContentMetaBinary::validateExtendedHeaderSize(cnmt::ContentMetaType type, size_t exhdrSize) const -{ - bool validSize = false; - - switch (type) - { - case (cnmt::METATYPE_APPLICATION): - validSize = (exhdrSize == sizeof(sApplicationMetaExtendedHeader)); - break; - case (cnmt::METATYPE_PATCH): - validSize = (exhdrSize == sizeof(sPatchMetaExtendedHeader)); - break; - case (cnmt::METATYPE_ADD_ON_CONTENT): - validSize = (exhdrSize == sizeof(sAddOnContentMetaExtendedHeader)); - break; - case (cnmt::METATYPE_DELTA): - validSize = (exhdrSize == sizeof(sDeltaMetaExtendedHeader)); - break; - default: - validSize = (exhdrSize == 0); - } - - return validSize; -} - -size_t nn::hac::ContentMetaBinary::getExtendedDataSize(cnmt::ContentMetaType type, const byte_t * data) const -{ - size_t exdata_len = 0; - if (type == cnmt::METATYPE_PATCH) - { - const sPatchMetaExtendedHeader* exhdr = (const sPatchMetaExtendedHeader*)(data); - exdata_len = exhdr->extended_data_size.get(); - } - else if (type == cnmt::METATYPE_DELTA) - { - const sDeltaMetaExtendedHeader* exhdr = (const sDeltaMetaExtendedHeader*)(data); - exdata_len = exhdr->extended_data_size.get(); - } - return exdata_len; -} - -void nn::hac::ContentMetaBinary::validateBinary(const byte_t * data, size_t len) const -{ - // check if it is large enough to read the header - if (len < sizeof(sContentMetaHeader)) - { - throw fnd::Exception(kModuleName, "Binary too small"); - } - - // get pointer to header structure - const sContentMetaHeader* hdr = (const sContentMetaHeader*)data; - - // validate extended header size - if (validateExtendedHeaderSize((cnmt::ContentMetaType)hdr->type, hdr->exhdr_size.get()) == false) - { - throw fnd::Exception(kModuleName, "Invalid extended header size"); - } - - // check binary size again for new minimum size - if (len < getTotalSize(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), 0)) - { - throw fnd::Exception(kModuleName, "Binary too small"); - } - - // check binary size again with extended data size - if (len < getTotalSize(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), getExtendedDataSize((cnmt::ContentMetaType)hdr->type, data + getExtendedHeaderOffset()))) - { - throw fnd::Exception(kModuleName, "Binary too small"); - } +#include + +nn::hac::ContentMeta::ContentMeta() +{ + clear(); +} + +nn::hac::ContentMeta::ContentMeta(const ContentMeta & other) +{ + *this = other; +} + +void nn::hac::ContentMeta::operator=(const ContentMeta& other) +{ + if (other.getBytes().size() > 0) + { + fromBytes(other.getBytes().data(), other.getBytes().size()); + } + else + { + clear(); + mTitleId = other.mTitleId; + mTitleVersion = other.mTitleVersion; + mType = other.mType; + mAttributes = other.mAttributes; + mRequiredDownloadSystemVersion = other.mRequiredDownloadSystemVersion; + mApplicationMetaExtendedHeader = other.mApplicationMetaExtendedHeader; + mPatchMetaExtendedHeader = other.mPatchMetaExtendedHeader; + mAddOnContentMetaExtendedHeader = other.mAddOnContentMetaExtendedHeader; + mDeltaMetaExtendedHeader = other.mDeltaMetaExtendedHeader; + mContentInfo = other.mContentInfo; + mContentMetaInfo = other.mContentMetaInfo; + mExtendedData = other.mExtendedData; + memcpy(mDigest.data, other.mDigest.data, cnmt::kDigestLen); + } +} + +bool nn::hac::ContentMeta::operator==(const ContentMeta& other) const +{ + return (mTitleId == other.mTitleId) \ + && (mTitleVersion == other.mTitleVersion) \ + && (mType == other.mType) \ + && (mAttributes == other.mAttributes) \ + && (mRequiredDownloadSystemVersion == other.mRequiredDownloadSystemVersion) \ + && (mApplicationMetaExtendedHeader == other.mApplicationMetaExtendedHeader) \ + && (mPatchMetaExtendedHeader == other.mPatchMetaExtendedHeader) \ + && (mAddOnContentMetaExtendedHeader == other.mAddOnContentMetaExtendedHeader) \ + && (mDeltaMetaExtendedHeader == other.mDeltaMetaExtendedHeader) \ + && (mContentInfo == other.mContentInfo) \ + && (mContentMetaInfo == other.mContentMetaInfo) \ + && (mExtendedData == other.mExtendedData) \ + && (memcmp(mDigest.data, other.mDigest.data, cnmt::kDigestLen) == 0); +} + +bool nn::hac::ContentMeta::operator!=(const ContentMeta& other) const +{ + return !(*this == other); +} + +void nn::hac::ContentMeta::toBytes() +{ + throw fnd::Exception(kModuleName, "toBytes() not implemented"); +} + +void nn::hac::ContentMeta::fromBytes(const byte_t* data, size_t len) +{ + // clear member variables + clear(); + + // validate layout + validateBinary(data, len); + + // get pointer to header structure + const sContentMetaHeader* hdr = (const sContentMetaHeader*)data; + + mTitleId = hdr->id.get(); + mTitleVersion = hdr->version.get(); + mType = (cnmt::ContentMetaType)hdr->type; + mAttributes = hdr->attributes; + mRequiredDownloadSystemVersion = hdr->required_download_system_version.get(); + size_t exdata_size = 0; + + // save exheader + if (hdr->exhdr_size.get() > 0) + { + switch (mType) + { + case (cnmt::METATYPE_APPLICATION): + mApplicationMetaExtendedHeader.fromBytes(data + getExtendedHeaderOffset(), hdr->exhdr_size.get()); + exdata_size = 0; + break; + case (cnmt::METATYPE_PATCH): + mPatchMetaExtendedHeader.fromBytes(data + getExtendedHeaderOffset(), hdr->exhdr_size.get()); + exdata_size = mPatchMetaExtendedHeader.getExtendedDataSize(); + break; + case (cnmt::METATYPE_ADD_ON_CONTENT): + mAddOnContentMetaExtendedHeader.fromBytes(data + getExtendedHeaderOffset(), hdr->exhdr_size.get()); + exdata_size = 0; + break; + case (cnmt::METATYPE_DELTA): + mDeltaMetaExtendedHeader.fromBytes(data + getExtendedHeaderOffset(), hdr->exhdr_size.get()); + exdata_size = mDeltaMetaExtendedHeader.getExtendedDataSize(); + break; + default: + throw fnd::Exception(kModuleName, "Unhandled extended header for ContentMeta"); + //exdata_size = 0; + //break; + } + } + + // save content info + if (hdr->content_count.get() > 0) + { + const sContentInfo* info = (const sContentInfo*)(data + getContentInfoOffset(hdr->exhdr_size.get())); + ContentInfo cinfo; + for (size_t i = 0; i < hdr->content_count.get(); i++) + { + cinfo.fromBytes((const byte_t*)&info[i], sizeof(sContentInfo)); + mContentInfo.addElement(cinfo); + } + } + + // save content meta info + if (hdr->content_meta_count.get() > 0) + { + const sContentMetaInfo* info = (const sContentMetaInfo*)(data + getContentMetaInfoOffset(hdr->exhdr_size.get(), hdr->content_count.get())); + ContentMetaInfo cmeta; + for (size_t i = 0; i < hdr->content_meta_count.get(); i++) + { + cmeta.fromBytes((const byte_t*)&info[i], sizeof(sContentMetaInfo)); + mContentMetaInfo.addElement(cmeta); + } + } + + // save exdata + if (exdata_size > 0) + { + mExtendedData.alloc(exdata_size); + memcpy(mExtendedData.data(), data + getExtendedDataOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get()), exdata_size); + } + + // save digest + memcpy(mDigest.data, data + getDigestOffset(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), exdata_size), cnmt::kDigestLen); +} + +const fnd::Vec& nn::hac::ContentMeta::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::ContentMeta::clear() +{ + mRawBinary.clear(); + mTitleId = 0; + mTitleVersion = 0; + mType = cnmt::METATYPE_SYSTEM_PROGRAM; + mAttributes = 0; + mRequiredDownloadSystemVersion = 0; + mApplicationMetaExtendedHeader.clear(); + mPatchMetaExtendedHeader.clear(); + mAddOnContentMetaExtendedHeader.clear(); + mDeltaMetaExtendedHeader.clear(); + mContentInfo.clear(); + mContentMetaInfo.clear(); + mExtendedData.clear(); + memset(mDigest.data, 0, cnmt::kDigestLen); +} + +uint64_t nn::hac::ContentMeta::getTitleId() const +{ + return mTitleId; +} + +void nn::hac::ContentMeta::setTitleId(uint64_t title_id) +{ + mTitleId = title_id; +} + +uint32_t nn::hac::ContentMeta::getTitleVersion() const +{ + return mTitleVersion; +} + +void nn::hac::ContentMeta::setTitleVersion(uint32_t version) +{ + mTitleVersion = version; +} + +nn::hac::cnmt::ContentMetaType nn::hac::ContentMeta::getContentMetaType() const +{ + return mType; +} + +void nn::hac::ContentMeta::setContentMetaType(cnmt::ContentMetaType type) +{ + mType = type; +} + +byte_t nn::hac::ContentMeta::getAttributes() const +{ + return mAttributes; +} + +void nn::hac::ContentMeta::setAttributes(byte_t attributes) +{ + mAttributes = attributes; +} + +uint32_t nn::hac::ContentMeta::getRequiredDownloadSystemVersion() const +{ + return mRequiredDownloadSystemVersion; +} + +void nn::hac::ContentMeta::setRequiredDownloadSystemVersion(uint32_t version) +{ + mRequiredDownloadSystemVersion = version; +} + +const nn::hac::ApplicationMetaExtendedHeader& nn::hac::ContentMeta::getApplicationMetaExtendedHeader() const +{ + return mApplicationMetaExtendedHeader; +} + +void nn::hac::ContentMeta::setApplicationMetaExtendedHeader(const ApplicationMetaExtendedHeader& exhdr) +{ + mApplicationMetaExtendedHeader = exhdr; +} + +const nn::hac::PatchMetaExtendedHeader& nn::hac::ContentMeta::getPatchMetaExtendedHeader() const +{ + return mPatchMetaExtendedHeader; +} + +void nn::hac::ContentMeta::setPatchMetaExtendedHeader(const PatchMetaExtendedHeader& exhdr) +{ + mPatchMetaExtendedHeader = exhdr; +} + +const nn::hac::AddOnContentMetaExtendedHeader& nn::hac::ContentMeta::getAddOnContentMetaExtendedHeader() const +{ + return mAddOnContentMetaExtendedHeader; +} + +void nn::hac::ContentMeta::setAddOnContentMetaExtendedHeader(const AddOnContentMetaExtendedHeader& exhdr) +{ + mAddOnContentMetaExtendedHeader = exhdr; +} + +const nn::hac::DeltaMetaExtendedHeader& nn::hac::ContentMeta::getDeltaMetaExtendedHeader() const +{ + return mDeltaMetaExtendedHeader; +} + +void nn::hac::ContentMeta::setDeltaMetaExtendedHeader(const DeltaMetaExtendedHeader& exhdr) +{ + mDeltaMetaExtendedHeader = exhdr; +} + +const fnd::List& nn::hac::ContentMeta::getContentInfo() const +{ + return mContentInfo; +} + +void nn::hac::ContentMeta::setContentInfo(const fnd::List& info) +{ + mContentInfo = info; +} + +const fnd::List& nn::hac::ContentMeta::getContentMetaInfo() const +{ + return mContentMetaInfo; +} + +void nn::hac::ContentMeta::setContentMetaInfo(const fnd::List& info) +{ + mContentMetaInfo = info; +} + +const fnd::Vec & nn::hac::ContentMeta::getExtendedData() const +{ + return mExtendedData; +} + +void nn::hac::ContentMeta::setExtendedData(const fnd::Vec& data) +{ + mExtendedData = data; +} + +const nn::hac::cnmt::sDigest & nn::hac::ContentMeta::getDigest() const +{ + return mDigest; +} + +void nn::hac::ContentMeta::setDigest(const nn::hac::cnmt::sDigest& digest) +{ + mDigest = digest; +} + +bool nn::hac::ContentMeta::validateExtendedHeaderSize(cnmt::ContentMetaType type, size_t exhdrSize) const +{ + bool validSize = false; + + switch (type) + { + case (cnmt::METATYPE_APPLICATION): + validSize = (exhdrSize == sizeof(sApplicationMetaExtendedHeader)); + break; + case (cnmt::METATYPE_PATCH): + validSize = (exhdrSize == sizeof(sPatchMetaExtendedHeader)); + break; + case (cnmt::METATYPE_ADD_ON_CONTENT): + validSize = (exhdrSize == sizeof(sAddOnContentMetaExtendedHeader)); + break; + case (cnmt::METATYPE_DELTA): + validSize = (exhdrSize == sizeof(sDeltaMetaExtendedHeader)); + break; + default: + validSize = (exhdrSize == 0); + } + + return validSize; +} + +size_t nn::hac::ContentMeta::getExtendedDataSize(cnmt::ContentMetaType type, const byte_t * data) const +{ + size_t exdata_len = 0; + if (type == cnmt::METATYPE_PATCH) + { + const sPatchMetaExtendedHeader* exhdr = (const sPatchMetaExtendedHeader*)(data); + exdata_len = exhdr->extended_data_size.get(); + } + else if (type == cnmt::METATYPE_DELTA) + { + const sDeltaMetaExtendedHeader* exhdr = (const sDeltaMetaExtendedHeader*)(data); + exdata_len = exhdr->extended_data_size.get(); + } + return exdata_len; +} + +void nn::hac::ContentMeta::validateBinary(const byte_t * data, size_t len) const +{ + // check if it is large enough to read the header + if (len < sizeof(sContentMetaHeader)) + { + throw fnd::Exception(kModuleName, "Binary too small"); + } + + // get pointer to header structure + const sContentMetaHeader* hdr = (const sContentMetaHeader*)data; + + // validate extended header size + if (validateExtendedHeaderSize((cnmt::ContentMetaType)hdr->type, hdr->exhdr_size.get()) == false) + { + throw fnd::Exception(kModuleName, "Invalid extended header size"); + } + + // check binary size again for new minimum size + if (len < getTotalSize(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), 0)) + { + throw fnd::Exception(kModuleName, "Binary too small"); + } + + // check binary size again with extended data size + if (len < getTotalSize(hdr->exhdr_size.get(), hdr->content_count.get(), hdr->content_meta_count.get(), getExtendedDataSize((cnmt::ContentMetaType)hdr->type, data + getExtendedHeaderOffset()))) + { + throw fnd::Exception(kModuleName, "Binary too small"); + } } \ No newline at end of file diff --git a/lib/libhac/source/ContentMetaInfo.cpp b/lib/libhac/source/ContentMetaInfo.cpp new file mode 100644 index 0000000..3a1e4fe --- /dev/null +++ b/lib/libhac/source/ContentMetaInfo.cpp @@ -0,0 +1,114 @@ +#include + +nn::hac::ContentMetaInfo::ContentMetaInfo() +{ + clear(); +} + +nn::hac::ContentMetaInfo::ContentMetaInfo(const ContentMetaInfo& other) +{ + *this = other; +} + +void nn::hac::ContentMetaInfo::operator=(const ContentMetaInfo& other) +{ + clear(); + mRawBinary = other.mRawBinary; + mTitleId = other.mTitleId; + mTitleVersion = other.mTitleVersion; + mType = other.mType; + mAttributes = other.mAttributes; +} + +bool nn::hac::ContentMetaInfo::operator==(const ContentMetaInfo& other) const +{ + return (mTitleId == other.mTitleId) \ + && (mTitleVersion == other.mTitleVersion) \ + && (mType == other.mType) \ + && (mAttributes == other.mAttributes); +} + +bool nn::hac::ContentMetaInfo::operator!=(const ContentMetaInfo& other) const +{ + return !(*this == other); +} + +void nn::hac::ContentMetaInfo::toBytes() +{ + mRawBinary.alloc(sizeof(sContentMetaInfo)); + sContentMetaInfo* info = (sContentMetaInfo*)mRawBinary.data(); + + info->id = mTitleId; + info->version = mTitleVersion; + info->type = mType; + info->attributes = mAttributes; +} + +void nn::hac::ContentMetaInfo::fromBytes(const byte_t* bytes, size_t len) +{ + if (len < sizeof(sContentMetaInfo)) + { + throw fnd::Exception(kModuleName, "ContentMetaInfo too small"); + } + + const sContentMetaInfo* info = (const sContentMetaInfo*)bytes; + + mTitleId = info->id.get(); + mTitleVersion = info->version.get(); + mType = (cnmt::ContentMetaType)info->type; + mAttributes = info->attributes; +} + +const fnd::Vec& nn::hac::ContentMetaInfo::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::ContentMetaInfo::clear() +{ + mRawBinary.clear(); + mTitleId = 0; + mTitleVersion = 0; + mType = cnmt::ContentMetaType::METATYPE_APPLICATION; + mAttributes = 0; +} + +uint64_t nn::hac::ContentMetaInfo::getTitleId() const +{ + return mTitleId; +} + +void nn::hac::ContentMetaInfo::setTitleId(uint64_t title_id) +{ + mTitleId = title_id; +} + +uint32_t nn::hac::ContentMetaInfo::getTitleVersion() const +{ + return mTitleVersion; +} + +void nn::hac::ContentMetaInfo::setTitleVersion(uint32_t ver) +{ + mTitleVersion = ver; +} + +nn::hac::cnmt::ContentMetaType nn::hac::ContentMetaInfo::getContentMetaType() const +{ + return mType; +} + +void nn::hac::ContentMetaInfo::setContentMetaType(cnmt::ContentMetaType type) +{ + mType = type; +} + +byte_t nn::hac::ContentMetaInfo::getAttributes() const +{ + return mAttributes; +} + +void nn::hac::ContentMetaInfo::setAttributes(byte_t attr) +{ + mAttributes = attr; +} diff --git a/lib/libhac/source/DeltaMetaExtendedHeader.cpp b/lib/libhac/source/DeltaMetaExtendedHeader.cpp new file mode 100644 index 0000000..b69afa7 --- /dev/null +++ b/lib/libhac/source/DeltaMetaExtendedHeader.cpp @@ -0,0 +1,84 @@ +#include + +nn::hac::DeltaMetaExtendedHeader::DeltaMetaExtendedHeader() +{ + clear(); +} + +nn::hac::DeltaMetaExtendedHeader::DeltaMetaExtendedHeader(const DeltaMetaExtendedHeader& other) +{ + *this = other; +} + +void nn::hac::DeltaMetaExtendedHeader::operator=(const DeltaMetaExtendedHeader& other) +{ + clear(); + mRawBinary = other.mRawBinary; + mApplicationId = other.mApplicationId; + mExtendedDataSize = other.mExtendedDataSize; +} + +bool nn::hac::DeltaMetaExtendedHeader::operator==(const DeltaMetaExtendedHeader& other) const +{ + return (mApplicationId == other.mApplicationId) \ + && (mExtendedDataSize == other.mExtendedDataSize); +} + +bool nn::hac::DeltaMetaExtendedHeader::operator!=(const DeltaMetaExtendedHeader& other) const +{ + return !(*this == other); +} + +void nn::hac::DeltaMetaExtendedHeader::toBytes() +{ + mRawBinary.alloc(sizeof(sDeltaMetaExtendedHeader)); + sDeltaMetaExtendedHeader* info = (sDeltaMetaExtendedHeader*)mRawBinary.data(); + + info->application_id = mApplicationId; + info->extended_data_size = mExtendedDataSize; +} + +void nn::hac::DeltaMetaExtendedHeader::fromBytes(const byte_t* bytes, size_t len) +{ + if (len < sizeof(sDeltaMetaExtendedHeader)) + { + throw fnd::Exception(kModuleName, "DeltaMetaExtendedHeader too small"); + } + + const sDeltaMetaExtendedHeader* info = (const sDeltaMetaExtendedHeader*)bytes; + + mApplicationId = info->application_id.get(); + mExtendedDataSize = info->extended_data_size.get(); +} + +const fnd::Vec& nn::hac::DeltaMetaExtendedHeader::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::DeltaMetaExtendedHeader::clear() +{ + mRawBinary.clear(); + mApplicationId = 0; + mExtendedDataSize = 0; +} + +uint64_t nn::hac::DeltaMetaExtendedHeader::getApplicationId() const +{ + return mApplicationId; +} + +void nn::hac::DeltaMetaExtendedHeader::setApplicationId(uint64_t application_id) +{ + mApplicationId = application_id; +} + +uint32_t nn::hac::DeltaMetaExtendedHeader::getExtendedDataSize() const +{ + return mExtendedDataSize; +} + +void nn::hac::DeltaMetaExtendedHeader::setExtendedDataSize(uint32_t size) +{ + mExtendedDataSize = size; +} \ No newline at end of file diff --git a/lib/libhac/source/FileSystemAccessControlBinary.cpp b/lib/libhac/source/FileSystemAccessControl.cpp similarity index 77% rename from lib/libhac/source/FileSystemAccessControlBinary.cpp rename to lib/libhac/source/FileSystemAccessControl.cpp index 18f08af..ce0e3d9 100644 --- a/lib/libhac/source/FileSystemAccessControlBinary.cpp +++ b/lib/libhac/source/FileSystemAccessControl.cpp @@ -1,219 +1,219 @@ -#include -#include - -nn::hac::FileSystemAccessControlBinary::FileSystemAccessControlBinary() -{ - clear(); -} - -nn::hac::FileSystemAccessControlBinary::FileSystemAccessControlBinary(const FileSystemAccessControlBinary & other) -{ - *this = other; -} - -void nn::hac::FileSystemAccessControlBinary::operator=(const FileSystemAccessControlBinary & other) -{ - mRawBinary = other.mRawBinary; - mVersion = other.mVersion; - mFsaRights = other.mFsaRights; - mContentOwnerIdList = other.mContentOwnerIdList; - mSaveDataOwnerIdList = other.mSaveDataOwnerIdList; -} - -bool nn::hac::FileSystemAccessControlBinary::operator==(const FileSystemAccessControlBinary & other) const -{ - return (mVersion == other.mVersion) \ - && (mFsaRights == other.mFsaRights) \ - && (mContentOwnerIdList == other.mContentOwnerIdList) \ - && (mSaveDataOwnerIdList == other.mSaveDataOwnerIdList); -} - -bool nn::hac::FileSystemAccessControlBinary::operator!=(const FileSystemAccessControlBinary & other) const -{ - return !(*this == other); -} - -void nn::hac::FileSystemAccessControlBinary::toBytes() -{ - // determine section layout - struct sLayout { - uint32_t offset, size; - } content, savedata; - - content.offset = (uint32_t)align(sizeof(sFacHeader), fac::kSectionAlignSize); - if (mContentOwnerIdList.size() > 0) - content.size = (uint32_t)(sizeof(uint32_t) + mContentOwnerIdList.size() * sizeof(uint64_t)); - else - content.size = 0; - - savedata.offset = (uint32_t)(content.offset + (content.size > 0 ? align(content.size, fac::kSectionAlignSize) : 0)); - if (mSaveDataOwnerIdList.size() > 0) - savedata.size = (uint32_t)(sizeof(uint32_t) + align(mSaveDataOwnerIdList.size(), fac::kSectionAlignSize) + mSaveDataOwnerIdList.size() * sizeof(uint64_t)); - else - savedata.size = 0; - - - // get total size - size_t total_size = _MAX(_MAX(content.offset + content.size, savedata.offset + savedata.size), align(sizeof(sFacHeader), fac::kSectionAlignSize)); - - mRawBinary.alloc(total_size); - sFacHeader* hdr = (sFacHeader*)mRawBinary.data(); - - // set type - hdr->version = mVersion; - - // flags - uint64_t flag = 0; - for (size_t i = 0; i < mFsaRights.size(); i++) - { - flag |= _BIT((uint64_t)mFsaRights[i]); - } - hdr->fac_flags = flag; - - // set offset/size - hdr->content_owner_ids.offset = content.offset; - if (content.size > 0) - hdr->content_owner_ids.size = content.size; - hdr->save_data_owner_ids.offset = savedata.offset; - if (savedata.size > 0) - hdr->save_data_owner_ids.size = savedata.size; - - // set ids - le_uint32_t* content_owner_id_num = (le_uint32_t*)(mRawBinary.data() + content.offset); - le_uint64_t* content_owner_ids = (le_uint64_t*)(mRawBinary.data() + content.offset + sizeof(uint32_t)); - content_owner_id_num->set((uint32_t)mContentOwnerIdList.size()); - for (size_t i = 0; i < mContentOwnerIdList.size(); i++) - { - content_owner_ids[i] = mContentOwnerIdList[i]; - } - - le_uint32_t* save_data_owner_id_num = (le_uint32_t*)(mRawBinary.data() + savedata.offset); - byte_t* save_data_owner_id_accessibility_array = (mRawBinary.data() + savedata.offset + sizeof(uint32_t)); - le_uint64_t* save_data_owner_ids = (le_uint64_t*)(mRawBinary.data() + savedata.offset + sizeof(uint32_t) + align(mSaveDataOwnerIdList.size(), sizeof(uint32_t))); - save_data_owner_id_num->set((uint32_t)mSaveDataOwnerIdList.size()); - for (size_t i = 0; i < mSaveDataOwnerIdList.size(); i++) - { - save_data_owner_id_accessibility_array[i] = mSaveDataOwnerIdList[i].access_type; - save_data_owner_ids[i] = mSaveDataOwnerIdList[i].id; - } -} - -void nn::hac::FileSystemAccessControlBinary::fromBytes(const byte_t* data, size_t len) -{ - // check size - if (len < sizeof(sFacHeader)) - { - throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo binary is too small"); - } - - // clear variables - clear(); - - // save a copy of the header - sFacHeader hdr; - memcpy((void*)&hdr, data, sizeof(sFacHeader)); - - // check format version - if (hdr.version.get() != fac::kFacFormatVersion) - { - throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo format version unsupported"); - } - - // get total size - size_t total_size = _MAX(_MAX(hdr.content_owner_ids.offset.get() + hdr.content_owner_ids.size.get(), hdr.save_data_owner_ids.offset.get() + hdr.save_data_owner_ids.size.get()), align(sizeof(sFacHeader), fac::kSectionAlignSize)); - - // validate binary size - if (len < total_size) - { - throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo binary is too small"); - } - - // allocate memory - mRawBinary.alloc(total_size); - memcpy(mRawBinary.data(), data, mRawBinary.size()); - - // save variables - mVersion = hdr.version.get(); - for (size_t i = 0; i < 64; i++) - { - if (_HAS_BIT(hdr.fac_flags.get(), i)) - { - mFsaRights.addElement((fac::FsAccessFlag)i); - } - } - - // save ids - if (hdr.content_owner_ids.size.get() > 0) - { - size_t content_owner_id_num = ((le_uint32_t*)(mRawBinary.data() + hdr.content_owner_ids.offset.get()))->get(); - le_uint64_t* content_owner_ids = (le_uint64_t*)(mRawBinary.data() + hdr.content_owner_ids.offset.get() + sizeof(uint32_t)); - for (size_t i = 0; i < content_owner_id_num; i++) - { - mContentOwnerIdList.addElement(content_owner_ids[i].get()); - } - } - if (hdr.save_data_owner_ids.size.get() > 0) - { - size_t save_data_owner_id_num = ((le_uint32_t*)(mRawBinary.data() + hdr.save_data_owner_ids.offset.get()))->get(); - byte_t* save_data_owner_id_accessibility_array = (mRawBinary.data() + hdr.save_data_owner_ids.offset.get() + sizeof(uint32_t)); - le_uint64_t* save_data_owner_ids = (le_uint64_t*)(mRawBinary.data() + hdr.save_data_owner_ids.offset.get() + sizeof(uint32_t) + align(save_data_owner_id_num, fac::kSectionAlignSize)); - for (size_t i = 0; i < save_data_owner_id_num; i++) - { - mSaveDataOwnerIdList.addElement({ (fac::SaveDataOwnerIdAccessType)save_data_owner_id_accessibility_array[i], save_data_owner_ids[i].get() }); - } - } -} - -const fnd::Vec& nn::hac::FileSystemAccessControlBinary::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::FileSystemAccessControlBinary::clear() -{ - mRawBinary.clear(); - mVersion = 0; - mFsaRights.clear(); - mContentOwnerIdList.clear(); - mSaveDataOwnerIdList.clear(); -} - -uint32_t nn::hac::FileSystemAccessControlBinary::getFormatVersion() const -{ - return mVersion; -} - -void nn::hac::FileSystemAccessControlBinary::setFormatVersion(uint32_t format_version) -{ - mVersion = format_version; -} - -const fnd::List& nn::hac::FileSystemAccessControlBinary::getFsaRightsList() const -{ - return mFsaRights; -} - -void nn::hac::FileSystemAccessControlBinary::setFsaRightsList(const fnd::List& list) -{ - mFsaRights = list; -} - -const fnd::List& nn::hac::FileSystemAccessControlBinary::getContentOwnerIdList() const -{ - return mContentOwnerIdList; -} - -void nn::hac::FileSystemAccessControlBinary::setContentOwnerIdList(const fnd::List& list) -{ - mContentOwnerIdList = list; -} - -const fnd::List& nn::hac::FileSystemAccessControlBinary::getSaveDataOwnerIdList() const -{ - return mSaveDataOwnerIdList; -} - -void nn::hac::FileSystemAccessControlBinary::setSaveDataOwnerIdList(const fnd::List& list) -{ - mSaveDataOwnerIdList = list; +#include +#include + +nn::hac::FileSystemAccessControl::FileSystemAccessControl() +{ + clear(); +} + +nn::hac::FileSystemAccessControl::FileSystemAccessControl(const FileSystemAccessControl & other) +{ + *this = other; +} + +void nn::hac::FileSystemAccessControl::operator=(const FileSystemAccessControl & other) +{ + mRawBinary = other.mRawBinary; + mVersion = other.mVersion; + mFsaRights = other.mFsaRights; + mContentOwnerIdList = other.mContentOwnerIdList; + mSaveDataOwnerIdList = other.mSaveDataOwnerIdList; +} + +bool nn::hac::FileSystemAccessControl::operator==(const FileSystemAccessControl & other) const +{ + return (mVersion == other.mVersion) \ + && (mFsaRights == other.mFsaRights) \ + && (mContentOwnerIdList == other.mContentOwnerIdList) \ + && (mSaveDataOwnerIdList == other.mSaveDataOwnerIdList); +} + +bool nn::hac::FileSystemAccessControl::operator!=(const FileSystemAccessControl & other) const +{ + return !(*this == other); +} + +void nn::hac::FileSystemAccessControl::toBytes() +{ + // determine section layout + struct sLayout { + uint32_t offset, size; + } content, savedata; + + content.offset = (uint32_t)align(sizeof(sFacHeader), fac::kSectionAlignSize); + if (mContentOwnerIdList.size() > 0) + content.size = (uint32_t)(sizeof(uint32_t) + mContentOwnerIdList.size() * sizeof(uint64_t)); + else + content.size = 0; + + savedata.offset = (uint32_t)(content.offset + (content.size > 0 ? align(content.size, fac::kSectionAlignSize) : 0)); + if (mSaveDataOwnerIdList.size() > 0) + savedata.size = (uint32_t)(sizeof(uint32_t) + align(mSaveDataOwnerIdList.size(), fac::kSectionAlignSize) + mSaveDataOwnerIdList.size() * sizeof(uint64_t)); + else + savedata.size = 0; + + + // get total size + size_t total_size = _MAX(_MAX(content.offset + content.size, savedata.offset + savedata.size), align(sizeof(sFacHeader), fac::kSectionAlignSize)); + + mRawBinary.alloc(total_size); + sFacHeader* hdr = (sFacHeader*)mRawBinary.data(); + + // set type + hdr->version = mVersion; + + // flags + uint64_t flag = 0; + for (size_t i = 0; i < mFsaRights.size(); i++) + { + flag |= _BIT((uint64_t)mFsaRights[i]); + } + hdr->fac_flags = flag; + + // set offset/size + hdr->content_owner_ids.offset = content.offset; + if (content.size > 0) + hdr->content_owner_ids.size = content.size; + hdr->save_data_owner_ids.offset = savedata.offset; + if (savedata.size > 0) + hdr->save_data_owner_ids.size = savedata.size; + + // set ids + le_uint32_t* content_owner_id_num = (le_uint32_t*)(mRawBinary.data() + content.offset); + le_uint64_t* content_owner_ids = (le_uint64_t*)(mRawBinary.data() + content.offset + sizeof(uint32_t)); + content_owner_id_num->set((uint32_t)mContentOwnerIdList.size()); + for (size_t i = 0; i < mContentOwnerIdList.size(); i++) + { + content_owner_ids[i] = mContentOwnerIdList[i]; + } + + le_uint32_t* save_data_owner_id_num = (le_uint32_t*)(mRawBinary.data() + savedata.offset); + byte_t* save_data_owner_id_accessibility_array = (mRawBinary.data() + savedata.offset + sizeof(uint32_t)); + le_uint64_t* save_data_owner_ids = (le_uint64_t*)(mRawBinary.data() + savedata.offset + sizeof(uint32_t) + align(mSaveDataOwnerIdList.size(), sizeof(uint32_t))); + save_data_owner_id_num->set((uint32_t)mSaveDataOwnerIdList.size()); + for (size_t i = 0; i < mSaveDataOwnerIdList.size(); i++) + { + save_data_owner_id_accessibility_array[i] = mSaveDataOwnerIdList[i].access_type; + save_data_owner_ids[i] = mSaveDataOwnerIdList[i].id; + } +} + +void nn::hac::FileSystemAccessControl::fromBytes(const byte_t* data, size_t len) +{ + // check size + if (len < sizeof(sFacHeader)) + { + throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo binary is too small"); + } + + // clear variables + clear(); + + // save a copy of the header + sFacHeader hdr; + memcpy((void*)&hdr, data, sizeof(sFacHeader)); + + // check format version + if (hdr.version.get() != fac::kFacFormatVersion) + { + throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo format version unsupported"); + } + + // get total size + size_t total_size = _MAX(_MAX(hdr.content_owner_ids.offset.get() + hdr.content_owner_ids.size.get(), hdr.save_data_owner_ids.offset.get() + hdr.save_data_owner_ids.size.get()), align(sizeof(sFacHeader), fac::kSectionAlignSize)); + + // validate binary size + if (len < total_size) + { + throw fnd::Exception(kModuleName, "FileSystemAccessControlInfo binary is too small"); + } + + // allocate memory + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + // save variables + mVersion = hdr.version.get(); + for (size_t i = 0; i < 64; i++) + { + if (_HAS_BIT(hdr.fac_flags.get(), i)) + { + mFsaRights.addElement((fac::FsAccessFlag)i); + } + } + + // save ids + if (hdr.content_owner_ids.size.get() > 0) + { + size_t content_owner_id_num = ((le_uint32_t*)(mRawBinary.data() + hdr.content_owner_ids.offset.get()))->get(); + le_uint64_t* content_owner_ids = (le_uint64_t*)(mRawBinary.data() + hdr.content_owner_ids.offset.get() + sizeof(uint32_t)); + for (size_t i = 0; i < content_owner_id_num; i++) + { + mContentOwnerIdList.addElement(content_owner_ids[i].get()); + } + } + if (hdr.save_data_owner_ids.size.get() > 0) + { + size_t save_data_owner_id_num = ((le_uint32_t*)(mRawBinary.data() + hdr.save_data_owner_ids.offset.get()))->get(); + byte_t* save_data_owner_id_accessibility_array = (mRawBinary.data() + hdr.save_data_owner_ids.offset.get() + sizeof(uint32_t)); + le_uint64_t* save_data_owner_ids = (le_uint64_t*)(mRawBinary.data() + hdr.save_data_owner_ids.offset.get() + sizeof(uint32_t) + align(save_data_owner_id_num, fac::kSectionAlignSize)); + for (size_t i = 0; i < save_data_owner_id_num; i++) + { + mSaveDataOwnerIdList.addElement({ (fac::SaveDataOwnerIdAccessType)save_data_owner_id_accessibility_array[i], save_data_owner_ids[i].get() }); + } + } +} + +const fnd::Vec& nn::hac::FileSystemAccessControl::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::FileSystemAccessControl::clear() +{ + mRawBinary.clear(); + mVersion = 0; + mFsaRights.clear(); + mContentOwnerIdList.clear(); + mSaveDataOwnerIdList.clear(); +} + +uint32_t nn::hac::FileSystemAccessControl::getFormatVersion() const +{ + return mVersion; +} + +void nn::hac::FileSystemAccessControl::setFormatVersion(uint32_t format_version) +{ + mVersion = format_version; +} + +const fnd::List& nn::hac::FileSystemAccessControl::getFsaRightsList() const +{ + return mFsaRights; +} + +void nn::hac::FileSystemAccessControl::setFsaRightsList(const fnd::List& list) +{ + mFsaRights = list; +} + +const fnd::List& nn::hac::FileSystemAccessControl::getContentOwnerIdList() const +{ + return mContentOwnerIdList; +} + +void nn::hac::FileSystemAccessControl::setContentOwnerIdList(const fnd::List& list) +{ + mContentOwnerIdList = list; +} + +const fnd::List& nn::hac::FileSystemAccessControl::getSaveDataOwnerIdList() const +{ + return mSaveDataOwnerIdList; +} + +void nn::hac::FileSystemAccessControl::setSaveDataOwnerIdList(const fnd::List& list) +{ + mSaveDataOwnerIdList = list; } \ No newline at end of file diff --git a/lib/libhac/source/XciHeader.cpp b/lib/libhac/source/GameCardHeader.cpp similarity index 54% rename from lib/libhac/source/XciHeader.cpp rename to lib/libhac/source/GameCardHeader.cpp index e786a7f..dc6bb7d 100644 --- a/lib/libhac/source/XciHeader.cpp +++ b/lib/libhac/source/GameCardHeader.cpp @@ -1,16 +1,16 @@ -#include +#include -nn::hac::XciHeader::XciHeader() +nn::hac::GameCardHeader::GameCardHeader() { clear(); } -nn::hac::XciHeader::XciHeader(const XciHeader& other) +nn::hac::GameCardHeader::GameCardHeader(const GameCardHeader& other) { *this = other; } -void nn::hac::XciHeader::operator=(const XciHeader& other) +void nn::hac::GameCardHeader::operator=(const GameCardHeader& other) { mRomAreaStartPage = other.mRomAreaStartPage; mBackupAreaStartPage = other.mBackupAreaStartPage; @@ -39,11 +39,11 @@ void nn::hac::XciHeader::operator=(const XciHeader& other) mWait2TimeWrite = other.mWait2TimeWrite; mFwMode = other.mFwMode; mUppVersion = other.mUppVersion; - memcpy(mUppHash, other.mUppHash, xci::kUppHashLen); + memcpy(mUppHash, other.mUppHash, gc::kUppHashLen); mUppId = other.mUppId; } -bool nn::hac::XciHeader::operator==(const XciHeader& other) const +bool nn::hac::GameCardHeader::operator==(const GameCardHeader& other) const { return (mRomAreaStartPage == other.mRomAreaStartPage) && (mBackupAreaStartPage == other.mBackupAreaStartPage) @@ -72,42 +72,42 @@ bool nn::hac::XciHeader::operator==(const XciHeader& other) const && (mWait2TimeWrite == other.mWait2TimeWrite) && (mFwMode == other.mFwMode) && (mUppVersion == other.mUppVersion) - && (memcmp(mUppHash, other.mUppHash, xci::kUppHashLen) == 0) + && (memcmp(mUppHash, other.mUppHash, gc::kUppHashLen) == 0) && (mUppId == other.mUppId); } -bool nn::hac::XciHeader::operator!=(const XciHeader& other) const +bool nn::hac::GameCardHeader::operator!=(const GameCardHeader& other) const { return !(*this == other); } -void nn::hac::XciHeader::toBytes() +void nn::hac::GameCardHeader::toBytes() { - fnd::Exception(kModuleName, "exportBinary() not implemented"); + fnd::Exception(kModuleName, "toBytes() not implemented"); } -void nn::hac::XciHeader::fromBytes(const byte_t* data, size_t len) +void nn::hac::GameCardHeader::fromBytes(const byte_t* data, size_t len) { // check input data size - if (len < sizeof(sXciHeader)) + if (len < sizeof(sGcHeader)) { - throw fnd::Exception(kModuleName, "XCI header size is too small"); + throw fnd::Exception(kModuleName, "GameCardImage header size is too small"); } // clear internal members clear(); // allocate internal local binary copy - mRawBinary.alloc(sizeof(sXciHeader)); + mRawBinary.alloc(sizeof(sGcHeader)); memcpy(mRawBinary.data(), data, mRawBinary.size()); - // get sXciHeader ptr - const nn::hac::sXciHeader* hdr = (const nn::hac::sXciHeader*)mRawBinary.data(); + // get sGcHeader ptr + const nn::hac::sGcHeader* hdr = (const nn::hac::sGcHeader*)mRawBinary.data(); - // check XCI signature - if (hdr->st_magic.get() != xci::kXciStructMagic) + // check GameCardImage signature + if (hdr->st_magic.get() != gc::kGcHeaderStructMagic) { - throw fnd::Exception(kModuleName, "XCI header corrupt"); + throw fnd::Exception(kModuleName, "GameCardImage header corrupt"); } mRomAreaStartPage = hdr->rom_area_start_page.get(); @@ -133,8 +133,8 @@ void nn::hac::XciHeader::fromBytes(const byte_t* data, size_t len) // if decrypted if (hdr->reserved_02[sizeof(hdr->reserved_02)-1] == 0x00 && hdr->reserved_02[sizeof(hdr->reserved_02)-2] == 0x00) { - mFwVersion[xci::FWVER_MAJOR] = hdr->fw_version[xci::FWVER_MAJOR].get(); - mFwVersion[xci::FWVER_MINOR] = hdr->fw_version[xci::FWVER_MINOR].get(); + mFwVersion[gc::FWVER_MAJOR] = hdr->fw_version[gc::FWVER_MAJOR].get(); + mFwVersion[gc::FWVER_MINOR] = hdr->fw_version[gc::FWVER_MINOR].get(); mAccCtrl1 = hdr->acc_ctrl_1.get(); mWait1TimeRead = hdr->wait_1_time_read.get(); mWait2TimeRead = hdr->wait_2_time_read.get(); @@ -142,19 +142,19 @@ void nn::hac::XciHeader::fromBytes(const byte_t* data, size_t len) mWait2TimeWrite = hdr->wait_2_time_write.get(); mFwMode = hdr->fw_mode.get(); mUppVersion = hdr->upp_version.get(); - memcpy(mUppHash, hdr->upp_hash, xci::kUppHashLen); + memcpy(mUppHash, hdr->upp_hash, gc::kUppHashLen); mUppId = hdr->upp_id.get(); } } -const fnd::Vec& nn::hac::XciHeader::getBytes() const +const fnd::Vec& nn::hac::GameCardHeader::getBytes() const { return mRawBinary; } // variables -void nn::hac::XciHeader::clear() +void nn::hac::GameCardHeader::clear() { mRomAreaStartPage = 0; mBackupAreaStartPage = 0; @@ -183,297 +183,297 @@ void nn::hac::XciHeader::clear() mWait2TimeWrite = 0; mFwMode = 0; mUppVersion = 0; - memset(mUppHash, 0, xci::kUppHashLen); + memset(mUppHash, 0, gc::kUppHashLen); mUppId = 0; } -uint32_t nn::hac::XciHeader::getRomAreaStartPage() const +uint32_t nn::hac::GameCardHeader::getRomAreaStartPage() const { return mRomAreaStartPage; } -void nn::hac::XciHeader::setRomAreaStartPage(uint32_t startPage) +void nn::hac::GameCardHeader::setRomAreaStartPage(uint32_t startPage) { mRomAreaStartPage = startPage; } -uint32_t nn::hac::XciHeader::getBackupAreaStartPage() const +uint32_t nn::hac::GameCardHeader::getBackupAreaStartPage() const { return mBackupAreaStartPage; } -void nn::hac::XciHeader::setBackupAreaStartPage(uint32_t startPage) +void nn::hac::GameCardHeader::setBackupAreaStartPage(uint32_t startPage) { mBackupAreaStartPage = startPage; } -byte_t nn::hac::XciHeader::getKekIndex() const +byte_t nn::hac::GameCardHeader::getKekIndex() const { return mKekIndex; } -void nn::hac::XciHeader::setKekIndex(byte_t kekIndex) +void nn::hac::GameCardHeader::setKekIndex(byte_t kekIndex) { mKekIndex = kekIndex; } -byte_t nn::hac::XciHeader::getTitleKeyDecIndex() const +byte_t nn::hac::GameCardHeader::getTitleKeyDecIndex() const { return mTitleKeyDecIndex; } -void nn::hac::XciHeader::setTitleKeyDecIndex(byte_t index) +void nn::hac::GameCardHeader::setTitleKeyDecIndex(byte_t index) { mTitleKeyDecIndex = index; } -byte_t nn::hac::XciHeader::getRomSizeType() const +byte_t nn::hac::GameCardHeader::getRomSizeType() const { return mRomSize; } -void nn::hac::XciHeader::setRomSizeType(byte_t romSizeType) +void nn::hac::GameCardHeader::setRomSizeType(byte_t romSizeType) { mRomSize = romSizeType; } -byte_t nn::hac::XciHeader::getCardHeaderVersion() const +byte_t nn::hac::GameCardHeader::getCardHeaderVersion() const { return mCardHeaderVersion; } -void nn::hac::XciHeader::setCardHeaderVersion(byte_t version) +void nn::hac::GameCardHeader::setCardHeaderVersion(byte_t version) { mCardHeaderVersion = version; } -byte_t nn::hac::XciHeader::getFlags() const +byte_t nn::hac::GameCardHeader::getFlags() const { return mFlags; } -void nn::hac::XciHeader::setFlags(byte_t flags) +void nn::hac::GameCardHeader::setFlags(byte_t flags) { mFlags = flags; } -uint64_t nn::hac::XciHeader::getPackageId() const +uint64_t nn::hac::GameCardHeader::getPackageId() const { return mPackageId; } -void nn::hac::XciHeader::setPackageId(uint64_t id) +void nn::hac::GameCardHeader::setPackageId(uint64_t id) { mPackageId = id; } -uint32_t nn::hac::XciHeader::getValidDataEndPage() const +uint32_t nn::hac::GameCardHeader::getValidDataEndPage() const { return mValidDataEndPage; } -void nn::hac::XciHeader::setValidDataEndPage(uint32_t page) +void nn::hac::GameCardHeader::setValidDataEndPage(uint32_t page) { mValidDataEndPage = page; } -const fnd::aes::sAesIvCtr& nn::hac::XciHeader::getAesCbcIv() const +const fnd::aes::sAesIvCtr& nn::hac::GameCardHeader::getAesCbcIv() const { return mAesCbcIv; } -void nn::hac::XciHeader::setAesCbcIv(const fnd::aes::sAesIvCtr& iv) +void nn::hac::GameCardHeader::setAesCbcIv(const fnd::aes::sAesIvCtr& iv) { mAesCbcIv = iv; } -uint64_t nn::hac::XciHeader::getPartitionFsAddress() const +uint64_t nn::hac::GameCardHeader::getPartitionFsAddress() const { return mPartitionFsHeaderAddress; } -void nn::hac::XciHeader::setPartitionFsAddress(uint64_t address) +void nn::hac::GameCardHeader::setPartitionFsAddress(uint64_t address) { mPartitionFsHeaderAddress = address; } -uint64_t nn::hac::XciHeader::getPartitionFsSize() const +uint64_t nn::hac::GameCardHeader::getPartitionFsSize() const { return mPartitionFsHeaderSize; } -void nn::hac::XciHeader::setPartitionFsSize(uint64_t size) +void nn::hac::GameCardHeader::setPartitionFsSize(uint64_t size) { mPartitionFsHeaderSize = size; } -const fnd::sha::sSha256Hash& nn::hac::XciHeader::getPartitionFsHash() const +const fnd::sha::sSha256Hash& nn::hac::GameCardHeader::getPartitionFsHash() const { return mPartitionFsHeaderHash; } -void nn::hac::XciHeader::setPartitionFsHash(const fnd::sha::sSha256Hash& hash) +void nn::hac::GameCardHeader::setPartitionFsHash(const fnd::sha::sSha256Hash& hash) { mPartitionFsHeaderHash = hash; } -const fnd::sha::sSha256Hash& nn::hac::XciHeader::getInitialDataHash() const +const fnd::sha::sSha256Hash& nn::hac::GameCardHeader::getInitialDataHash() const { return mInitialDataHash; } -void nn::hac::XciHeader::setInitialDataHash(const fnd::sha::sSha256Hash& hash) +void nn::hac::GameCardHeader::setInitialDataHash(const fnd::sha::sSha256Hash& hash) { mInitialDataHash = hash; } -uint32_t nn::hac::XciHeader::getSelSec() const +uint32_t nn::hac::GameCardHeader::getSelSec() const { return mSelSec; } -void nn::hac::XciHeader::setSelSec(uint32_t sel_sec) +void nn::hac::GameCardHeader::setSelSec(uint32_t sel_sec) { mSelSec = sel_sec; } -uint32_t nn::hac::XciHeader::getSelT1Key() const +uint32_t nn::hac::GameCardHeader::getSelT1Key() const { return mSelT1Key; } -void nn::hac::XciHeader::setSelT1Key(uint32_t sel_t1_key) +void nn::hac::GameCardHeader::setSelT1Key(uint32_t sel_t1_key) { mSelT1Key = sel_t1_key; } -uint32_t nn::hac::XciHeader::getSelKey() const +uint32_t nn::hac::GameCardHeader::getSelKey() const { return mSelKey; } -void nn::hac::XciHeader::setSelKey(uint32_t sel_key) +void nn::hac::GameCardHeader::setSelKey(uint32_t sel_key) { mSelKey = sel_key; } -uint32_t nn::hac::XciHeader::getLimAreaPage() const +uint32_t nn::hac::GameCardHeader::getLimAreaPage() const { return mLimAreaPage; } -void nn::hac::XciHeader::setLimAreaPage(uint32_t page) +void nn::hac::GameCardHeader::setLimAreaPage(uint32_t page) { mLimAreaPage = page; } -uint32_t nn::hac::XciHeader::getFwVerMajor() const +uint32_t nn::hac::GameCardHeader::getFwVerMajor() const { - return mFwVersion[xci::FWVER_MAJOR]; + return mFwVersion[gc::FWVER_MAJOR]; } -void nn::hac::XciHeader::setFwVerMajor(uint32_t ver) +void nn::hac::GameCardHeader::setFwVerMajor(uint32_t ver) { - mFwVersion[xci::FWVER_MAJOR] = ver; + mFwVersion[gc::FWVER_MAJOR] = ver; } -uint32_t nn::hac::XciHeader::getFwVerMinor() const +uint32_t nn::hac::GameCardHeader::getFwVerMinor() const { - return mFwVersion[xci::FWVER_MINOR]; + return mFwVersion[gc::FWVER_MINOR]; } -void nn::hac::XciHeader::setFwVerMinor(uint32_t ver) +void nn::hac::GameCardHeader::setFwVerMinor(uint32_t ver) { - mFwVersion[xci::FWVER_MINOR] = ver; + mFwVersion[gc::FWVER_MINOR] = ver; } -uint32_t nn::hac::XciHeader::getAccCtrl1() const +uint32_t nn::hac::GameCardHeader::getAccCtrl1() const { return mAccCtrl1; } -void nn::hac::XciHeader::setAccCtrl1(uint32_t acc_ctrl_1) +void nn::hac::GameCardHeader::setAccCtrl1(uint32_t acc_ctrl_1) { mAccCtrl1 = acc_ctrl_1; } -uint32_t nn::hac::XciHeader::getWait1TimeRead() const +uint32_t nn::hac::GameCardHeader::getWait1TimeRead() const { return mWait1TimeRead; } -void nn::hac::XciHeader::setWait1TimeRead(uint32_t seconds) +void nn::hac::GameCardHeader::setWait1TimeRead(uint32_t seconds) { mWait1TimeRead = seconds; } -uint32_t nn::hac::XciHeader::getWait2TimeRead() const +uint32_t nn::hac::GameCardHeader::getWait2TimeRead() const { return mWait2TimeRead; } -void nn::hac::XciHeader::setWait2TimeRead(uint32_t seconds) +void nn::hac::GameCardHeader::setWait2TimeRead(uint32_t seconds) { mWait2TimeRead = seconds; } -uint32_t nn::hac::XciHeader::getWait1TimeWrite() const +uint32_t nn::hac::GameCardHeader::getWait1TimeWrite() const { return mWait1TimeWrite; } -void nn::hac::XciHeader::setWait1TimeWrite(uint32_t seconds) +void nn::hac::GameCardHeader::setWait1TimeWrite(uint32_t seconds) { mWait1TimeWrite = seconds; } -uint32_t nn::hac::XciHeader::getWait2TimeWrite() const +uint32_t nn::hac::GameCardHeader::getWait2TimeWrite() const { return mWait2TimeWrite; } -void nn::hac::XciHeader::setWait2TimeWrite(uint32_t seconds) +void nn::hac::GameCardHeader::setWait2TimeWrite(uint32_t seconds) { mWait2TimeWrite = seconds; } -uint32_t nn::hac::XciHeader::getFwMode() const +uint32_t nn::hac::GameCardHeader::getFwMode() const { return mFwMode; } -void nn::hac::XciHeader::setFwMode(uint32_t fw_mode) +void nn::hac::GameCardHeader::setFwMode(uint32_t fw_mode) { mFwMode = fw_mode; } -uint32_t nn::hac::XciHeader::getUppVersion() const +uint32_t nn::hac::GameCardHeader::getUppVersion() const { return mUppVersion; } -void nn::hac::XciHeader::setUppVersion(uint32_t version) +void nn::hac::GameCardHeader::setUppVersion(uint32_t version) { mUppVersion = version; } -const byte_t* nn::hac::XciHeader::getUppHash() const +const byte_t* nn::hac::GameCardHeader::getUppHash() const { return mUppHash; } -void nn::hac::XciHeader::setUppHash(const byte_t* hash) +void nn::hac::GameCardHeader::setUppHash(const byte_t* hash) { - memcpy(mUppHash, hash, xci::kUppHashLen); + memcpy(mUppHash, hash, gc::kUppHashLen); } -uint64_t nn::hac::XciHeader::getUppId() const +uint64_t nn::hac::GameCardHeader::getUppId() const { return mUppId; } -void nn::hac::XciHeader::setUppId(uint64_t id) +void nn::hac::GameCardHeader::setUppId(uint64_t id) { mUppId = id; } diff --git a/lib/libhac/source/GameCardUtils.cpp b/lib/libhac/source/GameCardUtils.cpp new file mode 100644 index 0000000..891736e --- /dev/null +++ b/lib/libhac/source/GameCardUtils.cpp @@ -0,0 +1,22 @@ +#include + +void nn::hac::GameCardUtils::getXciHeaderAesIv(const nn::hac::sGcHeader* hdr, byte_t* iv) +{ + for (size_t i = 0; i < 16; i++) + { + iv[15-i] = hdr->aescbc_iv.iv[i]; + } +} + +void nn::hac::GameCardUtils::decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key) +{ + byte_t iv[fnd::aes::kAesBlockSize]; + + getXciHeaderAesIv((const nn::hac::sGcHeader*)src, iv); + + // copy plain + memcpy(dst, src, nn::hac::gc::kHeaderEncOffset); + + // decrypt encrypted data + fnd::aes::AesCbcDecrypt(src + nn::hac::gc::kHeaderEncOffset, nn::hac::gc::kHeaderEncSize, key, iv, dst + nn::hac::gc::kHeaderEncOffset); +} \ No newline at end of file diff --git a/lib/libhac/source/KernelCapabilityBinary.cpp b/lib/libhac/source/KernelCapabilityControl.cpp similarity index 64% rename from lib/libhac/source/KernelCapabilityBinary.cpp rename to lib/libhac/source/KernelCapabilityControl.cpp index 096c7b3..dc04074 100644 --- a/lib/libhac/source/KernelCapabilityBinary.cpp +++ b/lib/libhac/source/KernelCapabilityControl.cpp @@ -1,231 +1,231 @@ -#include - -nn::hac::KernelCapabilityBinary::KernelCapabilityBinary() -{} - -nn::hac::KernelCapabilityBinary::KernelCapabilityBinary(const KernelCapabilityBinary & other) -{ - *this = other; -} - -void nn::hac::KernelCapabilityBinary::operator=(const KernelCapabilityBinary & other) -{ - clear(); - mRawBinary = other.mRawBinary; - mThreadInfo = other.mThreadInfo; - mSystemCalls = other.mSystemCalls; - mMemoryMap = other.mMemoryMap; - mInterupts = other.mInterupts; - mMiscParams = other.mMiscParams; - mKernelVersion = other.mKernelVersion; - mHandleTableSize = other.mHandleTableSize; - mMiscFlags = other.mMiscFlags; -} - -bool nn::hac::KernelCapabilityBinary::operator==(const KernelCapabilityBinary & other) const -{ - return (mThreadInfo == other.mThreadInfo) \ - && (mSystemCalls == other.mSystemCalls) \ - && (mMemoryMap == other.mMemoryMap) \ - && (mInterupts == other.mInterupts) \ - && (mMiscParams == other.mMiscParams) \ - && (mKernelVersion == other.mKernelVersion) \ - && (mHandleTableSize == other.mHandleTableSize) \ - && (mMiscFlags == other.mMiscFlags); -} - -bool nn::hac::KernelCapabilityBinary::operator!=(const KernelCapabilityBinary & other) const -{ - return !(*this == other); -} - -void nn::hac::KernelCapabilityBinary::toBytes() -{ - fnd::List caps; - - // get kernel capabiliteis - mThreadInfo.exportKernelCapabilityList(caps); - mSystemCalls.exportKernelCapabilityList(caps); - mMemoryMap.exportKernelCapabilityList(caps); - mInterupts.exportKernelCapabilityList(caps); - mMiscParams.exportKernelCapabilityList(caps); - mKernelVersion.exportKernelCapabilityList(caps); - mHandleTableSize.exportKernelCapabilityList(caps); - mMiscFlags.exportKernelCapabilityList(caps); - - // allocate memory - mRawBinary.alloc(caps.size() * sizeof(uint32_t)); - - // write to binary - uint32_t* raw_caps = (uint32_t*)mRawBinary.data(); - for (size_t i = 0; i < caps.size(); i++) - { - raw_caps[i] = le_word(caps[i].getCap()); - } -} - -void nn::hac::KernelCapabilityBinary::fromBytes(const byte_t * data, size_t len) -{ - if ((len % sizeof(uint32_t)) != 0) - { - throw fnd::Exception(kModuleName, "KernelCapabilityEntry list must be aligned to 4 bytes"); - } - - // save copy of KernelCapabilityBinary - mRawBinary.alloc(len); - memcpy(mRawBinary.data(), data, len); - - fnd::List threadInfoCaps; - fnd::List systemCallCaps; - fnd::List memoryMapCaps; - fnd::List interuptCaps; - fnd::List miscParamCaps; - fnd::List kernelVersionCaps; - fnd::List handleTableSizeCaps; - fnd::List miscFlagsCaps; - - const uint32_t* raw_caps = (const uint32_t*)mRawBinary.data(); - size_t cap_num = mRawBinary.size() / sizeof(uint32_t); - KernelCapabilityEntry cap; - for (size_t i = 0; i < cap_num; i++) - { - cap.setCap(le_word(raw_caps[i])); - switch (cap.getType()) - { - case (kc::KC_THREAD_INFO) : - threadInfoCaps.addElement(cap); - break; - case (kc::KC_ENABLE_SYSTEM_CALLS): - systemCallCaps.addElement(cap); - break; - case (kc::KC_MEMORY_MAP): - case (kc::KC_IO_MEMORY_MAP): - memoryMapCaps.addElement(cap); - break; - case (kc::KC_ENABLE_INTERUPTS): - interuptCaps.addElement(cap); - break; - case (kc::KC_MISC_PARAMS): - miscParamCaps.addElement(cap); - break; - case (kc::KC_KERNEL_VERSION): - kernelVersionCaps.addElement(cap); - break; - case (kc::KC_HANDLE_TABLE_SIZE): - handleTableSizeCaps.addElement(cap); - break; - case (kc::KC_MISC_FLAGS): - miscFlagsCaps.addElement(cap); - break; - default: - throw fnd::Exception(kModuleName, "Unsupported kernel capability type"); - } - } - - mThreadInfo.importKernelCapabilityList(threadInfoCaps); - mSystemCalls.importKernelCapabilityList(systemCallCaps); - mMemoryMap.importKernelCapabilityList(memoryMapCaps); - mInterupts.importKernelCapabilityList(interuptCaps); - mMiscParams.importKernelCapabilityList(miscParamCaps); - mKernelVersion.importKernelCapabilityList(kernelVersionCaps); - mHandleTableSize.importKernelCapabilityList(handleTableSizeCaps); - mMiscFlags.importKernelCapabilityList(miscFlagsCaps); -} - -const fnd::Vec& nn::hac::KernelCapabilityBinary::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::KernelCapabilityBinary::clear() -{ - mRawBinary.clear(); - mThreadInfo.clear(); - mSystemCalls.clear(); - mMemoryMap.clear(); - mInterupts.clear(); - mMiscParams.clear(); - mKernelVersion.clear(); - mHandleTableSize.clear(); - mMiscFlags.clear(); -} - -const nn::hac::ThreadInfoHandler & nn::hac::KernelCapabilityBinary::getThreadInfo() const -{ - return mThreadInfo; -} - -nn::hac::ThreadInfoHandler & nn::hac::KernelCapabilityBinary::getThreadInfo() -{ - return mThreadInfo; -} - -const nn::hac::SystemCallHandler & nn::hac::KernelCapabilityBinary::getSystemCalls() const -{ - return mSystemCalls; -} - -nn::hac::SystemCallHandler & nn::hac::KernelCapabilityBinary::getSystemCalls() -{ - return mSystemCalls; -} - -const nn::hac::MemoryMappingHandler & nn::hac::KernelCapabilityBinary::getMemoryMaps() const -{ - return mMemoryMap; -} - -nn::hac::MemoryMappingHandler & nn::hac::KernelCapabilityBinary::getMemoryMaps() -{ - return mMemoryMap; -} - -const nn::hac::InteruptHandler & nn::hac::KernelCapabilityBinary::getInterupts() const -{ - return mInterupts; -} - -nn::hac::InteruptHandler & nn::hac::KernelCapabilityBinary::getInterupts() -{ - return mInterupts; -} - -const nn::hac::MiscParamsHandler & nn::hac::KernelCapabilityBinary::getMiscParams() const -{ - return mMiscParams; -} - -nn::hac::MiscParamsHandler & nn::hac::KernelCapabilityBinary::getMiscParams() -{ - return mMiscParams; -} - -const nn::hac::KernelVersionHandler & nn::hac::KernelCapabilityBinary::getKernelVersion() const -{ - return mKernelVersion; -} - -nn::hac::KernelVersionHandler & nn::hac::KernelCapabilityBinary::getKernelVersion() -{ - return mKernelVersion; -} - -const nn::hac::HandleTableSizeHandler & nn::hac::KernelCapabilityBinary::getHandleTableSize() const -{ - return mHandleTableSize; -} - -nn::hac::HandleTableSizeHandler & nn::hac::KernelCapabilityBinary::getHandleTableSize() -{ - return mHandleTableSize; -} - -const nn::hac::MiscFlagsHandler & nn::hac::KernelCapabilityBinary::getMiscFlags() const -{ - return mMiscFlags; -} - -nn::hac::MiscFlagsHandler & nn::hac::KernelCapabilityBinary::getMiscFlags() -{ - return mMiscFlags; +#include + +nn::hac::KernelCapabilityControl::KernelCapabilityControl() +{} + +nn::hac::KernelCapabilityControl::KernelCapabilityControl(const KernelCapabilityControl & other) +{ + *this = other; +} + +void nn::hac::KernelCapabilityControl::operator=(const KernelCapabilityControl & other) +{ + clear(); + mRawBinary = other.mRawBinary; + mThreadInfo = other.mThreadInfo; + mSystemCalls = other.mSystemCalls; + mMemoryMap = other.mMemoryMap; + mInterupts = other.mInterupts; + mMiscParams = other.mMiscParams; + mKernelVersion = other.mKernelVersion; + mHandleTableSize = other.mHandleTableSize; + mMiscFlags = other.mMiscFlags; +} + +bool nn::hac::KernelCapabilityControl::operator==(const KernelCapabilityControl & other) const +{ + return (mThreadInfo == other.mThreadInfo) \ + && (mSystemCalls == other.mSystemCalls) \ + && (mMemoryMap == other.mMemoryMap) \ + && (mInterupts == other.mInterupts) \ + && (mMiscParams == other.mMiscParams) \ + && (mKernelVersion == other.mKernelVersion) \ + && (mHandleTableSize == other.mHandleTableSize) \ + && (mMiscFlags == other.mMiscFlags); +} + +bool nn::hac::KernelCapabilityControl::operator!=(const KernelCapabilityControl & other) const +{ + return !(*this == other); +} + +void nn::hac::KernelCapabilityControl::toBytes() +{ + fnd::List caps; + + // get kernel capabiliteis + mThreadInfo.exportKernelCapabilityList(caps); + mSystemCalls.exportKernelCapabilityList(caps); + mMemoryMap.exportKernelCapabilityList(caps); + mInterupts.exportKernelCapabilityList(caps); + mMiscParams.exportKernelCapabilityList(caps); + mKernelVersion.exportKernelCapabilityList(caps); + mHandleTableSize.exportKernelCapabilityList(caps); + mMiscFlags.exportKernelCapabilityList(caps); + + // allocate memory + mRawBinary.alloc(caps.size() * sizeof(uint32_t)); + + // write to binary + uint32_t* raw_caps = (uint32_t*)mRawBinary.data(); + for (size_t i = 0; i < caps.size(); i++) + { + raw_caps[i] = le_word(caps[i].getCap()); + } +} + +void nn::hac::KernelCapabilityControl::fromBytes(const byte_t * data, size_t len) +{ + if ((len % sizeof(uint32_t)) != 0) + { + throw fnd::Exception(kModuleName, "KernelCapabilityEntry list must be aligned to 4 bytes"); + } + + // save copy of KernelCapabilityControl + mRawBinary.alloc(len); + memcpy(mRawBinary.data(), data, len); + + fnd::List threadInfoCaps; + fnd::List systemCallCaps; + fnd::List memoryMapCaps; + fnd::List interuptCaps; + fnd::List miscParamCaps; + fnd::List kernelVersionCaps; + fnd::List handleTableSizeCaps; + fnd::List miscFlagsCaps; + + const uint32_t* raw_caps = (const uint32_t*)mRawBinary.data(); + size_t cap_num = mRawBinary.size() / sizeof(uint32_t); + KernelCapabilityEntry cap; + for (size_t i = 0; i < cap_num; i++) + { + cap.setCap(le_word(raw_caps[i])); + switch (cap.getType()) + { + case (kc::KC_THREAD_INFO) : + threadInfoCaps.addElement(cap); + break; + case (kc::KC_ENABLE_SYSTEM_CALLS): + systemCallCaps.addElement(cap); + break; + case (kc::KC_MEMORY_MAP): + case (kc::KC_IO_MEMORY_MAP): + memoryMapCaps.addElement(cap); + break; + case (kc::KC_ENABLE_INTERUPTS): + interuptCaps.addElement(cap); + break; + case (kc::KC_MISC_PARAMS): + miscParamCaps.addElement(cap); + break; + case (kc::KC_KERNEL_VERSION): + kernelVersionCaps.addElement(cap); + break; + case (kc::KC_HANDLE_TABLE_SIZE): + handleTableSizeCaps.addElement(cap); + break; + case (kc::KC_MISC_FLAGS): + miscFlagsCaps.addElement(cap); + break; + default: + throw fnd::Exception(kModuleName, "Unsupported kernel capability type"); + } + } + + mThreadInfo.importKernelCapabilityList(threadInfoCaps); + mSystemCalls.importKernelCapabilityList(systemCallCaps); + mMemoryMap.importKernelCapabilityList(memoryMapCaps); + mInterupts.importKernelCapabilityList(interuptCaps); + mMiscParams.importKernelCapabilityList(miscParamCaps); + mKernelVersion.importKernelCapabilityList(kernelVersionCaps); + mHandleTableSize.importKernelCapabilityList(handleTableSizeCaps); + mMiscFlags.importKernelCapabilityList(miscFlagsCaps); +} + +const fnd::Vec& nn::hac::KernelCapabilityControl::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::KernelCapabilityControl::clear() +{ + mRawBinary.clear(); + mThreadInfo.clear(); + mSystemCalls.clear(); + mMemoryMap.clear(); + mInterupts.clear(); + mMiscParams.clear(); + mKernelVersion.clear(); + mHandleTableSize.clear(); + mMiscFlags.clear(); +} + +const nn::hac::ThreadInfoHandler & nn::hac::KernelCapabilityControl::getThreadInfo() const +{ + return mThreadInfo; +} + +nn::hac::ThreadInfoHandler & nn::hac::KernelCapabilityControl::getThreadInfo() +{ + return mThreadInfo; +} + +const nn::hac::SystemCallHandler & nn::hac::KernelCapabilityControl::getSystemCalls() const +{ + return mSystemCalls; +} + +nn::hac::SystemCallHandler & nn::hac::KernelCapabilityControl::getSystemCalls() +{ + return mSystemCalls; +} + +const nn::hac::MemoryMappingHandler & nn::hac::KernelCapabilityControl::getMemoryMaps() const +{ + return mMemoryMap; +} + +nn::hac::MemoryMappingHandler & nn::hac::KernelCapabilityControl::getMemoryMaps() +{ + return mMemoryMap; +} + +const nn::hac::InteruptHandler & nn::hac::KernelCapabilityControl::getInterupts() const +{ + return mInterupts; +} + +nn::hac::InteruptHandler & nn::hac::KernelCapabilityControl::getInterupts() +{ + return mInterupts; +} + +const nn::hac::MiscParamsHandler & nn::hac::KernelCapabilityControl::getMiscParams() const +{ + return mMiscParams; +} + +nn::hac::MiscParamsHandler & nn::hac::KernelCapabilityControl::getMiscParams() +{ + return mMiscParams; +} + +const nn::hac::KernelVersionHandler & nn::hac::KernelCapabilityControl::getKernelVersion() const +{ + return mKernelVersion; +} + +nn::hac::KernelVersionHandler & nn::hac::KernelCapabilityControl::getKernelVersion() +{ + return mKernelVersion; +} + +const nn::hac::HandleTableSizeHandler & nn::hac::KernelCapabilityControl::getHandleTableSize() const +{ + return mHandleTableSize; +} + +nn::hac::HandleTableSizeHandler & nn::hac::KernelCapabilityControl::getHandleTableSize() +{ + return mHandleTableSize; +} + +const nn::hac::MiscFlagsHandler & nn::hac::KernelCapabilityControl::getMiscFlags() const +{ + return mMiscFlags; +} + +nn::hac::MiscFlagsHandler & nn::hac::KernelCapabilityControl::getMiscFlags() +{ + return mMiscFlags; } \ No newline at end of file diff --git a/lib/libhac/source/MetaBinary.cpp b/lib/libhac/source/Meta.cpp similarity index 73% rename from lib/libhac/source/MetaBinary.cpp rename to lib/libhac/source/Meta.cpp index 234b916..34e994c 100644 --- a/lib/libhac/source/MetaBinary.cpp +++ b/lib/libhac/source/Meta.cpp @@ -1,295 +1,295 @@ -#include - -#include - -nn::hac::MetaBinary::MetaBinary() -{ - clear(); -} - -nn::hac::MetaBinary::MetaBinary(const MetaBinary & other) : - MetaBinary() -{ - *this = other; -} - -void nn::hac::MetaBinary::operator=(const MetaBinary & other) -{ - mRawBinary = other.mRawBinary; - mInstructionType = other.mInstructionType; - mProcAddressSpaceType = other.mProcAddressSpaceType; - mMainThreadPriority = other.mMainThreadPriority; - mMainThreadCpuId = other.mMainThreadCpuId; - mVersion = other.mVersion; - mMainThreadStackSize = other.mMainThreadStackSize; - mName = other.mName; - mProductCode = other.mProductCode; - mAci = other.mAci; - mAcid = other.mAcid; -} - -bool nn::hac::MetaBinary::operator==(const MetaBinary & other) const -{ - return (mInstructionType == other.mInstructionType) \ - && (mProcAddressSpaceType == other.mProcAddressSpaceType) \ - && (mMainThreadPriority == other.mMainThreadPriority) \ - && (mMainThreadCpuId == other.mMainThreadCpuId) \ - && (mVersion == other.mVersion) \ - && (mMainThreadStackSize == other.mMainThreadStackSize) \ - && (mName == other.mName) \ - && (mProductCode == other.mProductCode) \ - && (mAci == other.mAci) \ - && (mAcid == other.mAcid); -} - -bool nn::hac::MetaBinary::operator!=(const MetaBinary & other) const -{ - return !(*this == other); -} - -void nn::hac::MetaBinary::toBytes() -{ - if (mAcid.getBytes().size() == 0) - mAcid.toBytes(); - - if (mAci.getBytes().size() == 0) - mAci.toBytes(); - - - // determine section layout - struct sLayout { - uint32_t offset, size; - } acid, aci; - - acid.offset = (uint32_t)align(sizeof(sMetaHeader), meta::kSectionAlignSize); - acid.size = (uint32_t)mAcid.getBytes().size(); - aci.offset = (uint32_t)(acid.offset + align(acid.size, meta::kSectionAlignSize)); - aci.size = (uint32_t)mAci.getBytes().size(); - - - // get total size - size_t total_size = _MAX(_MAX(acid.offset + acid.size, aci.offset + aci.size), align(sizeof(sMetaHeader), meta::kSectionAlignSize)); - - mRawBinary.alloc(total_size); - sMetaHeader* hdr = (sMetaHeader*)mRawBinary.data(); - - // set type - hdr->st_magic = meta::kMetaStructMagic; - - // set variables - byte_t flag = ((byte_t)(mInstructionType & 1) | (byte_t)((mProcAddressSpaceType & 3) << 1)) & 0xf; - hdr->flags = flag; - hdr->main_thread_priority = mMainThreadPriority; - hdr->main_thread_cpu_id = mMainThreadCpuId; - hdr->version = mVersion; - hdr->main_thread_stack_size = mMainThreadStackSize; - strncpy(hdr->name, mName.c_str(), meta::kNameMaxLen); - strncpy(hdr->product_code, mProductCode.c_str(), meta::kProductCodeMaxLen); - - // set offset/size - hdr->aci.offset = aci.offset; - hdr->aci.size = aci.size; - hdr->acid.offset = acid.offset; - hdr->acid.size = acid.size; - - // write aci & acid - if (mAci.getBytes().size() > 0) - { - memcpy(mRawBinary.data() + aci.offset, mAci.getBytes().data(), mAci.getBytes().size()); - } - if (mAcid.getBytes().size() > 0) - { - memcpy(mRawBinary.data() + acid.offset, mAcid.getBytes().data(), mAcid.getBytes().size()); - } -} - -void nn::hac::MetaBinary::fromBytes(const byte_t* data, size_t len) -{ - // check size - if (len < sizeof(sMetaHeader)) - { - throw fnd::Exception(kModuleName, "META binary is too small"); - } - - // clear variables - clear(); - - // save a copy of the header - sMetaHeader hdr; - memcpy((void*)&hdr, data, sizeof(sMetaHeader)); - - // check magic - if (hdr.st_magic.get() != meta::kMetaStructMagic) - { - throw fnd::Exception(kModuleName, "META header corrupt (unrecognised struct signature)"); - } - - // save variables - byte_t flag = hdr.flags & 0xf; - mInstructionType = (meta::InstructionType)(flag & 1); - mProcAddressSpaceType = (meta::ProcAddrSpaceType)((flag >> 1) & 3); - mMainThreadPriority = hdr.main_thread_priority; - mMainThreadCpuId = hdr.main_thread_cpu_id; - mVersion = hdr.version.get(); - mMainThreadStackSize = hdr.main_thread_stack_size.get(); - mName = std::string(hdr.name, _MIN(strlen(hdr.name), meta::kNameMaxLen)); - mProductCode = std::string(hdr.product_code, _MIN(strlen(hdr.product_code), meta::kProductCodeMaxLen)); - - // total size - size_t total_size = _MAX(_MAX(hdr.acid.offset.get() + hdr.acid.size.get(), hdr.aci.offset.get() + hdr.aci.size.get()), sizeof(sMetaHeader)); - - // check size - if (total_size > len) - { - throw fnd::Exception(kModuleName, "META binary too small"); - } - - // save local copy - mRawBinary.alloc(total_size); - memcpy(mRawBinary.data(), data, mRawBinary.size()); - - // import Aci/Acid - if (hdr.aci.size.get()) - { - mAci.fromBytes(mRawBinary.data() + hdr.aci.offset.get(), hdr.aci.size.get()); - } - if (hdr.acid.size.get()) - { - mAcid.fromBytes(mRawBinary.data() + hdr.acid.offset.get(), hdr.acid.size.get()); - } -} - -const fnd::Vec& nn::hac::MetaBinary::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::MetaBinary::clear() -{ - mRawBinary.clear(); - mInstructionType = meta::INSTR_64BIT; - mProcAddressSpaceType = meta::ADDR_SPACE_64BIT; - mMainThreadPriority = 0; - mMainThreadCpuId = 0; - mVersion = 0; - mMainThreadStackSize = 0; - mName.clear(); - mProductCode.clear(); - mAci.clear(); - mAcid.clear(); -} - -nn::hac::meta::InstructionType nn::hac::MetaBinary::getInstructionType() const -{ - return mInstructionType; -} - -void nn::hac::MetaBinary::setInstructionType(meta::InstructionType type) -{ - mInstructionType = type; -} - -nn::hac::meta::ProcAddrSpaceType nn::hac::MetaBinary::getProcAddressSpaceType() const -{ - return mProcAddressSpaceType; -} - -void nn::hac::MetaBinary::setProcAddressSpaceType(meta::ProcAddrSpaceType type) -{ - mProcAddressSpaceType = type; -} - -byte_t nn::hac::MetaBinary::getMainThreadPriority() const -{ - return mMainThreadPriority; -} - -void nn::hac::MetaBinary::setMainThreadPriority(byte_t priority) -{ - if (priority > meta::kMaxPriority) - { - throw fnd::Exception(kModuleName, "Illegal main thread priority (range 0-63)"); - } - - mMainThreadPriority = priority; -} - -byte_t nn::hac::MetaBinary::getMainThreadCpuId() const -{ - return mMainThreadCpuId; -} - -void nn::hac::MetaBinary::setMainThreadCpuId(byte_t core_num) -{ - mMainThreadCpuId = core_num; -} - -uint32_t nn::hac::MetaBinary::getVersion() const -{ - return mVersion; -} - -void nn::hac::MetaBinary::setVersion(uint32_t version) -{ - mVersion = version; -} - -uint32_t nn::hac::MetaBinary::getMainThreadStackSize() const -{ - return mMainThreadStackSize; -} - -void nn::hac::MetaBinary::setMainThreadStackSize(uint32_t size) -{ - mMainThreadStackSize = size; -} - -const std::string & nn::hac::MetaBinary::getName() const -{ - return mName; -} - -void nn::hac::MetaBinary::setName(const std::string & name) -{ - if (name.length() > meta::kNameMaxLen) - { - throw fnd::Exception(kModuleName, "Name is too long"); - } - - mName = name; -} - -const std::string & nn::hac::MetaBinary::getProductCode() const -{ - return mProductCode; -} - -void nn::hac::MetaBinary::setProductCode(const std::string & product_code) -{ - if (product_code.length() > meta::kProductCodeMaxLen) - { - throw fnd::Exception(kModuleName, "Product Code is too long"); - } - - mProductCode = product_code; -} - -const nn::hac::AccessControlInfoBinary & nn::hac::MetaBinary::getAci() const -{ - return mAci; -} - -void nn::hac::MetaBinary::setAci(const AccessControlInfoBinary & aci) -{ - mAci = aci; -} - -const nn::hac::AccessControlInfoDescBinary & nn::hac::MetaBinary::getAcid() const -{ - return mAcid; -} - -void nn::hac::MetaBinary::setAcid(const AccessControlInfoDescBinary & acid) -{ - mAcid = acid; +#include + +#include + +nn::hac::Meta::Meta() +{ + clear(); +} + +nn::hac::Meta::Meta(const Meta & other) : + Meta() +{ + *this = other; +} + +void nn::hac::Meta::operator=(const Meta & other) +{ + mRawBinary = other.mRawBinary; + mInstructionType = other.mInstructionType; + mProcAddressSpaceType = other.mProcAddressSpaceType; + mMainThreadPriority = other.mMainThreadPriority; + mMainThreadCpuId = other.mMainThreadCpuId; + mVersion = other.mVersion; + mMainThreadStackSize = other.mMainThreadStackSize; + mName = other.mName; + mProductCode = other.mProductCode; + mAci = other.mAci; + mAcid = other.mAcid; +} + +bool nn::hac::Meta::operator==(const Meta & other) const +{ + return (mInstructionType == other.mInstructionType) \ + && (mProcAddressSpaceType == other.mProcAddressSpaceType) \ + && (mMainThreadPriority == other.mMainThreadPriority) \ + && (mMainThreadCpuId == other.mMainThreadCpuId) \ + && (mVersion == other.mVersion) \ + && (mMainThreadStackSize == other.mMainThreadStackSize) \ + && (mName == other.mName) \ + && (mProductCode == other.mProductCode) \ + && (mAci == other.mAci) \ + && (mAcid == other.mAcid); +} + +bool nn::hac::Meta::operator!=(const Meta & other) const +{ + return !(*this == other); +} + +void nn::hac::Meta::toBytes() +{ + if (mAcid.getBytes().size() == 0) + mAcid.toBytes(); + + if (mAci.getBytes().size() == 0) + mAci.toBytes(); + + + // determine section layout + struct sLayout { + uint32_t offset, size; + } acid, aci; + + acid.offset = (uint32_t)align(sizeof(sMetaHeader), meta::kSectionAlignSize); + acid.size = (uint32_t)mAcid.getBytes().size(); + aci.offset = (uint32_t)(acid.offset + align(acid.size, meta::kSectionAlignSize)); + aci.size = (uint32_t)mAci.getBytes().size(); + + + // get total size + size_t total_size = _MAX(_MAX(acid.offset + acid.size, aci.offset + aci.size), align(sizeof(sMetaHeader), meta::kSectionAlignSize)); + + mRawBinary.alloc(total_size); + sMetaHeader* hdr = (sMetaHeader*)mRawBinary.data(); + + // set type + hdr->st_magic = meta::kMetaStructMagic; + + // set variables + byte_t flag = ((byte_t)(mInstructionType & 1) | (byte_t)((mProcAddressSpaceType & 3) << 1)) & 0xf; + hdr->flags = flag; + hdr->main_thread_priority = mMainThreadPriority; + hdr->main_thread_cpu_id = mMainThreadCpuId; + hdr->version = mVersion; + hdr->main_thread_stack_size = mMainThreadStackSize; + strncpy(hdr->name, mName.c_str(), meta::kNameMaxLen); + strncpy(hdr->product_code, mProductCode.c_str(), meta::kProductCodeMaxLen); + + // set offset/size + hdr->aci.offset = aci.offset; + hdr->aci.size = aci.size; + hdr->acid.offset = acid.offset; + hdr->acid.size = acid.size; + + // write aci & acid + if (mAci.getBytes().size() > 0) + { + memcpy(mRawBinary.data() + aci.offset, mAci.getBytes().data(), mAci.getBytes().size()); + } + if (mAcid.getBytes().size() > 0) + { + memcpy(mRawBinary.data() + acid.offset, mAcid.getBytes().data(), mAcid.getBytes().size()); + } +} + +void nn::hac::Meta::fromBytes(const byte_t* data, size_t len) +{ + // check size + if (len < sizeof(sMetaHeader)) + { + throw fnd::Exception(kModuleName, "META binary is too small"); + } + + // clear variables + clear(); + + // save a copy of the header + sMetaHeader hdr; + memcpy((void*)&hdr, data, sizeof(sMetaHeader)); + + // check magic + if (hdr.st_magic.get() != meta::kMetaStructMagic) + { + throw fnd::Exception(kModuleName, "META header corrupt (unrecognised struct signature)"); + } + + // save variables + byte_t flag = hdr.flags & 0xf; + mInstructionType = (meta::InstructionType)(flag & 1); + mProcAddressSpaceType = (meta::ProcAddrSpaceType)((flag >> 1) & 3); + mMainThreadPriority = hdr.main_thread_priority; + mMainThreadCpuId = hdr.main_thread_cpu_id; + mVersion = hdr.version.get(); + mMainThreadStackSize = hdr.main_thread_stack_size.get(); + mName = std::string(hdr.name, _MIN(strlen(hdr.name), meta::kNameMaxLen)); + mProductCode = std::string(hdr.product_code, _MIN(strlen(hdr.product_code), meta::kProductCodeMaxLen)); + + // total size + size_t total_size = _MAX(_MAX(hdr.acid.offset.get() + hdr.acid.size.get(), hdr.aci.offset.get() + hdr.aci.size.get()), sizeof(sMetaHeader)); + + // check size + if (total_size > len) + { + throw fnd::Exception(kModuleName, "META binary too small"); + } + + // save local copy + mRawBinary.alloc(total_size); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + // import Aci/Acid + if (hdr.aci.size.get()) + { + mAci.fromBytes(mRawBinary.data() + hdr.aci.offset.get(), hdr.aci.size.get()); + } + if (hdr.acid.size.get()) + { + mAcid.fromBytes(mRawBinary.data() + hdr.acid.offset.get(), hdr.acid.size.get()); + } +} + +const fnd::Vec& nn::hac::Meta::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::Meta::clear() +{ + mRawBinary.clear(); + mInstructionType = meta::INSTR_64BIT; + mProcAddressSpaceType = meta::ADDR_SPACE_64BIT; + mMainThreadPriority = 0; + mMainThreadCpuId = 0; + mVersion = 0; + mMainThreadStackSize = 0; + mName.clear(); + mProductCode.clear(); + mAci.clear(); + mAcid.clear(); +} + +nn::hac::meta::InstructionType nn::hac::Meta::getInstructionType() const +{ + return mInstructionType; +} + +void nn::hac::Meta::setInstructionType(meta::InstructionType type) +{ + mInstructionType = type; +} + +nn::hac::meta::ProcAddrSpaceType nn::hac::Meta::getProcAddressSpaceType() const +{ + return mProcAddressSpaceType; +} + +void nn::hac::Meta::setProcAddressSpaceType(meta::ProcAddrSpaceType type) +{ + mProcAddressSpaceType = type; +} + +byte_t nn::hac::Meta::getMainThreadPriority() const +{ + return mMainThreadPriority; +} + +void nn::hac::Meta::setMainThreadPriority(byte_t priority) +{ + if (priority > meta::kMaxPriority) + { + throw fnd::Exception(kModuleName, "Illegal main thread priority (range 0-63)"); + } + + mMainThreadPriority = priority; +} + +byte_t nn::hac::Meta::getMainThreadCpuId() const +{ + return mMainThreadCpuId; +} + +void nn::hac::Meta::setMainThreadCpuId(byte_t core_num) +{ + mMainThreadCpuId = core_num; +} + +uint32_t nn::hac::Meta::getVersion() const +{ + return mVersion; +} + +void nn::hac::Meta::setVersion(uint32_t version) +{ + mVersion = version; +} + +uint32_t nn::hac::Meta::getMainThreadStackSize() const +{ + return mMainThreadStackSize; +} + +void nn::hac::Meta::setMainThreadStackSize(uint32_t size) +{ + mMainThreadStackSize = size; +} + +const std::string & nn::hac::Meta::getName() const +{ + return mName; +} + +void nn::hac::Meta::setName(const std::string & name) +{ + if (name.length() > meta::kNameMaxLen) + { + throw fnd::Exception(kModuleName, "Name is too long"); + } + + mName = name; +} + +const std::string & nn::hac::Meta::getProductCode() const +{ + return mProductCode; +} + +void nn::hac::Meta::setProductCode(const std::string & product_code) +{ + if (product_code.length() > meta::kProductCodeMaxLen) + { + throw fnd::Exception(kModuleName, "Product Code is too long"); + } + + mProductCode = product_code; +} + +const nn::hac::AccessControlInfo & nn::hac::Meta::getAci() const +{ + return mAci; +} + +void nn::hac::Meta::setAci(const AccessControlInfo & aci) +{ + mAci = aci; +} + +const nn::hac::AccessControlInfoDesc & nn::hac::Meta::getAcid() const +{ + return mAcid; +} + +void nn::hac::Meta::setAcid(const AccessControlInfoDesc & acid) +{ + mAcid = acid; } \ No newline at end of file diff --git a/lib/libhac/source/NcaHeader.cpp b/lib/libhac/source/NcaHeader.cpp deleted file mode 100644 index 12edd1d..0000000 --- a/lib/libhac/source/NcaHeader.cpp +++ /dev/null @@ -1,327 +0,0 @@ -#include - -nn::hac::NcaHeader::NcaHeader() -{ - clear(); -} - -nn::hac::NcaHeader::NcaHeader(const NcaHeader & other) -{ - *this = other; -} - -bool nn::hac::NcaHeader::operator==(const NcaHeader & other) const -{ - return (mDistributionType == other.mDistributionType) \ - && (mContentType == other.mContentType) \ - && (mKeyGeneration == other.mKeyGeneration) \ - && (mKaekIndex == other.mKaekIndex) \ - && (mContentSize == other.mContentSize) \ - && (mProgramId == other.mProgramId) \ - && (mContentIndex == other.mContentIndex) \ - && (mSdkAddonVersion == other.mSdkAddonVersion) \ - && (mPartitions == other.mPartitions) \ - && (mEncAesKeys == other.mEncAesKeys); -} - -bool nn::hac::NcaHeader::operator!=(const NcaHeader & other) const -{ - return !(*this == other); -} - -void nn::hac::NcaHeader::operator=(const NcaHeader & other) -{ - if (other.getBytes().size()) - { - fromBytes(other.getBytes().data(), other.getBytes().size()); - } - else - { - mRawBinary.clear(); - mDistributionType = other.mDistributionType; - mContentType = other.mContentType; - mKeyGeneration = other.mKeyGeneration; - mKaekIndex = other.mKaekIndex; - mContentSize = other.mContentSize; - mProgramId = other.mProgramId; - mContentIndex = other.mContentIndex; - mSdkAddonVersion = other.mSdkAddonVersion; - mPartitions = other.mPartitions; - mEncAesKeys = other.mEncAesKeys; - } -} - -void nn::hac::NcaHeader::toBytes() -{ - mRawBinary.alloc(sizeof(sNcaHeader)); - sNcaHeader* hdr = (sNcaHeader*)mRawBinary.data(); - - - switch(mFormatVersion) - { - case (NCA2_FORMAT): - hdr->st_magic = nca::kNca2StructMagic; - break; - case (NCA3_FORMAT): - hdr->st_magic = nca::kNca3StructMagic; - break; - default: - throw fnd::Exception(kModuleName, "Unsupported format version"); - } - hdr->distribution_type = mDistributionType; - hdr->content_type = mContentType; - if (mKeyGeneration > 2) - { - hdr->key_generation = 2; - hdr->key_generation_2 = mKeyGeneration; - } - else - { - hdr->key_generation = mKeyGeneration; - hdr->key_generation_2 = 0; - } - - hdr->key_area_encryption_key_index = mKaekIndex; - hdr->content_size = mContentSize; - hdr->program_id = mProgramId; - hdr->content_index = mContentIndex; - hdr->sdk_addon_version = mSdkAddonVersion; - memcpy(hdr->rights_id, mRightsId, nca::kRightsIdLen); - - // TODO: properly reconstruct NCA layout? atm in hands of user - for (size_t i = 0; i < mPartitions.size(); i++) - { - // determine partition index - byte_t idx = mPartitions[i].index; - - if (mPartitions[i].index >= nca::kPartitionNum || hdr->partition[idx].enabled) continue; - - hdr->partition[idx].start = sizeToBlockNum(mPartitions[i].offset); - hdr->partition[idx].end = (sizeToBlockNum(mPartitions[i].offset) + sizeToBlockNum(mPartitions[i].size)); - hdr->partition[idx].enabled = true; - hdr->partition_hash[idx] = mPartitions[i].hash; - } - - for (size_t i = 0; i < nca::kAesKeyNum; i++) - { - hdr->enc_aes_key[i] = mEncAesKeys[i]; - } -} - -void nn::hac::NcaHeader::fromBytes(const byte_t * data, size_t len) -{ - if (len < sizeof(sNcaHeader)) - { - throw fnd::Exception(kModuleName, "NCA header size is too small"); - } - - clear(); - - mRawBinary.alloc(sizeof(sNcaHeader)); - memcpy(mRawBinary.data(), data, sizeof(sNcaHeader)); - - sNcaHeader* hdr = (sNcaHeader*)mRawBinary.data(); - - switch(hdr->st_magic.get()) - { - case (nca::kNca2StructMagic) : - mFormatVersion = NCA2_FORMAT; - break; - case (nca::kNca3StructMagic) : - mFormatVersion = NCA3_FORMAT; - break; - throw fnd::Exception(kModuleName, "NCA header corrupt"); - } - - mDistributionType = (nca::DistributionType)hdr->distribution_type; - mContentType = (nca::ContentType)hdr->content_type; - mKeyGeneration = _MAX(hdr->key_generation, hdr->key_generation_2); - mKaekIndex = hdr->key_area_encryption_key_index; - mContentSize = *hdr->content_size; - mProgramId = *hdr->program_id; - mContentIndex = *hdr->content_index; - mSdkAddonVersion = *hdr->sdk_addon_version; - memcpy(mRightsId, hdr->rights_id, nca::kRightsIdLen); - - for (size_t i = 0; i < nca::kPartitionNum; i++) - { - // skip sections that don't exist - if (hdr->partition[i].enabled == 0) continue; - - // add high level struct - mPartitions.addElement({(byte_t)i, blockNumToSize(hdr->partition[i].start.get()), blockNumToSize(hdr->partition[i].end.get() - hdr->partition[i].start.get()), hdr->partition_hash[i] }); - } - - for (size_t i = 0; i < nca::kAesKeyNum; i++) - { - mEncAesKeys.addElement(hdr->enc_aes_key[i]); - } -} - -const fnd::Vec& nn::hac::NcaHeader::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::NcaHeader::clear() -{ - mFormatVersion = NCA3_FORMAT; - mDistributionType = nca::DIST_DOWNLOAD; - mContentType = nca::TYPE_PROGRAM; - mKeyGeneration = 0; - mKaekIndex = 0; - mContentSize = 0; - mProgramId = 0; - mContentIndex = 0; - mSdkAddonVersion = 0; - - mPartitions.clear(); - mEncAesKeys.clear(); -} - -nn::hac::NcaHeader::FormatVersion nn::hac::NcaHeader::getFormatVersion() const -{ - return mFormatVersion; -} - -void nn::hac::NcaHeader::setFormatVersion(FormatVersion version) -{ - mFormatVersion = version; -} - -nn::hac::nca::DistributionType nn::hac::NcaHeader::getDistributionType() const -{ - return mDistributionType; -} - -void nn::hac::NcaHeader::setDistributionType(nca::DistributionType type) -{ - mDistributionType = type; -} - -nn::hac::nca::ContentType nn::hac::NcaHeader::getContentType() const -{ - return mContentType; -} - -void nn::hac::NcaHeader::setContentType(nca::ContentType type) -{ - mContentType = type; -} - -byte_t nn::hac::NcaHeader::getKeyGeneration() const -{ - return mKeyGeneration; -} - -void nn::hac::NcaHeader::setKeyGeneration(byte_t gen) -{ - mKeyGeneration = gen; -} - -byte_t nn::hac::NcaHeader::getKaekIndex() const -{ - return mKaekIndex; -} - -void nn::hac::NcaHeader::setKaekIndex(byte_t index) -{ - mKaekIndex = index; -} - -uint64_t nn::hac::NcaHeader::getContentSize() const -{ - return mContentSize; -} - -void nn::hac::NcaHeader::setContentSize(uint64_t size) -{ - mContentSize = size; -} - -uint64_t nn::hac::NcaHeader::getProgramId() const -{ - return mProgramId; -} - -void nn::hac::NcaHeader::setProgramId(uint64_t program_id) -{ - mProgramId = program_id; -} - -uint32_t nn::hac::NcaHeader::getContentIndex() const -{ - return mContentIndex; -} - -void nn::hac::NcaHeader::setContentIndex(uint32_t index) -{ - mContentIndex = index; -} - -uint32_t nn::hac::NcaHeader::getSdkAddonVersion() const -{ - return mSdkAddonVersion; -} - -void nn::hac::NcaHeader::setSdkAddonVersion(uint32_t version) -{ - mSdkAddonVersion = version; -} - -bool nn::hac::NcaHeader::hasRightsId() const -{ - bool rightsIdIsSet = false; - - for (size_t i = 0; i < nca::kRightsIdLen; i++) - { - if (mRightsId[i] != 0) - rightsIdIsSet = true; - } - - return rightsIdIsSet; -} - -const byte_t* nn::hac::NcaHeader::getRightsId() const -{ - return mRightsId; -} - -void nn::hac::NcaHeader::setRightsId(const byte_t* rights_id) -{ - memcpy(mRightsId, rights_id, nca::kRightsIdLen); -} - -const fnd::List& nn::hac::NcaHeader::getPartitions() const -{ - return mPartitions; -} - -void nn::hac::NcaHeader::setPartitions(const fnd::List& partitions) -{ - mPartitions = partitions; - if (mPartitions.size() >= nca::kPartitionNum) - { - throw fnd::Exception(kModuleName, "Too many NCA partitions"); - } -} - -const fnd::List& nn::hac::NcaHeader::getEncAesKeys() const -{ - return mEncAesKeys; -} - -void nn::hac::NcaHeader::setEncAesKeys(const fnd::List& keys) -{ - mEncAesKeys = keys; -} - -uint64_t nn::hac::NcaHeader::blockNumToSize(uint32_t block_num) const -{ - return block_num*nca::kSectorSize; -} - -uint32_t nn::hac::NcaHeader::sizeToBlockNum(uint64_t real_size) const -{ - return (uint32_t)(align(real_size, nca::kSectorSize) / nca::kSectorSize); -} \ No newline at end of file diff --git a/lib/libhac/source/PfsHeader.cpp b/lib/libhac/source/PartitionFsHeader.cpp similarity index 82% rename from lib/libhac/source/PfsHeader.cpp rename to lib/libhac/source/PartitionFsHeader.cpp index 14cd2ec..1e4a431 100644 --- a/lib/libhac/source/PfsHeader.cpp +++ b/lib/libhac/source/PartitionFsHeader.cpp @@ -1,16 +1,16 @@ -#include +#include -nn::hac::PfsHeader::PfsHeader() +nn::hac::PartitionFsHeader::PartitionFsHeader() { clear(); } -nn::hac::PfsHeader::PfsHeader(const PfsHeader & other) +nn::hac::PartitionFsHeader::PartitionFsHeader(const PartitionFsHeader & other) { *this = other; } -void nn::hac::PfsHeader::operator=(const PfsHeader & other) +void nn::hac::PartitionFsHeader::operator=(const PartitionFsHeader & other) { if (other.getBytes().size()) { @@ -24,24 +24,24 @@ void nn::hac::PfsHeader::operator=(const PfsHeader & other) } } -bool nn::hac::PfsHeader::operator==(const PfsHeader & other) const +bool nn::hac::PartitionFsHeader::operator==(const PartitionFsHeader & other) const { return (mFsType == other.mFsType) \ && (mFileList == other.mFileList); } -bool nn::hac::PfsHeader::operator!=(const PfsHeader & other) const +bool nn::hac::PartitionFsHeader::operator!=(const PartitionFsHeader & other) const { return !(*this == other); } -const fnd::Vec& nn::hac::PfsHeader::getBytes() const +const fnd::Vec& nn::hac::PartitionFsHeader::getBytes() const { return mRawBinary; } -void nn::hac::PfsHeader::toBytes() +void nn::hac::PartitionFsHeader::toBytes() { // calculate name table size size_t name_table_size = 0; @@ -113,7 +113,7 @@ void nn::hac::PfsHeader::toBytes() } -void nn::hac::PfsHeader::fromBytes(const byte_t* data, size_t len) +void nn::hac::PartitionFsHeader::fromBytes(const byte_t* data, size_t len) { // check input length meets minimum size if (len < sizeof(sPfsHeader)) @@ -195,39 +195,39 @@ void nn::hac::PfsHeader::fromBytes(const byte_t* data, size_t len) } -void nn::hac::PfsHeader::clear() +void nn::hac::PartitionFsHeader::clear() { mRawBinary.clear(); mFsType = TYPE_PFS0; mFileList.clear(); } -nn::hac::PfsHeader::FsType nn::hac::PfsHeader::getFsType() const +nn::hac::PartitionFsHeader::FsType nn::hac::PartitionFsHeader::getFsType() const { return mFsType; } -void nn::hac::PfsHeader::setFsType(FsType type) +void nn::hac::PartitionFsHeader::setFsType(FsType type) { mFsType = type; } -const fnd::List& nn::hac::PfsHeader::getFileList() const +const fnd::List& nn::hac::PartitionFsHeader::getFileList() const { return mFileList; } -void nn::hac::PfsHeader::addFile(const std::string & name, size_t size) +void nn::hac::PartitionFsHeader::addFile(const std::string & name, size_t size) { mFileList.addElement({ name, 0, size, 0 }); } -void nn::hac::PfsHeader::addFile(const std::string & name, size_t size, size_t hash_protected_size, const fnd::sha::sSha256Hash& hash) +void nn::hac::PartitionFsHeader::addFile(const std::string & name, size_t size, size_t hash_protected_size, const fnd::sha::sSha256Hash& hash) { mFileList.addElement({ name, 0, size, hash_protected_size, hash }); } -size_t nn::hac::PfsHeader::getFileEntrySize(FsType fs_type) +size_t nn::hac::PartitionFsHeader::getFileEntrySize(FsType fs_type) { size_t size = 0; switch(fs_type) @@ -244,7 +244,7 @@ size_t nn::hac::PfsHeader::getFileEntrySize(FsType fs_type) return size; } -void nn::hac::PfsHeader::calculateOffsets(size_t data_offset) +void nn::hac::PartitionFsHeader::calculateOffsets(size_t data_offset) { for (size_t i = 0; i < mFileList.size(); i++) { diff --git a/lib/libhac/source/PatchMetaExtendedHeader.cpp b/lib/libhac/source/PatchMetaExtendedHeader.cpp new file mode 100644 index 0000000..02a0f4c --- /dev/null +++ b/lib/libhac/source/PatchMetaExtendedHeader.cpp @@ -0,0 +1,99 @@ +#include + +nn::hac::PatchMetaExtendedHeader::PatchMetaExtendedHeader() +{ + clear(); +} + +nn::hac::PatchMetaExtendedHeader::PatchMetaExtendedHeader(const PatchMetaExtendedHeader& other) +{ + *this = other; +} + +void nn::hac::PatchMetaExtendedHeader::operator=(const PatchMetaExtendedHeader& other) +{ + clear(); + mRawBinary = other.mRawBinary; + mApplicationId = other.mApplicationId; + mRequiredSystemVersion = other.mRequiredSystemVersion; + mExtendedDataSize = other.mExtendedDataSize; +} + +bool nn::hac::PatchMetaExtendedHeader::operator==(const PatchMetaExtendedHeader& other) const +{ + return (mApplicationId == other.mApplicationId) \ + && (mRequiredSystemVersion == other.mRequiredSystemVersion) \ + && (mExtendedDataSize == other.mExtendedDataSize); +} + +bool nn::hac::PatchMetaExtendedHeader::operator!=(const PatchMetaExtendedHeader& other) const +{ + return !(*this == other); +} + +void nn::hac::PatchMetaExtendedHeader::toBytes() +{ + mRawBinary.alloc(sizeof(sPatchMetaExtendedHeader)); + sPatchMetaExtendedHeader* info = (sPatchMetaExtendedHeader*)mRawBinary.data(); + + info->application_id = mApplicationId; + info->required_system_version = mRequiredSystemVersion; + info->extended_data_size = mExtendedDataSize; +} + +void nn::hac::PatchMetaExtendedHeader::fromBytes(const byte_t* bytes, size_t len) +{ + if (len < sizeof(sPatchMetaExtendedHeader)) + { + throw fnd::Exception(kModuleName, "PatchMetaExtendedHeader too small"); + } + + const sPatchMetaExtendedHeader* info = (const sPatchMetaExtendedHeader*)bytes; + + mApplicationId = info->application_id.get(); + mRequiredSystemVersion = info->required_system_version.get(); + mExtendedDataSize = info->extended_data_size.get(); +} + +const fnd::Vec& nn::hac::PatchMetaExtendedHeader::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::PatchMetaExtendedHeader::clear() +{ + mRawBinary.clear(); + mApplicationId = 0; + mRequiredSystemVersion = 0; + mExtendedDataSize = 0; +} + +uint64_t nn::hac::PatchMetaExtendedHeader::getApplicationId() const +{ + return mApplicationId; +} + +void nn::hac::PatchMetaExtendedHeader::setApplicationId(uint64_t application_id) +{ + mApplicationId = application_id; +} + +uint32_t nn::hac::PatchMetaExtendedHeader::getRequiredSystemVersion() const +{ + return mRequiredSystemVersion; +} + +void nn::hac::PatchMetaExtendedHeader::setRequiredSystemVersion(uint32_t sys_ver) +{ + mRequiredSystemVersion = sys_ver; +} + +uint32_t nn::hac::PatchMetaExtendedHeader::getExtendedDataSize() const +{ + return mExtendedDataSize; +} + +void nn::hac::PatchMetaExtendedHeader::setExtendedDataSize(uint32_t size) +{ + mExtendedDataSize = size; +} \ No newline at end of file diff --git a/lib/libhac/source/ServiceAccessControlBinary.cpp b/lib/libhac/source/ServiceAccessControl.cpp similarity index 52% rename from lib/libhac/source/ServiceAccessControlBinary.cpp rename to lib/libhac/source/ServiceAccessControl.cpp index dd53c27..eaca784 100644 --- a/lib/libhac/source/ServiceAccessControlBinary.cpp +++ b/lib/libhac/source/ServiceAccessControl.cpp @@ -1,79 +1,79 @@ -#include -#include - -nn::hac::ServiceAccessControlBinary::ServiceAccessControlBinary() -{ - clear(); -} - -nn::hac::ServiceAccessControlBinary::ServiceAccessControlBinary(const ServiceAccessControlBinary & other) -{ - *this = other; -} - -void nn::hac::ServiceAccessControlBinary::operator=(const ServiceAccessControlBinary & other) -{ - mRawBinary = other.mRawBinary; - mServices = other.mServices; -} - -bool nn::hac::ServiceAccessControlBinary::operator==(const ServiceAccessControlBinary & other) const -{ - return (mServices == other.mServices); -} - -bool nn::hac::ServiceAccessControlBinary::operator!=(const ServiceAccessControlBinary & other) const -{ - return !(*this == other); -} - -void nn::hac::ServiceAccessControlBinary::toBytes() -{ - size_t totalSize = 0; - for (size_t i = 0; i < mServices.size(); i++) - { - mServices[i].toBytes(); - totalSize += mServices[i].getBytes().size(); - } - - mRawBinary.alloc(totalSize); - for (size_t i = 0, pos = 0; i < mServices.size(); pos += mServices[i].getBytes().size(), i++) - { - memcpy((mRawBinary.data() + pos), mServices[i].getBytes().data(), mServices[i].getBytes().size()); - } -} - -void nn::hac::ServiceAccessControlBinary::fromBytes(const byte_t* data, size_t len) -{ - clear(); - mRawBinary.alloc(len); - memcpy(mRawBinary.data(), data, mRawBinary.size()); - - ServiceAccessControlEntry sac; - for (size_t pos = 0; pos < len; pos += mServices.atBack().getBytes().size()) - { - sac.fromBytes((const byte_t*)(mRawBinary.data() + pos), len - pos); - mServices.addElement(sac); - } -} - -const fnd::Vec& nn::hac::ServiceAccessControlBinary::getBytes() const -{ - return mRawBinary; -} - -void nn::hac::ServiceAccessControlBinary::clear() -{ - mRawBinary.clear(); - mServices.clear(); -} - -const fnd::List& nn::hac::ServiceAccessControlBinary::getServiceList() const -{ - return mServices; -} - -void nn::hac::ServiceAccessControlBinary::addService(const ServiceAccessControlEntry& service) -{ - mServices.addElement(service); +#include +#include + +nn::hac::ServiceAccessControl::ServiceAccessControl() +{ + clear(); +} + +nn::hac::ServiceAccessControl::ServiceAccessControl(const ServiceAccessControl & other) +{ + *this = other; +} + +void nn::hac::ServiceAccessControl::operator=(const ServiceAccessControl & other) +{ + mRawBinary = other.mRawBinary; + mServices = other.mServices; +} + +bool nn::hac::ServiceAccessControl::operator==(const ServiceAccessControl & other) const +{ + return (mServices == other.mServices); +} + +bool nn::hac::ServiceAccessControl::operator!=(const ServiceAccessControl & other) const +{ + return !(*this == other); +} + +void nn::hac::ServiceAccessControl::toBytes() +{ + size_t totalSize = 0; + for (size_t i = 0; i < mServices.size(); i++) + { + mServices[i].toBytes(); + totalSize += mServices[i].getBytes().size(); + } + + mRawBinary.alloc(totalSize); + for (size_t i = 0, pos = 0; i < mServices.size(); pos += mServices[i].getBytes().size(), i++) + { + memcpy((mRawBinary.data() + pos), mServices[i].getBytes().data(), mServices[i].getBytes().size()); + } +} + +void nn::hac::ServiceAccessControl::fromBytes(const byte_t* data, size_t len) +{ + clear(); + mRawBinary.alloc(len); + memcpy(mRawBinary.data(), data, mRawBinary.size()); + + ServiceAccessControlEntry sac; + for (size_t pos = 0; pos < len; pos += mServices.atBack().getBytes().size()) + { + sac.fromBytes((const byte_t*)(mRawBinary.data() + pos), len - pos); + mServices.addElement(sac); + } +} + +const fnd::Vec& nn::hac::ServiceAccessControl::getBytes() const +{ + return mRawBinary; +} + +void nn::hac::ServiceAccessControl::clear() +{ + mRawBinary.clear(); + mServices.clear(); +} + +const fnd::List& nn::hac::ServiceAccessControl::getServiceList() const +{ + return mServices; +} + +void nn::hac::ServiceAccessControl::setServiceList(const fnd::List& list) +{ + mServices = list; } \ No newline at end of file diff --git a/lib/libhac/source/XciUtils.cpp b/lib/libhac/source/XciUtils.cpp deleted file mode 100644 index 1954699..0000000 --- a/lib/libhac/source/XciUtils.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include - -void nn::hac::XciUtils::getXciHeaderAesIv(const nn::hac::sXciHeader* hdr, byte_t* iv) -{ - for (size_t i = 0; i < 16; i++) - { - iv[15-i] = hdr->aescbc_iv.iv[i]; - } -} - -void nn::hac::XciUtils::decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key) -{ - byte_t iv[fnd::aes::kAesBlockSize]; - - getXciHeaderAesIv((const nn::hac::sXciHeader*)src, iv); - - // copy plain - memcpy(dst, src, nn::hac::xci::kHeaderEncOffset); - - // decrypt encrypted data - fnd::aes::AesCbcDecrypt(src + nn::hac::xci::kHeaderEncOffset, nn::hac::xci::kHeaderEncSize, key, iv, dst + nn::hac::xci::kHeaderEncOffset); -} \ No newline at end of file diff --git a/lib/libpki/include/nn/pki/CertificateBody.h b/lib/libpki/include/nn/pki/CertificateBody.h index ea9042a..68205e7 100644 --- a/lib/libpki/include/nn/pki/CertificateBody.h +++ b/lib/libpki/include/nn/pki/CertificateBody.h @@ -1,67 +1,67 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace pki -{ - class CertificateBody - : public fnd::ISerialisable - { - public: - CertificateBody(); - CertificateBody(const CertificateBody& other); - - void operator=(const CertificateBody& other); - bool operator==(const CertificateBody& other) const; - bool operator!=(const CertificateBody& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* src, size_t size); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const std::string& getIssuer() const; - void setIssuer(const std::string& issuer); - - pki::cert::PublicKeyType getPublicKeyType() const; - void setPublicKeyType(cert::PublicKeyType type); - - const std::string& getSubject() const; - void setSubject(const std::string& subject); - - uint32_t getCertId() const; - void setCertId(uint32_t id); - - const fnd::rsa::sRsa4096Key& getRsa4098PublicKey() const; - void setRsa4098PublicKey(const fnd::rsa::sRsa4096Key& key); - - const fnd::rsa::sRsa2048Key& getRsa2048PublicKey() const; - void setRsa2048PublicKey(const fnd::rsa::sRsa2048Key& key); - - const fnd::ecdsa::sEcdsa240Point& getEcdsa240PublicKey() const; - void setEcdsa240PublicKey(const fnd::ecdsa::sEcdsa240Point& key); - - private: - const std::string kModuleName = "CERTIFICATE_BODY"; - - // raw binary - fnd::Vec mRawBinary; - - // variables - std::string mIssuer; - std::string mSubject; - uint32_t mCertId; - cert::PublicKeyType mPublicKeyType; - - fnd::rsa::sRsa4096Key mRsa4096PublicKey; - fnd::rsa::sRsa2048Key mRsa2048PublicKey; - fnd::ecdsa::sEcdsa240Point mEcdsa240PublicKey; - }; -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace pki +{ + class CertificateBody + : public fnd::IByteModel + { + public: + CertificateBody(); + CertificateBody(const CertificateBody& other); + + void operator=(const CertificateBody& other); + bool operator==(const CertificateBody& other) const; + bool operator!=(const CertificateBody& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* src, size_t size); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const std::string& getIssuer() const; + void setIssuer(const std::string& issuer); + + pki::cert::PublicKeyType getPublicKeyType() const; + void setPublicKeyType(cert::PublicKeyType type); + + const std::string& getSubject() const; + void setSubject(const std::string& subject); + + uint32_t getCertId() const; + void setCertId(uint32_t id); + + const fnd::rsa::sRsa4096Key& getRsa4098PublicKey() const; + void setRsa4098PublicKey(const fnd::rsa::sRsa4096Key& key); + + const fnd::rsa::sRsa2048Key& getRsa2048PublicKey() const; + void setRsa2048PublicKey(const fnd::rsa::sRsa2048Key& key); + + const fnd::ecdsa::sEcdsa240Point& getEcdsa240PublicKey() const; + void setEcdsa240PublicKey(const fnd::ecdsa::sEcdsa240Point& key); + + private: + const std::string kModuleName = "CERTIFICATE_BODY"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + std::string mIssuer; + std::string mSubject; + uint32_t mCertId; + cert::PublicKeyType mPublicKeyType; + + fnd::rsa::sRsa4096Key mRsa4096PublicKey; + fnd::rsa::sRsa2048Key mRsa2048PublicKey; + fnd::ecdsa::sEcdsa240Point mEcdsa240PublicKey; + }; +} } \ No newline at end of file diff --git a/lib/libpki/include/nn/pki/SignatureBlock.h b/lib/libpki/include/nn/pki/SignatureBlock.h index 0b2ed71..42e41b3 100644 --- a/lib/libpki/include/nn/pki/SignatureBlock.h +++ b/lib/libpki/include/nn/pki/SignatureBlock.h @@ -1,51 +1,51 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace pki -{ - class SignatureBlock - : public fnd::ISerialisable - { - public: - SignatureBlock(); - SignatureBlock(const SignatureBlock& other); - - void operator=(const SignatureBlock& other); - bool operator==(const SignatureBlock& other) const; - bool operator!=(const SignatureBlock& other) const; - - // export/import binary - void toBytes(); - void fromBytes(const byte_t* src, size_t size); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - pki::sign::SignatureId getSignType() const; - void setSignType(pki::sign::SignatureId type); - - bool isLittleEndian() const; - void setLittleEndian(bool isLE); - - const fnd::Vec& getSignature() const; - void setSignature(const fnd::Vec& signature); - - - private: - const std::string kModuleName = "SIGNATURE_BLOCK"; - - // raw binary - fnd::Vec mRawBinary; - - // variables - pki::sign::SignatureId mSignType; - bool mIsLittleEndian; - fnd::Vec mSignature; - }; -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace pki +{ + class SignatureBlock + : public fnd::IByteModel + { + public: + SignatureBlock(); + SignatureBlock(const SignatureBlock& other); + + void operator=(const SignatureBlock& other); + bool operator==(const SignatureBlock& other) const; + bool operator!=(const SignatureBlock& other) const; + + // IByteModel + void toBytes(); + void fromBytes(const byte_t* src, size_t size); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + pki::sign::SignatureId getSignType() const; + void setSignType(pki::sign::SignatureId type); + + bool isLittleEndian() const; + void setLittleEndian(bool isLE); + + const fnd::Vec& getSignature() const; + void setSignature(const fnd::Vec& signature); + + + private: + const std::string kModuleName = "SIGNATURE_BLOCK"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + pki::sign::SignatureId mSignType; + bool mIsLittleEndian; + fnd::Vec mSignature; + }; +} } \ No newline at end of file diff --git a/lib/libpki/include/nn/pki/SignedData.h b/lib/libpki/include/nn/pki/SignedData.h index 0997cd4..3180974 100644 --- a/lib/libpki/include/nn/pki/SignedData.h +++ b/lib/libpki/include/nn/pki/SignedData.h @@ -1,139 +1,139 @@ -#pragma once -#include -#include -#include - -namespace nn -{ -namespace pki -{ - template - class SignedData - : public fnd::ISerialisable - { - public: - SignedData(); - SignedData(const SignedData& other); - - void operator=(const SignedData& other); - bool operator==(const SignedData& other) const; - bool operator!=(const SignedData& other) const; - - // export/import - void toBytes(); - void fromBytes(const byte_t* src, size_t size); - const fnd::Vec& getBytes() const; - - // variables - void clear(); - - const pki::SignatureBlock& getSignature() const; - void setSignature(const SignatureBlock& signature); - - const T& getBody() const; - void setBody(const T& body); - private: - const std::string kModuleName = "SIGNED_DATA"; - - // raw binary - fnd::Vec mRawBinary; - - // variables - SignatureBlock mSignature; - T mBody; - }; - - template - inline SignedData::SignedData() - { - clear(); - } - - template - inline SignedData::SignedData(const SignedData& other) - { - *this = other; - } - - template - inline void SignedData::operator=(const SignedData& other) - { - mRawBinary = other.mRawBinary; - mSignature = other.mSignature; - mBody = other.mBody; - } - - template - inline bool SignedData::operator==(const SignedData& other) const - { - return (mSignature == other.mSignature) \ - && (mBody == other.mBody); - } - - template - inline bool SignedData::operator!=(const SignedData& other) const - { - return !(*this == other); - } - - template - inline void SignedData::toBytes() - { - mSignature.toBytes(); - mBody.toBytes(); - - mRawBinary.alloc(mSignature.getBytes().size() + mBody.getBytes().size()); - - memcpy(mRawBinary.data(), mSignature.getBytes().data(), mSignature.getBytes().size()); - memcpy(mRawBinary.data() + mSignature.getBytes().size(), mBody.getBytes().data(), mBody.getBytes().size()); - } - - template - inline void SignedData::fromBytes(const byte_t* src, size_t size) - { - mSignature.fromBytes(src, size); - mBody.fromBytes(src + mSignature.getBytes().size(), size - mSignature.getBytes().size()); - - mRawBinary.alloc(mSignature.getBytes().size() + mBody.getBytes().size()); - memcpy(mRawBinary.data(), src, mRawBinary.size()); - } - - template - inline const fnd::Vec& SignedData::getBytes() const - { - return mRawBinary; - } - - template - inline void SignedData::clear() - { - mRawBinary.clear(); - mSignature.clear(); - mBody.clear(); - } - - template - inline const pki::SignatureBlock& SignedData::getSignature() const - { - return mSignature; - } - - template - inline void SignedData::setSignature(const SignatureBlock& signature) - { - mSignature = signature; - } - - template - inline const T& SignedData::getBody() const - { - return mBody; - } - - template - inline void SignedData::setBody(const T& body) - { - mBody = body; - } -} +#pragma once +#include +#include +#include + +namespace nn +{ +namespace pki +{ + template + class SignedData + : public fnd::IByteModel + { + public: + SignedData(); + SignedData(const SignedData& other); + + void operator=(const SignedData& other); + bool operator==(const SignedData& other) const; + bool operator!=(const SignedData& other) const; + + // export/import + void toBytes(); + void fromBytes(const byte_t* src, size_t size); + const fnd::Vec& getBytes() const; + + // variables + void clear(); + + const pki::SignatureBlock& getSignature() const; + void setSignature(const SignatureBlock& signature); + + const T& getBody() const; + void setBody(const T& body); + private: + const std::string kModuleName = "SIGNED_DATA"; + + // raw binary + fnd::Vec mRawBinary; + + // variables + SignatureBlock mSignature; + T mBody; + }; + + template + inline SignedData::SignedData() + { + clear(); + } + + template + inline SignedData::SignedData(const SignedData& other) + { + *this = other; + } + + template + inline void SignedData::operator=(const SignedData& other) + { + mRawBinary = other.mRawBinary; + mSignature = other.mSignature; + mBody = other.mBody; + } + + template + inline bool SignedData::operator==(const SignedData& other) const + { + return (mSignature == other.mSignature) \ + && (mBody == other.mBody); + } + + template + inline bool SignedData::operator!=(const SignedData& other) const + { + return !(*this == other); + } + + template + inline void SignedData::toBytes() + { + mSignature.toBytes(); + mBody.toBytes(); + + mRawBinary.alloc(mSignature.getBytes().size() + mBody.getBytes().size()); + + memcpy(mRawBinary.data(), mSignature.getBytes().data(), mSignature.getBytes().size()); + memcpy(mRawBinary.data() + mSignature.getBytes().size(), mBody.getBytes().data(), mBody.getBytes().size()); + } + + template + inline void SignedData::fromBytes(const byte_t* src, size_t size) + { + mSignature.fromBytes(src, size); + mBody.fromBytes(src + mSignature.getBytes().size(), size - mSignature.getBytes().size()); + + mRawBinary.alloc(mSignature.getBytes().size() + mBody.getBytes().size()); + memcpy(mRawBinary.data(), src, mRawBinary.size()); + } + + template + inline const fnd::Vec& SignedData::getBytes() const + { + return mRawBinary; + } + + template + inline void SignedData::clear() + { + mRawBinary.clear(); + mSignature.clear(); + mBody.clear(); + } + + template + inline const pki::SignatureBlock& SignedData::getSignature() const + { + return mSignature; + } + + template + inline void SignedData::setSignature(const SignatureBlock& signature) + { + mSignature = signature; + } + + template + inline const T& SignedData::getBody() const + { + return mBody; + } + + template + inline void SignedData::setBody(const T& body) + { + mBody = body; + } +} } \ No newline at end of file diff --git a/programs/nstool/README.md b/programs/nstool/README.md index 0fbcae3..2c1618e 100644 --- a/programs/nstool/README.md +++ b/programs/nstool/README.md @@ -1,74 +1,74 @@ -# Nintendo Switch Tool (NSTool) ![DeviceTag](https://img.shields.io/badge/Device-SWITCH-e60012.svg) -General purpose reading/extraction tool for Nintendo Switch file formats. - -## Supported File Formats -* Meta (.npdm) -* PartitionFS (and HashedPartitionFS) (includes raw .nsp) -* RomFS -* GameCard Image (.xci) -* Nintendo Content Archive (.nca) -* Content Metadata (.cnmt) -* Nintendo Software Object (.nso) -* Nintendo Relocatable Software Object (.nro) -* Nintendo Application Control Property (.nacp) -* ES Ticket (v2 only) (.tik) -* PKI Certificate (.cert) - -# Usage -``` -Usage: nstool [options... ] - - General Options: - -d, --dev Use devkit keyset. - -k, --keyset Specify keyset file. - -t, --type Specify input file type. [xci, pfs, romfs, nca, meta, cnmt, nso, nro, nacp, aset, cert, tik] - -y, --verify Verify file. - - Output Options: - --showkeys Show keys generated. - --showlayout Show layout metadata. - -v, --verbose Verbose output. - - XCI (GameCard Image) - nstool [--listfs] [--update --logo --normal --secure ] <.xci file> - --listfs Print file system in embedded partitions. - --update Extract "update" partition to directory. - --logo Extract "logo" partition to directory. - --normal Extract "normal" partition to directory. - --secure Extract "secure" partition to directory. - - PFS0/HFS0 (PartitionFs), RomFs, NSP (Ninendo Submission Package) - nstool [--listfs] [--fsdir ] - --listfs Print file system. - --fsdir Extract file system to directory. - - NCA (Nintendo Content Archive) - nstool [--listfs] [--bodykey --titlekey ] [--part0 ...] <.nca file> - --listfs Print file system in embedded partitions. - --titlekey Specify title key extracted from ticket. - --bodykey Specify body encryption key. - --tik Specify ticket to source title key. - --cert Specify certificate chain to verify ticket. - --part0 Extract "partition 0" to directory. - --part1 Extract "partition 1" to directory. - --part2 Extract "partition 2" to directory. - --part3 Extract "partition 3" to directory. - - NSO (Nintendo Software Object), NRO (Nintendo Relocatable Object) - nstool [--listapi --listsym] [--insttype ] - --listapi Print SDK API List. - --listsym Print Code Symbols. - --insttype Specify instruction type [64bit|32bit] (64bit is assumed). - - ASET (Homebrew Asset Blob) - nstool [--listfs] [--icon --nacp --fsdir ] - --listfs Print filesystem in embedded RomFS partition. - --icon Extract icon partition to file. - --nacp Extract NACP partition to file. - --fsdir Extract RomFS partition to directory. -``` - -# External Keys -NSTool doesn't embed any keys that are copyright protected. However keys can be imported via various keyset files. - -See [SWITCH_KEYS.md](/SWITCH_KEYS.md) for more info. +# Nintendo Switch Tool (NSTool) ![DeviceTag](https://img.shields.io/badge/Device-SWITCH-e60012.svg) +General purpose reading/extraction tool for Nintendo Switch file formats. + +## Supported File Formats +* Meta (.npdm) +* PartitionFS (and HashedPartitionFS) (includes raw .nsp) +* RomFS +* GameCard Image (.xci) +* Nintendo Content Archive (.nca) +* Content Metadata (.cnmt) +* Nintendo Software Object (.nso) +* Nintendo Relocatable Software Object (.nro) +* Nintendo Application Control Property (.nacp) +* ES Ticket (v2 only) (.tik) +* PKI Certificate (.cert) + +# Usage +``` +Usage: nstool [options... ] + + General Options: + -d, --dev Use devkit keyset. + -k, --keyset Specify keyset file. + -t, --type Specify input file type. [xci, pfs, romfs, nca, meta, cnmt, nso, nro, nacp, aset, cert, tik] + -y, --verify Verify file. + + Output Options: + --showkeys Show keys generated. + --showlayout Show layout metadata. + -v, --verbose Verbose output. + + XCI (GameCard Image) + nstool [--listfs] [--update --logo --normal --secure ] <.xci file> + --listfs Print file system in embedded partitions. + --update Extract "update" partition to directory. + --logo Extract "logo" partition to directory. + --normal Extract "normal" partition to directory. + --secure Extract "secure" partition to directory. + + PFS0/HFS0 (PartitionFs), RomFs, NSP (Ninendo Submission Package) + nstool [--listfs] [--fsdir ] + --listfs Print file system. + --fsdir Extract file system to directory. + + NCA (Nintendo Content Archive) + nstool [--listfs] [--bodykey --titlekey ] [--part0 ...] <.nca file> + --listfs Print file system in embedded partitions. + --titlekey Specify title key extracted from ticket. + --bodykey Specify body encryption key. + --tik Specify ticket to source title key. + --cert Specify certificate chain to verify ticket. + --part0 Extract "partition 0" to directory. + --part1 Extract "partition 1" to directory. + --part2 Extract "partition 2" to directory. + --part3 Extract "partition 3" to directory. + + NSO (Nintendo Software Object), NRO (Nintendo Relocatable Object) + nstool [--listapi --listsym] [--insttype ] + --listapi Print SDK API List. + --listsym Print Code Symbols. + --insttype Specify instruction type [64bit|32bit] (64bit is assumed). + + ASET (Homebrew Asset Blob) + nstool [--listfs] [--icon --nacp --fsdir ] + --listfs Print filesystem in embedded RomFS partition. + --icon Extract icon partition to file. + --nacp Extract NACP partition to file. + --fsdir Extract RomFS partition to directory. +``` + +# External Keys +NSTool doesn't embed any keys that are copyright protected. However keys can be imported via various keyset files. + +See [SWITCH_KEYS.md](/SWITCH_KEYS.md) for more info. diff --git a/programs/nstool/nstool.vcxproj b/programs/nstool/nstool.vcxproj index 0cec4b7..ed9eff4 100644 --- a/programs/nstool/nstool.vcxproj +++ b/programs/nstool/nstool.vcxproj @@ -1,226 +1,226 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {AF09FA96-4463-417D-8FE6-526063F41349} - Win32Proj - nstool - 10.0.16299.0 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - true - - - false - - - false - - - - NotUsing - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - ..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libhac\include;..\..\lib\libhac-hb\include - - - Console - true - - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - ..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libhac\include;..\..\lib\libhac-hb\include - - - Console - true - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - ..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libhac\include;..\..\lib\libhac-hb\include - - - Console - true - true - true - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - ..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libhac\include;..\..\lib\libhac-hb\include - - - Console - true - true - true - - - - - {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1} - - - {AB0C3362-63AB-480A-ADBC-2EF7D859778B} - - - {7be99936-0d40-410d-944b-4513c2eff8dc} - - - {4d27edb9-5110-44fe-8ce2-d46c5ad3c55b} - - - {738cb4fc-cd9e-4b81-a04b-deadbfa71c63} - - - {91ba9e79-8242-4f7d-b997-0dfec95ea22b} - - - {b9113734-6e84-44ff-8cf7-58199aa815c5} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {AF09FA96-4463-417D-8FE6-526063F41349} + Win32Proj + nstool + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libhac\include;..\..\lib\libhac-hb\include + + + Console + true + + + + + NotUsing + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libhac\include;..\..\lib\libhac-hb\include + + + Console + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libhac\include;..\..\lib\libhac-hb\include + + + Console + true + true + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libhac\include;..\..\lib\libhac-hb\include + + + Console + true + true + true + + + + + {394EFC16-BD3A-4538-B33D-7BA1EDB8DAC1} + + + {AB0C3362-63AB-480A-ADBC-2EF7D859778B} + + + {7be99936-0d40-410d-944b-4513c2eff8dc} + + + {4d27edb9-5110-44fe-8ce2-d46c5ad3c55b} + + + {738cb4fc-cd9e-4b81-a04b-deadbfa71c63} + + + {91ba9e79-8242-4f7d-b997-0dfec95ea22b} + + + {b9113734-6e84-44ff-8cf7-58199aa815c5} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/programs/nstool/nstool.vcxproj.filters b/programs/nstool/nstool.vcxproj.filters index de89389..7febb7a 100644 --- a/programs/nstool/nstool.vcxproj.filters +++ b/programs/nstool/nstool.vcxproj.filters @@ -1,142 +1,142 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/programs/nstool/source/CnmtProcess.cpp b/programs/nstool/source/CnmtProcess.cpp index e49093d..dfcf9ea 100644 --- a/programs/nstool/source/CnmtProcess.cpp +++ b/programs/nstool/source/CnmtProcess.cpp @@ -1,249 +1,249 @@ -#include -#include -#include -#include -#include "CnmtProcess.h" - -CnmtProcess::CnmtProcess() : - mFile(), - mCliOutputMode(_BIT(OUTPUT_BASIC)), - mVerify(false) -{ -} - -void CnmtProcess::process() -{ - importCnmt(); - - if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) - displayCnmt(); -} - -void CnmtProcess::setInputFile(const fnd::SharedPtr& file) -{ - mFile = file; -} - -void CnmtProcess::setCliOutputMode(CliOutputMode type) -{ - mCliOutputMode = type; -} - -void CnmtProcess::setVerifyMode(bool verify) -{ - mVerify = verify; -} - -const nn::hac::ContentMetaBinary& CnmtProcess::getContentMetaBinary() const -{ - return mCnmt; -} - -void CnmtProcess::importCnmt() -{ - fnd::Vec scratch; - - if (*mFile == nullptr) - { - throw fnd::Exception(kModuleName, "No file reader set."); - } - - scratch.alloc((*mFile)->size()); - (*mFile)->read(scratch.data(), 0, scratch.size()); - - mCnmt.fromBytes(scratch.data(), scratch.size()); -} - -void CnmtProcess::displayCnmt() -{ -#define _SPLIT_VER(ver) (uint32_t)((ver>>26) & 0x3f) << "." << (uint32_t)((ver>>20) & 0x3f) << "." << (uint32_t)((ver>>16) & 0xf) << "." << (uint32_t)(ver & 0xffff) - - std::cout << "[ContentMeta]" << std::endl; - std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getTitleId() << std::endl; - std::cout << " Version: v" << std::dec << mCnmt.getTitleVersion() << " (" << _SPLIT_VER(mCnmt.getTitleVersion()) << ")"<< std::endl; - std::cout << " Type: " << getContentMetaTypeStr(mCnmt.getType()) << " (" << std::dec << mCnmt.getType() << ")" << std::endl; - std::cout << " Attributes: 0x" << std::hex << (uint32_t)mCnmt.getAttributes() << std::endl; - std::cout << " IncludesExFatDriver: " << getBoolStr(_HAS_BIT(mCnmt.getAttributes(), nn::hac::cnmt::ATTRIBUTE_INCLUDES_EX_FAT_DRIVER)) << std::endl; - std::cout << " Rebootless: " << getBoolStr(_HAS_BIT(mCnmt.getAttributes(), nn::hac::cnmt::ATTRIBUTE_REBOOTLESS)) << std::endl; - std::cout << " RequiredDownloadSystemVersion: v" << mCnmt.getRequiredDownloadSystemVersion() << " (" << _SPLIT_VER(mCnmt.getRequiredDownloadSystemVersion()) << ")"<< std::endl; - switch(mCnmt.getType()) - { - case (nn::hac::cnmt::METATYPE_APPLICATION): - std::cout << " ApplicationExtendedHeader:" << std::endl; - std::cout << " RequiredSystemVersion: v" << std::dec << mCnmt.getApplicationMetaExtendedHeader().required_system_version << " (" << _SPLIT_VER(mCnmt.getApplicationMetaExtendedHeader().required_system_version) << ")"<< std::endl; - std::cout << " PatchId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getApplicationMetaExtendedHeader().patch_id << std::endl; - break; - case (nn::hac::cnmt::METATYPE_PATCH): - std::cout << " PatchMetaExtendedHeader:" << std::endl; - std::cout << " RequiredSystemVersion: v" << std::dec << mCnmt.getPatchMetaExtendedHeader().required_system_version << " (" << _SPLIT_VER(mCnmt.getPatchMetaExtendedHeader().required_system_version) << ")"<< std::endl; - std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getPatchMetaExtendedHeader().application_id << std::endl; - break; - case (nn::hac::cnmt::METATYPE_ADD_ON_CONTENT): - std::cout << " AddOnContentMetaExtendedHeader:" << std::endl; - std::cout << " RequiredApplicationVersion: v" << std::dec << mCnmt.getAddOnContentMetaExtendedHeader().required_application_version << " (" << _SPLIT_VER(mCnmt.getAddOnContentMetaExtendedHeader().required_application_version) << ")" << std::endl; - std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getAddOnContentMetaExtendedHeader().application_id << std::endl; - break; - case (nn::hac::cnmt::METATYPE_DELTA): - std::cout << " DeltaMetaExtendedHeader:" << std::endl; - std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getDeltaMetaExtendedHeader().application_id << std::endl; - break; - default: - break; - } - if (mCnmt.getContentInfo().size() > 0) - { - printf(" ContentInfo:\n"); - for (size_t i = 0; i < mCnmt.getContentInfo().size(); i++) - { - const nn::hac::ContentMetaBinary::ContentInfo& info = mCnmt.getContentInfo()[i]; - std::cout << " " << std::dec << i << std::endl; - std::cout << " Type: " << getContentTypeStr(info.type) << " (" << std::dec << info.type << ")" << std::endl; - std::cout << " Id: " << fnd::SimpleTextOutput::arrayToString(info.nca_id, nn::hac::cnmt::kContentIdLen, false, "") << std::endl; - std::cout << " Size: 0x" << std::hex << info.size << std::endl; - std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(info.hash.bytes, sizeof(info.hash), false, "") << std::endl; - } - } - if (mCnmt.getContentMetaInfo().size() > 0) - { - std::cout << " ContentMetaInfo:" << std::endl; - for (size_t i = 0; i < mCnmt.getContentMetaInfo().size(); i++) - { - const nn::hac::ContentMetaBinary::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i]; - std::cout << " " << std::dec << i << std::endl; - std::cout << " Id: 0x" << std::hex << std::setw(16) << std::setfill('0') << info.id << std::endl; - std::cout << " Version: v" << std::dec << info.version << " (" << _SPLIT_VER(info.version) << ")"<< std::endl; - std::cout << " Type: " << getContentMetaTypeStr(info.type) << " (" << std::dec << info.type << ")" << std::endl; - std::cout << " Attributes: 0x" << std::hex << (uint32_t)info.attributes << std::endl; - std::cout << " IncludesExFatDriver: " << getBoolStr(_HAS_BIT(info.attributes, nn::hac::cnmt::ATTRIBUTE_INCLUDES_EX_FAT_DRIVER)) << std::endl; - std::cout << " Rebootless: " << getBoolStr(_HAS_BIT(info.attributes, nn::hac::cnmt::ATTRIBUTE_REBOOTLESS)) << std::endl; - } - } - - std::cout << " Digest: " << fnd::SimpleTextOutput::arrayToString(mCnmt.getDigest().data, nn::hac::cnmt::kDigestLen, false, "") << std::endl; - -#undef _SPLIT_VER -} - -const char* CnmtProcess::getBoolStr(bool state) const -{ - return state? "TRUE" : "FALSE"; -} - -const char* CnmtProcess::getContentTypeStr(nn::hac::cnmt::ContentType type) const -{ - const char* str = nullptr; - - switch (type) - { - case (nn::hac::cnmt::TYPE_META): - str = "Meta"; - break; - case (nn::hac::cnmt::TYPE_PROGRAM): - str = "Program"; - break; - case (nn::hac::cnmt::TYPE_DATA): - str = "Data"; - break; - case (nn::hac::cnmt::TYPE_CONTROL): - str = "Control"; - break; - case (nn::hac::cnmt::TYPE_HTML_DOCUMENT): - str = "HtmlDocument"; - break; - case (nn::hac::cnmt::TYPE_LEGAL_INFORMATION): - str = "LegalInformation"; - break; - case (nn::hac::cnmt::TYPE_DELTA_FRAGMENT): - str = "DeltaFragment"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* CnmtProcess::getContentMetaTypeStr(nn::hac::cnmt::ContentMetaType type) const -{ - const char* str = nullptr; - - switch (type) - { - case (nn::hac::cnmt::METATYPE_SYSTEM_PROGRAM): - str = "SystemProgram"; - break; - case (nn::hac::cnmt::METATYPE_SYSTEM_DATA): - str = "SystemData"; - break; - case (nn::hac::cnmt::METATYPE_SYSTEM_UPDATE): - str = "SystemUpdate"; - break; - case (nn::hac::cnmt::METATYPE_BOOT_IMAGE_PACKAGE): - str = "BootImagePackage"; - break; - case (nn::hac::cnmt::METATYPE_BOOT_IMAGE_PACKAGE_SAFE): - str = "BootImagePackageSafe"; - break; - case (nn::hac::cnmt::METATYPE_APPLICATION): - str = "Application"; - break; - case (nn::hac::cnmt::METATYPE_PATCH): - str = "Patch"; - break; - case (nn::hac::cnmt::METATYPE_ADD_ON_CONTENT): - str = "AddOnContent"; - break; - case (nn::hac::cnmt::METATYPE_DELTA): - str = "Delta"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* CnmtProcess::getUpdateTypeStr(nn::hac::cnmt::UpdateType type) const -{ - const char* str = nullptr; - - switch (type) - { - case (nn::hac::cnmt::UPDATETYPE_APPLY_AS_DELTA): - str = "ApplyAsDelta"; - break; - case (nn::hac::cnmt::UPDATETYPE_OVERWRITE): - str = "Overwrite"; - break; - case (nn::hac::cnmt::UPDATETYPE_CREATE): - str = "Create"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* CnmtProcess::getContentMetaAttrStr(nn::hac::cnmt::ContentMetaAttribute attr) const -{ - const char* str = nullptr; - - switch (attr) - { - case (nn::hac::cnmt::ATTRIBUTE_INCLUDES_EX_FAT_DRIVER): - str = "IncludesExFatDriver"; - break; - case (nn::hac::cnmt::ATTRIBUTE_REBOOTLESS): - str = "Rebootless"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} +#include +#include +#include +#include +#include "CnmtProcess.h" + +CnmtProcess::CnmtProcess() : + mFile(), + mCliOutputMode(_BIT(OUTPUT_BASIC)), + mVerify(false) +{ +} + +void CnmtProcess::process() +{ + importCnmt(); + + if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) + displayCnmt(); +} + +void CnmtProcess::setInputFile(const fnd::SharedPtr& file) +{ + mFile = file; +} + +void CnmtProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void CnmtProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +const nn::hac::ContentMeta& CnmtProcess::getContentMeta() const +{ + return mCnmt; +} + +void CnmtProcess::importCnmt() +{ + fnd::Vec scratch; + + if (*mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + scratch.alloc((*mFile)->size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); + + mCnmt.fromBytes(scratch.data(), scratch.size()); +} + +void CnmtProcess::displayCnmt() +{ +#define _SPLIT_VER(ver) (uint32_t)((ver>>26) & 0x3f) << "." << (uint32_t)((ver>>20) & 0x3f) << "." << (uint32_t)((ver>>16) & 0xf) << "." << (uint32_t)(ver & 0xffff) + + std::cout << "[ContentMeta]" << std::endl; + std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getTitleId() << std::endl; + std::cout << " Version: v" << std::dec << mCnmt.getTitleVersion() << " (" << _SPLIT_VER(mCnmt.getTitleVersion()) << ")"<< std::endl; + std::cout << " Type: " << getContentMetaTypeStr(mCnmt.getContentMetaType()) << " (" << std::dec << mCnmt.getContentMetaType() << ")" << std::endl; + std::cout << " Attributes: 0x" << std::hex << (uint32_t)mCnmt.getAttributes() << std::endl; + std::cout << " IncludesExFatDriver: " << getBoolStr(_HAS_BIT(mCnmt.getAttributes(), nn::hac::cnmt::ATTRIBUTE_INCLUDES_EX_FAT_DRIVER)) << std::endl; + std::cout << " Rebootless: " << getBoolStr(_HAS_BIT(mCnmt.getAttributes(), nn::hac::cnmt::ATTRIBUTE_REBOOTLESS)) << std::endl; + std::cout << " RequiredDownloadSystemVersion: v" << mCnmt.getRequiredDownloadSystemVersion() << " (" << _SPLIT_VER(mCnmt.getRequiredDownloadSystemVersion()) << ")"<< std::endl; + switch(mCnmt.getContentMetaType()) + { + case (nn::hac::cnmt::METATYPE_APPLICATION): + std::cout << " ApplicationExtendedHeader:" << std::endl; + std::cout << " RequiredSystemVersion: v" << std::dec << mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion() << " (" << _SPLIT_VER(mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()) << ")"<< std::endl; + std::cout << " PatchId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getApplicationMetaExtendedHeader().getPatchId() << std::endl; + break; + case (nn::hac::cnmt::METATYPE_PATCH): + std::cout << " PatchMetaExtendedHeader:" << std::endl; + std::cout << " RequiredSystemVersion: v" << std::dec << mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion() << " (" << _SPLIT_VER(mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()) << ")"<< std::endl; + std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getPatchMetaExtendedHeader().getApplicationId() << std::endl; + break; + case (nn::hac::cnmt::METATYPE_ADD_ON_CONTENT): + std::cout << " AddOnContentMetaExtendedHeader:" << std::endl; + std::cout << " RequiredApplicationVersion: v" << std::dec << mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion() << " (" << _SPLIT_VER(mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()) << ")" << std::endl; + std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getAddOnContentMetaExtendedHeader().getApplicationId() << std::endl; + break; + case (nn::hac::cnmt::METATYPE_DELTA): + std::cout << " DeltaMetaExtendedHeader:" << std::endl; + std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getDeltaMetaExtendedHeader().getApplicationId() << std::endl; + break; + default: + break; + } + if (mCnmt.getContentInfo().size() > 0) + { + printf(" ContentInfo:\n"); + for (size_t i = 0; i < mCnmt.getContentInfo().size(); i++) + { + const nn::hac::ContentInfo& info = mCnmt.getContentInfo()[i]; + std::cout << " " << std::dec << i << std::endl; + std::cout << " Type: " << getContentTypeStr(info.getContentType()) << " (" << std::dec << info.getContentType() << ")" << std::endl; + std::cout << " Id: " << fnd::SimpleTextOutput::arrayToString(info.getContentId().data, nn::hac::cnmt::kContentIdLen, false, "") << std::endl; + std::cout << " Size: 0x" << std::hex << info.getContentSize() << std::endl; + std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(info.getContentHash().bytes, sizeof(info.getContentHash()), false, "") << std::endl; + } + } + if (mCnmt.getContentMetaInfo().size() > 0) + { + std::cout << " ContentMetaInfo:" << std::endl; + for (size_t i = 0; i < mCnmt.getContentMetaInfo().size(); i++) + { + const nn::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i]; + std::cout << " " << std::dec << i << std::endl; + std::cout << " Id: 0x" << std::hex << std::setw(16) << std::setfill('0') << info.getTitleId() << std::endl; + std::cout << " Version: v" << std::dec << info.getTitleVersion() << " (" << _SPLIT_VER(info.getTitleVersion()) << ")"<< std::endl; + std::cout << " Type: " << getContentMetaTypeStr(info.getContentMetaType()) << " (" << std::dec << info.getContentMetaType() << ")" << std::endl; + std::cout << " Attributes: 0x" << std::hex << (uint32_t)info.getAttributes() << std::endl; + std::cout << " IncludesExFatDriver: " << getBoolStr(_HAS_BIT(info.getAttributes(), nn::hac::cnmt::ATTRIBUTE_INCLUDES_EX_FAT_DRIVER)) << std::endl; + std::cout << " Rebootless: " << getBoolStr(_HAS_BIT(info.getAttributes(), nn::hac::cnmt::ATTRIBUTE_REBOOTLESS)) << std::endl; + } + } + + std::cout << " Digest: " << fnd::SimpleTextOutput::arrayToString(mCnmt.getDigest().data, nn::hac::cnmt::kDigestLen, false, "") << std::endl; + +#undef _SPLIT_VER +} + +const char* CnmtProcess::getBoolStr(bool state) const +{ + return state? "TRUE" : "FALSE"; +} + +const char* CnmtProcess::getContentTypeStr(nn::hac::cnmt::ContentType type) const +{ + const char* str = nullptr; + + switch (type) + { + case (nn::hac::cnmt::TYPE_META): + str = "Meta"; + break; + case (nn::hac::cnmt::TYPE_PROGRAM): + str = "Program"; + break; + case (nn::hac::cnmt::TYPE_DATA): + str = "Data"; + break; + case (nn::hac::cnmt::TYPE_CONTROL): + str = "Control"; + break; + case (nn::hac::cnmt::TYPE_HTML_DOCUMENT): + str = "HtmlDocument"; + break; + case (nn::hac::cnmt::TYPE_LEGAL_INFORMATION): + str = "LegalInformation"; + break; + case (nn::hac::cnmt::TYPE_DELTA_FRAGMENT): + str = "DeltaFragment"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* CnmtProcess::getContentMetaTypeStr(nn::hac::cnmt::ContentMetaType type) const +{ + const char* str = nullptr; + + switch (type) + { + case (nn::hac::cnmt::METATYPE_SYSTEM_PROGRAM): + str = "SystemProgram"; + break; + case (nn::hac::cnmt::METATYPE_SYSTEM_DATA): + str = "SystemData"; + break; + case (nn::hac::cnmt::METATYPE_SYSTEM_UPDATE): + str = "SystemUpdate"; + break; + case (nn::hac::cnmt::METATYPE_BOOT_IMAGE_PACKAGE): + str = "BootImagePackage"; + break; + case (nn::hac::cnmt::METATYPE_BOOT_IMAGE_PACKAGE_SAFE): + str = "BootImagePackageSafe"; + break; + case (nn::hac::cnmt::METATYPE_APPLICATION): + str = "Application"; + break; + case (nn::hac::cnmt::METATYPE_PATCH): + str = "Patch"; + break; + case (nn::hac::cnmt::METATYPE_ADD_ON_CONTENT): + str = "AddOnContent"; + break; + case (nn::hac::cnmt::METATYPE_DELTA): + str = "Delta"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* CnmtProcess::getUpdateTypeStr(nn::hac::cnmt::UpdateType type) const +{ + const char* str = nullptr; + + switch (type) + { + case (nn::hac::cnmt::UPDATETYPE_APPLY_AS_DELTA): + str = "ApplyAsDelta"; + break; + case (nn::hac::cnmt::UPDATETYPE_OVERWRITE): + str = "Overwrite"; + break; + case (nn::hac::cnmt::UPDATETYPE_CREATE): + str = "Create"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* CnmtProcess::getContentMetaAttrStr(nn::hac::cnmt::ContentMetaAttribute attr) const +{ + const char* str = nullptr; + + switch (attr) + { + case (nn::hac::cnmt::ATTRIBUTE_INCLUDES_EX_FAT_DRIVER): + str = "IncludesExFatDriver"; + break; + case (nn::hac::cnmt::ATTRIBUTE_REBOOTLESS): + str = "Rebootless"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} diff --git a/programs/nstool/source/CnmtProcess.h b/programs/nstool/source/CnmtProcess.h index 4fa561c..36cef2a 100644 --- a/programs/nstool/source/CnmtProcess.h +++ b/programs/nstool/source/CnmtProcess.h @@ -1,40 +1,40 @@ -#pragma once -#include -#include -#include -#include -#include - -#include "common.h" - -class CnmtProcess -{ -public: - CnmtProcess(); - - void process(); - - void setInputFile(const fnd::SharedPtr& file); - void setCliOutputMode(CliOutputMode type); - void setVerifyMode(bool verify); - - const nn::hac::ContentMetaBinary& getContentMetaBinary() const; - -private: - const std::string kModuleName = "CnmtProcess"; - - fnd::SharedPtr mFile; - CliOutputMode mCliOutputMode; - bool mVerify; - - nn::hac::ContentMetaBinary mCnmt; - - void importCnmt(); - void displayCnmt(); - - const char* getBoolStr(bool state) const; - const char* getContentTypeStr(nn::hac::cnmt::ContentType type) const; - const char* getContentMetaTypeStr(nn::hac::cnmt::ContentMetaType type) const; - const char* getUpdateTypeStr(nn::hac::cnmt::UpdateType type) const; - const char* getContentMetaAttrStr(nn::hac::cnmt::ContentMetaAttribute attr) const; +#pragma once +#include +#include +#include +#include +#include + +#include "common.h" + +class CnmtProcess +{ +public: + CnmtProcess(); + + void process(); + + void setInputFile(const fnd::SharedPtr& file); + void setCliOutputMode(CliOutputMode type); + void setVerifyMode(bool verify); + + const nn::hac::ContentMeta& getContentMeta() const; + +private: + const std::string kModuleName = "CnmtProcess"; + + fnd::SharedPtr mFile; + CliOutputMode mCliOutputMode; + bool mVerify; + + nn::hac::ContentMeta mCnmt; + + void importCnmt(); + void displayCnmt(); + + const char* getBoolStr(bool state) const; + const char* getContentTypeStr(nn::hac::cnmt::ContentType type) const; + const char* getContentMetaTypeStr(nn::hac::cnmt::ContentMetaType type) const; + const char* getUpdateTypeStr(nn::hac::cnmt::UpdateType type) const; + const char* getContentMetaAttrStr(nn::hac::cnmt::ContentMetaAttribute attr) const; }; \ No newline at end of file diff --git a/programs/nstool/source/XciProcess.cpp b/programs/nstool/source/GameCardProcess.cpp similarity index 75% rename from programs/nstool/source/XciProcess.cpp rename to programs/nstool/source/GameCardProcess.cpp index d86c630..d4c52d0 100644 --- a/programs/nstool/source/XciProcess.cpp +++ b/programs/nstool/source/GameCardProcess.cpp @@ -2,10 +2,10 @@ #include #include #include -#include -#include "XciProcess.h" +#include +#include "GameCardProcess.h" -XciProcess::XciProcess() : +GameCardProcess::GameCardProcess() : mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false), @@ -15,7 +15,7 @@ XciProcess::XciProcess() : { } -void XciProcess::process() +void GameCardProcess::process() { importHeader(); @@ -34,37 +34,37 @@ void XciProcess::process() processPartitionPfs(); } -void XciProcess::setInputFile(const fnd::SharedPtr& file) +void GameCardProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; } -void XciProcess::setKeyCfg(const KeyConfiguration& keycfg) +void GameCardProcess::setKeyCfg(const KeyConfiguration& keycfg) { mKeyCfg = keycfg; } -void XciProcess::setCliOutputMode(CliOutputMode type) +void GameCardProcess::setCliOutputMode(CliOutputMode type) { mCliOutputMode = type; } -void XciProcess::setVerifyMode(bool verify) +void GameCardProcess::setVerifyMode(bool verify) { mVerify = verify; } -void XciProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path) +void GameCardProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path) { mExtractInfo.addElement({partition_name, extract_path}); } -void XciProcess::setListFs(bool list_fs) +void GameCardProcess::setListFs(bool list_fs) { mListFs = list_fs; } -void XciProcess::importHeader() +void GameCardProcess::importHeader() { fnd::Vec scratch; @@ -74,22 +74,22 @@ void XciProcess::importHeader() } // read header page - (*mFile)->read((byte_t*)&mHdrPage, 0, sizeof(nn::hac::sXciHeaderPage)); + (*mFile)->read((byte_t*)&mHdrPage, 0, sizeof(nn::hac::sGcHeaderPage)); // allocate memory for and decrypt sXciHeader - scratch.alloc(sizeof(nn::hac::sXciHeader)); + scratch.alloc(sizeof(nn::hac::sGcHeader)); fnd::aes::sAes128Key header_key; mKeyCfg.getXciHeaderKey(header_key); - nn::hac::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.data(), header_key.key); + nn::hac::GameCardUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.data(), header_key.key); // deserialise header mHdr.fromBytes(scratch.data(), scratch.size()); } -void XciProcess::displayHeader() +void GameCardProcess::displayHeader() { - std::cout << "[XCI Header]" << std::endl; + std::cout << "[GameCard Header]" << std::endl; std::cout << " CardHeaderVersion: " << std::dec << (uint32_t)mHdr.getCardHeaderVersion() << std::endl; std::cout << " RomSize: " << getRomSizeStr(mHdr.getRomSizeType()); if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) @@ -128,22 +128,22 @@ void XciProcess::displayHeader() { std::cout << " RomAreaStartPage: 0x" << std::hex << mHdr.getRomAreaStartPage(); if (mHdr.getRomAreaStartPage() != (uint32_t)(-1)) - std::cout << " (0x" << std::hex << nn::hac::XciUtils::blockToAddr(mHdr.getRomAreaStartPage()) << ")"; + std::cout << " (0x" << std::hex << nn::hac::GameCardUtils::blockToAddr(mHdr.getRomAreaStartPage()) << ")"; std::cout << std::endl; std::cout << " BackupAreaStartPage: 0x" << std::hex << mHdr.getBackupAreaStartPage(); if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1)) - std::cout << " (0x" << std::hex << nn::hac::XciUtils::blockToAddr(mHdr.getBackupAreaStartPage()) << ")"; + std::cout << " (0x" << std::hex << nn::hac::GameCardUtils::blockToAddr(mHdr.getBackupAreaStartPage()) << ")"; std::cout << std::endl; std::cout << " ValidDataEndPage: 0x" << std::hex << mHdr.getValidDataEndPage(); if (mHdr.getValidDataEndPage() != (uint32_t)(-1)) - std::cout << " (0x" << std::hex << nn::hac::XciUtils::blockToAddr(mHdr.getValidDataEndPage()) << ")"; + std::cout << " (0x" << std::hex << nn::hac::GameCardUtils::blockToAddr(mHdr.getValidDataEndPage()) << ")"; std::cout << std::endl; std::cout << " LimArea: 0x" << std::hex << mHdr.getLimAreaPage(); if (mHdr.getLimAreaPage() != (uint32_t)(-1)) - std::cout << " (0x" << std::hex << nn::hac::XciUtils::blockToAddr(mHdr.getLimAreaPage()) << ")"; + std::cout << " (0x" << std::hex << nn::hac::GameCardUtils::blockToAddr(mHdr.getLimAreaPage()) << ")"; std::cout << std::endl; std::cout << " PartitionFs Header:" << std::endl; @@ -160,7 +160,7 @@ void XciProcess::displayHeader() if (mHdr.getFwVerMinor() != 0) { - std::cout << "[XCI Extended Header]" << std::endl; + std::cout << "[GameCard Extended Header]" << std::endl; std::cout << " FwVersion: v" << std::dec << mHdr.getFwVerMajor() << "." << mHdr.getFwVerMinor() << std::endl; std::cout << " AccCtrl1: 0x" << std::hex << mHdr.getAccCtrl1() << std::endl; std::cout << " CardClockRate: " << getCardClockRate(mHdr.getAccCtrl1()) << std::endl; @@ -178,7 +178,7 @@ void XciProcess::displayHeader() } } -bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash) +bool GameCardProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash) { fnd::Vec scratch; fnd::sha::sSha256Hash calc_hash; @@ -188,23 +188,23 @@ bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* t return calc_hash.compare(test_hash); } -void XciProcess::validateXciSignature() +void GameCardProcess::validateXciSignature() { fnd::rsa::sRsa2048Key header_sign_key; fnd::sha::sSha256Hash calc_hash; - fnd::sha::Sha256((byte_t*)&mHdrPage.header, sizeof(nn::hac::sXciHeader), calc_hash.bytes); + fnd::sha::Sha256((byte_t*)&mHdrPage.header, sizeof(nn::hac::sGcHeader), calc_hash.bytes); mKeyCfg.getXciHeaderSignKey(header_sign_key); if (fnd::rsa::pkcs::rsaVerify(header_sign_key, fnd::sha::HASH_SHA256, calc_hash.bytes, mHdrPage.signature) != 0) { - std::cout << "[WARNING] XCI Header Signature: FAIL" << std::endl; + std::cout << "[WARNING] GameCard Header Signature: FAIL" << std::endl; } } -void XciProcess::processRootPfs() +void GameCardProcess::processRootPfs() { if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().bytes) == false) { - std::cout << "[WARNING] XCI Root HFS0: FAIL (bad hash)" << std::endl; + std::cout << "[WARNING] GameCard Root HFS0: FAIL (bad hash)" << std::endl; } mRootPfs.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize())); mRootPfs.setListFs(mListFs); @@ -214,15 +214,15 @@ void XciProcess::processRootPfs() mRootPfs.process(); } -void XciProcess::processPartitionPfs() +void GameCardProcess::processPartitionPfs() { - const fnd::List& rootPartitions = mRootPfs.getPfsHeader().getFileList(); + const fnd::List& rootPartitions = mRootPfs.getPfsHeader().getFileList(); for (size_t i = 0; i < rootPartitions.size(); i++) { // this must be validated here because only the size of the root partiton header is known at verification time if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].hash_protected_size, rootPartitions[i].hash.bytes) == false) { - std::cout << "[WARNING] XCI " << rootPartitions[i].name << " Partition HFS0: FAIL (bad hash)" << std::endl; + std::cout << "[WARNING] GameCard " << rootPartitions[i].name << " Partition HFS0: FAIL (bad hash)" << std::endl; } PfsProcess tmp; @@ -238,28 +238,28 @@ void XciProcess::processPartitionPfs() } } -const char* XciProcess::getRomSizeStr(byte_t rom_size) const +const char* GameCardProcess::getRomSizeStr(byte_t rom_size) const { const char* str = nullptr; switch (rom_size) { - case (nn::hac::xci::ROM_SIZE_1GB): + case (nn::hac::gc::ROM_SIZE_1GB): str = "1GB"; break; - case (nn::hac::xci::ROM_SIZE_2GB): + case (nn::hac::gc::ROM_SIZE_2GB): str = "2GB"; break; - case (nn::hac::xci::ROM_SIZE_4GB): + case (nn::hac::gc::ROM_SIZE_4GB): str = "4GB"; break; - case (nn::hac::xci::ROM_SIZE_8GB): + case (nn::hac::gc::ROM_SIZE_8GB): str = "8GB"; break; - case (nn::hac::xci::ROM_SIZE_16GB): + case (nn::hac::gc::ROM_SIZE_16GB): str = "16GB"; break; - case (nn::hac::xci::ROM_SIZE_32GB): + case (nn::hac::gc::ROM_SIZE_32GB): str = "32GB"; break; default: @@ -270,19 +270,19 @@ const char* XciProcess::getRomSizeStr(byte_t rom_size) const return str; } -const char* XciProcess::getHeaderFlagStr(byte_t flag) const +const char* GameCardProcess::getHeaderFlagStr(byte_t flag) const { const char* str = nullptr; switch (flag) { - case (nn::hac::xci::FLAG_AUTOBOOT): + case (nn::hac::gc::FLAG_AUTOBOOT): str = "AutoBoot"; break; - case (nn::hac::xci::FLAG_HISTORY_ERASE): + case (nn::hac::gc::FLAG_HISTORY_ERASE): str = "HistoryErase"; break; - case (nn::hac::xci::FLAG_REPAIR_TOOL): + case (nn::hac::gc::FLAG_REPAIR_TOOL): str = "RepairTool"; break; default: @@ -294,16 +294,16 @@ const char* XciProcess::getHeaderFlagStr(byte_t flag) const } -const char* XciProcess::getCardClockRate(uint32_t acc_ctrl_1) const +const char* GameCardProcess::getCardClockRate(uint32_t acc_ctrl_1) const { const char* str = nullptr; switch (acc_ctrl_1) { - case (nn::hac::xci::CLOCK_RATE_25): + case (nn::hac::gc::CLOCK_RATE_25): str = "20 MHz"; break; - case (nn::hac::xci::CLOCK_RATE_50): + case (nn::hac::gc::CLOCK_RATE_50): str = "50 MHz"; break; default: diff --git a/programs/nstool/source/XciProcess.h b/programs/nstool/source/GameCardProcess.h similarity index 88% rename from programs/nstool/source/XciProcess.h rename to programs/nstool/source/GameCardProcess.h index 6e034e7..d1cba42 100644 --- a/programs/nstool/source/XciProcess.h +++ b/programs/nstool/source/GameCardProcess.h @@ -4,16 +4,16 @@ #include #include #include -#include +#include #include "KeyConfiguration.h" #include "PfsProcess.h" #include "common.h" -class XciProcess +class GameCardProcess { public: - XciProcess(); + GameCardProcess(); void process(); @@ -28,7 +28,7 @@ public: void setListFs(bool list_fs); private: - const std::string kModuleName = "XciProcess"; + const std::string kModuleName = "GameCardProcess"; const std::string kXciMountPointName = "gamecard:/"; fnd::SharedPtr mFile; @@ -55,8 +55,8 @@ private: bool mListFs; - nn::hac::sXciHeaderPage mHdrPage; - nn::hac::XciHeader mHdr; + nn::hac::sGcHeaderPage mHdrPage; + nn::hac::GameCardHeader mHdr; PfsProcess mRootPfs; fnd::List mExtractInfo; diff --git a/programs/nstool/source/KeyConfiguration.cpp b/programs/nstool/source/KeyConfiguration.cpp index 91c1122..d674319 100644 --- a/programs/nstool/source/KeyConfiguration.cpp +++ b/programs/nstool/source/KeyConfiguration.cpp @@ -1,376 +1,376 @@ -#include "KeyConfiguration.h" -#include -#include -#include -#include - -KeyConfiguration::KeyConfiguration() -{ - clearGeneralKeyConfiguration(); - clearNcaExternalKeys(); -} - -KeyConfiguration::KeyConfiguration(const KeyConfiguration& other) -{ - *this = other; -} - -void KeyConfiguration::operator=(const KeyConfiguration& other) -{ - mAcidSignKey = other.mAcidSignKey; - mPkg2SignKey = other.mPkg2SignKey; - mNcaHeader0SignKey = other.mNcaHeader0SignKey; - mXciHeaderSignKey = other.mXciHeaderSignKey; - - mNcaHeaderKey = other.mNcaHeaderKey; - mXciHeaderKey = other.mXciHeaderKey; - - for (size_t i = 0; i < kMasterKeyNum; i++) - { - mPkg2Key[i] = other.mPkg2Key[i]; - mPkg1Key[i] = other.mPkg1Key[i]; - mNcaKeyAreaEncryptionKey[0][i] = other.mNcaKeyAreaEncryptionKey[0][i]; - mNcaKeyAreaEncryptionKey[1][i] = other.mNcaKeyAreaEncryptionKey[1][i]; - mNcaKeyAreaEncryptionKey[2][i] = other.mNcaKeyAreaEncryptionKey[2][i]; - mNcaKeyAreaEncryptionKeyHw[0][i] = other.mNcaKeyAreaEncryptionKeyHw[0][i]; - mNcaKeyAreaEncryptionKeyHw[1][i] = other.mNcaKeyAreaEncryptionKeyHw[1][i]; - mNcaKeyAreaEncryptionKeyHw[2][i] = other.mNcaKeyAreaEncryptionKeyHw[2][i]; - mETicketCommonKey[i] = other.mETicketCommonKey[i]; - } - - mPkiRootKeyList = other.mPkiRootKeyList; - - mNcaExternalContentKeyList = other.mNcaExternalContentKeyList; -} - -void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path) -{ - clearGeneralKeyConfiguration(); - - fnd::ResourceFileReader res; - try - { - res.processFile(path); - } - catch (const fnd::Exception&) - { - throw fnd::Exception(kModuleName, "Failed to open key file: " + path); - } - - // internally used sources - fnd::aes::sAes128Key master_key[kMasterKeyNum] = { kNullAesKey }; - fnd::aes::sAes128Key package2_key_source = kNullAesKey; - fnd::aes::sAes128Key ticket_titlekek_source = kNullAesKey; - fnd::aes::sAes128Key key_area_key_source[kNcaKeakNum] = { kNullAesKey, kNullAesKey, kNullAesKey }; - fnd::aes::sAes128Key aes_kek_generation_source = kNullAesKey; - fnd::aes::sAes128Key aes_key_generation_source = kNullAesKey; - fnd::aes::sAes128Key nca_header_kek_source = kNullAesKey; - fnd::aes::sAesXts128Key nca_header_key_source = kNullAesXtsKey; - fnd::rsa::sRsa4096Key pki_root_sign_key = kNullRsa4096Key; - -#define _CONCAT_2_STRINGS(str1, str2) ((str1) + "_" + (str2)) -#define _CONCAT_3_STRINGS(str1, str2, str3) _CONCAT_2_STRINGS(_CONCAT_2_STRINGS(str1, str2), str3) - - std::string key,val; - fnd::Vec dec_array; - -#define _SAVE_KEYDATA(key_name, array, len) \ - key = (key_name); \ - val = res[key]; \ - if (val.empty() == false) { \ - fnd::SimpleTextOutput::stringToArray(val, dec_array); \ - if (dec_array.size() != len) \ - throw fnd::Exception(kModuleName, "Key: \"" + key_name + "\" has incorrect length"); \ - memcpy(array, dec_array.data(), len); \ - } - - for (size_t nameidx = 0; nameidx < kNameVariantNum; nameidx++) - { - // import sources - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kKeyStr, kSourceStr), package2_key_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kTicketCommonKeyBase[nameidx], kSourceStr), ticket_titlekek_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kSourceStr), key_area_key_source[0].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kSourceStr), key_area_key_source[1].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kSourceStr), key_area_key_source[2].key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kKekGenBase[nameidx], kSourceStr), aes_kek_generation_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kKeyGenBase[nameidx], kSourceStr), aes_key_generation_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kKekStr, kSourceStr), nca_header_kek_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kKeyStr, kSourceStr), nca_header_key_source.key, 0x20); - - // Store Key Variants/Derivatives - for (size_t mkeyidx = 0; mkeyidx < kMasterKeyNum; mkeyidx++) - { - - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kMasterBase[nameidx], kKeyStr, kKeyIndex[mkeyidx]), master_key[mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg1Base[nameidx], kKeyStr, kKeyIndex[mkeyidx]), mPkg1Key[mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kKeyStr, kKeyIndex[mkeyidx]), mPkg2Key[mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kTicketCommonKeyBase[nameidx], kKeyIndex[mkeyidx]), mETicketCommonKey[mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKey[0][mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKey[1][mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKey[2][mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[0][mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[1][mkeyidx].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[2][mkeyidx].key, 0x10); - } - - // store nca header key - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[nameidx], kKeyStr), mNcaHeaderKey.key[0], 0x20); - - // store xci header key - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kKeyStr), mXciHeaderKey.key, 0x10); - - // store rsa keys - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[nameidx], kRsaKeyPrivate), mNcaHeader0SignKey.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[nameidx], kRsaKeyModulus), mNcaHeader0SignKey.modulus, fnd::rsa::kRsa2048Size); - - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyPrivate), mXciHeaderSignKey.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyModulus), mXciHeaderSignKey.modulus, fnd::rsa::kRsa2048Size); - - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyPrivate), mAcidSignKey.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyModulus), mAcidSignKey.modulus, fnd::rsa::kRsa2048Size); - - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyPrivate), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyModulus), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size); - - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyPrivate), pki_root_sign_key.priv_exponent, fnd::rsa::kRsa4096Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyModulus), pki_root_sign_key.modulus, fnd::rsa::kRsa4096Size); - } - -#undef _SAVE_KEYDATA -#undef _CONCAT_3_STRINGS -#undef _CONCAT_2_STRINGS - - // Derive keys - for (size_t i = 0; i < kMasterKeyNum; i++) - { - if (master_key[i] != kNullAesKey) - { - if (aes_kek_generation_source != kNullAesKey && aes_key_generation_source != kNullAesKey) - { - if (i == 0 && nca_header_kek_source != kNullAesKey && nca_header_key_source != kNullAesXtsKey) - { - if (mNcaHeaderKey == kNullAesXtsKey) - { - fnd::aes::sAes128Key nca_header_kek; - nn::hac::AesKeygen::generateKey(nca_header_kek.key, aes_kek_generation_source.key, nca_header_kek_source.key, aes_key_generation_source.key, master_key[i].key); - nn::hac::AesKeygen::generateKey(mNcaHeaderKey.key[0], nca_header_key_source.key[0], nca_header_kek.key); - nn::hac::AesKeygen::generateKey(mNcaHeaderKey.key[1], nca_header_key_source.key[1], nca_header_kek.key); - } - } - - for (size_t j = 0; j < nn::hac::nca::kKeyAreaEncryptionKeyNum; j++) - { - if (key_area_key_source[j] != kNullAesKey && mNcaKeyAreaEncryptionKey[j][i] == kNullAesKey) - { - nn::hac::AesKeygen::generateKey(mNcaKeyAreaEncryptionKey[j][i].key, aes_kek_generation_source.key, key_area_key_source[j].key, aes_key_generation_source.key, master_key[i].key); - } - } - } - - if (ticket_titlekek_source != kNullAesKey && mETicketCommonKey[i] == kNullAesKey) - { - nn::hac::AesKeygen::generateKey(mETicketCommonKey[i].key, ticket_titlekek_source.key, master_key[i].key); - } - if (package2_key_source != kNullAesKey && mPkg2Key[i] == kNullAesKey) - { - nn::hac::AesKeygen::generateKey(mPkg2Key[i].key, package2_key_source.key, master_key[i].key); - } - } - } - - // populate pki root keys - if (pki_root_sign_key != kNullRsa4096Key) - { - sPkiRootKey tmp; - - tmp.name = nn::pki::sign::kRootIssuerStr; - tmp.key_type = nn::pki::sign::SIGN_ALGO_RSA4096; - tmp.rsa4096_key = pki_root_sign_key; - - mPkiRootKeyList.addElement(tmp); - } -} - - -void KeyConfiguration::clearGeneralKeyConfiguration() -{ - mAcidSignKey = kNullRsa2048Key; - mPkg2SignKey = kNullRsa2048Key; - mNcaHeader0SignKey = kNullRsa2048Key; - mXciHeaderSignKey = kNullRsa2048Key; - mPkiRootKeyList.clear(); - - mNcaHeaderKey = kNullAesXtsKey; - mXciHeaderKey = kNullAesKey; - - for (size_t i = 0; i < kMasterKeyNum; i++) - { - mPkg1Key[i] = kNullAesKey; - mPkg2Key[i] = kNullAesKey; - mETicketCommonKey[i] = kNullAesKey; - for (size_t j = 0; j < kNcaKeakNum; j++) - { - mNcaKeyAreaEncryptionKey[j][i] = kNullAesKey; - mNcaKeyAreaEncryptionKey[j][i] = kNullAesKey; - } - } -} - -void KeyConfiguration::clearNcaExternalKeys() -{ - mNcaExternalContentKeyList.clear(); -} - -bool KeyConfiguration::getNcaHeaderKey(fnd::aes::sAesXts128Key& key) const -{ - return copyOutKeyResourceIfExists(mNcaHeaderKey, key, kNullAesXtsKey); -} - -bool KeyConfiguration::getNcaHeader0SignKey(fnd::rsa::sRsa2048Key& key) const -{ - return copyOutKeyResourceIfExists(mNcaHeader0SignKey, key, kNullRsa2048Key); -} - -bool KeyConfiguration::getAcidSignKey(fnd::rsa::sRsa2048Key& key) const -{ - return copyOutKeyResourceIfExists(mAcidSignKey, key, kNullRsa2048Key); -} - -bool KeyConfiguration::getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const -{ - if (keak_type >= kNcaKeakNum || masterkey_index >= kMasterKeyNum) - { - return false; - } - return copyOutKeyResourceIfExists(mNcaKeyAreaEncryptionKey[keak_type][masterkey_index], key, kNullAesKey); -} - -bool KeyConfiguration::getNcaKeyAreaEncryptionKeyHw(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const -{ - if (keak_type >= kNcaKeakNum || masterkey_index >= kMasterKeyNum) - { - return false; - } - return copyOutKeyResourceIfExists(mNcaKeyAreaEncryptionKeyHw[keak_type][masterkey_index], key, kNullAesKey); -} - -void KeyConfiguration::addNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], const fnd::aes::sAes128Key& key) -{ - sNcaExternalContentKey tmp; - memcpy(tmp.rights_id.data, rights_id, nn::hac::nca::kRightsIdLen); - tmp.key = key; - - if (mNcaExternalContentKeyList.hasElement(tmp)) - return; - - mNcaExternalContentKeyList.addElement(tmp); -} - -bool KeyConfiguration::getNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], fnd::aes::sAes128Key& key) const -{ - sRightsId id; - bool res_exists = false; - - memcpy(id.data, rights_id, nn::hac::nca::kRightsIdLen); - for (size_t i = 0; i < mNcaExternalContentKeyList.size(); i++) - { - if (mNcaExternalContentKeyList[i].rights_id == id) - { - res_exists = true; - key = mNcaExternalContentKeyList[i].key; - break; - } - } - - return res_exists; -} - -bool KeyConfiguration::getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const -{ - if (masterkey_index >= kMasterKeyNum) - { - return false; - } - return copyOutKeyResourceIfExists(mPkg1Key[masterkey_index], key, kNullAesKey); -} - -bool KeyConfiguration::getPkg2Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const -{ - if (masterkey_index >= kMasterKeyNum) - { - return false; - } - return copyOutKeyResourceIfExists(mPkg2Key[masterkey_index], key, kNullAesKey); -} - -bool KeyConfiguration::getPkg2SignKey(fnd::rsa::sRsa2048Key& key) const -{ - return copyOutKeyResourceIfExists(mPkg2SignKey, key, kNullRsa2048Key); -} - -bool KeyConfiguration::getXciHeaderSignKey(fnd::rsa::sRsa2048Key& key) const -{ - return copyOutKeyResourceIfExists(mXciHeaderSignKey, key, kNullRsa2048Key); -} - -bool KeyConfiguration::getXciHeaderKey(fnd::aes::sAes128Key& key) const -{ - return copyOutKeyResourceIfExists(mXciHeaderKey, key, kNullAesKey); -} - -bool KeyConfiguration::getETicketCommonKey(byte_t masterkey_index, fnd::aes::sAes128Key& key) const -{ - if (masterkey_index >= kMasterKeyNum) - { - return false; - } - return copyOutKeyResourceIfExists(mETicketCommonKey[masterkey_index], key, kNullAesKey); -} - -bool KeyConfiguration::getPkiRootSignKey(const std::string& root_name, fnd::rsa::sRsa4096Key& key) const -{ - bool res_exists = false; - for (size_t i = 0; i < mPkiRootKeyList.size(); i++) - { - if (root_name == mPkiRootKeyList[i].name && mPkiRootKeyList[i].key_type == nn::pki::sign::SIGN_ALGO_RSA4096) - { - res_exists = true; - key = mPkiRootKeyList[i].rsa4096_key; - break; - } - } - - return res_exists; -} - -bool KeyConfiguration::getPkiRootSignKey(const std::string& root_name, fnd::rsa::sRsa2048Key& key) const -{ - bool res_exists = false; - for (size_t i = 0; i < mPkiRootKeyList.size(); i++) - { - if (root_name == mPkiRootKeyList[i].name && mPkiRootKeyList[i].key_type == nn::pki::sign::SIGN_ALGO_RSA2048) - { - res_exists = true; - key = mPkiRootKeyList[i].rsa2048_key; - break; - } - } - - return res_exists; -} - -bool KeyConfiguration::getPkiRootSignKey(const std::string& root_name, fnd::ecdsa::sEcdsa240Key& key) const -{ - bool res_exists = false; - for (size_t i = 0; i < mPkiRootKeyList.size(); i++) - { - if (root_name == mPkiRootKeyList[i].name && mPkiRootKeyList[i].key_type == nn::pki::sign::SIGN_ALGO_ECDSA240) - { - res_exists = true; - key = mPkiRootKeyList[i].ecdsa240_key; - break; - } - } - - return res_exists; +#include "KeyConfiguration.h" +#include +#include +#include +#include + +KeyConfiguration::KeyConfiguration() +{ + clearGeneralKeyConfiguration(); + clearNcaExternalKeys(); +} + +KeyConfiguration::KeyConfiguration(const KeyConfiguration& other) +{ + *this = other; +} + +void KeyConfiguration::operator=(const KeyConfiguration& other) +{ + mAcidSignKey = other.mAcidSignKey; + mPkg2SignKey = other.mPkg2SignKey; + mContentArchiveHeader0SignKey = other.mContentArchiveHeader0SignKey; + mXciHeaderSignKey = other.mXciHeaderSignKey; + + mContentArchiveHeaderKey = other.mContentArchiveHeaderKey; + mXciHeaderKey = other.mXciHeaderKey; + + for (size_t i = 0; i < kMasterKeyNum; i++) + { + mPkg2Key[i] = other.mPkg2Key[i]; + mPkg1Key[i] = other.mPkg1Key[i]; + mNcaKeyAreaEncryptionKey[0][i] = other.mNcaKeyAreaEncryptionKey[0][i]; + mNcaKeyAreaEncryptionKey[1][i] = other.mNcaKeyAreaEncryptionKey[1][i]; + mNcaKeyAreaEncryptionKey[2][i] = other.mNcaKeyAreaEncryptionKey[2][i]; + mNcaKeyAreaEncryptionKeyHw[0][i] = other.mNcaKeyAreaEncryptionKeyHw[0][i]; + mNcaKeyAreaEncryptionKeyHw[1][i] = other.mNcaKeyAreaEncryptionKeyHw[1][i]; + mNcaKeyAreaEncryptionKeyHw[2][i] = other.mNcaKeyAreaEncryptionKeyHw[2][i]; + mETicketCommonKey[i] = other.mETicketCommonKey[i]; + } + + mPkiRootKeyList = other.mPkiRootKeyList; + + mNcaExternalContentKeyList = other.mNcaExternalContentKeyList; +} + +void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path) +{ + clearGeneralKeyConfiguration(); + + fnd::ResourceFileReader res; + try + { + res.processFile(path); + } + catch (const fnd::Exception&) + { + throw fnd::Exception(kModuleName, "Failed to open key file: " + path); + } + + // internally used sources + fnd::aes::sAes128Key master_key[kMasterKeyNum] = { kNullAesKey }; + fnd::aes::sAes128Key package2_key_source = kNullAesKey; + fnd::aes::sAes128Key ticket_titlekek_source = kNullAesKey; + fnd::aes::sAes128Key key_area_key_source[kNcaKeakNum] = { kNullAesKey, kNullAesKey, kNullAesKey }; + fnd::aes::sAes128Key aes_kek_generation_source = kNullAesKey; + fnd::aes::sAes128Key aes_key_generation_source = kNullAesKey; + fnd::aes::sAes128Key nca_header_kek_source = kNullAesKey; + fnd::aes::sAesXts128Key nca_header_key_source = kNullAesXtsKey; + fnd::rsa::sRsa4096Key pki_root_sign_key = kNullRsa4096Key; + +#define _CONCAT_2_STRINGS(str1, str2) ((str1) + "_" + (str2)) +#define _CONCAT_3_STRINGS(str1, str2, str3) _CONCAT_2_STRINGS(_CONCAT_2_STRINGS(str1, str2), str3) + + std::string key,val; + fnd::Vec dec_array; + +#define _SAVE_KEYDATA(key_name, array, len) \ + key = (key_name); \ + val = res[key]; \ + if (val.empty() == false) { \ + fnd::SimpleTextOutput::stringToArray(val, dec_array); \ + if (dec_array.size() != len) \ + throw fnd::Exception(kModuleName, "Key: \"" + key_name + "\" has incorrect length"); \ + memcpy(array, dec_array.data(), len); \ + } + + for (size_t nameidx = 0; nameidx < kNameVariantNum; nameidx++) + { + // import sources + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kKeyStr, kSourceStr), package2_key_source.key, 0x10); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kTicketCommonKeyBase[nameidx], kSourceStr), ticket_titlekek_source.key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kSourceStr), key_area_key_source[0].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kSourceStr), key_area_key_source[1].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kSourceStr), key_area_key_source[2].key, 0x10); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kKekGenBase[nameidx], kSourceStr), aes_kek_generation_source.key, 0x10); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kKeyGenBase[nameidx], kSourceStr), aes_key_generation_source.key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kKekStr, kSourceStr), nca_header_kek_source.key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kKeyStr, kSourceStr), nca_header_key_source.key, 0x20); + + // Store Key Variants/Derivatives + for (size_t mkeyidx = 0; mkeyidx < kMasterKeyNum; mkeyidx++) + { + + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kMasterBase[nameidx], kKeyStr, kKeyIndex[mkeyidx]), master_key[mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg1Base[nameidx], kKeyStr, kKeyIndex[mkeyidx]), mPkg1Key[mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kKeyStr, kKeyIndex[mkeyidx]), mPkg2Key[mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kTicketCommonKeyBase[nameidx], kKeyIndex[mkeyidx]), mETicketCommonKey[mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKey[0][mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKey[1][mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKey[2][mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[0][mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[1][mkeyidx].key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[2][mkeyidx].key, 0x10); + } + + // store nca header key + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kContentArchiveHeaderBase[nameidx], kKeyStr), mContentArchiveHeaderKey.key[0], 0x20); + + // store xci header key + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kKeyStr), mXciHeaderKey.key, 0x10); + + // store rsa keys + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kContentArchiveHeaderBase[nameidx], kRsaKeyPrivate), mContentArchiveHeader0SignKey.priv_exponent, fnd::rsa::kRsa2048Size); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kContentArchiveHeaderBase[nameidx], kRsaKeyModulus), mContentArchiveHeader0SignKey.modulus, fnd::rsa::kRsa2048Size); + + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyPrivate), mXciHeaderSignKey.priv_exponent, fnd::rsa::kRsa2048Size); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyModulus), mXciHeaderSignKey.modulus, fnd::rsa::kRsa2048Size); + + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyPrivate), mAcidSignKey.priv_exponent, fnd::rsa::kRsa2048Size); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyModulus), mAcidSignKey.modulus, fnd::rsa::kRsa2048Size); + + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyPrivate), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyModulus), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size); + + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyPrivate), pki_root_sign_key.priv_exponent, fnd::rsa::kRsa4096Size); + _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyModulus), pki_root_sign_key.modulus, fnd::rsa::kRsa4096Size); + } + +#undef _SAVE_KEYDATA +#undef _CONCAT_3_STRINGS +#undef _CONCAT_2_STRINGS + + // Derive keys + for (size_t i = 0; i < kMasterKeyNum; i++) + { + if (master_key[i] != kNullAesKey) + { + if (aes_kek_generation_source != kNullAesKey && aes_key_generation_source != kNullAesKey) + { + if (i == 0 && nca_header_kek_source != kNullAesKey && nca_header_key_source != kNullAesXtsKey) + { + if (mContentArchiveHeaderKey == kNullAesXtsKey) + { + fnd::aes::sAes128Key nca_header_kek; + nn::hac::AesKeygen::generateKey(nca_header_kek.key, aes_kek_generation_source.key, nca_header_kek_source.key, aes_key_generation_source.key, master_key[i].key); + nn::hac::AesKeygen::generateKey(mContentArchiveHeaderKey.key[0], nca_header_key_source.key[0], nca_header_kek.key); + nn::hac::AesKeygen::generateKey(mContentArchiveHeaderKey.key[1], nca_header_key_source.key[1], nca_header_kek.key); + } + } + + for (size_t j = 0; j < nn::hac::nca::kKeyAreaEncryptionKeyNum; j++) + { + if (key_area_key_source[j] != kNullAesKey && mNcaKeyAreaEncryptionKey[j][i] == kNullAesKey) + { + nn::hac::AesKeygen::generateKey(mNcaKeyAreaEncryptionKey[j][i].key, aes_kek_generation_source.key, key_area_key_source[j].key, aes_key_generation_source.key, master_key[i].key); + } + } + } + + if (ticket_titlekek_source != kNullAesKey && mETicketCommonKey[i] == kNullAesKey) + { + nn::hac::AesKeygen::generateKey(mETicketCommonKey[i].key, ticket_titlekek_source.key, master_key[i].key); + } + if (package2_key_source != kNullAesKey && mPkg2Key[i] == kNullAesKey) + { + nn::hac::AesKeygen::generateKey(mPkg2Key[i].key, package2_key_source.key, master_key[i].key); + } + } + } + + // populate pki root keys + if (pki_root_sign_key != kNullRsa4096Key) + { + sPkiRootKey tmp; + + tmp.name = nn::pki::sign::kRootIssuerStr; + tmp.key_type = nn::pki::sign::SIGN_ALGO_RSA4096; + tmp.rsa4096_key = pki_root_sign_key; + + mPkiRootKeyList.addElement(tmp); + } +} + + +void KeyConfiguration::clearGeneralKeyConfiguration() +{ + mAcidSignKey = kNullRsa2048Key; + mPkg2SignKey = kNullRsa2048Key; + mContentArchiveHeader0SignKey = kNullRsa2048Key; + mXciHeaderSignKey = kNullRsa2048Key; + mPkiRootKeyList.clear(); + + mContentArchiveHeaderKey = kNullAesXtsKey; + mXciHeaderKey = kNullAesKey; + + for (size_t i = 0; i < kMasterKeyNum; i++) + { + mPkg1Key[i] = kNullAesKey; + mPkg2Key[i] = kNullAesKey; + mETicketCommonKey[i] = kNullAesKey; + for (size_t j = 0; j < kNcaKeakNum; j++) + { + mNcaKeyAreaEncryptionKey[j][i] = kNullAesKey; + mNcaKeyAreaEncryptionKey[j][i] = kNullAesKey; + } + } +} + +void KeyConfiguration::clearNcaExternalKeys() +{ + mNcaExternalContentKeyList.clear(); +} + +bool KeyConfiguration::getContentArchiveHeaderKey(fnd::aes::sAesXts128Key& key) const +{ + return copyOutKeyResourceIfExists(mContentArchiveHeaderKey, key, kNullAesXtsKey); +} + +bool KeyConfiguration::getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key) const +{ + return copyOutKeyResourceIfExists(mContentArchiveHeader0SignKey, key, kNullRsa2048Key); +} + +bool KeyConfiguration::getAcidSignKey(fnd::rsa::sRsa2048Key& key) const +{ + return copyOutKeyResourceIfExists(mAcidSignKey, key, kNullRsa2048Key); +} + +bool KeyConfiguration::getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const +{ + if (keak_type >= kNcaKeakNum || masterkey_index >= kMasterKeyNum) + { + return false; + } + return copyOutKeyResourceIfExists(mNcaKeyAreaEncryptionKey[keak_type][masterkey_index], key, kNullAesKey); +} + +bool KeyConfiguration::getNcaKeyAreaEncryptionKeyHw(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const +{ + if (keak_type >= kNcaKeakNum || masterkey_index >= kMasterKeyNum) + { + return false; + } + return copyOutKeyResourceIfExists(mNcaKeyAreaEncryptionKeyHw[keak_type][masterkey_index], key, kNullAesKey); +} + +void KeyConfiguration::addNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], const fnd::aes::sAes128Key& key) +{ + sNcaExternalContentKey tmp; + memcpy(tmp.rights_id.data, rights_id, nn::hac::nca::kRightsIdLen); + tmp.key = key; + + if (mNcaExternalContentKeyList.hasElement(tmp)) + return; + + mNcaExternalContentKeyList.addElement(tmp); +} + +bool KeyConfiguration::getNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], fnd::aes::sAes128Key& key) const +{ + sRightsId id; + bool res_exists = false; + + memcpy(id.data, rights_id, nn::hac::nca::kRightsIdLen); + for (size_t i = 0; i < mNcaExternalContentKeyList.size(); i++) + { + if (mNcaExternalContentKeyList[i].rights_id == id) + { + res_exists = true; + key = mNcaExternalContentKeyList[i].key; + break; + } + } + + return res_exists; +} + +bool KeyConfiguration::getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const +{ + if (masterkey_index >= kMasterKeyNum) + { + return false; + } + return copyOutKeyResourceIfExists(mPkg1Key[masterkey_index], key, kNullAesKey); +} + +bool KeyConfiguration::getPkg2Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const +{ + if (masterkey_index >= kMasterKeyNum) + { + return false; + } + return copyOutKeyResourceIfExists(mPkg2Key[masterkey_index], key, kNullAesKey); +} + +bool KeyConfiguration::getPkg2SignKey(fnd::rsa::sRsa2048Key& key) const +{ + return copyOutKeyResourceIfExists(mPkg2SignKey, key, kNullRsa2048Key); +} + +bool KeyConfiguration::getXciHeaderSignKey(fnd::rsa::sRsa2048Key& key) const +{ + return copyOutKeyResourceIfExists(mXciHeaderSignKey, key, kNullRsa2048Key); +} + +bool KeyConfiguration::getXciHeaderKey(fnd::aes::sAes128Key& key) const +{ + return copyOutKeyResourceIfExists(mXciHeaderKey, key, kNullAesKey); +} + +bool KeyConfiguration::getETicketCommonKey(byte_t masterkey_index, fnd::aes::sAes128Key& key) const +{ + if (masterkey_index >= kMasterKeyNum) + { + return false; + } + return copyOutKeyResourceIfExists(mETicketCommonKey[masterkey_index], key, kNullAesKey); +} + +bool KeyConfiguration::getPkiRootSignKey(const std::string& root_name, fnd::rsa::sRsa4096Key& key) const +{ + bool res_exists = false; + for (size_t i = 0; i < mPkiRootKeyList.size(); i++) + { + if (root_name == mPkiRootKeyList[i].name && mPkiRootKeyList[i].key_type == nn::pki::sign::SIGN_ALGO_RSA4096) + { + res_exists = true; + key = mPkiRootKeyList[i].rsa4096_key; + break; + } + } + + return res_exists; +} + +bool KeyConfiguration::getPkiRootSignKey(const std::string& root_name, fnd::rsa::sRsa2048Key& key) const +{ + bool res_exists = false; + for (size_t i = 0; i < mPkiRootKeyList.size(); i++) + { + if (root_name == mPkiRootKeyList[i].name && mPkiRootKeyList[i].key_type == nn::pki::sign::SIGN_ALGO_RSA2048) + { + res_exists = true; + key = mPkiRootKeyList[i].rsa2048_key; + break; + } + } + + return res_exists; +} + +bool KeyConfiguration::getPkiRootSignKey(const std::string& root_name, fnd::ecdsa::sEcdsa240Key& key) const +{ + bool res_exists = false; + for (size_t i = 0; i < mPkiRootKeyList.size(); i++) + { + if (root_name == mPkiRootKeyList[i].name && mPkiRootKeyList[i].key_type == nn::pki::sign::SIGN_ALGO_ECDSA240) + { + res_exists = true; + key = mPkiRootKeyList[i].ecdsa240_key; + break; + } + } + + return res_exists; } \ No newline at end of file diff --git a/programs/nstool/source/KeyConfiguration.h b/programs/nstool/source/KeyConfiguration.h index 8925708..5716379 100644 --- a/programs/nstool/source/KeyConfiguration.h +++ b/programs/nstool/source/KeyConfiguration.h @@ -1,209 +1,209 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class KeyConfiguration -{ -public: - KeyConfiguration(); - KeyConfiguration(const KeyConfiguration& other); - - void operator=(const KeyConfiguration& other); - - void importHactoolGenericKeyfile(const std::string& path); - //void importHactoolTitleKeyfile(const std::string& path); - - void clearGeneralKeyConfiguration(); - void clearNcaExternalKeys(); - - // nca keys - bool getNcaHeaderKey(fnd::aes::sAesXts128Key& key) const; - bool getNcaHeader0SignKey(fnd::rsa::sRsa2048Key& key) const; - bool getAcidSignKey(fnd::rsa::sRsa2048Key& key) const; - bool getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const; - bool getNcaKeyAreaEncryptionKeyHw(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const; - - // external content keys - void addNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], const fnd::aes::sAes128Key& key); - bool getNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], fnd::aes::sAes128Key& key) const; - - // pkg1/pkg2 - bool getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const; - bool getPkg2Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const; - bool getPkg2SignKey(fnd::rsa::sRsa2048Key& key) const; - - // xci keys - bool getXciHeaderSignKey(fnd::rsa::sRsa2048Key& key) const; - bool getXciHeaderKey(fnd::aes::sAes128Key& key) const; - - // ticket - bool getETicketCommonKey(byte_t masterkey_index, fnd::aes::sAes128Key& key) const; - - // pki - bool getPkiRootSignKey(const std::string& root_name, fnd::rsa::sRsa4096Key& key) const; - bool getPkiRootSignKey(const std::string& root_name, fnd::rsa::sRsa2048Key& key) const; - bool getPkiRootSignKey(const std::string& root_name, fnd::ecdsa::sEcdsa240Key& key) const; -private: - const std::string kModuleName = "KeyConfiguration"; - const fnd::aes::sAes128Key kNullAesKey = {{0}}; - const fnd::aes::sAesXts128Key kNullAesXtsKey = {{{0}}}; - const fnd::rsa::sRsa4096Key kNullRsa4096Key = {{0}, {0}, {0}}; - const fnd::rsa::sRsa2048Key kNullRsa2048Key = {{0}, {0}, {0}}; - static const size_t kMasterKeyNum = 0x20; - static const size_t kNcaKeakNum = nn::hac::nca::kKeyAreaEncryptionKeyNum; - - // keynames - enum NameVariantIndex - { - NNTOOLS, - LEGACY_HACTOOL, - LEGACY_0 - }; - static const size_t kNameVariantNum = 3; - const std::string kMasterBase[kNameVariantNum] = { "master", "master", "master" }; - const std::string kPkg1Base[kNameVariantNum] = { "package1", "package1", "package1" }; - const std::string kPkg2Base[kNameVariantNum] = { "package2", "package2", "package2" }; - const std::string kXciHeaderBase[kNameVariantNum] = { "xci_header", "xci_header", "xci_header" }; - const std::string kNcaHeaderBase[kNameVariantNum] = { "nca_header", "header", "nca_header" }; - const std::string kAcidBase[kNameVariantNum] = { "acid", "acid", "acid" }; - const std::string kPkiRootBase[kNameVariantNum] = { "pki_root", "pki_root", "pki_root" }; - const std::string kTicketCommonKeyBase[kNameVariantNum] = { "ticket_commonkey", "titlekek", "ticket_commonkey" }; - const std::string kNcaKeyAreaEncKeyBase[kNameVariantNum] = { "nca_key_area_key", "key_area_key", "nca_body_keak" }; - const std::string kNcaKeyAreaEncKeyHwBase[kNameVariantNum] = { "nca_key_area_key_hw", "key_area_hw_key", "nca_key_area_key_hw" }; - const std::string kKekGenBase[kNameVariantNum] = { "aes_kek_generation", "aes_kek_generation", "aes_kek_generation" }; - const std::string kKeyGenBase[kNameVariantNum] = { "aes_key_generation", "aes_key_generation", "aes_key_generation" }; - - // misc str - const std::string kKeyStr = "key"; - const std::string kKekStr = "kek"; - const std::string kSourceStr = "source"; - const std::string kRsaKeyModulus = "sign_key_modulus"; - const std::string kRsaKeyPrivate = "sign_key_private"; - const std::string kNcaKeyAreaKeyIndexStr[kNcaKeakNum] = { "application", "ocean", "system" }; - const std::string kKeyIndex[kMasterKeyNum] = {"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"}; - - struct sRightsId - { - byte_t data[nn::hac::nca::kRightsIdLen]; - - void operator=(const sRightsId& other) - { - memcpy(this->data, other.data, nn::hac::nca::kRightsIdLen); - } - - bool operator==(const sRightsId& other) const - { - return memcmp(this->data, other.data, nn::hac::nca::kRightsIdLen) == 0; - } - - bool operator!=(const sRightsId& other) const - { - return !(operator==(other)); - } - }; - - struct sNcaExternalContentKey - { - sRightsId rights_id; - fnd::aes::sAes128Key key; - - void operator=(const sNcaExternalContentKey& other) - { - rights_id = other.rights_id; - key = other.key; - } - - bool operator==(const sNcaExternalContentKey& other) const - { - return (rights_id == other.rights_id) \ - && (key == other.key); - } - - bool operator!=(const sNcaExternalContentKey& other) const - { - return !(operator==(other)); - } - }; - - struct sPkiRootKey - { - std::string name; - nn::pki::sign::SignatureAlgo key_type; - fnd::rsa::sRsa4096Key rsa4096_key; - fnd::rsa::sRsa2048Key rsa2048_key; - fnd::ecdsa::sEcdsa240Key ecdsa240_key; - - void operator=(const sPkiRootKey& other) - { - name = other.name; - key_type = other.key_type; - rsa4096_key = other.rsa4096_key; - rsa2048_key = other.rsa2048_key; - ecdsa240_key = other.ecdsa240_key; - } - - bool operator==(const sPkiRootKey& other) const - { - return (name == other.name) \ - && (key_type == other.key_type) \ - && (rsa4096_key == other.rsa4096_key) \ - && (rsa2048_key == other.rsa2048_key) \ - && (ecdsa240_key == other.ecdsa240_key); - } - - bool operator!=(const sPkiRootKey& other) const - { - return !(operator==(other)); - } - }; - - - /* general key config */ - // acid - fnd::rsa::sRsa2048Key mAcidSignKey; - - // pkg1 and pkg2 - fnd::aes::sAes128Key mPkg1Key[kMasterKeyNum]; - fnd::rsa::sRsa2048Key mPkg2SignKey; - fnd::aes::sAes128Key mPkg2Key[kMasterKeyNum]; - - // nca - fnd::rsa::sRsa2048Key mNcaHeader0SignKey; - fnd::aes::sAesXts128Key mNcaHeaderKey; - fnd::aes::sAes128Key mNcaKeyAreaEncryptionKey[kNcaKeakNum][kMasterKeyNum]; - fnd::aes::sAes128Key mNcaKeyAreaEncryptionKeyHw[kNcaKeakNum][kMasterKeyNum]; - - // xci - fnd::rsa::sRsa2048Key mXciHeaderSignKey; - fnd::aes::sAes128Key mXciHeaderKey; - - // ticket - fnd::aes::sAes128Key mETicketCommonKey[kMasterKeyNum]; - - // pki - fnd::List mPkiRootKeyList; - - /* Nca External Keys */ - fnd::List mNcaExternalContentKeyList; - - template - bool copyOutKeyResourceIfExists(const T& src, T& dst, const T& null_sample) const - { - bool resource_exists = false; - - if (src != null_sample) - { - resource_exists = true; - dst = src; - } - - return resource_exists; - } +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class KeyConfiguration +{ +public: + KeyConfiguration(); + KeyConfiguration(const KeyConfiguration& other); + + void operator=(const KeyConfiguration& other); + + void importHactoolGenericKeyfile(const std::string& path); + //void importHactoolTitleKeyfile(const std::string& path); + + void clearGeneralKeyConfiguration(); + void clearNcaExternalKeys(); + + // nca keys + bool getContentArchiveHeaderKey(fnd::aes::sAesXts128Key& key) const; + bool getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key) const; + bool getAcidSignKey(fnd::rsa::sRsa2048Key& key) const; + bool getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const; + bool getNcaKeyAreaEncryptionKeyHw(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const; + + // external content keys + void addNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], const fnd::aes::sAes128Key& key); + bool getNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], fnd::aes::sAes128Key& key) const; + + // pkg1/pkg2 + bool getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const; + bool getPkg2Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const; + bool getPkg2SignKey(fnd::rsa::sRsa2048Key& key) const; + + // xci keys + bool getXciHeaderSignKey(fnd::rsa::sRsa2048Key& key) const; + bool getXciHeaderKey(fnd::aes::sAes128Key& key) const; + + // ticket + bool getETicketCommonKey(byte_t masterkey_index, fnd::aes::sAes128Key& key) const; + + // pki + bool getPkiRootSignKey(const std::string& root_name, fnd::rsa::sRsa4096Key& key) const; + bool getPkiRootSignKey(const std::string& root_name, fnd::rsa::sRsa2048Key& key) const; + bool getPkiRootSignKey(const std::string& root_name, fnd::ecdsa::sEcdsa240Key& key) const; +private: + const std::string kModuleName = "KeyConfiguration"; + const fnd::aes::sAes128Key kNullAesKey = {{0}}; + const fnd::aes::sAesXts128Key kNullAesXtsKey = {{{0}}}; + const fnd::rsa::sRsa4096Key kNullRsa4096Key = {{0}, {0}, {0}}; + const fnd::rsa::sRsa2048Key kNullRsa2048Key = {{0}, {0}, {0}}; + static const size_t kMasterKeyNum = 0x20; + static const size_t kNcaKeakNum = nn::hac::nca::kKeyAreaEncryptionKeyNum; + + // keynames + enum NameVariantIndex + { + NNTOOLS, + LEGACY_HACTOOL, + LEGACY_0 + }; + static const size_t kNameVariantNum = 3; + const std::string kMasterBase[kNameVariantNum] = { "master", "master", "master" }; + const std::string kPkg1Base[kNameVariantNum] = { "package1", "package1", "package1" }; + const std::string kPkg2Base[kNameVariantNum] = { "package2", "package2", "package2" }; + const std::string kXciHeaderBase[kNameVariantNum] = { "xci_header", "xci_header", "xci_header" }; + const std::string kContentArchiveHeaderBase[kNameVariantNum] = { "nca_header", "header", "nca_header" }; + const std::string kAcidBase[kNameVariantNum] = { "acid", "acid", "acid" }; + const std::string kPkiRootBase[kNameVariantNum] = { "pki_root", "pki_root", "pki_root" }; + const std::string kTicketCommonKeyBase[kNameVariantNum] = { "ticket_commonkey", "titlekek", "ticket_commonkey" }; + const std::string kNcaKeyAreaEncKeyBase[kNameVariantNum] = { "nca_key_area_key", "key_area_key", "nca_body_keak" }; + const std::string kNcaKeyAreaEncKeyHwBase[kNameVariantNum] = { "nca_key_area_key_hw", "key_area_hw_key", "nca_key_area_key_hw" }; + const std::string kKekGenBase[kNameVariantNum] = { "aes_kek_generation", "aes_kek_generation", "aes_kek_generation" }; + const std::string kKeyGenBase[kNameVariantNum] = { "aes_key_generation", "aes_key_generation", "aes_key_generation" }; + + // misc str + const std::string kKeyStr = "key"; + const std::string kKekStr = "kek"; + const std::string kSourceStr = "source"; + const std::string kRsaKeyModulus = "sign_key_modulus"; + const std::string kRsaKeyPrivate = "sign_key_private"; + const std::string kNcaKeyAreaKeyIndexStr[kNcaKeakNum] = { "application", "ocean", "system" }; + const std::string kKeyIndex[kMasterKeyNum] = {"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"}; + + struct sRightsId + { + byte_t data[nn::hac::nca::kRightsIdLen]; + + void operator=(const sRightsId& other) + { + memcpy(this->data, other.data, nn::hac::nca::kRightsIdLen); + } + + bool operator==(const sRightsId& other) const + { + return memcmp(this->data, other.data, nn::hac::nca::kRightsIdLen) == 0; + } + + bool operator!=(const sRightsId& other) const + { + return !(operator==(other)); + } + }; + + struct sNcaExternalContentKey + { + sRightsId rights_id; + fnd::aes::sAes128Key key; + + void operator=(const sNcaExternalContentKey& other) + { + rights_id = other.rights_id; + key = other.key; + } + + bool operator==(const sNcaExternalContentKey& other) const + { + return (rights_id == other.rights_id) \ + && (key == other.key); + } + + bool operator!=(const sNcaExternalContentKey& other) const + { + return !(operator==(other)); + } + }; + + struct sPkiRootKey + { + std::string name; + nn::pki::sign::SignatureAlgo key_type; + fnd::rsa::sRsa4096Key rsa4096_key; + fnd::rsa::sRsa2048Key rsa2048_key; + fnd::ecdsa::sEcdsa240Key ecdsa240_key; + + void operator=(const sPkiRootKey& other) + { + name = other.name; + key_type = other.key_type; + rsa4096_key = other.rsa4096_key; + rsa2048_key = other.rsa2048_key; + ecdsa240_key = other.ecdsa240_key; + } + + bool operator==(const sPkiRootKey& other) const + { + return (name == other.name) \ + && (key_type == other.key_type) \ + && (rsa4096_key == other.rsa4096_key) \ + && (rsa2048_key == other.rsa2048_key) \ + && (ecdsa240_key == other.ecdsa240_key); + } + + bool operator!=(const sPkiRootKey& other) const + { + return !(operator==(other)); + } + }; + + + /* general key config */ + // acid + fnd::rsa::sRsa2048Key mAcidSignKey; + + // pkg1 and pkg2 + fnd::aes::sAes128Key mPkg1Key[kMasterKeyNum]; + fnd::rsa::sRsa2048Key mPkg2SignKey; + fnd::aes::sAes128Key mPkg2Key[kMasterKeyNum]; + + // nca + fnd::rsa::sRsa2048Key mContentArchiveHeader0SignKey; + fnd::aes::sAesXts128Key mContentArchiveHeaderKey; + fnd::aes::sAes128Key mNcaKeyAreaEncryptionKey[kNcaKeakNum][kMasterKeyNum]; + fnd::aes::sAes128Key mNcaKeyAreaEncryptionKeyHw[kNcaKeakNum][kMasterKeyNum]; + + // xci + fnd::rsa::sRsa2048Key mXciHeaderSignKey; + fnd::aes::sAes128Key mXciHeaderKey; + + // ticket + fnd::aes::sAes128Key mETicketCommonKey[kMasterKeyNum]; + + // pki + fnd::List mPkiRootKeyList; + + /* Nca External Keys */ + fnd::List mNcaExternalContentKeyList; + + template + bool copyOutKeyResourceIfExists(const T& src, T& dst, const T& null_sample) const + { + bool resource_exists = false; + + if (src != null_sample) + { + resource_exists = true; + dst = src; + } + + return resource_exists; + } }; \ No newline at end of file diff --git a/programs/nstool/source/MetaProcess.cpp b/programs/nstool/source/MetaProcess.cpp index e67687c..7297504 100644 --- a/programs/nstool/source/MetaProcess.cpp +++ b/programs/nstool/source/MetaProcess.cpp @@ -1,1118 +1,1118 @@ -#include -#include -#include "MetaProcess.h" - -MetaProcess::MetaProcess() : - mFile(), - mCliOutputMode(_BIT(OUTPUT_BASIC)), - mVerify(false) -{ -} - -void MetaProcess::process() -{ - importMeta(); - - if (mVerify) - { - validateAcidSignature(mMeta.getAcid()); - validateAciFromAcid(mMeta.getAci(), mMeta.getAcid()); - } - - if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) - { - // npdm binary - displayMetaHeader(mMeta); - - // aci binary - displayAciHdr(mMeta.getAci()); - displayFac(mMeta.getAci().getFileSystemAccessControl()); - displaySac(mMeta.getAci().getServiceAccessControl()); - displayKernelCap(mMeta.getAci().getKernelCapabilities()); - - // acid binary - if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - displayAciDescHdr(mMeta.getAcid()); - displayFac(mMeta.getAcid().getFileSystemAccessControl()); - displaySac(mMeta.getAcid().getServiceAccessControl()); - displayKernelCap(mMeta.getAcid().getKernelCapabilities()); - } - } -} - -void MetaProcess::setInputFile(const fnd::SharedPtr& file) -{ - mFile = file; -} - -void MetaProcess::setKeyCfg(const KeyConfiguration& keycfg) -{ - mKeyCfg = keycfg; -} - -void MetaProcess::setCliOutputMode(CliOutputMode type) -{ - mCliOutputMode = type; -} - -void MetaProcess::setVerifyMode(bool verify) -{ - mVerify = verify; -} - -const nn::hac::MetaBinary& MetaProcess::getMetaBinary() const -{ - return mMeta; -} - -void MetaProcess::importMeta() -{ - fnd::Vec scratch; - - if (*mFile == nullptr) - { - throw fnd::Exception(kModuleName, "No file reader set."); - } - - scratch.alloc((*mFile)->size()); - (*mFile)->read(scratch.data(), 0, scratch.size()); - - mMeta.fromBytes(scratch.data(), scratch.size()); -} - -void MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfoDescBinary& acid) -{ - try { - fnd::rsa::sRsa2048Key acid_sign_key; - if (mKeyCfg.getAcidSignKey(acid_sign_key) != true) - throw fnd::Exception(); - - acid.validateSignature(acid_sign_key); - } - catch (...) { - std::cout << "[WARNING] ACID Signature: FAIL" << std::endl; - } - -} - -void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfoBinary& aci, const nn::hac::AccessControlInfoDescBinary& acid) -{ - // check Program ID - if (acid.getProgramIdRestrict().min > 0 && aci.getProgramId() < acid.getProgramIdRestrict().min) - { - std::cout << "[WARNING] ACI ProgramId: FAIL (Outside Legal Range)" << std::endl; - } - else if (acid.getProgramIdRestrict().max > 0 && aci.getProgramId() > acid.getProgramIdRestrict().max) - { - std::cout << "[WARNING] ACI ProgramId: FAIL (Outside Legal Range)" << std::endl; - } - - for (size_t i = 0; i < aci.getFileSystemAccessControl().getFsaRightsList().size(); i++) - { - bool fsaRightFound = false; - for (size_t j = 0; j < acid.getFileSystemAccessControl().getFsaRightsList().size() && fsaRightFound == false; j++) - { - if (aci.getFileSystemAccessControl().getFsaRightsList()[i] == acid.getFileSystemAccessControl().getFsaRightsList()[j]) - fsaRightFound = true; - } - - if (fsaRightFound == false) - { - - std::cout << "[WARNING] ACI/FAC FsaRights: FAIL (" << getFsaRightStr(aci.getFileSystemAccessControl().getFsaRightsList()[i]) << " not permitted)" << std::endl; - } - } - - for (size_t i = 0; i < aci.getFileSystemAccessControl().getContentOwnerIdList().size(); i++) - { - bool rightFound = false; - for (size_t j = 0; j < acid.getFileSystemAccessControl().getContentOwnerIdList().size() && rightFound == false; j++) - { - if (aci.getFileSystemAccessControl().getContentOwnerIdList()[i] == acid.getFileSystemAccessControl().getContentOwnerIdList()[j]) - rightFound = true; - } - - if (rightFound == false) - { - - std::cout << "[WARNING] ACI/FAC ContentOwnerId: FAIL (" << std::hex << std::setw(16) << std::setfill('0') << aci.getFileSystemAccessControl().getContentOwnerIdList()[i] << " not permitted)" << std::endl; - } - } - - for (size_t i = 0; i < aci.getFileSystemAccessControl().getSaveDataOwnerIdList().size(); i++) - { - bool rightFound = false; - for (size_t j = 0; j < acid.getFileSystemAccessControl().getSaveDataOwnerIdList().size() && rightFound == false; j++) - { - if (aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i] == acid.getFileSystemAccessControl().getSaveDataOwnerIdList()[j]) - rightFound = true; - } - - if (rightFound == false) - { - - std::cout << "[WARNING] ACI/FAC SaveDataOwnerId: FAIL (" << std::hex << std::setw(16) << std::setfill('0') << aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id << "(" << std::dec << (uint32_t)aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type << ") not permitted)" << std::endl; - } - } - - // check SAC - for (size_t i = 0; i < aci.getServiceAccessControl().getServiceList().size(); i++) - { - bool rightFound = false; - for (size_t j = 0; j < acid.getServiceAccessControl().getServiceList().size() && rightFound == false; j++) - { - if (aci.getServiceAccessControl().getServiceList()[i] == acid.getServiceAccessControl().getServiceList()[j]) - rightFound = true; - } - - if (rightFound == false) - { - std::cout << "[WARNING] ACI/SAC ServiceList: FAIL (" << aci.getServiceAccessControl().getServiceList()[i].getName() << (aci.getServiceAccessControl().getServiceList()[i].isServer()? " (Server)" : "") << " not permitted)" << std::endl; - } - } - - // check KC - // check thread info - if (aci.getKernelCapabilities().getThreadInfo().getMaxCpuId() != acid.getKernelCapabilities().getThreadInfo().getMaxCpuId()) - { - std::cout << "[WARNING] ACI/KC ThreadInfo/MaxCpuId: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMaxCpuId() << " not permitted)" << std::endl; - } - if (aci.getKernelCapabilities().getThreadInfo().getMinCpuId() != acid.getKernelCapabilities().getThreadInfo().getMinCpuId()) - { - std::cout << "[WARNING] ACI/KC ThreadInfo/MinCpuId: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMinCpuId() << " not permitted)" << std::endl; - } - if (aci.getKernelCapabilities().getThreadInfo().getMaxPriority() != acid.getKernelCapabilities().getThreadInfo().getMaxPriority()) - { - std::cout << "[WARNING] ACI/KC ThreadInfo/MaxPriority: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMaxPriority() << " not permitted)" << std::endl; - } - if (aci.getKernelCapabilities().getThreadInfo().getMinPriority() != acid.getKernelCapabilities().getThreadInfo().getMinPriority()) - { - std::cout << "[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMinPriority() << " not permitted)" << std::endl; - } - // check system calls - for (size_t i = 0; i < aci.getKernelCapabilities().getSystemCalls().getSystemCalls().size(); i++) - { - bool rightFound = false; - for (size_t j = 0; j < acid.getKernelCapabilities().getSystemCalls().getSystemCalls().size() && rightFound == false; j++) - { - if (aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i] == acid.getKernelCapabilities().getSystemCalls().getSystemCalls()[j]) - rightFound = true; - } - - if (rightFound == false) - { - std::cout << "[WARNING] ACI/KC SystemCallList: FAIL (" << getSystemCallStr(aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i]) << " not permitted)" << std::endl; - } - } - // check memory maps - for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps().size(); i++) - { - bool rightFound = false; - for (size_t j = 0; j < acid.getKernelCapabilities().getMemoryMaps().getMemoryMaps().size() && rightFound == false; j++) - { - if (aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i] == acid.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[j]) - rightFound = true; - } - - if (rightFound == false) - { - const nn::hac::MemoryMappingHandler::sMemoryMapping& map = aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i]; - - std::cout << "[WARNING] ACI/KC MemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << getMemMapPermStr(map.perm) << ") (type=" << getMemMapTypeStr(map.type) << ") not permitted)" << std::endl; - } - } - for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size(); i++) - { - bool rightFound = false; - for (size_t j = 0; j < acid.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size() && rightFound == false; j++) - { - if (aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i] == acid.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[j]) - rightFound = true; - } - - if (rightFound == false) - { - const nn::hac::MemoryMappingHandler::sMemoryMapping& map = aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i]; - - std::cout << "[WARNING] ACI/KC IoMemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << getMemMapPermStr(map.perm) << ") (type=" << getMemMapTypeStr(map.type) << ") not permitted)" << std::endl; - } - } - // check interupts - for (size_t i = 0; i < aci.getKernelCapabilities().getInterupts().getInteruptList().size(); i++) - { - bool rightFound = false; - for (size_t j = 0; j < acid.getKernelCapabilities().getInterupts().getInteruptList().size() && rightFound == false; j++) - { - if (aci.getKernelCapabilities().getInterupts().getInteruptList()[i] == acid.getKernelCapabilities().getInterupts().getInteruptList()[j]) - rightFound = true; - } - - if (rightFound == false) - { - std::cout << "[WARNING] ACI/KC InteruptsList: FAIL (0x" << std::hex << (uint32_t)aci.getKernelCapabilities().getInterupts().getInteruptList()[i] << " not permitted)" << std::endl; - } - } - // check misc params - if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType()) - { - std::cout << "[WARNING] ACI/KC ProgramType: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getMiscParams().getProgramType() << " not permitted)" << std::endl; - } - // check kernel version - uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor(); - uint32_t acidKernelVersion = (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMinor(); - if (aciKernelVersion < acidKernelVersion) - { - std::cout << "[WARNING] ACI/KC RequiredKernelVersion: FAIL (" << std::dec << aci.getKernelCapabilities().getKernelVersion().getVerMajor() << "." << aci.getKernelCapabilities().getKernelVersion().getVerMinor() << " not permitted)" << std::endl; - } - // check handle table size - if (aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() > acid.getKernelCapabilities().getHandleTableSize().getHandleTableSize()) - { - std::cout << "[WARNING] ACI/KC HandleTableSize: FAIL (0x" << std::hex << (uint32_t)aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() << " too large)" << std::endl; - } - // check misc flags - for (size_t i = 0; i < aci.getKernelCapabilities().getMiscFlags().getFlagList().size(); i++) - { - bool rightFound = false; - for (size_t j = 0; j < acid.getKernelCapabilities().getMiscFlags().getFlagList().size() && rightFound == false; j++) - { - if (aci.getKernelCapabilities().getMiscFlags().getFlagList()[i] == acid.getKernelCapabilities().getMiscFlags().getFlagList()[j]) - rightFound = true; - } - - if (rightFound == false) - { - std::cout << "[WARNING] ACI/KC MiscFlag: FAIL (" << getMiscFlagStr(aci.getKernelCapabilities().getMiscFlags().getFlagList()[i]) << " not permitted)" << std::endl; - } - } -} - -void MetaProcess::displayMetaHeader(const nn::hac::MetaBinary& hdr) -{ - std::cout << "[Meta Header]" << std::endl; - std::cout << " Process Architecture Params:" << std::endl; - std::cout << " Ins. Type: " << getInstructionTypeStr(hdr.getInstructionType()) << std::endl; - std::cout << " Addr Space: " << getProcAddressSpaceTypeStr(hdr.getProcAddressSpaceType()) << std::endl; - std::cout << " Main Thread Params:" << std::endl; - std::cout << " Priority: " << std::dec << (uint32_t)hdr.getMainThreadPriority() << std::endl; - std::cout << " CpuId: " << std::dec << (uint32_t)hdr.getMainThreadCpuId() << std::endl; - std::cout << " StackSize: 0x" << std::hex << hdr.getMainThreadStackSize() << std::endl; - std::cout << " TitleInfo:" << std::endl; - std::cout << " Version: v" << std::dec << hdr.getVersion() << std::endl; - std::cout << " Name: " << hdr.getName() << std::endl; - if (hdr.getProductCode().length()) - { - std::cout << " ProductCode: " << hdr.getProductCode() << std::endl; - } -} - -void MetaProcess::displayAciHdr(const nn::hac::AccessControlInfoBinary& aci) -{ - std::cout << "[Access Control Info]" << std::endl; - std::cout << " ProgramID: 0x" << std::hex << std::setw(16) << std::setfill('0') << aci.getProgramId() << std::endl; -} - -void MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDescBinary& acid) -{ - std::cout << "[Access Control Info Desc]" << std::endl; - if (acid.getFlagList().size() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " Flags: " << std::endl; - for (size_t i = 0; i < acid.getFlagList().size(); i++) - { - std::cout << " " << getAcidFlagStr(acid.getFlagList()[i]) << " (" << std::dec << (uint32_t)acid.getFlagList()[i] << ")" << std::endl; - } - } - std::cout << " ProgramID Restriction" << std::endl; - std::cout << " Min: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().min << std::endl; - std::cout << " Max: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().max << std::endl; -} - -void MetaProcess::displayFac(const nn::hac::FileSystemAccessControlBinary& fac) -{ - std::cout << "[FS Access Control]" << std::endl; - std::cout << " Format Version: " << std::dec << (uint32_t)fac.getFormatVersion() << std::endl; - - if (fac.getFsaRightsList().size()) - { - std::cout << " FS Rights:" << std::endl; - for (size_t i = 0; i < fac.getFsaRightsList().size(); i++) - { - if (i % 10 == 0) - { - if (i != 0) - std::cout << std::endl; - std::cout << " "; - } - std::cout << getFsaRightStr(fac.getFsaRightsList()[i]); - if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - std::cout << " (bit " << std::dec << (uint32_t)fac.getFsaRightsList()[i] << ")"; - if (fac.getFsaRightsList()[i] != fac.getFsaRightsList().atBack()) - std::cout << ", "; - std::cout << std::endl; - } - } - - if (fac.getContentOwnerIdList().size()) - { - std::cout << " Content Owner IDs:" << std::endl; - for (size_t i = 0; i < fac.getContentOwnerIdList().size(); i++) - { - std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << fac.getContentOwnerIdList()[i] << std::endl; - } - } - - if (fac.getSaveDataOwnerIdList().size()) - { - std::cout << " Save Data Owner IDs:" << std::endl; - for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++) - { - std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << fac.getSaveDataOwnerIdList()[i].id << " (" << getSaveDataOwnerAccessModeStr(fac.getSaveDataOwnerIdList()[i].access_type) << ")" << std::endl; - } - } - -} - -void MetaProcess::displaySac(const nn::hac::ServiceAccessControlBinary& sac) -{ - std::cout << "[Service Access Control]" << std::endl; - std::cout << " Service List:" << std::endl; - for (size_t i = 0; i < sac.getServiceList().size(); i++) - { - if (i % 10 == 0) - { - if (i != 0) - std::cout << std::endl; - std::cout << " "; - } - std::cout << sac.getServiceList()[i].getName(); - if (sac.getServiceList()[i].isServer()) - std::cout << "(isSrv)"; - if (sac.getServiceList()[i] != sac.getServiceList().atBack()) - std::cout << ", "; - } - std::cout << std::endl; -} - -void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityBinary& kern) -{ - std::cout << "[Kernel Capabilities]" << std::endl; - if (kern.getThreadInfo().isSet()) - { - nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo(); - std::cout << " Thread Priority:" << std::endl; - std::cout << " Min: " << std::dec << (uint32_t)threadInfo.getMinPriority() << std::endl; - std::cout << " Max: " << std::dec << (uint32_t)threadInfo.getMaxPriority() << std::endl; - std::cout << " CpuId:" << std::endl; - std::cout << " Min: " << std::dec << (uint32_t)threadInfo.getMinCpuId() << std::endl; - std::cout << " Max: " << std::dec << (uint32_t)threadInfo.getMaxCpuId() << std::endl; - } - - if (kern.getSystemCalls().isSet()) - { - fnd::List syscalls = kern.getSystemCalls().getSystemCalls(); - std::cout << " SystemCalls:" << std::endl; - std::cout << " "; - size_t lineLen = 0; - for (size_t i = 0; i < syscalls.size(); i++) - { - if (lineLen > 60) - { - lineLen = 0; - std::cout << std::endl; - std::cout << " "; - } - std::cout << getSystemCallStr(syscalls[i]); - if (syscalls[i] != syscalls.atBack()) - std::cout << ", "; - lineLen += strlen(getSystemCallStr(syscalls[i])); - } - std::cout << std::endl; - } - if (kern.getMemoryMaps().isSet()) - { - fnd::List maps = kern.getMemoryMaps().getMemoryMaps(); - fnd::List ioMaps = kern.getMemoryMaps().getIoMemoryMaps(); - - std::cout << " MemoryMaps:" << std::endl; - for (size_t i = 0; i < maps.size(); i++) - { - std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)maps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(maps[i].addr + maps[i].size) << 12) - 1) << " (perm=" << getMemMapPermStr(maps[i].perm) << ") (type=" << getMemMapTypeStr(maps[i].type) << ") not permitted)" << std::endl; - } - //std::cout << " IoMaps:" << std::endl; - for (size_t i = 0; i < ioMaps.size(); i++) - { - std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)ioMaps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(ioMaps[i].addr + ioMaps[i].size) << 12) - 1) << " (perm=" << getMemMapPermStr(ioMaps[i].perm) << ") (type=" << getMemMapTypeStr(ioMaps[i].type) << ") not permitted)" << std::endl; - } - } - if (kern.getInterupts().isSet()) - { - fnd::List interupts = kern.getInterupts().getInteruptList(); - std::cout << " Interupts Flags:" << std::endl; - for (uint32_t i = 0; i < interupts.size(); i++) - { - if (i % 10 == 0) - { - if (i != 0) - std::cout << std::endl; - std::cout << " "; - } - std::cout << "0x" << std::hex << (uint32_t)interupts[i]; - if (interupts[i] != interupts.atBack()) - std::cout << ", "; - std::cout << std::endl; - } - } - if (kern.getMiscParams().isSet()) - { - std::cout << " ProgramType: " << std::dec << (uint32_t)kern.getMiscParams().getProgramType() << std::endl; - } - if (kern.getKernelVersion().isSet()) - { - std::cout << " Kernel Version: " << std::dec << (uint32_t)kern.getKernelVersion().getVerMajor() << "." << (uint32_t)kern.getKernelVersion().getVerMinor() << std::endl; - } - if (kern.getHandleTableSize().isSet()) - { - std::cout << " Handle Table Size: 0x" << std::hex << kern.getHandleTableSize().getHandleTableSize() << std::endl; - } - if (kern.getMiscFlags().isSet()) - { - fnd::List flagList = kern.getMiscFlags().getFlagList(); - - std::cout << " Misc Flags:" << std::endl; - for (uint32_t i = 0; i < flagList.size(); i++) - { - if (i % 10 == 0) - { - if (i != 0) - std::cout << std::endl; - std::cout << " "; - } - std::cout << getMiscFlagStr(flagList[i]); - if (flagList[i] != flagList.atBack()) - std::cout << ", "; - std::cout << std::endl; - } - } -} - -const char* MetaProcess::getInstructionTypeStr(nn::hac::meta::InstructionType type) const -{ - const char* str = nullptr; - - switch(type) - { - case (nn::hac::meta::INSTR_32BIT): - str = "32Bit"; - break; - case (nn::hac::meta::INSTR_64BIT): - str = "64Bit"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* MetaProcess::getProcAddressSpaceTypeStr(nn::hac::meta::ProcAddrSpaceType type) const -{ - const char* str = nullptr; - - switch(type) - { - case (nn::hac::meta::ADDR_SPACE_64BIT): - str = "64Bit"; - break; - case (nn::hac::meta::ADDR_SPACE_32BIT): - str = "32Bit"; - break; - case (nn::hac::meta::ADDR_SPACE_32BIT_NO_RESERVED): - str = "32Bit no reserved"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* MetaProcess::getAcidFlagStr(nn::hac::aci::Flag flag) const -{ - const char* str = nullptr; - - switch(flag) - { - case (nn::hac::aci::FLAG_PRODUCTION): - str = "Production"; - break; - case (nn::hac::aci::FLAG_UNQUALIFIED_APPROVAL): - str = "UnqualifiedApproval"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* MetaProcess::getMiscFlagStr(nn::hac::MiscFlagsHandler::Flags flag) const -{ - const char* str = nullptr; - - switch(flag) - { - case (nn::hac::MiscFlagsHandler::FLAG_ENABLE_DEBUG): - str = "EnableDebug"; - break; - case (nn::hac::MiscFlagsHandler::FLAG_FORCE_DEBUG): - str = "ForceDebug"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* MetaProcess::getFsaRightStr(nn::hac::fac::FsAccessFlag flag) const -{ - const char* str = nullptr; - - switch(flag) - { - case (nn::hac::fac::FSA_APPLICATION_INFO): - str = "ApplicationInfo"; - break; - case (nn::hac::fac::FSA_BOOT_MODE_CONTROL): - str = "BootModeControl"; - break; - case (nn::hac::fac::FSA_CALIBRATION): - str = "Calibration"; - break; - case (nn::hac::fac::FSA_SYSTEM_SAVE_DATA): - str = "SystemSaveData"; - break; - case (nn::hac::fac::FSA_GAME_CARD): - str = "GameCard"; - break; - case (nn::hac::fac::FSA_SAVE_DATA_BACKUP): - str = "SaveDataBackUp"; - break; - case (nn::hac::fac::FSA_SAVE_DATA_MANAGEMENT): - str = "SaveDataManagement"; - break; - case (nn::hac::fac::FSA_BIS_ALL_RAW): - str = "BisAllRaw"; - break; - case (nn::hac::fac::FSA_GAME_CARD_RAW): - str = "GameCardRaw"; - break; - case (nn::hac::fac::FSA_GAME_CARD_PRIVATE): - str = "GameCardPrivate"; - break; - case (nn::hac::fac::FSA_SET_TIME): - str = "SetTime"; - break; - case (nn::hac::fac::FSA_CONTENT_MANAGER): - str = "ContentManager"; - break; - case (nn::hac::fac::FSA_IMAGE_MANAGER): - str = "ImageManager"; - break; - case (nn::hac::fac::FSA_CREATE_SAVE_DATA): - str = "CreateSaveData"; - break; - case (nn::hac::fac::FSA_SYSTEM_SAVE_DATA_MANAGEMENT): - str = "SystemSaveDataManagement"; - break; - case (nn::hac::fac::FSA_BIS_FILE_SYSTEM): - str = "BisFileSystem"; - break; - case (nn::hac::fac::FSA_SYSTEM_UPDATE): - str = "SystemUpdate"; - break; - case (nn::hac::fac::FSA_SAVE_DATA_META): - str = "SaveDataMeta"; - break; - case (nn::hac::fac::FSA_DEVICE_SAVE_CONTROL): - str = "DeviceSaveData"; - break; - case (nn::hac::fac::FSA_SETTINGS_CONTROL): - str = "SettingsControl"; - break; - case (nn::hac::fac::FSA_DEBUG): - str = "Debug"; - break; - case (nn::hac::fac::FSA_FULL_PERMISSION): - str = "FullPermission"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* MetaProcess::getSaveDataOwnerAccessModeStr(nn::hac::fac::SaveDataOwnerIdAccessType type) const -{ - const char* str = nullptr; - - switch(type) - { - case (nn::hac::fac::SDO_READ): - str = "Read"; - break; - case (nn::hac::fac::SDO_WRITE): - str = "Write"; - break; - case (nn::hac::fac::SDO_READWRITE): - str = "ReadWrite"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* MetaProcess::getSystemCallStr(byte_t syscall_id) const -{ - const char* str = nullptr; - - switch(syscall_id) - { - case (0x01): - str = "SetHeapSize"; - break; - case (0x02): - str = "SetMemoryPermission"; - break; - case (0x03): - str = "SetMemoryAttribute"; - break; - case (0x04): - str = "MapMemory"; - break; - case (0x05): - str = "UnmapMemory"; - break; - case (0x06): - str = "QueryMemory"; - break; - case (0x07): - str = "ExitProcess"; - break; - case (0x08): - str = "CreateThread"; - break; - case (0x09): - str = "StartThread"; - break; - case (0x0a): - str = "ExitThread"; - break; - case (0x0b): - str = "SleepThread"; - break; - case (0x0c): - str = "GetThreadPriority"; - break; - case (0x0d): - str = "SetThreadPriority"; - break; - case (0x0e): - str = "GetThreadCoreMask"; - break; - case (0x0f): - str = "SetThreadCoreMask"; - break; - case (0x10): - str = "GetCurrentProcessorNumber"; - break; - case (0x11): - str = "SignalEvent"; - break; - case (0x12): - str = "ClearEvent"; - break; - case (0x13): - str = "MapSharedMemory"; - break; - case (0x14): - str = "UnmapSharedMemory"; - break; - case (0x15): - str = "CreateTransferMemory"; - break; - case (0x16): - str = "CloseHandle"; - break; - case (0x17): - str = "ResetSignal"; - break; - case (0x18): - str = "WaitSynchronization"; - break; - case (0x19): - str = "CancelSynchronization"; - break; - case (0x1a): - str = "ArbitrateLock"; - break; - case (0x1b): - str = "ArbitrateUnlock"; - break; - case (0x1c): - str = "WaitProcessWideKeyAtomic"; - break; - case (0x1d): - str = "SignalProcessWideKey"; - break; - case (0x1e): - str = "GetSystemTick"; - break; - case (0x1f): - str = "ConnectToNamedPort"; - break; - case (0x20): - str = "SendSyncRequestLight"; - break; - case (0x21): - str = "SendSyncRequest"; - break; - case (0x22): - str = "SendSyncRequestWithUserBuffer"; - break; - case (0x23): - str = "SendAsyncRequestWithUserBuffer"; - break; - case (0x24): - str = "GetProcessId"; - break; - case (0x25): - str = "GetThreadId"; - break; - case (0x26): - str = "Break"; - break; - case (0x27): - str = "OutputDebugString"; - break; - case (0x28): - str = "ReturnFromException"; - break; - case (0x29): - str = "GetInfo"; - break; - case (0x2a): - str = "FlushEntireDataCache"; - break; - case (0x2b): - str = "FlushDataCache"; - break; - case (0x2c): - str = "MapPhysicalMemory"; - break; - case (0x2d): - str = "UnmapPhysicalMemory"; - break; - case (0x2e): - str = "GetFutureThreadInfo"; - break; - case (0x2f): - str = "GetLastThreadInfo"; - break; - case (0x30): - str = "GetResourceLimitLimitValue"; - break; - case (0x31): - str = "GetResourceLimitCurrentValue"; - break; - case (0x32): - str = "SetThreadActivity"; - break; - case (0x33): - str = "GetThreadContext3"; - break; - case (0x34): - str = "WaitForAddress"; - break; - case (0x35): - str = "SignalToAddress"; - break; - case (0x36): - str = "svc36"; - break; - case (0x37): - str = "svc37"; - break; - case (0x38): - str = "svc38"; - break; - case (0x39): - str = "svc39"; - break; - case (0x3a): - str = "svc3A"; - break; - case (0x3b): - str = "svc3B"; - break; - case (0x3c): - str = "DumpInfo"; - break; - case (0x3d): - str = "DumpInfoNew"; - break; - case (0x3e): - str = "svc3E"; - break; - case (0x3f): - str = "svc3F"; - break; - case (0x40): - str = "CreateSession"; - break; - case (0x41): - str = "AcceptSession"; - break; - case (0x42): - str = "ReplyAndReceiveLight"; - break; - case (0x43): - str = "ReplyAndReceive"; - break; - case (0x44): - str = "ReplyAndReceiveWithUserBuffer"; - break; - case (0x45): - str = "CreateEvent"; - break; - case (0x46): - str = "svc46"; - break; - case (0x47): - str = "svc47"; - break; - case (0x48): - str = "MapPhysicalMemoryUnsafe"; - break; - case (0x49): - str = "UnmapPhysicalMemoryUnsafe"; - break; - case (0x4a): - str = "SetUnsafeLimit"; - break; - case (0x4b): - str = "CreateCodeMemory"; - break; - case (0x4c): - str = "ControlCodeMemory"; - break; - case (0x4d): - str = "SleepSystem"; - break; - case (0x4e): - str = "ReadWriteRegister"; - break; - case (0x4f): - str = "SetProcessActivity"; - break; - case (0x50): - str = "CreateSharedMemory"; - break; - case (0x51): - str = "MapTransferMemory"; - break; - case (0x52): - str = "UnmapTransferMemory"; - break; - case (0x53): - str = "CreateInterruptEvent"; - break; - case (0x54): - str = "QueryPhysicalAddress"; - break; - case (0x55): - str = "QueryIoMapping"; - break; - case (0x56): - str = "CreateDeviceAddressSpace"; - break; - case (0x57): - str = "AttachDeviceAddressSpace"; - break; - case (0x58): - str = "DetachDeviceAddressSpace"; - break; - case (0x59): - str = "MapDeviceAddressSpaceByForce"; - break; - case (0x5a): - str = "MapDeviceAddressSpaceAligned"; - break; - case (0x5b): - str = "MapDeviceAddressSpace"; - break; - case (0x5c): - str = "UnmapDeviceAddressSpace"; - break; - case (0x5d): - str = "InvalidateProcessDataCache"; - break; - case (0x5e): - str = "StoreProcessDataCache"; - break; - case (0x5f): - str = "FlushProcessDataCache"; - break; - case (0x60): - str = "DebugActiveProcess"; - break; - case (0x61): - str = "BreakDebugProcess"; - break; - case (0x62): - str = "TerminateDebugProcess"; - break; - case (0x63): - str = "GetDebugEvent"; - break; - case (0x64): - str = "ContinueDebugEvent"; - break; - case (0x65): - str = "GetProcessList"; - break; - case (0x66): - str = "GetThreadList"; - break; - case (0x67): - str = "GetDebugThreadContext"; - break; - case (0x68): - str = "SetDebugThreadContext"; - break; - case (0x69): - str = "QueryDebugProcessMemory"; - break; - case (0x6a): - str = "ReadDebugProcessMemory"; - break; - case (0x6b): - str = "WriteDebugProcessMemory"; - break; - case (0x6c): - str = "SetHardwareBreakPoint"; - break; - case (0x6d): - str = "GetDebugThreadParam"; - break; - case (0x6e): - str = "svc6E"; - break; - case (0x6f): - str = "GetSystemInfo"; - break; - case (0x70): - str = "CreatePort"; - break; - case (0x71): - str = "ManageNamedPort"; - break; - case (0x72): - str = "ConnectToPort"; - break; - case (0x73): - str = "SetProcessMemoryPermission"; - break; - case (0x74): - str = "MapProcessMemory"; - break; - case (0x75): - str = "UnmapProcessMemory"; - break; - case (0x76): - str = "QueryProcessMemory"; - break; - case (0x77): - str = "MapProcessCodeMemory"; - break; - case (0x78): - str = "UnmapProcessCodeMemory"; - break; - case (0x79): - str = "CreateProcess"; - break; - case (0x7a): - str = "StartProcess"; - break; - case (0x7b): - str = "TerminateProcess"; - break; - case (0x7c): - str = "GetProcessInfo"; - break; - case (0x7d): - str = "CreateResourceLimit"; - break; - case (0x7e): - str = "SetResourceLimitLimitValue"; - break; - case (0x7f): - str = "CallSecureMonitor"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* MetaProcess::getMemMapPermStr(nn::hac::MemoryMappingHandler::MemoryPerm type) const -{ - const char* str = nullptr; - - switch(type) - { - case (nn::hac::MemoryMappingHandler::MEM_RW): - str = "RW"; - break; - case (nn::hac::MemoryMappingHandler::MEM_RO): - str = "RO"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* MetaProcess::getMemMapTypeStr(nn::hac::MemoryMappingHandler::MappingType type) const -{ - const char* str = nullptr; - - switch(type) - { - case (nn::hac::MemoryMappingHandler::MAP_IO): - str = "Io"; - break; - case (nn::hac::MemoryMappingHandler::MAP_STATIC): - str = "Static"; - break; - default: - str = "Unknown"; - break; - } - - return str; +#include +#include +#include "MetaProcess.h" + +MetaProcess::MetaProcess() : + mFile(), + mCliOutputMode(_BIT(OUTPUT_BASIC)), + mVerify(false) +{ +} + +void MetaProcess::process() +{ + importMeta(); + + if (mVerify) + { + validateAcidSignature(mMeta.getAcid()); + validateAciFromAcid(mMeta.getAci(), mMeta.getAcid()); + } + + if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) + { + // npdm binary + displayMetaHeader(mMeta); + + // aci binary + displayAciHdr(mMeta.getAci()); + displayFac(mMeta.getAci().getFileSystemAccessControl()); + displaySac(mMeta.getAci().getServiceAccessControl()); + displayKernelCap(mMeta.getAci().getKernelCapabilities()); + + // acid binary + if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + displayAciDescHdr(mMeta.getAcid()); + displayFac(mMeta.getAcid().getFileSystemAccessControl()); + displaySac(mMeta.getAcid().getServiceAccessControl()); + displayKernelCap(mMeta.getAcid().getKernelCapabilities()); + } + } +} + +void MetaProcess::setInputFile(const fnd::SharedPtr& file) +{ + mFile = file; +} + +void MetaProcess::setKeyCfg(const KeyConfiguration& keycfg) +{ + mKeyCfg = keycfg; +} + +void MetaProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void MetaProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +const nn::hac::Meta& MetaProcess::getMeta() const +{ + return mMeta; +} + +void MetaProcess::importMeta() +{ + fnd::Vec scratch; + + if (*mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + scratch.alloc((*mFile)->size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); + + mMeta.fromBytes(scratch.data(), scratch.size()); +} + +void MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid) +{ + try { + fnd::rsa::sRsa2048Key acid_sign_key; + if (mKeyCfg.getAcidSignKey(acid_sign_key) != true) + throw fnd::Exception(); + + acid.validateSignature(acid_sign_key); + } + catch (...) { + std::cout << "[WARNING] ACID Signature: FAIL" << std::endl; + } + +} + +void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, const nn::hac::AccessControlInfoDesc& acid) +{ + // check Program ID + if (acid.getProgramIdRestrict().min > 0 && aci.getProgramId() < acid.getProgramIdRestrict().min) + { + std::cout << "[WARNING] ACI ProgramId: FAIL (Outside Legal Range)" << std::endl; + } + else if (acid.getProgramIdRestrict().max > 0 && aci.getProgramId() > acid.getProgramIdRestrict().max) + { + std::cout << "[WARNING] ACI ProgramId: FAIL (Outside Legal Range)" << std::endl; + } + + for (size_t i = 0; i < aci.getFileSystemAccessControl().getFsaRightsList().size(); i++) + { + bool fsaRightFound = false; + for (size_t j = 0; j < acid.getFileSystemAccessControl().getFsaRightsList().size() && fsaRightFound == false; j++) + { + if (aci.getFileSystemAccessControl().getFsaRightsList()[i] == acid.getFileSystemAccessControl().getFsaRightsList()[j]) + fsaRightFound = true; + } + + if (fsaRightFound == false) + { + + std::cout << "[WARNING] ACI/FAC FsaRights: FAIL (" << getFsaRightStr(aci.getFileSystemAccessControl().getFsaRightsList()[i]) << " not permitted)" << std::endl; + } + } + + for (size_t i = 0; i < aci.getFileSystemAccessControl().getContentOwnerIdList().size(); i++) + { + bool rightFound = false; + for (size_t j = 0; j < acid.getFileSystemAccessControl().getContentOwnerIdList().size() && rightFound == false; j++) + { + if (aci.getFileSystemAccessControl().getContentOwnerIdList()[i] == acid.getFileSystemAccessControl().getContentOwnerIdList()[j]) + rightFound = true; + } + + if (rightFound == false) + { + + std::cout << "[WARNING] ACI/FAC ContentOwnerId: FAIL (" << std::hex << std::setw(16) << std::setfill('0') << aci.getFileSystemAccessControl().getContentOwnerIdList()[i] << " not permitted)" << std::endl; + } + } + + for (size_t i = 0; i < aci.getFileSystemAccessControl().getSaveDataOwnerIdList().size(); i++) + { + bool rightFound = false; + for (size_t j = 0; j < acid.getFileSystemAccessControl().getSaveDataOwnerIdList().size() && rightFound == false; j++) + { + if (aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i] == acid.getFileSystemAccessControl().getSaveDataOwnerIdList()[j]) + rightFound = true; + } + + if (rightFound == false) + { + + std::cout << "[WARNING] ACI/FAC SaveDataOwnerId: FAIL (" << std::hex << std::setw(16) << std::setfill('0') << aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id << "(" << std::dec << (uint32_t)aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type << ") not permitted)" << std::endl; + } + } + + // check SAC + for (size_t i = 0; i < aci.getServiceAccessControl().getServiceList().size(); i++) + { + bool rightFound = false; + for (size_t j = 0; j < acid.getServiceAccessControl().getServiceList().size() && rightFound == false; j++) + { + if (aci.getServiceAccessControl().getServiceList()[i] == acid.getServiceAccessControl().getServiceList()[j]) + rightFound = true; + } + + if (rightFound == false) + { + std::cout << "[WARNING] ACI/SAC ServiceList: FAIL (" << aci.getServiceAccessControl().getServiceList()[i].getName() << (aci.getServiceAccessControl().getServiceList()[i].isServer()? " (Server)" : "") << " not permitted)" << std::endl; + } + } + + // check KC + // check thread info + if (aci.getKernelCapabilities().getThreadInfo().getMaxCpuId() != acid.getKernelCapabilities().getThreadInfo().getMaxCpuId()) + { + std::cout << "[WARNING] ACI/KC ThreadInfo/MaxCpuId: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMaxCpuId() << " not permitted)" << std::endl; + } + if (aci.getKernelCapabilities().getThreadInfo().getMinCpuId() != acid.getKernelCapabilities().getThreadInfo().getMinCpuId()) + { + std::cout << "[WARNING] ACI/KC ThreadInfo/MinCpuId: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMinCpuId() << " not permitted)" << std::endl; + } + if (aci.getKernelCapabilities().getThreadInfo().getMaxPriority() != acid.getKernelCapabilities().getThreadInfo().getMaxPriority()) + { + std::cout << "[WARNING] ACI/KC ThreadInfo/MaxPriority: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMaxPriority() << " not permitted)" << std::endl; + } + if (aci.getKernelCapabilities().getThreadInfo().getMinPriority() != acid.getKernelCapabilities().getThreadInfo().getMinPriority()) + { + std::cout << "[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMinPriority() << " not permitted)" << std::endl; + } + // check system calls + for (size_t i = 0; i < aci.getKernelCapabilities().getSystemCalls().getSystemCalls().size(); i++) + { + bool rightFound = false; + for (size_t j = 0; j < acid.getKernelCapabilities().getSystemCalls().getSystemCalls().size() && rightFound == false; j++) + { + if (aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i] == acid.getKernelCapabilities().getSystemCalls().getSystemCalls()[j]) + rightFound = true; + } + + if (rightFound == false) + { + std::cout << "[WARNING] ACI/KC SystemCallList: FAIL (" << getSystemCallStr(aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i]) << " not permitted)" << std::endl; + } + } + // check memory maps + for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps().size(); i++) + { + bool rightFound = false; + for (size_t j = 0; j < acid.getKernelCapabilities().getMemoryMaps().getMemoryMaps().size() && rightFound == false; j++) + { + if (aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i] == acid.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[j]) + rightFound = true; + } + + if (rightFound == false) + { + const nn::hac::MemoryMappingHandler::sMemoryMapping& map = aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i]; + + std::cout << "[WARNING] ACI/KC MemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << getMemMapPermStr(map.perm) << ") (type=" << getMemMapTypeStr(map.type) << ") not permitted)" << std::endl; + } + } + for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size(); i++) + { + bool rightFound = false; + for (size_t j = 0; j < acid.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size() && rightFound == false; j++) + { + if (aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i] == acid.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[j]) + rightFound = true; + } + + if (rightFound == false) + { + const nn::hac::MemoryMappingHandler::sMemoryMapping& map = aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i]; + + std::cout << "[WARNING] ACI/KC IoMemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << getMemMapPermStr(map.perm) << ") (type=" << getMemMapTypeStr(map.type) << ") not permitted)" << std::endl; + } + } + // check interupts + for (size_t i = 0; i < aci.getKernelCapabilities().getInterupts().getInteruptList().size(); i++) + { + bool rightFound = false; + for (size_t j = 0; j < acid.getKernelCapabilities().getInterupts().getInteruptList().size() && rightFound == false; j++) + { + if (aci.getKernelCapabilities().getInterupts().getInteruptList()[i] == acid.getKernelCapabilities().getInterupts().getInteruptList()[j]) + rightFound = true; + } + + if (rightFound == false) + { + std::cout << "[WARNING] ACI/KC InteruptsList: FAIL (0x" << std::hex << (uint32_t)aci.getKernelCapabilities().getInterupts().getInteruptList()[i] << " not permitted)" << std::endl; + } + } + // check misc params + if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType()) + { + std::cout << "[WARNING] ACI/KC ProgramType: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getMiscParams().getProgramType() << " not permitted)" << std::endl; + } + // check kernel version + uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor(); + uint32_t acidKernelVersion = (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)acid.getKernelCapabilities().getKernelVersion().getVerMinor(); + if (aciKernelVersion < acidKernelVersion) + { + std::cout << "[WARNING] ACI/KC RequiredKernelVersion: FAIL (" << std::dec << aci.getKernelCapabilities().getKernelVersion().getVerMajor() << "." << aci.getKernelCapabilities().getKernelVersion().getVerMinor() << " not permitted)" << std::endl; + } + // check handle table size + if (aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() > acid.getKernelCapabilities().getHandleTableSize().getHandleTableSize()) + { + std::cout << "[WARNING] ACI/KC HandleTableSize: FAIL (0x" << std::hex << (uint32_t)aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() << " too large)" << std::endl; + } + // check misc flags + for (size_t i = 0; i < aci.getKernelCapabilities().getMiscFlags().getFlagList().size(); i++) + { + bool rightFound = false; + for (size_t j = 0; j < acid.getKernelCapabilities().getMiscFlags().getFlagList().size() && rightFound == false; j++) + { + if (aci.getKernelCapabilities().getMiscFlags().getFlagList()[i] == acid.getKernelCapabilities().getMiscFlags().getFlagList()[j]) + rightFound = true; + } + + if (rightFound == false) + { + std::cout << "[WARNING] ACI/KC MiscFlag: FAIL (" << getMiscFlagStr(aci.getKernelCapabilities().getMiscFlags().getFlagList()[i]) << " not permitted)" << std::endl; + } + } +} + +void MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr) +{ + std::cout << "[Meta Header]" << std::endl; + std::cout << " Process Architecture Params:" << std::endl; + std::cout << " Ins. Type: " << getInstructionTypeStr(hdr.getInstructionType()) << std::endl; + std::cout << " Addr Space: " << getProcAddressSpaceTypeStr(hdr.getProcAddressSpaceType()) << std::endl; + std::cout << " Main Thread Params:" << std::endl; + std::cout << " Priority: " << std::dec << (uint32_t)hdr.getMainThreadPriority() << std::endl; + std::cout << " CpuId: " << std::dec << (uint32_t)hdr.getMainThreadCpuId() << std::endl; + std::cout << " StackSize: 0x" << std::hex << hdr.getMainThreadStackSize() << std::endl; + std::cout << " TitleInfo:" << std::endl; + std::cout << " Version: v" << std::dec << hdr.getVersion() << std::endl; + std::cout << " Name: " << hdr.getName() << std::endl; + if (hdr.getProductCode().length()) + { + std::cout << " ProductCode: " << hdr.getProductCode() << std::endl; + } +} + +void MetaProcess::displayAciHdr(const nn::hac::AccessControlInfo& aci) +{ + std::cout << "[Access Control Info]" << std::endl; + std::cout << " ProgramID: 0x" << std::hex << std::setw(16) << std::setfill('0') << aci.getProgramId() << std::endl; +} + +void MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc& acid) +{ + std::cout << "[Access Control Info Desc]" << std::endl; + if (acid.getFlagList().size() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " Flags: " << std::endl; + for (size_t i = 0; i < acid.getFlagList().size(); i++) + { + std::cout << " " << getAcidFlagStr(acid.getFlagList()[i]) << " (" << std::dec << (uint32_t)acid.getFlagList()[i] << ")" << std::endl; + } + } + std::cout << " ProgramID Restriction" << std::endl; + std::cout << " Min: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().min << std::endl; + std::cout << " Max: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().max << std::endl; +} + +void MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac) +{ + std::cout << "[FS Access Control]" << std::endl; + std::cout << " Format Version: " << std::dec << (uint32_t)fac.getFormatVersion() << std::endl; + + if (fac.getFsaRightsList().size()) + { + std::cout << " FS Rights:" << std::endl; + for (size_t i = 0; i < fac.getFsaRightsList().size(); i++) + { + if (i % 10 == 0) + { + if (i != 0) + std::cout << std::endl; + std::cout << " "; + } + std::cout << getFsaRightStr(fac.getFsaRightsList()[i]); + if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + std::cout << " (bit " << std::dec << (uint32_t)fac.getFsaRightsList()[i] << ")"; + if (fac.getFsaRightsList()[i] != fac.getFsaRightsList().atBack()) + std::cout << ", "; + } + std::cout << std::endl; + } + + if (fac.getContentOwnerIdList().size()) + { + std::cout << " Content Owner IDs:" << std::endl; + for (size_t i = 0; i < fac.getContentOwnerIdList().size(); i++) + { + std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << fac.getContentOwnerIdList()[i] << std::endl; + } + } + + if (fac.getSaveDataOwnerIdList().size()) + { + std::cout << " Save Data Owner IDs:" << std::endl; + for (size_t i = 0; i < fac.getSaveDataOwnerIdList().size(); i++) + { + std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << fac.getSaveDataOwnerIdList()[i].id << " (" << getSaveDataOwnerAccessModeStr(fac.getSaveDataOwnerIdList()[i].access_type) << ")" << std::endl; + } + } + +} + +void MetaProcess::displaySac(const nn::hac::ServiceAccessControl& sac) +{ + std::cout << "[Service Access Control]" << std::endl; + std::cout << " Service List:" << std::endl; + for (size_t i = 0; i < sac.getServiceList().size(); i++) + { + if (i % 10 == 0) + { + if (i != 0) + std::cout << std::endl; + std::cout << " "; + } + std::cout << sac.getServiceList()[i].getName(); + if (sac.getServiceList()[i].isServer()) + std::cout << "(isSrv)"; + if (sac.getServiceList()[i] != sac.getServiceList().atBack()) + std::cout << ", "; + } + std::cout << std::endl; +} + +void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) +{ + std::cout << "[Kernel Capabilities]" << std::endl; + if (kern.getThreadInfo().isSet()) + { + nn::hac::ThreadInfoHandler threadInfo = kern.getThreadInfo(); + std::cout << " Thread Priority:" << std::endl; + std::cout << " Min: " << std::dec << (uint32_t)threadInfo.getMinPriority() << std::endl; + std::cout << " Max: " << std::dec << (uint32_t)threadInfo.getMaxPriority() << std::endl; + std::cout << " CpuId:" << std::endl; + std::cout << " Min: " << std::dec << (uint32_t)threadInfo.getMinCpuId() << std::endl; + std::cout << " Max: " << std::dec << (uint32_t)threadInfo.getMaxCpuId() << std::endl; + } + + if (kern.getSystemCalls().isSet()) + { + fnd::List syscalls = kern.getSystemCalls().getSystemCalls(); + std::cout << " SystemCalls:" << std::endl; + std::cout << " "; + size_t lineLen = 0; + for (size_t i = 0; i < syscalls.size(); i++) + { + if (lineLen > 60) + { + lineLen = 0; + std::cout << std::endl; + std::cout << " "; + } + std::cout << getSystemCallStr(syscalls[i]); + if (syscalls[i] != syscalls.atBack()) + std::cout << ", "; + lineLen += strlen(getSystemCallStr(syscalls[i])); + } + std::cout << std::endl; + } + if (kern.getMemoryMaps().isSet()) + { + fnd::List maps = kern.getMemoryMaps().getMemoryMaps(); + fnd::List ioMaps = kern.getMemoryMaps().getIoMemoryMaps(); + + std::cout << " MemoryMaps:" << std::endl; + for (size_t i = 0; i < maps.size(); i++) + { + std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)maps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(maps[i].addr + maps[i].size) << 12) - 1) << " (perm=" << getMemMapPermStr(maps[i].perm) << ") (type=" << getMemMapTypeStr(maps[i].type) << ")" << std::endl; + } + //std::cout << " IoMaps:" << std::endl; + for (size_t i = 0; i < ioMaps.size(); i++) + { + std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)ioMaps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(ioMaps[i].addr + ioMaps[i].size) << 12) - 1) << " (perm=" << getMemMapPermStr(ioMaps[i].perm) << ") (type=" << getMemMapTypeStr(ioMaps[i].type) << ")" << std::endl; + } + } + if (kern.getInterupts().isSet()) + { + fnd::List interupts = kern.getInterupts().getInteruptList(); + std::cout << " Interupts Flags:" << std::endl; + for (uint32_t i = 0; i < interupts.size(); i++) + { + if (i % 10 == 0) + { + if (i != 0) + std::cout << std::endl; + std::cout << " "; + } + std::cout << "0x" << std::hex << (uint32_t)interupts[i]; + if (interupts[i] != interupts.atBack()) + std::cout << ", "; + std::cout << std::endl; + } + } + if (kern.getMiscParams().isSet()) + { + std::cout << " ProgramType: " << std::dec << (uint32_t)kern.getMiscParams().getProgramType() << std::endl; + } + if (kern.getKernelVersion().isSet()) + { + std::cout << " Kernel Version: " << std::dec << (uint32_t)kern.getKernelVersion().getVerMajor() << "." << (uint32_t)kern.getKernelVersion().getVerMinor() << std::endl; + } + if (kern.getHandleTableSize().isSet()) + { + std::cout << " Handle Table Size: 0x" << std::hex << kern.getHandleTableSize().getHandleTableSize() << std::endl; + } + if (kern.getMiscFlags().isSet()) + { + fnd::List flagList = kern.getMiscFlags().getFlagList(); + + std::cout << " Misc Flags:" << std::endl; + for (uint32_t i = 0; i < flagList.size(); i++) + { + if (i % 10 == 0) + { + if (i != 0) + std::cout << std::endl; + std::cout << " "; + } + std::cout << getMiscFlagStr(flagList[i]); + if (flagList[i] != flagList.atBack()) + std::cout << ", "; + std::cout << std::endl; + } + } +} + +const char* MetaProcess::getInstructionTypeStr(nn::hac::meta::InstructionType type) const +{ + const char* str = nullptr; + + switch(type) + { + case (nn::hac::meta::INSTR_32BIT): + str = "32Bit"; + break; + case (nn::hac::meta::INSTR_64BIT): + str = "64Bit"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* MetaProcess::getProcAddressSpaceTypeStr(nn::hac::meta::ProcAddrSpaceType type) const +{ + const char* str = nullptr; + + switch(type) + { + case (nn::hac::meta::ADDR_SPACE_64BIT): + str = "64Bit"; + break; + case (nn::hac::meta::ADDR_SPACE_32BIT): + str = "32Bit"; + break; + case (nn::hac::meta::ADDR_SPACE_32BIT_NO_RESERVED): + str = "32Bit no reserved"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* MetaProcess::getAcidFlagStr(nn::hac::aci::Flag flag) const +{ + const char* str = nullptr; + + switch(flag) + { + case (nn::hac::aci::FLAG_PRODUCTION): + str = "Production"; + break; + case (nn::hac::aci::FLAG_UNQUALIFIED_APPROVAL): + str = "UnqualifiedApproval"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* MetaProcess::getMiscFlagStr(nn::hac::MiscFlagsHandler::Flags flag) const +{ + const char* str = nullptr; + + switch(flag) + { + case (nn::hac::MiscFlagsHandler::FLAG_ENABLE_DEBUG): + str = "EnableDebug"; + break; + case (nn::hac::MiscFlagsHandler::FLAG_FORCE_DEBUG): + str = "ForceDebug"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* MetaProcess::getFsaRightStr(nn::hac::fac::FsAccessFlag flag) const +{ + const char* str = nullptr; + + switch(flag) + { + case (nn::hac::fac::FSA_APPLICATION_INFO): + str = "ApplicationInfo"; + break; + case (nn::hac::fac::FSA_BOOT_MODE_CONTROL): + str = "BootModeControl"; + break; + case (nn::hac::fac::FSA_CALIBRATION): + str = "Calibration"; + break; + case (nn::hac::fac::FSA_SYSTEM_SAVE_DATA): + str = "SystemSaveData"; + break; + case (nn::hac::fac::FSA_GAME_CARD): + str = "GameCard"; + break; + case (nn::hac::fac::FSA_SAVE_DATA_BACKUP): + str = "SaveDataBackUp"; + break; + case (nn::hac::fac::FSA_SAVE_DATA_MANAGEMENT): + str = "SaveDataManagement"; + break; + case (nn::hac::fac::FSA_BIS_ALL_RAW): + str = "BisAllRaw"; + break; + case (nn::hac::fac::FSA_GAME_CARD_RAW): + str = "GameCardRaw"; + break; + case (nn::hac::fac::FSA_GAME_CARD_PRIVATE): + str = "GameCardPrivate"; + break; + case (nn::hac::fac::FSA_SET_TIME): + str = "SetTime"; + break; + case (nn::hac::fac::FSA_CONTENT_MANAGER): + str = "ContentManager"; + break; + case (nn::hac::fac::FSA_IMAGE_MANAGER): + str = "ImageManager"; + break; + case (nn::hac::fac::FSA_CREATE_SAVE_DATA): + str = "CreateSaveData"; + break; + case (nn::hac::fac::FSA_SYSTEM_SAVE_DATA_MANAGEMENT): + str = "SystemSaveDataManagement"; + break; + case (nn::hac::fac::FSA_BIS_FILE_SYSTEM): + str = "BisFileSystem"; + break; + case (nn::hac::fac::FSA_SYSTEM_UPDATE): + str = "SystemUpdate"; + break; + case (nn::hac::fac::FSA_SAVE_DATA_META): + str = "SaveDataMeta"; + break; + case (nn::hac::fac::FSA_DEVICE_SAVE_CONTROL): + str = "DeviceSaveData"; + break; + case (nn::hac::fac::FSA_SETTINGS_CONTROL): + str = "SettingsControl"; + break; + case (nn::hac::fac::FSA_DEBUG): + str = "Debug"; + break; + case (nn::hac::fac::FSA_FULL_PERMISSION): + str = "FullPermission"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* MetaProcess::getSaveDataOwnerAccessModeStr(nn::hac::fac::SaveDataOwnerIdAccessType type) const +{ + const char* str = nullptr; + + switch(type) + { + case (nn::hac::fac::SDO_READ): + str = "Read"; + break; + case (nn::hac::fac::SDO_WRITE): + str = "Write"; + break; + case (nn::hac::fac::SDO_READWRITE): + str = "ReadWrite"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* MetaProcess::getSystemCallStr(byte_t syscall_id) const +{ + const char* str = nullptr; + + switch(syscall_id) + { + case (0x01): + str = "SetHeapSize"; + break; + case (0x02): + str = "SetMemoryPermission"; + break; + case (0x03): + str = "SetMemoryAttribute"; + break; + case (0x04): + str = "MapMemory"; + break; + case (0x05): + str = "UnmapMemory"; + break; + case (0x06): + str = "QueryMemory"; + break; + case (0x07): + str = "ExitProcess"; + break; + case (0x08): + str = "CreateThread"; + break; + case (0x09): + str = "StartThread"; + break; + case (0x0a): + str = "ExitThread"; + break; + case (0x0b): + str = "SleepThread"; + break; + case (0x0c): + str = "GetThreadPriority"; + break; + case (0x0d): + str = "SetThreadPriority"; + break; + case (0x0e): + str = "GetThreadCoreMask"; + break; + case (0x0f): + str = "SetThreadCoreMask"; + break; + case (0x10): + str = "GetCurrentProcessorNumber"; + break; + case (0x11): + str = "SignalEvent"; + break; + case (0x12): + str = "ClearEvent"; + break; + case (0x13): + str = "MapSharedMemory"; + break; + case (0x14): + str = "UnmapSharedMemory"; + break; + case (0x15): + str = "CreateTransferMemory"; + break; + case (0x16): + str = "CloseHandle"; + break; + case (0x17): + str = "ResetSignal"; + break; + case (0x18): + str = "WaitSynchronization"; + break; + case (0x19): + str = "CancelSynchronization"; + break; + case (0x1a): + str = "ArbitrateLock"; + break; + case (0x1b): + str = "ArbitrateUnlock"; + break; + case (0x1c): + str = "WaitProcessWideKeyAtomic"; + break; + case (0x1d): + str = "SignalProcessWideKey"; + break; + case (0x1e): + str = "GetSystemTick"; + break; + case (0x1f): + str = "ConnectToNamedPort"; + break; + case (0x20): + str = "SendSyncRequestLight"; + break; + case (0x21): + str = "SendSyncRequest"; + break; + case (0x22): + str = "SendSyncRequestWithUserBuffer"; + break; + case (0x23): + str = "SendAsyncRequestWithUserBuffer"; + break; + case (0x24): + str = "GetProcessId"; + break; + case (0x25): + str = "GetThreadId"; + break; + case (0x26): + str = "Break"; + break; + case (0x27): + str = "OutputDebugString"; + break; + case (0x28): + str = "ReturnFromException"; + break; + case (0x29): + str = "GetInfo"; + break; + case (0x2a): + str = "FlushEntireDataCache"; + break; + case (0x2b): + str = "FlushDataCache"; + break; + case (0x2c): + str = "MapPhysicalMemory"; + break; + case (0x2d): + str = "UnmapPhysicalMemory"; + break; + case (0x2e): + str = "GetFutureThreadInfo"; + break; + case (0x2f): + str = "GetLastThreadInfo"; + break; + case (0x30): + str = "GetResourceLimitLimitValue"; + break; + case (0x31): + str = "GetResourceLimitCurrentValue"; + break; + case (0x32): + str = "SetThreadActivity"; + break; + case (0x33): + str = "GetThreadContext3"; + break; + case (0x34): + str = "WaitForAddress"; + break; + case (0x35): + str = "SignalToAddress"; + break; + case (0x36): + str = "svc36"; + break; + case (0x37): + str = "svc37"; + break; + case (0x38): + str = "svc38"; + break; + case (0x39): + str = "svc39"; + break; + case (0x3a): + str = "svc3A"; + break; + case (0x3b): + str = "svc3B"; + break; + case (0x3c): + str = "DumpInfo"; + break; + case (0x3d): + str = "DumpInfoNew"; + break; + case (0x3e): + str = "svc3E"; + break; + case (0x3f): + str = "svc3F"; + break; + case (0x40): + str = "CreateSession"; + break; + case (0x41): + str = "AcceptSession"; + break; + case (0x42): + str = "ReplyAndReceiveLight"; + break; + case (0x43): + str = "ReplyAndReceive"; + break; + case (0x44): + str = "ReplyAndReceiveWithUserBuffer"; + break; + case (0x45): + str = "CreateEvent"; + break; + case (0x46): + str = "svc46"; + break; + case (0x47): + str = "svc47"; + break; + case (0x48): + str = "MapPhysicalMemoryUnsafe"; + break; + case (0x49): + str = "UnmapPhysicalMemoryUnsafe"; + break; + case (0x4a): + str = "SetUnsafeLimit"; + break; + case (0x4b): + str = "CreateCodeMemory"; + break; + case (0x4c): + str = "ControlCodeMemory"; + break; + case (0x4d): + str = "SleepSystem"; + break; + case (0x4e): + str = "ReadWriteRegister"; + break; + case (0x4f): + str = "SetProcessActivity"; + break; + case (0x50): + str = "CreateSharedMemory"; + break; + case (0x51): + str = "MapTransferMemory"; + break; + case (0x52): + str = "UnmapTransferMemory"; + break; + case (0x53): + str = "CreateInterruptEvent"; + break; + case (0x54): + str = "QueryPhysicalAddress"; + break; + case (0x55): + str = "QueryIoMapping"; + break; + case (0x56): + str = "CreateDeviceAddressSpace"; + break; + case (0x57): + str = "AttachDeviceAddressSpace"; + break; + case (0x58): + str = "DetachDeviceAddressSpace"; + break; + case (0x59): + str = "MapDeviceAddressSpaceByForce"; + break; + case (0x5a): + str = "MapDeviceAddressSpaceAligned"; + break; + case (0x5b): + str = "MapDeviceAddressSpace"; + break; + case (0x5c): + str = "UnmapDeviceAddressSpace"; + break; + case (0x5d): + str = "InvalidateProcessDataCache"; + break; + case (0x5e): + str = "StoreProcessDataCache"; + break; + case (0x5f): + str = "FlushProcessDataCache"; + break; + case (0x60): + str = "DebugActiveProcess"; + break; + case (0x61): + str = "BreakDebugProcess"; + break; + case (0x62): + str = "TerminateDebugProcess"; + break; + case (0x63): + str = "GetDebugEvent"; + break; + case (0x64): + str = "ContinueDebugEvent"; + break; + case (0x65): + str = "GetProcessList"; + break; + case (0x66): + str = "GetThreadList"; + break; + case (0x67): + str = "GetDebugThreadContext"; + break; + case (0x68): + str = "SetDebugThreadContext"; + break; + case (0x69): + str = "QueryDebugProcessMemory"; + break; + case (0x6a): + str = "ReadDebugProcessMemory"; + break; + case (0x6b): + str = "WriteDebugProcessMemory"; + break; + case (0x6c): + str = "SetHardwareBreakPoint"; + break; + case (0x6d): + str = "GetDebugThreadParam"; + break; + case (0x6e): + str = "svc6E"; + break; + case (0x6f): + str = "GetSystemInfo"; + break; + case (0x70): + str = "CreatePort"; + break; + case (0x71): + str = "ManageNamedPort"; + break; + case (0x72): + str = "ConnectToPort"; + break; + case (0x73): + str = "SetProcessMemoryPermission"; + break; + case (0x74): + str = "MapProcessMemory"; + break; + case (0x75): + str = "UnmapProcessMemory"; + break; + case (0x76): + str = "QueryProcessMemory"; + break; + case (0x77): + str = "MapProcessCodeMemory"; + break; + case (0x78): + str = "UnmapProcessCodeMemory"; + break; + case (0x79): + str = "CreateProcess"; + break; + case (0x7a): + str = "StartProcess"; + break; + case (0x7b): + str = "TerminateProcess"; + break; + case (0x7c): + str = "GetProcessInfo"; + break; + case (0x7d): + str = "CreateResourceLimit"; + break; + case (0x7e): + str = "SetResourceLimitLimitValue"; + break; + case (0x7f): + str = "CallSecureMonitor"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* MetaProcess::getMemMapPermStr(nn::hac::MemoryMappingHandler::MemoryPerm type) const +{ + const char* str = nullptr; + + switch(type) + { + case (nn::hac::MemoryMappingHandler::MEM_RW): + str = "RW"; + break; + case (nn::hac::MemoryMappingHandler::MEM_RO): + str = "RO"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* MetaProcess::getMemMapTypeStr(nn::hac::MemoryMappingHandler::MappingType type) const +{ + const char* str = nullptr; + + switch(type) + { + case (nn::hac::MemoryMappingHandler::MAP_IO): + str = "Io"; + break; + case (nn::hac::MemoryMappingHandler::MAP_STATIC): + str = "Static"; + break; + default: + str = "Unknown"; + break; + } + + return str; } \ No newline at end of file diff --git a/programs/nstool/source/MetaProcess.h b/programs/nstool/source/MetaProcess.h index 415656e..3299b1b 100644 --- a/programs/nstool/source/MetaProcess.h +++ b/programs/nstool/source/MetaProcess.h @@ -1,56 +1,56 @@ -#pragma once -#include -#include -#include -#include -#include -#include "KeyConfiguration.h" - -#include "common.h" - -class MetaProcess -{ -public: - MetaProcess(); - - void process(); - - void setInputFile(const fnd::SharedPtr& file); - void setKeyCfg(const KeyConfiguration& keycfg); - void setCliOutputMode(CliOutputMode type); - void setVerifyMode(bool verify); - - const nn::hac::MetaBinary& getMetaBinary() const; - -private: - const std::string kModuleName = "MetaProcess"; - - fnd::SharedPtr mFile; - KeyConfiguration mKeyCfg; - CliOutputMode mCliOutputMode; - bool mVerify; - - nn::hac::MetaBinary mMeta; - - void importMeta(); - - void validateAcidSignature(const nn::hac::AccessControlInfoDescBinary& acid); - void validateAciFromAcid(const nn::hac::AccessControlInfoBinary& aci, const nn::hac::AccessControlInfoDescBinary& acid); - - void displayMetaHeader(const nn::hac::MetaBinary& hdr); - void displayAciHdr(const nn::hac::AccessControlInfoBinary& aci); - void displayAciDescHdr(const nn::hac::AccessControlInfoDescBinary& aci); - void displayFac(const nn::hac::FileSystemAccessControlBinary& fac); - void displaySac(const nn::hac::ServiceAccessControlBinary& sac); - void displayKernelCap(const nn::hac::KernelCapabilityBinary& kern); - - const char* getInstructionTypeStr(nn::hac::meta::InstructionType type) const; - const char* getProcAddressSpaceTypeStr(nn::hac::meta::ProcAddrSpaceType type) const; - const char* getAcidFlagStr(nn::hac::aci::Flag flag) const; - const char* getMiscFlagStr(nn::hac::MiscFlagsHandler::Flags flag) const; - const char* getFsaRightStr(nn::hac::fac::FsAccessFlag flag) const; - const char* getSaveDataOwnerAccessModeStr(nn::hac::fac::SaveDataOwnerIdAccessType type) const; - const char* getSystemCallStr(byte_t syscall_id) const; - const char* getMemMapPermStr(nn::hac::MemoryMappingHandler::MemoryPerm type) const; - const char* getMemMapTypeStr(nn::hac::MemoryMappingHandler::MappingType type) const; +#pragma once +#include +#include +#include +#include +#include +#include "KeyConfiguration.h" + +#include "common.h" + +class MetaProcess +{ +public: + MetaProcess(); + + void process(); + + void setInputFile(const fnd::SharedPtr& file); + void setKeyCfg(const KeyConfiguration& keycfg); + void setCliOutputMode(CliOutputMode type); + void setVerifyMode(bool verify); + + const nn::hac::Meta& getMeta() const; + +private: + const std::string kModuleName = "MetaProcess"; + + fnd::SharedPtr mFile; + KeyConfiguration mKeyCfg; + CliOutputMode mCliOutputMode; + bool mVerify; + + nn::hac::Meta mMeta; + + void importMeta(); + + void validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid); + void validateAciFromAcid(const nn::hac::AccessControlInfo& aci, const nn::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); + + const char* getInstructionTypeStr(nn::hac::meta::InstructionType type) const; + const char* getProcAddressSpaceTypeStr(nn::hac::meta::ProcAddrSpaceType type) const; + const char* getAcidFlagStr(nn::hac::aci::Flag flag) const; + const char* getMiscFlagStr(nn::hac::MiscFlagsHandler::Flags flag) const; + const char* getFsaRightStr(nn::hac::fac::FsAccessFlag flag) const; + const char* getSaveDataOwnerAccessModeStr(nn::hac::fac::SaveDataOwnerIdAccessType type) const; + const char* getSystemCallStr(byte_t syscall_id) const; + const char* getMemMapPermStr(nn::hac::MemoryMappingHandler::MemoryPerm type) const; + const char* getMemMapTypeStr(nn::hac::MemoryMappingHandler::MappingType type) const; }; \ No newline at end of file diff --git a/programs/nstool/source/NacpProcess.cpp b/programs/nstool/source/NacpProcess.cpp index fb04870..835e776 100644 --- a/programs/nstool/source/NacpProcess.cpp +++ b/programs/nstool/source/NacpProcess.cpp @@ -1,633 +1,633 @@ -#include -#include -#include -#include -#include -#include "NacpProcess.h" - -NacpProcess::NacpProcess() : - mFile(), - mCliOutputMode(_BIT(OUTPUT_BASIC)), - mVerify(false) -{ -} - -void NacpProcess::process() -{ - importNacp(); - - if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) - displayNacp(); -} - -void NacpProcess::setInputFile(const fnd::SharedPtr& file) -{ - mFile = file; -} - -void NacpProcess::setCliOutputMode(CliOutputMode type) -{ - mCliOutputMode = type; -} - -void NacpProcess::setVerifyMode(bool verify) -{ - mVerify = verify; -} - -const nn::hac::ApplicationControlPropertyBinary& NacpProcess::getApplicationControlPropertyBinary() const -{ - return mNacp; -} - -void NacpProcess::importNacp() -{ - fnd::Vec scratch; - - if (*mFile == nullptr) - { - throw fnd::Exception(kModuleName, "No file reader set."); - } - - scratch.alloc((*mFile)->size()); - (*mFile)->read(scratch.data(), 0, scratch.size()); - - mNacp.fromBytes(scratch.data(), scratch.size()); -} - -void NacpProcess::displayNacp() -{ - std::cout << "[ApplicationControlProperty]" << std::endl; - std::cout << " Menu Description:" << std::endl; - std::cout << " DisplayVersion: " << mNacp.getDisplayVersion() << std::endl; - if (mNacp.getIsbn().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - std::cout << " ISBN: " << mNacp.getIsbn() << std::endl; - for (size_t i = 0; i < mNacp.getTitle().size(); i++) - { - std::cout << " " << getLanguageStr(mNacp.getTitle()[i].language) << " Title:" << std::endl; - std::cout << " Name: " << mNacp.getTitle()[i].name << std::endl; - std::cout << " Publisher: " << mNacp.getTitle()[i].publisher << std::endl; - } - std::cout << " Logo:" << std::endl; - std::cout << " Type: " << getLogoTypeStr(mNacp.getLogoType()) << std::endl; - std::cout << " Handling: " << getLogoHandlingStr(mNacp.getLogoHandling()) << std::endl; - std::cout << " AddOnContent:" << std::endl; - std::cout << " BaseId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getAocBaseId() << std::endl; - std::cout << " RegistrationType: " << getAocRegistrationTypeStr(mNacp.getAocRegistrationType()) << std::endl; - std::cout << " RuntimeInstallMode: " << getRuntimeAocInstallModeStr(mNacp.getRuntimeAocInstallMode()) << std::endl; - std::cout << " Play Log:" << std::endl; - std::cout << " PlayLogPolicy: " << getPlayLogPolicyStr(mNacp.getPlayLogPolicy()) << std::endl; - std::cout << " PlayLogQueryCapability: " << getPlayLogQueryCapabilityStr(mNacp.getPlayLogQueryCapability()) << std::endl; - if (mNacp.getPlayLogQueryableApplicationId().size() > 0) - { - std::cout << " PlayLogQueryableApplicationId:" << std::endl; - for (size_t i = 0; i < mNacp.getPlayLogQueryableApplicationId().size(); i++) - { - std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getPlayLogQueryableApplicationId()[i] << std::endl; - } - } - std::cout << " Parental Controls:" << std::endl; - std::cout << " ParentalControlFlag: " << getParentalControlFlagStr(mNacp.getParentalControlFlag()) << std::endl; - for (size_t i = 0; i < mNacp.getRatingAge().size(); i++) - { - std::cout << " Age Restriction:" << std::endl; - std::cout << " Agency: " << getOrganisationStr(mNacp.getRatingAge()[i].organisation) << std::endl; - std::cout << " Age: " << std::dec << (uint32_t)mNacp.getRatingAge()[i].age << std::endl; - } - - if (mNacp.getBcatPassphase().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " BCAT:" << std::endl; - std::cout << " BcatPassphase: " << mNacp.getBcatPassphase() << std::endl; - std::cout << " DeliveryCacheStorageSize: 0x" << std::hex << mNacp.getBcatDeliveryCacheStorageSize() << std::endl; - } - if (mNacp.getLocalCommunicationId().size() > 0) - { - std::cout << " Local Area Communication:" << std::endl; - std::cout << " LocalCommunicationId:" << std::endl; - for (size_t i = 0; i < mNacp.getLocalCommunicationId().size(); i++) - { - std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getLocalCommunicationId()[i] << std::endl; - } - } - std::cout << " SaveData:" << std::endl; - std::cout << " SaveDatawOwnerId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSaveDatawOwnerId() << std::endl; - if (mNacp.getUserAccountSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " UserAccountSaveData:" << std::endl; - std::cout << " Size: " << getSaveDataSizeStr(mNacp.getUserAccountSaveDataSize().size) << std::endl; - std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getUserAccountSaveDataSize().journal_size) << std::endl; - } - if (mNacp.getDeviceSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " DeviceSaveData:" << std::endl; - std::cout << " Size: " << getSaveDataSizeStr(mNacp.getDeviceSaveDataSize().size) << std::endl; - std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getDeviceSaveDataSize().journal_size) << std::endl; - } - if (mNacp.getUserAccountSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " UserAccountSaveDataMax:" << std::endl; - std::cout << " Size: " << getSaveDataSizeStr(mNacp.getUserAccountSaveDataMax().size) << std::endl; - std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getUserAccountSaveDataMax().journal_size) << std::endl; - } - if (mNacp.getDeviceSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " DeviceSaveDataMax:" << std::endl; - std::cout << " Size: " << getSaveDataSizeStr(mNacp.getDeviceSaveDataMax().size) << std::endl; - std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getDeviceSaveDataMax().journal_size) << std::endl; - } - if (mNacp.getTemporaryStorageSize() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " TemporaryStorageSize: " << getSaveDataSizeStr(mNacp.getTemporaryStorageSize()) << std::endl; - } - if (mNacp.getCacheStorageSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " CacheStorage:" << std::endl; - std::cout << " Size: " << getSaveDataSizeStr(mNacp.getCacheStorageSize().size) << std::endl; - std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getCacheStorageSize().journal_size) << std::endl; - std::cout << " MaxDataAndJournalSize: " << getSaveDataSizeStr(mNacp.getCacheStorageDataAndJournalSizeMax()) << std::endl; - std::cout << " StorageIndexMax: 0x" << std::hex << mNacp.getCacheStorageIndexMax() << std::endl; - } - std::cout << " Other Flags:" << std::endl; - std::cout << " StartupUserAccount: " << getStartupUserAccountStr(mNacp.getStartupUserAccount()) << std::endl; - if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " TouchScreenUsageMode: " << getTouchScreenUsageModeStr(mNacp.getTouchScreenUsageMode()) << std::endl; - } - std::cout << " AttributeFlag: " << getAttributeFlagStr(mNacp.getAttributeFlag()) << std::endl; - std::cout << " CrashReportMode: " << getCrashReportModeStr(mNacp.getCrashReportMode()) << std::endl; - std::cout << " HDCP: " << getHdcpStr(mNacp.getHdcp()) << std::endl; - std::cout << " ScreenshotMode: " << getScreenshotModeStr(mNacp.getScreenshotMode()) << std::endl; - std::cout << " VideoCaptureMode: " << getVideoCaptureModeStr(mNacp.getVideoCaptureMode()) << std::endl; - std::cout << " DataLossConfirmation: " << getDataLossConfirmationStr(mNacp.getDataLossConfirmation()) << std::endl; - std::cout << " RepairFlag: " << getRepairFlagStr(mNacp.getRepairFlag()) << std::endl; - std::cout << " ProgramIndex: 0x" << std::hex << std::setw(2) << std::setfill('0') << (uint32_t)mNacp.getProgramIndex() << std::endl; - if (mNacp.getApplicationErrorCodeCategory().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " ApplicationErrorCodeCategory: " << mNacp.getApplicationErrorCodeCategory() << std::endl; - } - if (mNacp.getSeedForPsuedoDeviceId() > 0 || mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " Other Ids:" << std::endl; - if (mNacp.getSeedForPsuedoDeviceId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - std::cout << " SeedForPsuedoDeviceId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSeedForPsuedoDeviceId() << std::endl; - if (mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - std::cout << " PresenceGroupId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getPresenceGroupId() << std::endl; - } -} - -const char* NacpProcess::getLanguageStr(nn::hac::nacp::Language var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::LANG_AmericanEnglish): - str = "AmericanEnglish"; - break; - case (nn::hac::nacp::LANG_BritishEnglish): - str = "BritishEnglish"; - break; - case (nn::hac::nacp::LANG_Japanese): - str = "Japanese"; - break; - case (nn::hac::nacp::LANG_French): - str = "French"; - break; - case (nn::hac::nacp::LANG_German): - str = "German"; - break; - case (nn::hac::nacp::LANG_LatinAmericanSpanish): - str = "LatinAmericanSpanish"; - break; - case (nn::hac::nacp::LANG_Spanish): - str = "Spanish"; - break; - case (nn::hac::nacp::LANG_Italian): - str = "Italian"; - break; - case (nn::hac::nacp::LANG_Dutch): - str = "Dutch"; - break; - case (nn::hac::nacp::LANG_CanadianFrench): - str = "CanadianFrench"; - break; - case (nn::hac::nacp::LANG_Portuguese): - str = "Portuguese"; - break; - case (nn::hac::nacp::LANG_Russian): - str = "Russian"; - break; - case (nn::hac::nacp::LANG_Korean): - str = "Korean"; - break; - case (nn::hac::nacp::LANG_TraditionalChinese): - str = "TraditionalChinese"; - break; - case (nn::hac::nacp::LANG_SimplifiedChinese): - str = "SimplifiedChinese"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getStartupUserAccountStr(nn::hac::nacp::StartupUserAccount var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::USER_None): - str = "None"; - break; - case (nn::hac::nacp::USER_Required): - str = "Required"; - break; - case (nn::hac::nacp::USER_RequiredWithNetworkServiceAccountAvailable): - str = "RequiredWithNetworkServiceAccountAvailable"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getTouchScreenUsageModeStr(nn::hac::nacp::TouchScreenUsageMode var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::TOUCH_None): - str = "None"; - break; - case (nn::hac::nacp::TOUCH_Supported): - str = "Supported"; - break; - case (nn::hac::nacp::TOUCH_Required): - str = "Required"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getAocRegistrationTypeStr(nn::hac::nacp::AocRegistrationType var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::AOC_AllOnLaunch): - str = "AllOnLaunch"; - break; - case (nn::hac::nacp::AOC_OnDemand): - str = "OnDemand"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getAttributeFlagStr(nn::hac::nacp::AttributeFlag var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::ATTR_None): - str = "None"; - break; - case (nn::hac::nacp::ATTR_Demo): - str = "Demo"; - break; - case (nn::hac::nacp::ATTR_RetailInteractiveDisplay): - str = "RetailInteractiveDisplay"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getParentalControlFlagStr(nn::hac::nacp::ParentalControlFlag var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::PC_None): - str = "None"; - break; - case (nn::hac::nacp::PC_FreeCommunication): - str = "FreeCommunication"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getScreenshotModeStr(nn::hac::nacp::ScreenshotMode var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::SCRN_Allow): - str = "Allow"; - break; - case (nn::hac::nacp::SCRN_Deny): - str = "Deny"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getVideoCaptureModeStr(nn::hac::nacp::VideoCaptureMode var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::VCAP_Disable): - str = "Disable"; - break; - case (nn::hac::nacp::VCAP_Manual): - str = "Manual"; - break; - case (nn::hac::nacp::VCAP_Enable): - str = "Enable"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getDataLossConfirmationStr(nn::hac::nacp::DataLossConfirmation var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::DLOSS_None): - str = "None"; - break; - case (nn::hac::nacp::DLOSS_Required): - str = "Required"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getPlayLogPolicyStr(nn::hac::nacp::PlayLogPolicy var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::PLP_All): - str = "All"; - break; - case (nn::hac::nacp::PLP_LogOnly): - str = "LogOnly"; - break; - case (nn::hac::nacp::PLP_None): - str = "None"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getOrganisationStr(nn::hac::nacp::Organisation var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::ORGN_CERO): - str = "CERO"; - break; - case (nn::hac::nacp::ORGN_GRACGCRB): - str = "GRACGCRB"; - break; - case (nn::hac::nacp::ORGN_GSRMR): - str = "GSRMR"; - break; - case (nn::hac::nacp::ORGN_ESRB): - str = "ESRB"; - break; - case (nn::hac::nacp::ORGN_ClassInd): - str = "ClassInd"; - break; - case (nn::hac::nacp::ORGN_USK): - str = "USK"; - break; - case (nn::hac::nacp::ORGN_PEGI): - str = "PEGI"; - break; - case (nn::hac::nacp::ORGN_PEGIPortugal): - str = "PEGIPortugal"; - break; - case (nn::hac::nacp::ORGN_PEGIBBFC): - str = "PEGIBBFC"; - break; - case (nn::hac::nacp::ORGN_Russian): - str = "Russian"; - break; - case (nn::hac::nacp::ORGN_ACB): - str = "ACB"; - break; - case (nn::hac::nacp::ORGN_OFLC): - str = "OFLC"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getLogoTypeStr(nn::hac::nacp::LogoType var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::LOGO_LicensedByNintendo): - str = "LicensedByNintendo"; - break; - case (nn::hac::nacp::LOGO_DistributedByNintendo): - str = "DistributedByNintendo"; - break; - case (nn::hac::nacp::LOGO_Nintendo): - str = "Nintendo"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getLogoHandlingStr(nn::hac::nacp::LogoHandling var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::LHND_Auto): - str = "Auto"; - break; - case (nn::hac::nacp::LHND_None): - str = "None"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getRuntimeAocInstallModeStr(nn::hac::nacp::RuntimeAocInstallMode var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::RTAOC_Deny): - str = "Deny"; - break; - case (nn::hac::nacp::RTAOC_AllowAppend): - str = "AllowAppend"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getCrashReportModeStr(nn::hac::nacp::CrashReportMode var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::CREP_Deny): - str = "Deny"; - break; - case (nn::hac::nacp::CREP_Allow): - str = "Allow"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getHdcpStr(nn::hac::nacp::Hdcp var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::HDCP_None): - str = "None"; - break; - case (nn::hac::nacp::HDCP_Required): - str = "Required"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getPlayLogQueryCapabilityStr(nn::hac::nacp::PlayLogQueryCapability var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::PLQC_None): - str = "None"; - break; - case (nn::hac::nacp::PLQC_Whitelist): - str = "Whitelist"; - break; - case (nn::hac::nacp::PLQC_All): - str = "All"; - break; - default: - str = "Unknown"; - } - - return str; -} - -const char* NacpProcess::getRepairFlagStr(nn::hac::nacp::RepairFlag var) const -{ - const char* str = nullptr; - - switch(var) - { - case (nn::hac::nacp::REPF_None): - str = "None"; - break; - case (nn::hac::nacp::REPF_SuppressGameCardAccess): - str = "SuppressGameCardAccess"; - break; - default: - str = "Unknown"; - } - - return str; -} - -std::string NacpProcess::getSaveDataSizeStr(int64_t size) const -{ - static const int64_t kKiloByte = 1024; - static const int64_t kMegaByte = 1024 * 1024; - - std::stringstream sstr; - - - if (size < kKiloByte) - { - sstr << size << " B"; - } - else if (size < kMegaByte) - { - sstr << (size/kKiloByte) << " KB"; - } - else - { - sstr << (size/kMegaByte) << " MB"; - } - - return sstr.str(); +#include +#include +#include +#include +#include +#include "NacpProcess.h" + +NacpProcess::NacpProcess() : + mFile(), + mCliOutputMode(_BIT(OUTPUT_BASIC)), + mVerify(false) +{ +} + +void NacpProcess::process() +{ + importNacp(); + + if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) + displayNacp(); +} + +void NacpProcess::setInputFile(const fnd::SharedPtr& file) +{ + mFile = file; +} + +void NacpProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void NacpProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +const nn::hac::ApplicationControlProperty& NacpProcess::getApplicationControlProperty() const +{ + return mNacp; +} + +void NacpProcess::importNacp() +{ + fnd::Vec scratch; + + if (*mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + scratch.alloc((*mFile)->size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); + + mNacp.fromBytes(scratch.data(), scratch.size()); +} + +void NacpProcess::displayNacp() +{ + std::cout << "[ApplicationControlProperty]" << std::endl; + std::cout << " Menu Description:" << std::endl; + std::cout << " DisplayVersion: " << mNacp.getDisplayVersion() << std::endl; + if (mNacp.getIsbn().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + std::cout << " ISBN: " << mNacp.getIsbn() << std::endl; + for (size_t i = 0; i < mNacp.getTitle().size(); i++) + { + std::cout << " " << getLanguageStr(mNacp.getTitle()[i].language) << " Title:" << std::endl; + std::cout << " Name: " << mNacp.getTitle()[i].name << std::endl; + std::cout << " Publisher: " << mNacp.getTitle()[i].publisher << std::endl; + } + std::cout << " Logo:" << std::endl; + std::cout << " Type: " << getLogoTypeStr(mNacp.getLogoType()) << std::endl; + std::cout << " Handling: " << getLogoHandlingStr(mNacp.getLogoHandling()) << std::endl; + std::cout << " AddOnContent:" << std::endl; + std::cout << " BaseId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getAocBaseId() << std::endl; + std::cout << " RegistrationType: " << getAocRegistrationTypeStr(mNacp.getAocRegistrationType()) << std::endl; + std::cout << " RuntimeInstallMode: " << getRuntimeAocInstallModeStr(mNacp.getRuntimeAocInstallMode()) << std::endl; + std::cout << " Play Log:" << std::endl; + std::cout << " PlayLogPolicy: " << getPlayLogPolicyStr(mNacp.getPlayLogPolicy()) << std::endl; + std::cout << " PlayLogQueryCapability: " << getPlayLogQueryCapabilityStr(mNacp.getPlayLogQueryCapability()) << std::endl; + if (mNacp.getPlayLogQueryableApplicationId().size() > 0) + { + std::cout << " PlayLogQueryableApplicationId:" << std::endl; + for (size_t i = 0; i < mNacp.getPlayLogQueryableApplicationId().size(); i++) + { + std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getPlayLogQueryableApplicationId()[i] << std::endl; + } + } + std::cout << " Parental Controls:" << std::endl; + std::cout << " ParentalControlFlag: " << getParentalControlFlagStr(mNacp.getParentalControlFlag()) << std::endl; + for (size_t i = 0; i < mNacp.getRatingAge().size(); i++) + { + std::cout << " Age Restriction:" << std::endl; + std::cout << " Agency: " << getOrganisationStr(mNacp.getRatingAge()[i].organisation) << std::endl; + std::cout << " Age: " << std::dec << (uint32_t)mNacp.getRatingAge()[i].age << std::endl; + } + + if (mNacp.getBcatPassphase().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " BCAT:" << std::endl; + std::cout << " BcatPassphase: " << mNacp.getBcatPassphase() << std::endl; + std::cout << " DeliveryCacheStorageSize: 0x" << std::hex << mNacp.getBcatDeliveryCacheStorageSize() << std::endl; + } + if (mNacp.getLocalCommunicationId().size() > 0) + { + std::cout << " Local Area Communication:" << std::endl; + std::cout << " LocalCommunicationId:" << std::endl; + for (size_t i = 0; i < mNacp.getLocalCommunicationId().size(); i++) + { + std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getLocalCommunicationId()[i] << std::endl; + } + } + std::cout << " SaveData:" << std::endl; + std::cout << " SaveDatawOwnerId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSaveDatawOwnerId() << std::endl; + if (mNacp.getUserAccountSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " UserAccountSaveData:" << std::endl; + std::cout << " Size: " << getSaveDataSizeStr(mNacp.getUserAccountSaveDataSize().size) << std::endl; + std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getUserAccountSaveDataSize().journal_size) << std::endl; + } + if (mNacp.getDeviceSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " DeviceSaveData:" << std::endl; + std::cout << " Size: " << getSaveDataSizeStr(mNacp.getDeviceSaveDataSize().size) << std::endl; + std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getDeviceSaveDataSize().journal_size) << std::endl; + } + if (mNacp.getUserAccountSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " UserAccountSaveDataMax:" << std::endl; + std::cout << " Size: " << getSaveDataSizeStr(mNacp.getUserAccountSaveDataMax().size) << std::endl; + std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getUserAccountSaveDataMax().journal_size) << std::endl; + } + if (mNacp.getDeviceSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " DeviceSaveDataMax:" << std::endl; + std::cout << " Size: " << getSaveDataSizeStr(mNacp.getDeviceSaveDataMax().size) << std::endl; + std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getDeviceSaveDataMax().journal_size) << std::endl; + } + if (mNacp.getTemporaryStorageSize() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " TemporaryStorageSize: " << getSaveDataSizeStr(mNacp.getTemporaryStorageSize()) << std::endl; + } + if (mNacp.getCacheStorageSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " CacheStorage:" << std::endl; + std::cout << " Size: " << getSaveDataSizeStr(mNacp.getCacheStorageSize().size) << std::endl; + std::cout << " JournalSize: " << getSaveDataSizeStr(mNacp.getCacheStorageSize().journal_size) << std::endl; + std::cout << " MaxDataAndJournalSize: " << getSaveDataSizeStr(mNacp.getCacheStorageDataAndJournalSizeMax()) << std::endl; + std::cout << " StorageIndexMax: 0x" << std::hex << mNacp.getCacheStorageIndexMax() << std::endl; + } + std::cout << " Other Flags:" << std::endl; + std::cout << " StartupUserAccount: " << getStartupUserAccountStr(mNacp.getStartupUserAccount()) << std::endl; + if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " TouchScreenUsageMode: " << getTouchScreenUsageModeStr(mNacp.getTouchScreenUsageMode()) << std::endl; + } + std::cout << " AttributeFlag: " << getAttributeFlagStr(mNacp.getAttributeFlag()) << std::endl; + std::cout << " CrashReportMode: " << getCrashReportModeStr(mNacp.getCrashReportMode()) << std::endl; + std::cout << " HDCP: " << getHdcpStr(mNacp.getHdcp()) << std::endl; + std::cout << " ScreenshotMode: " << getScreenshotModeStr(mNacp.getScreenshotMode()) << std::endl; + std::cout << " VideoCaptureMode: " << getVideoCaptureModeStr(mNacp.getVideoCaptureMode()) << std::endl; + std::cout << " DataLossConfirmation: " << getDataLossConfirmationStr(mNacp.getDataLossConfirmation()) << std::endl; + std::cout << " RepairFlag: " << getRepairFlagStr(mNacp.getRepairFlag()) << std::endl; + std::cout << " ProgramIndex: 0x" << std::hex << std::setw(2) << std::setfill('0') << (uint32_t)mNacp.getProgramIndex() << std::endl; + if (mNacp.getApplicationErrorCodeCategory().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " ApplicationErrorCodeCategory: " << mNacp.getApplicationErrorCodeCategory() << std::endl; + } + if (mNacp.getSeedForPsuedoDeviceId() > 0 || mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " Other Ids:" << std::endl; + if (mNacp.getSeedForPsuedoDeviceId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + std::cout << " SeedForPsuedoDeviceId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSeedForPsuedoDeviceId() << std::endl; + if (mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + std::cout << " PresenceGroupId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getPresenceGroupId() << std::endl; + } +} + +const char* NacpProcess::getLanguageStr(nn::hac::nacp::Language var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::LANG_AmericanEnglish): + str = "AmericanEnglish"; + break; + case (nn::hac::nacp::LANG_BritishEnglish): + str = "BritishEnglish"; + break; + case (nn::hac::nacp::LANG_Japanese): + str = "Japanese"; + break; + case (nn::hac::nacp::LANG_French): + str = "French"; + break; + case (nn::hac::nacp::LANG_German): + str = "German"; + break; + case (nn::hac::nacp::LANG_LatinAmericanSpanish): + str = "LatinAmericanSpanish"; + break; + case (nn::hac::nacp::LANG_Spanish): + str = "Spanish"; + break; + case (nn::hac::nacp::LANG_Italian): + str = "Italian"; + break; + case (nn::hac::nacp::LANG_Dutch): + str = "Dutch"; + break; + case (nn::hac::nacp::LANG_CanadianFrench): + str = "CanadianFrench"; + break; + case (nn::hac::nacp::LANG_Portuguese): + str = "Portuguese"; + break; + case (nn::hac::nacp::LANG_Russian): + str = "Russian"; + break; + case (nn::hac::nacp::LANG_Korean): + str = "Korean"; + break; + case (nn::hac::nacp::LANG_TraditionalChinese): + str = "TraditionalChinese"; + break; + case (nn::hac::nacp::LANG_SimplifiedChinese): + str = "SimplifiedChinese"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getStartupUserAccountStr(nn::hac::nacp::StartupUserAccount var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::USER_None): + str = "None"; + break; + case (nn::hac::nacp::USER_Required): + str = "Required"; + break; + case (nn::hac::nacp::USER_RequiredWithNetworkServiceAccountAvailable): + str = "RequiredWithNetworkServiceAccountAvailable"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getTouchScreenUsageModeStr(nn::hac::nacp::TouchScreenUsageMode var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::TOUCH_None): + str = "None"; + break; + case (nn::hac::nacp::TOUCH_Supported): + str = "Supported"; + break; + case (nn::hac::nacp::TOUCH_Required): + str = "Required"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getAocRegistrationTypeStr(nn::hac::nacp::AocRegistrationType var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::AOC_AllOnLaunch): + str = "AllOnLaunch"; + break; + case (nn::hac::nacp::AOC_OnDemand): + str = "OnDemand"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getAttributeFlagStr(nn::hac::nacp::AttributeFlag var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::ATTR_None): + str = "None"; + break; + case (nn::hac::nacp::ATTR_Demo): + str = "Demo"; + break; + case (nn::hac::nacp::ATTR_RetailInteractiveDisplay): + str = "RetailInteractiveDisplay"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getParentalControlFlagStr(nn::hac::nacp::ParentalControlFlag var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::PC_None): + str = "None"; + break; + case (nn::hac::nacp::PC_FreeCommunication): + str = "FreeCommunication"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getScreenshotModeStr(nn::hac::nacp::ScreenshotMode var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::SCRN_Allow): + str = "Allow"; + break; + case (nn::hac::nacp::SCRN_Deny): + str = "Deny"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getVideoCaptureModeStr(nn::hac::nacp::VideoCaptureMode var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::VCAP_Disable): + str = "Disable"; + break; + case (nn::hac::nacp::VCAP_Manual): + str = "Manual"; + break; + case (nn::hac::nacp::VCAP_Enable): + str = "Enable"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getDataLossConfirmationStr(nn::hac::nacp::DataLossConfirmation var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::DLOSS_None): + str = "None"; + break; + case (nn::hac::nacp::DLOSS_Required): + str = "Required"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getPlayLogPolicyStr(nn::hac::nacp::PlayLogPolicy var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::PLP_All): + str = "All"; + break; + case (nn::hac::nacp::PLP_LogOnly): + str = "LogOnly"; + break; + case (nn::hac::nacp::PLP_None): + str = "None"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getOrganisationStr(nn::hac::nacp::Organisation var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::ORGN_CERO): + str = "CERO"; + break; + case (nn::hac::nacp::ORGN_GRACGCRB): + str = "GRACGCRB"; + break; + case (nn::hac::nacp::ORGN_GSRMR): + str = "GSRMR"; + break; + case (nn::hac::nacp::ORGN_ESRB): + str = "ESRB"; + break; + case (nn::hac::nacp::ORGN_ClassInd): + str = "ClassInd"; + break; + case (nn::hac::nacp::ORGN_USK): + str = "USK"; + break; + case (nn::hac::nacp::ORGN_PEGI): + str = "PEGI"; + break; + case (nn::hac::nacp::ORGN_PEGIPortugal): + str = "PEGIPortugal"; + break; + case (nn::hac::nacp::ORGN_PEGIBBFC): + str = "PEGIBBFC"; + break; + case (nn::hac::nacp::ORGN_Russian): + str = "Russian"; + break; + case (nn::hac::nacp::ORGN_ACB): + str = "ACB"; + break; + case (nn::hac::nacp::ORGN_OFLC): + str = "OFLC"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getLogoTypeStr(nn::hac::nacp::LogoType var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::LOGO_LicensedByNintendo): + str = "LicensedByNintendo"; + break; + case (nn::hac::nacp::LOGO_DistributedByNintendo): + str = "DistributedByNintendo"; + break; + case (nn::hac::nacp::LOGO_Nintendo): + str = "Nintendo"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getLogoHandlingStr(nn::hac::nacp::LogoHandling var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::LHND_Auto): + str = "Auto"; + break; + case (nn::hac::nacp::LHND_None): + str = "None"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getRuntimeAocInstallModeStr(nn::hac::nacp::RuntimeAocInstallMode var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::RTAOC_Deny): + str = "Deny"; + break; + case (nn::hac::nacp::RTAOC_AllowAppend): + str = "AllowAppend"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getCrashReportModeStr(nn::hac::nacp::CrashReportMode var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::CREP_Deny): + str = "Deny"; + break; + case (nn::hac::nacp::CREP_Allow): + str = "Allow"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getHdcpStr(nn::hac::nacp::Hdcp var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::HDCP_None): + str = "None"; + break; + case (nn::hac::nacp::HDCP_Required): + str = "Required"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getPlayLogQueryCapabilityStr(nn::hac::nacp::PlayLogQueryCapability var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::PLQC_None): + str = "None"; + break; + case (nn::hac::nacp::PLQC_Whitelist): + str = "Whitelist"; + break; + case (nn::hac::nacp::PLQC_All): + str = "All"; + break; + default: + str = "Unknown"; + } + + return str; +} + +const char* NacpProcess::getRepairFlagStr(nn::hac::nacp::RepairFlag var) const +{ + const char* str = nullptr; + + switch(var) + { + case (nn::hac::nacp::REPF_None): + str = "None"; + break; + case (nn::hac::nacp::REPF_SuppressGameCardAccess): + str = "SuppressGameCardAccess"; + break; + default: + str = "Unknown"; + } + + return str; +} + +std::string NacpProcess::getSaveDataSizeStr(int64_t size) const +{ + static const int64_t kKiloByte = 1024; + static const int64_t kMegaByte = 1024 * 1024; + + std::stringstream sstr; + + + if (size < kKiloByte) + { + sstr << size << " B"; + } + else if (size < kMegaByte) + { + sstr << (size/kKiloByte) << " KB"; + } + else + { + sstr << (size/kMegaByte) << " MB"; + } + + return sstr.str(); } \ No newline at end of file diff --git a/programs/nstool/source/NacpProcess.h b/programs/nstool/source/NacpProcess.h index 8a5064c..2f3c1af 100644 --- a/programs/nstool/source/NacpProcess.h +++ b/programs/nstool/source/NacpProcess.h @@ -1,53 +1,53 @@ -#pragma once -#include -#include -#include -#include -#include - -#include "common.h" - -class NacpProcess -{ -public: - NacpProcess(); - - void process(); - - void setInputFile(const fnd::SharedPtr& file); - void setCliOutputMode(CliOutputMode type); - void setVerifyMode(bool verify); - - const nn::hac::ApplicationControlPropertyBinary& getApplicationControlPropertyBinary() const; - -private: - const std::string kModuleName = "NacpProcess"; - - fnd::SharedPtr mFile; - CliOutputMode mCliOutputMode; - bool mVerify; - - nn::hac::ApplicationControlPropertyBinary mNacp; - - void importNacp(); - void displayNacp(); - const char* getLanguageStr(nn::hac::nacp::Language var) const; - const char* getStartupUserAccountStr(nn::hac::nacp::StartupUserAccount var) const; - const char* getTouchScreenUsageModeStr(nn::hac::nacp::TouchScreenUsageMode var) const; - const char* getAocRegistrationTypeStr(nn::hac::nacp::AocRegistrationType var) const; - const char* getAttributeFlagStr(nn::hac::nacp::AttributeFlag var) const; - const char* getParentalControlFlagStr(nn::hac::nacp::ParentalControlFlag var) const; - const char* getScreenshotModeStr(nn::hac::nacp::ScreenshotMode var) const; - const char* getVideoCaptureModeStr(nn::hac::nacp::VideoCaptureMode var) const; - const char* getDataLossConfirmationStr(nn::hac::nacp::DataLossConfirmation var) const; - const char* getPlayLogPolicyStr(nn::hac::nacp::PlayLogPolicy var) const; - const char* getOrganisationStr(nn::hac::nacp::Organisation var) const; - const char* getLogoTypeStr(nn::hac::nacp::LogoType var) const; - const char* getLogoHandlingStr(nn::hac::nacp::LogoHandling var) const; - const char* getRuntimeAocInstallModeStr(nn::hac::nacp::RuntimeAocInstallMode var) const; - const char* getCrashReportModeStr(nn::hac::nacp::CrashReportMode var) const; - const char* getHdcpStr(nn::hac::nacp::Hdcp var) const; - const char* getPlayLogQueryCapabilityStr(nn::hac::nacp::PlayLogQueryCapability var) const; - const char* getRepairFlagStr(nn::hac::nacp::RepairFlag var) const; - std::string getSaveDataSizeStr(int64_t size) const; +#pragma once +#include +#include +#include +#include +#include + +#include "common.h" + +class NacpProcess +{ +public: + NacpProcess(); + + void process(); + + void setInputFile(const fnd::SharedPtr& file); + void setCliOutputMode(CliOutputMode type); + void setVerifyMode(bool verify); + + const nn::hac::ApplicationControlProperty& getApplicationControlProperty() const; + +private: + const std::string kModuleName = "NacpProcess"; + + fnd::SharedPtr mFile; + CliOutputMode mCliOutputMode; + bool mVerify; + + nn::hac::ApplicationControlProperty mNacp; + + void importNacp(); + void displayNacp(); + const char* getLanguageStr(nn::hac::nacp::Language var) const; + const char* getStartupUserAccountStr(nn::hac::nacp::StartupUserAccount var) const; + const char* getTouchScreenUsageModeStr(nn::hac::nacp::TouchScreenUsageMode var) const; + const char* getAocRegistrationTypeStr(nn::hac::nacp::AocRegistrationType var) const; + const char* getAttributeFlagStr(nn::hac::nacp::AttributeFlag var) const; + const char* getParentalControlFlagStr(nn::hac::nacp::ParentalControlFlag var) const; + const char* getScreenshotModeStr(nn::hac::nacp::ScreenshotMode var) const; + const char* getVideoCaptureModeStr(nn::hac::nacp::VideoCaptureMode var) const; + const char* getDataLossConfirmationStr(nn::hac::nacp::DataLossConfirmation var) const; + const char* getPlayLogPolicyStr(nn::hac::nacp::PlayLogPolicy var) const; + const char* getOrganisationStr(nn::hac::nacp::Organisation var) const; + const char* getLogoTypeStr(nn::hac::nacp::LogoType var) const; + const char* getLogoHandlingStr(nn::hac::nacp::LogoHandling var) const; + const char* getRuntimeAocInstallModeStr(nn::hac::nacp::RuntimeAocInstallMode var) const; + const char* getCrashReportModeStr(nn::hac::nacp::CrashReportMode var) const; + const char* getHdcpStr(nn::hac::nacp::Hdcp var) const; + const char* getPlayLogQueryCapabilityStr(nn::hac::nacp::PlayLogQueryCapability var) const; + const char* getRepairFlagStr(nn::hac::nacp::RepairFlag var) const; + std::string getSaveDataSizeStr(int64_t size) const; }; \ No newline at end of file diff --git a/programs/nstool/source/NcaProcess.cpp b/programs/nstool/source/NcaProcess.cpp index 323f5a4..575b96b 100644 --- a/programs/nstool/source/NcaProcess.cpp +++ b/programs/nstool/source/NcaProcess.cpp @@ -1,831 +1,834 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "NcaProcess.h" -#include "PfsProcess.h" -#include "RomfsProcess.h" -#include "MetaProcess.h" - - -NcaProcess::NcaProcess() : - mFile(), - mCliOutputMode(_BIT(OUTPUT_BASIC)), - mVerify(false), - mListFs(false) -{ - for (size_t i = 0; i < nn::hac::nca::kPartitionNum; i++) - { - mPartitionPath[i].doExtract = false; - } -} - -void NcaProcess::process() -{ - // import header - importHeader(); - - // determine keys - generateNcaBodyEncryptionKeys(); - - // import/generate fs header data - generatePartitionConfiguration(); - - // validate signatures - if (mVerify) - validateNcaSignatures(); - - // display header - if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) - displayHeader(); - - // process partition - processPartitions(); -} - -void NcaProcess::setInputFile(const fnd::SharedPtr& file) -{ - mFile = file; -} - -void NcaProcess::setKeyCfg(const KeyConfiguration& keycfg) -{ - mKeyCfg = keycfg; -} - -void NcaProcess::setCliOutputMode(CliOutputMode type) -{ - mCliOutputMode = type; -} - -void NcaProcess::setVerifyMode(bool verify) -{ - mVerify = verify; -} - -void NcaProcess::setPartition0ExtractPath(const std::string& path) -{ - mPartitionPath[0].path = path; - mPartitionPath[0].doExtract = true; -} - -void NcaProcess::setPartition1ExtractPath(const std::string& path) -{ - mPartitionPath[1].path = path; - mPartitionPath[1].doExtract = true; -} - -void NcaProcess::setPartition2ExtractPath(const std::string& path) -{ - mPartitionPath[2].path = path; - mPartitionPath[2].doExtract = true; -} - -void NcaProcess::setPartition3ExtractPath(const std::string& path) -{ - mPartitionPath[3].path = path; - mPartitionPath[3].doExtract = true; -} - -void NcaProcess::setListFs(bool list_fs) -{ - mListFs = list_fs; -} - -void NcaProcess::importHeader() -{ - if (*mFile == nullptr) - { - throw fnd::Exception(kModuleName, "No file reader set."); - } - - // read header block - (*mFile)->read((byte_t*)&mHdrBlock, 0, sizeof(nn::hac::sNcaHeaderBlock)); - - // decrypt header block - fnd::aes::sAesXts128Key header_key; - mKeyCfg.getNcaHeaderKey(header_key); - nn::hac::NcaUtils::decryptNcaHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, header_key); - - // generate header hash - fnd::sha::Sha256((byte_t*)&mHdrBlock.header, sizeof(nn::hac::sNcaHeader), mHdrHash.bytes); - - // proccess main header - mHdr.fromBytes((byte_t*)&mHdrBlock.header, sizeof(nn::hac::sNcaHeader)); -} - -void NcaProcess::generateNcaBodyEncryptionKeys() -{ - // create zeros key - fnd::aes::sAes128Key zero_aesctr_key; - memset(zero_aesctr_key.key, 0, sizeof(zero_aesctr_key)); - - // get key data from header - byte_t masterkey_rev = nn::hac::NcaUtils::getMasterKeyRevisionFromKeyGeneration(mHdr.getKeyGeneration()); - byte_t keak_index = mHdr.getKaekIndex(); - - // process key area - sKeys::sKeyAreaKey kak; - fnd::aes::sAes128Key key_area_enc_key; - for (size_t i = 0; i < nn::hac::nca::kAesKeyNum; i++) - { - if (mHdr.getEncAesKeys()[i] != zero_aesctr_key) - { - kak.index = (byte_t)i; - kak.enc = mHdr.getEncAesKeys()[i]; - // key[0-3] - if (i < 4 && mKeyCfg.getNcaKeyAreaEncryptionKey(masterkey_rev, keak_index, key_area_enc_key) == true) - { - kak.decrypted = true; - nn::hac::AesKeygen::generateKey(kak.dec.key, kak.enc.key, key_area_enc_key.key); - } - // key[4] - else if (i == 4 && mKeyCfg.getNcaKeyAreaEncryptionKeyHw(masterkey_rev, keak_index, key_area_enc_key) == true) - { - kak.decrypted = true; - nn::hac::AesKeygen::generateKey(kak.dec.key, kak.enc.key, key_area_enc_key.key); - } - else - { - kak.decrypted = false; - } - mContentKey.kak_list.addElement(kak); - } - } - - // set flag to indicate that the keys are not available - mContentKey.aes_ctr.isSet = false; - - // if this has a rights id, the key needs to be sourced from a ticket - if (mHdr.hasRightsId() == true) - { - fnd::aes::sAes128Key tmp_key; - if (mKeyCfg.getNcaExternalContentKey(mHdr.getRightsId(), tmp_key) == true) - { - mContentKey.aes_ctr = tmp_key; - } - else if (mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserTitleKey, tmp_key) == true) - { - fnd::aes::sAes128Key common_key; - if (mKeyCfg.getETicketCommonKey(masterkey_rev, common_key) == true) - { - nn::hac::AesKeygen::generateKey(tmp_key.key, tmp_key.key, common_key.key); - } - mContentKey.aes_ctr = tmp_key; - } - } - // otherwise decrypt key area - else - { - fnd::aes::sAes128Key kak_aes_ctr = zero_aesctr_key; - 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) - { - kak_aes_ctr = mContentKey.kak_list[i].dec; - } - } - - if (kak_aes_ctr != zero_aesctr_key) - { - mContentKey.aes_ctr = kak_aes_ctr; - } - } - - // if the keys weren't generated, check if the keys were supplied by the user - if (mContentKey.aes_ctr.isSet == false) - { - if (mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserBodyKey, mContentKey.aes_ctr.var) == true) - mContentKey.aes_ctr.isSet = true; - } - - - if (_HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA)) - { - if (mContentKey.aes_ctr.isSet) - { - std::cout << "[NCA Content Key]" << std::endl; - std::cout << " AES-CTR Key: " << fnd::SimpleTextOutput::arrayToString(mContentKey.aes_ctr.var.key, sizeof(mContentKey.aes_ctr.var), true, ":") << std::endl; - } - } - - -} - -void NcaProcess::generatePartitionConfiguration() -{ - std::stringstream error; - - for (size_t i = 0; i < mHdr.getPartitions().size(); i++) - { - // get reference to relevant structures - const nn::hac::NcaHeader::sPartition& partition = mHdr.getPartitions()[i]; - nn::hac::sNcaFsHeader& fs_header = mHdrBlock.fs_header[partition.index]; - - // output structure - sPartitionInfo& info = mPartitions[partition.index]; - - // validate header hash - fnd::sha::sSha256Hash calc_hash; - fnd::sha::Sha256((const byte_t*)&mHdrBlock.fs_header[partition.index], sizeof(nn::hac::sNcaFsHeader), calc_hash.bytes); - if (calc_hash.compare(partition.hash) == false) - { - error.clear(); - error << "NCA FS Header [" << partition.index << "] Hash: FAIL \n"; - throw fnd::Exception(kModuleName, error.str()); - } - - - if (fs_header.version.get() != nn::hac::nca::kDefaultFsHeaderVersion) - { - error.clear(); - error << "NCA FS Header [" << partition.index << "] Version(" << fs_header.version.get() << "): UNSUPPORTED"; - throw fnd::Exception(kModuleName, error.str()); - } - - // setup AES-CTR - nn::hac::NcaUtils::getNcaPartitionAesCtr(&fs_header, info.aes_ctr.iv); - - // save partition config - info.reader = nullptr; - 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::HASH_HIERARCHICAL_SHA256) - { - // info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, LayeredIntegrityMetadata::HASH_TYPE_SHA256); - nn::hac::HierarchicalSha256Header hdr; - fnd::List hash_layers; - fnd::LayeredIntegrityMetadata::sLayer data_layer; - fnd::List master_hash_list; - - // import raw data - hdr.fromBytes(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen); - for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) - { - fnd::LayeredIntegrityMetadata::sLayer layer; - layer.offset = hdr.getLayerInfo()[i].offset; - layer.size = hdr.getLayerInfo()[i].size; - layer.block_size = hdr.getHashBlockSize(); - if (i + 1 == hdr.getLayerInfo().size()) - { - data_layer = layer; - } - else - { - hash_layers.addElement(layer); - } - } - master_hash_list.addElement(hdr.getMasterHash()); - - // write data into metadata - info.layered_intergrity_metadata.setAlignHashToBlock(false); - info.layered_intergrity_metadata.setHashLayerInfo(hash_layers); - info.layered_intergrity_metadata.setDataLayerInfo(data_layer); - info.layered_intergrity_metadata.setMasterHashList(master_hash_list); - } - else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) - { - // info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, LayeredIntegrityMetadata::HASH_TYPE_INTEGRITY); - nn::hac::HierarchicalIntegrityHeader hdr; - fnd::List hash_layers; - fnd::LayeredIntegrityMetadata::sLayer data_layer; - fnd::List master_hash_list; - - hdr.fromBytes(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen); - for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) - { - fnd::LayeredIntegrityMetadata::sLayer layer; - layer.offset = hdr.getLayerInfo()[i].offset; - layer.size = hdr.getLayerInfo()[i].size; - layer.block_size = _BIT(hdr.getLayerInfo()[i].block_size); - if (i + 1 == hdr.getLayerInfo().size()) - { - data_layer = layer; - } - else - { - hash_layers.addElement(layer); - } - } - - // write data into metadata - info.layered_intergrity_metadata.setAlignHashToBlock(true); - info.layered_intergrity_metadata.setHashLayerInfo(hash_layers); - info.layered_intergrity_metadata.setDataLayerInfo(data_layer); - info.layered_intergrity_metadata.setMasterHashList(hdr.getMasterHashList()); - } - - // create reader - try - { - // filter out unrecognised format types - switch (info.format_type) - { - case (nn::hac::nca::FORMAT_PFS0): - case (nn::hac::nca::FORMAT_ROMFS): - break; - default: - error.clear(); - error << "FormatType(" << info.format_type << "): UNKNOWN"; - throw fnd::Exception(kModuleName, error.str()); - } - - // create reader based on encryption type0 - if (info.enc_type == nn::hac::nca::CRYPT_NONE) - { - info.reader = new fnd::OffsetAdjustedIFile(mFile, info.offset, info.size); - } - else if (info.enc_type == nn::hac::nca::CRYPT_AESCTR) - { - if (mContentKey.aes_ctr.isSet == false) - throw fnd::Exception(kModuleName, "AES-CTR Key was not determined"); - info.reader = new fnd::OffsetAdjustedIFile(new fnd::AesCtrWrappedIFile(mFile, mContentKey.aes_ctr.var, info.aes_ctr), info.offset, info.size); - } - else if (info.enc_type == nn::hac::nca::CRYPT_AESXTS || info.enc_type == nn::hac::nca::CRYPT_AESCTREX) - { - error.clear(); - error << "EncryptionType(" << getEncryptionTypeStr(info.enc_type) << "): UNSUPPORTED"; - throw fnd::Exception(kModuleName, error.str()); - } - else - { - error.clear(); - error << "EncryptionType(" << info.enc_type << "): UNKNOWN"; - throw fnd::Exception(kModuleName, error.str()); - } - - // filter out unrecognised hash types, and hash based readers - if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256 || info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) - { - info.reader = new fnd::LayeredIntegrityWrappedIFile(info.reader, info.layered_intergrity_metadata); - } - else if (info.hash_type != nn::hac::nca::HASH_NONE) - { - error.clear(); - error << "HashType(" << info.hash_type << "): UNKNOWN"; - throw fnd::Exception(kModuleName, error.str()); - } - } - catch (const fnd::Exception& e) - { - info.fail_reason = std::string(e.error()); - } - } -} - -void NcaProcess::validateNcaSignatures() -{ - // validate signature[0] - fnd::rsa::sRsa2048Key sign0_key; - mKeyCfg.getNcaHeader0SignKey(sign0_key); - if (fnd::rsa::pss::rsaVerify(sign0_key, fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_main) != 0) - { - std::cout << "[WARNING] NCA Header Main Signature: FAIL" << std::endl; - } - - // validate signature[1] - if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM) - { - if (mPartitions[nn::hac::nca::PARTITION_CODE].format_type == nn::hac::nca::FORMAT_PFS0) - { - if (*mPartitions[nn::hac::nca::PARTITION_CODE].reader != nullptr) - { - PfsProcess exefs; - exefs.setInputFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader); - exefs.setCliOutputMode(0); - exefs.process(); - - // open main.npdm - if (exefs.getPfsHeader().getFileList().hasElement(kNpdmExefsPath) == true) - { - const nn::hac::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList().getElement(kNpdmExefsPath); - - MetaProcess npdm; - npdm.setInputFile(new fnd::OffsetAdjustedIFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, file.offset, file.size)); - npdm.setCliOutputMode(0); - npdm.process(); - - if (fnd::rsa::pss::rsaVerify(npdm.getMetaBinary().getAcid().getNcaHeaderSignature2Key(), fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0) - { - std::cout << "[WARNING] NCA Header ACID Signature: FAIL" << std::endl; - } - - } - else - { - std::cout << "[WARNING] NCA Header ACID Signature: FAIL (\"" << kNpdmExefsPath << "\" not present in ExeFs)" << std::endl; - } - } - else - { - std::cout << "[WARNING] NCA Header ACID Signature: FAIL (ExeFs unreadable)" << std::endl; - } - } - else - { - std::cout << "[WARNING] NCA Header ACID Signature: FAIL (No ExeFs partition)" << std::endl; - } - } -} - -void NcaProcess::displayHeader() -{ - std::cout << "[NCA Header]" << std::endl; - std::cout << " Format Type: " << getFormatVersionStr(mHdr.getFormatVersion()) << std::endl; - std::cout << " Dist. Type: " << getDistributionTypeStr(mHdr.getDistributionType()) << std::endl; - std::cout << " Content Type: " << getContentTypeStr(mHdr.getContentType()) << std::endl; - std::cout << " Key Generation: " << std::dec << (uint32_t)mHdr.getKeyGeneration() << std::endl; - std::cout << " Kaek Index: " << getKaekIndexStr((nn::hac::nca::KeyAreaEncryptionKeyIndex)mHdr.getKaekIndex()) << " (" << std::dec << (uint32_t)mHdr.getKaekIndex() << ")" << std::endl; - std::cout << " Size: 0x" << std::hex << mHdr.getContentSize() << std::endl; - std::cout << " ProgID: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getProgramId() << std::endl; - std::cout << " Content Index: " << std::dec << mHdr.getContentIndex() << std::endl; -#define _SPLIT_VER(ver) std::dec << (uint32_t)((ver>>24) & 0xff) << "." << (uint32_t)((ver>>16) & 0xff) << "." << (uint32_t)((ver>>8) & 0xff) - std::cout << " SdkAddon Ver.: v" << std::dec << mHdr.getSdkAddonVersion() << " (" << _SPLIT_VER(mHdr.getSdkAddonVersion()) << ")" << std::endl; -#undef _SPLIT_VER - if (mHdr.hasRightsId()) - { - std::cout << " RightsId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRightsId(), nn::hac::nca::kRightsIdLen, true, "") << std::endl; - } - - if (mContentKey.kak_list.size() > 0 && _HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA)) - { - std::cout << " Key Area:" << std::endl; - std::cout << " <--------------------------------------------------------------------------------------------------------->" << std::endl; - std::cout << " | IDX | ENCRYPTED KEY | DECRYPTED KEY |" << std::endl; - std::cout << " |-----|-------------------------------------------------|-------------------------------------------------|" << std::endl; - for (size_t i = 0; i < mContentKey.kak_list.size(); i++) - { - std::cout << " | " << std::dec << std::setw(3) << std::setfill(' ') << (uint32_t)mContentKey.kak_list[i].index << " | "; - - std::cout << fnd::SimpleTextOutput::arrayToString(mContentKey.kak_list[i].enc.key, 16, true, ":") << " | "; - - - if (mContentKey.kak_list[i].decrypted) - std::cout << fnd::SimpleTextOutput::arrayToString(mContentKey.kak_list[i].dec.key, 16, true, ":"); - else - std::cout << " "; - - std::cout << " |" << std::endl; - } - std::cout << " <--------------------------------------------------------------------------------------------------------->" << std::endl; - } - - if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT)) - { - std::cout << " Partitions:" << std::endl; - for (size_t i = 0; i < mHdr.getPartitions().size(); i++) - { - size_t index = mHdr.getPartitions()[i].index; - sPartitionInfo& info = mPartitions[index]; - - std::cout << " " << std::dec << index << ":" << std::endl; - std::cout << " Offset: 0x" << std::hex << (uint64_t)info.offset << std::endl; - std::cout << " Size: 0x" << std::hex << (uint64_t)info.size << std::endl; - std::cout << " Format Type: " << getFormatTypeStr(info.format_type) << std::endl; - std::cout << " Hash Type: " << getHashTypeStr(info.hash_type) << std::endl; - std::cout << " Enc. Type: " << getEncryptionTypeStr(info.enc_type) << std::endl; - if (info.enc_type == nn::hac::nca::CRYPT_AESCTR) - { - fnd::aes::sAesIvCtr ctr; - fnd::aes::AesIncrementCounter(info.aes_ctr.iv, info.offset>>4, ctr.iv); - std::cout << " AesCtr Counter:" << std::endl; - std::cout << " " << fnd::SimpleTextOutput::arrayToString(ctr.iv, sizeof(fnd::aes::sAesIvCtr), true, ":") << std::endl; - } - if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) - { - fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata; - std::cout << " HierarchicalIntegrity Header:" << std::endl; - for (size_t j = 0; j < hash_hdr.getHashLayerInfo().size(); j++) - { - std::cout << " Hash Layer " << std::dec << j << ":" << std::endl; - std::cout << " Offset: 0x" << std::hex << (uint64_t)hash_hdr.getHashLayerInfo()[j].offset << std::endl; - std::cout << " Size: 0x" << std::hex << (uint64_t)hash_hdr.getHashLayerInfo()[j].size << std::endl; - std::cout << " BlockSize: 0x" << std::hex << (uint32_t)hash_hdr.getHashLayerInfo()[j].block_size << std::endl; - } - - std::cout << " Data Layer:" << std::endl; - std::cout << " Offset: 0x" << std::hex << (uint64_t)hash_hdr.getDataLayer().offset << std::endl; - std::cout << " Size: 0x" << std::hex << (uint64_t)hash_hdr.getDataLayer().size << std::endl; - std::cout << " BlockSize: 0x" << std::hex << (uint32_t)hash_hdr.getDataLayer().block_size << std::endl; - for (size_t j = 0; j < hash_hdr.getMasterHashList().size(); j++) - { - std::cout << " Master Hash " << std::dec << j << ":" << std::endl; - std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[j].bytes, 0x10, true, ":") << std::endl; - std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[j].bytes+0x10, 0x10, true, ":") << std::endl; - } - } - else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256) - { - fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata; - std::cout << " HierarchicalSha256 Header:" << std::endl; - std::cout << " Master Hash:" << std::endl; - std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[0].bytes, 0x10, true, ":") << std::endl; - std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[0].bytes+0x10, 0x10, true, ":") << std::endl; - std::cout << " HashBlockSize: 0x" << std::hex << (uint32_t)hash_hdr.getDataLayer().block_size << std::endl; - std::cout << " Hash Layer:" << std::endl; - std::cout << " Offset: 0x" << std::hex << (uint64_t)hash_hdr.getHashLayerInfo()[0].offset << std::endl; - std::cout << " Size: 0x" << std::hex << (uint64_t)hash_hdr.getHashLayerInfo()[0].size << std::endl; - std::cout << " Data Layer:" << std::endl; - std::cout << " Offset: 0x" << std::hex << (uint64_t)hash_hdr.getDataLayer().offset << std::endl; - std::cout << " Size: 0x" << std::hex << (uint64_t)hash_hdr.getDataLayer().size << std::endl; - } - } - } -} - - -void NcaProcess::processPartitions() -{ - for (size_t i = 0; i < mHdr.getPartitions().size(); i++) - { - size_t index = mHdr.getPartitions()[i].index; - struct sPartitionInfo& partition = mPartitions[index]; - - // if the reader is null, skip - if (*partition.reader == nullptr) - { - std::cout << "[WARNING] NCA Partition " << std::dec << index << " not readable."; - if (partition.fail_reason.empty() == false) - { - std::cout << " (" << partition.fail_reason << ")"; - } - std::cout << std::endl; - continue; - } - - if (partition.format_type == nn::hac::nca::FORMAT_PFS0) - { - PfsProcess pfs; - pfs.setInputFile(partition.reader); - pfs.setCliOutputMode(mCliOutputMode); - pfs.setListFs(mListFs); - if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM) - { - pfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/" + std::string(getProgramPartitionNameStr(index))); - } - else - { - pfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/"); - } - - if (mPartitionPath[index].doExtract) - pfs.setExtractPath(mPartitionPath[index].path); - pfs.process(); - } - else if (partition.format_type == nn::hac::nca::FORMAT_ROMFS) - { - RomfsProcess romfs; - romfs.setInputFile(partition.reader); - romfs.setCliOutputMode(mCliOutputMode); - romfs.setListFs(mListFs); - if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM) - { - romfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/" + std::string(getProgramPartitionNameStr(index))); - } - else - { - romfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/"); - } - - if (mPartitionPath[index].doExtract) - romfs.setExtractPath(mPartitionPath[index].path); - romfs.process(); - } - } -} - -const char* NcaProcess::getFormatVersionStr(nn::hac::NcaHeader::FormatVersion format_ver) const -{ - const char* str = nullptr; - - switch (format_ver) - { - case (nn::hac::NcaHeader::NCA2_FORMAT): - str = "NCA2"; - break; - case (nn::hac::NcaHeader::NCA3_FORMAT): - str = "NCA3"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* NcaProcess::getDistributionTypeStr(nn::hac::nca::DistributionType dist_type) const -{ - const char* str = nullptr; - - switch (dist_type) - { - case (nn::hac::nca::DIST_DOWNLOAD): - str = "Download"; - break; - case (nn::hac::nca::DIST_GAME_CARD): - str = "Game Card"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - - -const char* NcaProcess::getContentTypeStr(nn::hac::nca::ContentType cont_type) const -{ - const char* str = nullptr; - - switch (cont_type) - { - case (nn::hac::nca::TYPE_PROGRAM): - str = "Program"; - break; - case (nn::hac::nca::TYPE_META): - str = "Meta"; - break; - case (nn::hac::nca::TYPE_CONTROL): - str = "Control"; - break; - case (nn::hac::nca::TYPE_MANUAL): - str = "Manual"; - break; - case (nn::hac::nca::TYPE_DATA): - str = "Data"; - break; - case (nn::hac::nca::TYPE_PUBLIC_DATA): - str = "PublicData"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* NcaProcess::getEncryptionTypeStr(nn::hac::nca::EncryptionType enc_type) const -{ - const char* str = nullptr; - - switch (enc_type) - { - case (nn::hac::nca::CRYPT_AUTO): - str = "Auto"; - break; - case (nn::hac::nca::CRYPT_NONE): - str = "None"; - break; - case (nn::hac::nca::CRYPT_AESXTS): - str = "AesXts"; - break; - case (nn::hac::nca::CRYPT_AESCTR): - str = "AesCtr"; - break; - case (nn::hac::nca::CRYPT_AESCTREX): - str = "AesCtrEx"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* NcaProcess::getHashTypeStr(nn::hac::nca::HashType hash_type) const -{ - const char* str = nullptr; - - switch (hash_type) - { - case (nn::hac::nca::HASH_AUTO): - str = "Auto"; - break; - case (nn::hac::nca::HASH_NONE): - str = "None"; - break; - case (nn::hac::nca::HASH_HIERARCHICAL_SHA256): - str = "HierarchicalSha256"; - break; - case (nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY): - str = "HierarchicalIntegrity"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* NcaProcess::getFormatTypeStr(nn::hac::nca::FormatType format_type) const -{ - const char* str = nullptr; - - switch (format_type) - { - case (nn::hac::nca::FORMAT_ROMFS): - str = "RomFs"; - break; - case (nn::hac::nca::FORMAT_PFS0): - str = "PartitionFs"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* NcaProcess::getKaekIndexStr(nn::hac::nca::KeyAreaEncryptionKeyIndex keak_index) const -{ - const char* str = nullptr; - - switch (keak_index) - { - case (nn::hac::nca::KAEK_IDX_APPLICATION): - str = "Application"; - break; - case (nn::hac::nca::KAEK_IDX_OCEAN): - str = "Ocean"; - break; - case (nn::hac::nca::KAEK_IDX_SYSTEM): - str = "System"; - break; - default: - str = "Unknown"; - break; - } - - return str; -} - -const char* NcaProcess::getContentTypeForMountStr(nn::hac::nca::ContentType cont_type) const -{ - const char* str = nullptr; - - switch (cont_type) - { - case (nn::hac::nca::TYPE_PROGRAM): - str = "program"; - break; - case (nn::hac::nca::TYPE_META): - str = "meta"; - break; - case (nn::hac::nca::TYPE_CONTROL): - str = "control"; - break; - case (nn::hac::nca::TYPE_MANUAL): - str = "manual"; - break; - case (nn::hac::nca::TYPE_DATA): - str = "data"; - break; - case (nn::hac::nca::TYPE_PUBLIC_DATA): - str = "publicData"; - break; - default: - str = ""; - break; - } - - return str; -} - -const char* NcaProcess::getProgramPartitionNameStr(size_t i) const -{ - const char* str = nullptr; - - switch (i) - { - case (nn::hac::nca::PARTITION_CODE): - str = "code"; - break; - case (nn::hac::nca::PARTITION_DATA): - str = "data"; - break; - case (nn::hac::nca::PARTITION_LOGO): - str = "logo"; - break; - default: - str = ""; - break; - } - - return str; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "NcaProcess.h" +#include "PfsProcess.h" +#include "RomfsProcess.h" +#include "MetaProcess.h" + + +NcaProcess::NcaProcess() : + mFile(), + mCliOutputMode(_BIT(OUTPUT_BASIC)), + mVerify(false), + mListFs(false) +{ + for (size_t i = 0; i < nn::hac::nca::kPartitionNum; i++) + { + mPartitionPath[i].doExtract = false; + } +} + +void NcaProcess::process() +{ + // import header + importHeader(); + + // determine keys + generateNcaBodyEncryptionKeys(); + + // import/generate fs header data + generatePartitionConfiguration(); + + // validate signatures + if (mVerify) + validateNcaSignatures(); + + // display header + if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) + displayHeader(); + + // process partition + processPartitions(); +} + +void NcaProcess::setInputFile(const fnd::SharedPtr& file) +{ + mFile = file; +} + +void NcaProcess::setKeyCfg(const KeyConfiguration& keycfg) +{ + mKeyCfg = keycfg; +} + +void NcaProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void NcaProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +void NcaProcess::setPartition0ExtractPath(const std::string& path) +{ + mPartitionPath[0].path = path; + mPartitionPath[0].doExtract = true; +} + +void NcaProcess::setPartition1ExtractPath(const std::string& path) +{ + mPartitionPath[1].path = path; + mPartitionPath[1].doExtract = true; +} + +void NcaProcess::setPartition2ExtractPath(const std::string& path) +{ + mPartitionPath[2].path = path; + mPartitionPath[2].doExtract = true; +} + +void NcaProcess::setPartition3ExtractPath(const std::string& path) +{ + mPartitionPath[3].path = path; + mPartitionPath[3].doExtract = true; +} + +void NcaProcess::setListFs(bool list_fs) +{ + mListFs = list_fs; +} + +void NcaProcess::importHeader() +{ + if (*mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + // read header block + (*mFile)->read((byte_t*)&mHdrBlock, 0, sizeof(nn::hac::sContentArchiveHeaderBlock)); + + // decrypt header block + fnd::aes::sAesXts128Key header_key; + mKeyCfg.getContentArchiveHeaderKey(header_key); + nn::hac::ContentArchiveUtils::decryptContentArchiveHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, header_key); + + // generate header hash + fnd::sha::Sha256((byte_t*)&mHdrBlock.header, sizeof(nn::hac::sContentArchiveHeader), mHdrHash.bytes); + + // proccess main header + mHdr.fromBytes((byte_t*)&mHdrBlock.header, sizeof(nn::hac::sContentArchiveHeader)); +} + +void NcaProcess::generateNcaBodyEncryptionKeys() +{ + // create zeros key + fnd::aes::sAes128Key zero_aesctr_key; + memset(zero_aesctr_key.key, 0, sizeof(zero_aesctr_key)); + + // get key data from header + byte_t masterkey_rev = nn::hac::ContentArchiveUtils::getMasterKeyRevisionFromKeyGeneration(mHdr.getKeyGeneration()); + byte_t keak_index = mHdr.getKeyAreaEncryptionKeyIndex(); + + // process key area + sKeys::sKeyAreaKey kak; + fnd::aes::sAes128Key key_area_enc_key; + const fnd::aes::sAes128Key* key_area = (const fnd::aes::sAes128Key*) mHdr.getKeyArea(); + + for (size_t i = 0; i < nn::hac::nca::kKeyAreaKeyNum; i++) + { + if (key_area[i] != zero_aesctr_key) + { + kak.index = (byte_t)i; + kak.enc = key_area[i]; + // key[0-3] + if (i < 4 && mKeyCfg.getNcaKeyAreaEncryptionKey(masterkey_rev, keak_index, key_area_enc_key) == true) + { + kak.decrypted = true; + nn::hac::AesKeygen::generateKey(kak.dec.key, kak.enc.key, key_area_enc_key.key); + } + // key[KEY_AESCTR_HW] + else if (i == nn::hac::nca::KEY_AESCTR_HW && mKeyCfg.getNcaKeyAreaEncryptionKeyHw(masterkey_rev, keak_index, key_area_enc_key) == true) + { + kak.decrypted = true; + nn::hac::AesKeygen::generateKey(kak.dec.key, kak.enc.key, key_area_enc_key.key); + } + else + { + kak.decrypted = false; + } + mContentKey.kak_list.addElement(kak); + } + } + + // set flag to indicate that the keys are not available + mContentKey.aes_ctr.isSet = false; + + // if this has a rights id, the key needs to be sourced from a ticket + if (mHdr.hasRightsId() == true) + { + fnd::aes::sAes128Key tmp_key; + if (mKeyCfg.getNcaExternalContentKey(mHdr.getRightsId(), tmp_key) == true) + { + mContentKey.aes_ctr = tmp_key; + } + else if (mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserTitleKey, tmp_key) == true) + { + fnd::aes::sAes128Key common_key; + if (mKeyCfg.getETicketCommonKey(masterkey_rev, common_key) == true) + { + nn::hac::AesKeygen::generateKey(tmp_key.key, tmp_key.key, common_key.key); + } + mContentKey.aes_ctr = tmp_key; + } + } + // otherwise decrypt key area + else + { + fnd::aes::sAes128Key kak_aes_ctr = zero_aesctr_key; + 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) + { + kak_aes_ctr = mContentKey.kak_list[i].dec; + } + } + + if (kak_aes_ctr != zero_aesctr_key) + { + mContentKey.aes_ctr = kak_aes_ctr; + } + } + + // if the keys weren't generated, check if the keys were supplied by the user + if (mContentKey.aes_ctr.isSet == false) + { + if (mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserBodyKey, mContentKey.aes_ctr.var) == true) + mContentKey.aes_ctr.isSet = true; + } + + + if (_HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA)) + { + if (mContentKey.aes_ctr.isSet) + { + std::cout << "[NCA Content Key]" << std::endl; + std::cout << " AES-CTR Key: " << fnd::SimpleTextOutput::arrayToString(mContentKey.aes_ctr.var.key, sizeof(mContentKey.aes_ctr.var), true, ":") << std::endl; + } + } + + +} + +void NcaProcess::generatePartitionConfiguration() +{ + std::stringstream error; + + 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::sNcaFsHeader& fs_header = mHdrBlock.fs_header[partition.header_index]; + + // output structure + sPartitionInfo& info = mPartitions[partition.header_index]; + + // validate header hash + fnd::sha::sSha256Hash fs_header_hash; + fnd::sha::Sha256((const byte_t*)&mHdrBlock.fs_header[partition.header_index], sizeof(nn::hac::sNcaFsHeader), fs_header_hash.bytes); + if (fs_header_hash.compare(partition.fs_header_hash) == false) + { + error.clear(); + error << "NCA FS Header [" << partition.header_index << "] Hash: FAIL \n"; + throw fnd::Exception(kModuleName, error.str()); + } + + + if (fs_header.version.get() != nn::hac::nca::kDefaultFsHeaderVersion) + { + error.clear(); + error << "NCA FS Header [" << partition.header_index << "] Version(" << fs_header.version.get() << "): UNSUPPORTED"; + throw fnd::Exception(kModuleName, error.str()); + } + + // setup AES-CTR + nn::hac::ContentArchiveUtils::getNcaPartitionAesCtr(&fs_header, info.aes_ctr.iv); + + // save partition config + info.reader = nullptr; + 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::HASH_HIERARCHICAL_SHA256) + { + // info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, LayeredIntegrityMetadata::HASH_TYPE_SHA256); + nn::hac::HierarchicalSha256Header hdr; + fnd::List hash_layers; + fnd::LayeredIntegrityMetadata::sLayer data_layer; + fnd::List master_hash_list; + + // import raw data + hdr.fromBytes(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen); + for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) + { + fnd::LayeredIntegrityMetadata::sLayer layer; + layer.offset = hdr.getLayerInfo()[i].offset; + layer.size = hdr.getLayerInfo()[i].size; + layer.block_size = hdr.getHashBlockSize(); + if (i + 1 == hdr.getLayerInfo().size()) + { + data_layer = layer; + } + else + { + hash_layers.addElement(layer); + } + } + master_hash_list.addElement(hdr.getMasterHash()); + + // write data into metadata + info.layered_intergrity_metadata.setAlignHashToBlock(false); + info.layered_intergrity_metadata.setHashLayerInfo(hash_layers); + info.layered_intergrity_metadata.setDataLayerInfo(data_layer); + info.layered_intergrity_metadata.setMasterHashList(master_hash_list); + } + else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) + { + // info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, LayeredIntegrityMetadata::HASH_TYPE_INTEGRITY); + nn::hac::HierarchicalIntegrityHeader hdr; + fnd::List hash_layers; + fnd::LayeredIntegrityMetadata::sLayer data_layer; + fnd::List master_hash_list; + + hdr.fromBytes(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen); + for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) + { + fnd::LayeredIntegrityMetadata::sLayer layer; + layer.offset = hdr.getLayerInfo()[i].offset; + layer.size = hdr.getLayerInfo()[i].size; + layer.block_size = _BIT(hdr.getLayerInfo()[i].block_size); + if (i + 1 == hdr.getLayerInfo().size()) + { + data_layer = layer; + } + else + { + hash_layers.addElement(layer); + } + } + + // write data into metadata + info.layered_intergrity_metadata.setAlignHashToBlock(true); + info.layered_intergrity_metadata.setHashLayerInfo(hash_layers); + info.layered_intergrity_metadata.setDataLayerInfo(data_layer); + info.layered_intergrity_metadata.setMasterHashList(hdr.getMasterHashList()); + } + + // create reader + try + { + // filter out unrecognised format types + switch (info.format_type) + { + case (nn::hac::nca::FORMAT_PFS0): + case (nn::hac::nca::FORMAT_ROMFS): + break; + default: + error.clear(); + error << "FormatType(" << info.format_type << "): UNKNOWN"; + throw fnd::Exception(kModuleName, error.str()); + } + + // create reader based on encryption type0 + if (info.enc_type == nn::hac::nca::CRYPT_NONE) + { + info.reader = new fnd::OffsetAdjustedIFile(mFile, info.offset, info.size); + } + else if (info.enc_type == nn::hac::nca::CRYPT_AESCTR) + { + if (mContentKey.aes_ctr.isSet == false) + throw fnd::Exception(kModuleName, "AES-CTR Key was not determined"); + info.reader = new fnd::OffsetAdjustedIFile(new fnd::AesCtrWrappedIFile(mFile, mContentKey.aes_ctr.var, info.aes_ctr), info.offset, info.size); + } + else if (info.enc_type == nn::hac::nca::CRYPT_AESXTS || info.enc_type == nn::hac::nca::CRYPT_AESCTREX) + { + error.clear(); + error << "EncryptionType(" << getEncryptionTypeStr(info.enc_type) << "): UNSUPPORTED"; + throw fnd::Exception(kModuleName, error.str()); + } + else + { + error.clear(); + error << "EncryptionType(" << info.enc_type << "): UNKNOWN"; + throw fnd::Exception(kModuleName, error.str()); + } + + // filter out unrecognised hash types, and hash based readers + if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256 || info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) + { + info.reader = new fnd::LayeredIntegrityWrappedIFile(info.reader, info.layered_intergrity_metadata); + } + else if (info.hash_type != nn::hac::nca::HASH_NONE) + { + error.clear(); + error << "HashType(" << info.hash_type << "): UNKNOWN"; + throw fnd::Exception(kModuleName, error.str()); + } + } + catch (const fnd::Exception& e) + { + info.fail_reason = std::string(e.error()); + } + } +} + +void NcaProcess::validateNcaSignatures() +{ + // validate signature[0] + fnd::rsa::sRsa2048Key sign0_key; + mKeyCfg.getContentArchiveHeader0SignKey(sign0_key); + if (fnd::rsa::pss::rsaVerify(sign0_key, fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_main) != 0) + { + std::cout << "[WARNING] NCA Header Main Signature: FAIL" << std::endl; + } + + // validate signature[1] + if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM) + { + if (mPartitions[nn::hac::nca::PARTITION_CODE].format_type == nn::hac::nca::FORMAT_PFS0) + { + if (*mPartitions[nn::hac::nca::PARTITION_CODE].reader != nullptr) + { + PfsProcess exefs; + exefs.setInputFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader); + exefs.setCliOutputMode(0); + exefs.process(); + + // open main.npdm + if (exefs.getPfsHeader().getFileList().hasElement(kNpdmExefsPath) == true) + { + const nn::hac::PartitionFsHeader::sFile& file = exefs.getPfsHeader().getFileList().getElement(kNpdmExefsPath); + + MetaProcess npdm; + npdm.setInputFile(new fnd::OffsetAdjustedIFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, file.offset, file.size)); + npdm.setCliOutputMode(0); + npdm.process(); + + if (fnd::rsa::pss::rsaVerify(npdm.getMeta().getAcid().getContentArchiveHeaderSignature2Key(), fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0) + { + std::cout << "[WARNING] NCA Header ACID Signature: FAIL" << std::endl; + } + + } + else + { + std::cout << "[WARNING] NCA Header ACID Signature: FAIL (\"" << kNpdmExefsPath << "\" not present in ExeFs)" << std::endl; + } + } + else + { + std::cout << "[WARNING] NCA Header ACID Signature: FAIL (ExeFs unreadable)" << std::endl; + } + } + else + { + std::cout << "[WARNING] NCA Header ACID Signature: FAIL (No ExeFs partition)" << std::endl; + } + } +} + +void NcaProcess::displayHeader() +{ + std::cout << "[NCA Header]" << std::endl; + std::cout << " Format Type: " << getFormatVersionStr(mHdr.getFormatVersion()) << std::endl; + std::cout << " Dist. Type: " << getDistributionTypeStr(mHdr.getDistributionType()) << std::endl; + std::cout << " Content Type: " << getContentTypeStr(mHdr.getContentType()) << std::endl; + std::cout << " Key Generation: " << std::dec << (uint32_t)mHdr.getKeyGeneration() << std::endl; + std::cout << " Kaek Index: " << getKaekIndexStr((nn::hac::nca::KeyAreaEncryptionKeyIndex)mHdr.getKeyAreaEncryptionKeyIndex()) << " (" << std::dec << (uint32_t)mHdr.getKeyAreaEncryptionKeyIndex() << ")" << std::endl; + std::cout << " Size: 0x" << std::hex << mHdr.getContentSize() << std::endl; + std::cout << " ProgID: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getProgramId() << std::endl; + std::cout << " Content Index: " << std::dec << mHdr.getContentIndex() << std::endl; +#define _SPLIT_VER(ver) std::dec << (uint32_t)((ver>>24) & 0xff) << "." << (uint32_t)((ver>>16) & 0xff) << "." << (uint32_t)((ver>>8) & 0xff) + std::cout << " SdkAddon Ver.: v" << std::dec << mHdr.getSdkAddonVersion() << " (" << _SPLIT_VER(mHdr.getSdkAddonVersion()) << ")" << std::endl; +#undef _SPLIT_VER + if (mHdr.hasRightsId()) + { + std::cout << " RightsId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRightsId(), nn::hac::nca::kRightsIdLen, true, "") << std::endl; + } + + if (mContentKey.kak_list.size() > 0 && _HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA)) + { + std::cout << " Key Area:" << std::endl; + std::cout << " <--------------------------------------------------------------------------------------------------------->" << std::endl; + std::cout << " | IDX | ENCRYPTED KEY | DECRYPTED KEY |" << std::endl; + std::cout << " |-----|-------------------------------------------------|-------------------------------------------------|" << std::endl; + for (size_t i = 0; i < mContentKey.kak_list.size(); i++) + { + std::cout << " | " << std::dec << std::setw(3) << std::setfill(' ') << (uint32_t)mContentKey.kak_list[i].index << " | "; + + std::cout << fnd::SimpleTextOutput::arrayToString(mContentKey.kak_list[i].enc.key, 16, true, ":") << " | "; + + + if (mContentKey.kak_list[i].decrypted) + std::cout << fnd::SimpleTextOutput::arrayToString(mContentKey.kak_list[i].dec.key, 16, true, ":"); + else + std::cout << " "; + + std::cout << " |" << std::endl; + } + std::cout << " <--------------------------------------------------------------------------------------------------------->" << std::endl; + } + + if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT)) + { + std::cout << " Partitions:" << std::endl; + for (size_t i = 0; i < mHdr.getPartitionEntryList().size(); i++) + { + uint32_t index = mHdr.getPartitionEntryList()[i].header_index; + sPartitionInfo& info = mPartitions[index]; + if (info.size == 0) continue; + + std::cout << " " << std::dec << index << ":" << std::endl; + std::cout << " Offset: 0x" << std::hex << (uint64_t)info.offset << std::endl; + std::cout << " Size: 0x" << std::hex << (uint64_t)info.size << std::endl; + std::cout << " Format Type: " << getFormatTypeStr(info.format_type) << std::endl; + std::cout << " Hash Type: " << getHashTypeStr(info.hash_type) << std::endl; + std::cout << " Enc. Type: " << getEncryptionTypeStr(info.enc_type) << std::endl; + if (info.enc_type == nn::hac::nca::CRYPT_AESCTR) + { + fnd::aes::sAesIvCtr ctr; + fnd::aes::AesIncrementCounter(info.aes_ctr.iv, info.offset>>4, ctr.iv); + std::cout << " AesCtr Counter:" << std::endl; + std::cout << " " << fnd::SimpleTextOutput::arrayToString(ctr.iv, sizeof(fnd::aes::sAesIvCtr), true, ":") << std::endl; + } + if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) + { + fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata; + std::cout << " HierarchicalIntegrity Header:" << std::endl; + for (size_t j = 0; j < hash_hdr.getHashLayerInfo().size(); j++) + { + std::cout << " Hash Layer " << std::dec << j << ":" << std::endl; + std::cout << " Offset: 0x" << std::hex << (uint64_t)hash_hdr.getHashLayerInfo()[j].offset << std::endl; + std::cout << " Size: 0x" << std::hex << (uint64_t)hash_hdr.getHashLayerInfo()[j].size << std::endl; + std::cout << " BlockSize: 0x" << std::hex << (uint32_t)hash_hdr.getHashLayerInfo()[j].block_size << std::endl; + } + + std::cout << " Data Layer:" << std::endl; + std::cout << " Offset: 0x" << std::hex << (uint64_t)hash_hdr.getDataLayer().offset << std::endl; + std::cout << " Size: 0x" << std::hex << (uint64_t)hash_hdr.getDataLayer().size << std::endl; + std::cout << " BlockSize: 0x" << std::hex << (uint32_t)hash_hdr.getDataLayer().block_size << std::endl; + for (size_t j = 0; j < hash_hdr.getMasterHashList().size(); j++) + { + std::cout << " Master Hash " << std::dec << j << ":" << std::endl; + std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[j].bytes, 0x10, true, ":") << std::endl; + std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[j].bytes+0x10, 0x10, true, ":") << std::endl; + } + } + else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256) + { + fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata; + std::cout << " HierarchicalSha256 Header:" << std::endl; + std::cout << " Master Hash:" << std::endl; + std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[0].bytes, 0x10, true, ":") << std::endl; + std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[0].bytes+0x10, 0x10, true, ":") << std::endl; + std::cout << " HashBlockSize: 0x" << std::hex << (uint32_t)hash_hdr.getDataLayer().block_size << std::endl; + std::cout << " Hash Layer:" << std::endl; + std::cout << " Offset: 0x" << std::hex << (uint64_t)hash_hdr.getHashLayerInfo()[0].offset << std::endl; + std::cout << " Size: 0x" << std::hex << (uint64_t)hash_hdr.getHashLayerInfo()[0].size << std::endl; + std::cout << " Data Layer:" << std::endl; + std::cout << " Offset: 0x" << std::hex << (uint64_t)hash_hdr.getDataLayer().offset << std::endl; + std::cout << " Size: 0x" << std::hex << (uint64_t)hash_hdr.getDataLayer().size << std::endl; + } + } + } +} + + +void NcaProcess::processPartitions() +{ + for (size_t i = 0; i < mHdr.getPartitionEntryList().size(); i++) + { + uint32_t index = mHdr.getPartitionEntryList()[i].header_index; + struct sPartitionInfo& partition = mPartitions[index]; + + // if the reader is null, skip + if (*partition.reader == nullptr) + { + std::cout << "[WARNING] NCA Partition " << std::dec << index << " not readable."; + if (partition.fail_reason.empty() == false) + { + std::cout << " (" << partition.fail_reason << ")"; + } + std::cout << std::endl; + continue; + } + + if (partition.format_type == nn::hac::nca::FORMAT_PFS0) + { + PfsProcess pfs; + pfs.setInputFile(partition.reader); + pfs.setCliOutputMode(mCliOutputMode); + pfs.setListFs(mListFs); + if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM) + { + pfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/" + std::string(getProgramPartitionNameStr(index))); + } + else + { + pfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/"); + } + + if (mPartitionPath[index].doExtract) + pfs.setExtractPath(mPartitionPath[index].path); + pfs.process(); + } + else if (partition.format_type == nn::hac::nca::FORMAT_ROMFS) + { + RomfsProcess romfs; + romfs.setInputFile(partition.reader); + romfs.setCliOutputMode(mCliOutputMode); + romfs.setListFs(mListFs); + if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM) + { + romfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/" + std::string(getProgramPartitionNameStr(index))); + } + else + { + romfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/"); + } + + if (mPartitionPath[index].doExtract) + romfs.setExtractPath(mPartitionPath[index].path); + romfs.process(); + } + } +} + +const char* NcaProcess::getFormatVersionStr(byte_t format_ver) const +{ + const char* str = nullptr; + + switch (format_ver) + { + case (nn::hac::nca::FORMAT_NCA2): + str = "NCA2"; + break; + case (nn::hac::nca::FORMAT_NCA3): + str = "NCA3"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* NcaProcess::getDistributionTypeStr(nn::hac::nca::DistributionType dist_type) const +{ + const char* str = nullptr; + + switch (dist_type) + { + case (nn::hac::nca::DIST_DOWNLOAD): + str = "Download"; + break; + case (nn::hac::nca::DIST_GAME_CARD): + str = "Game Card"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + + +const char* NcaProcess::getContentTypeStr(nn::hac::nca::ContentType cont_type) const +{ + const char* str = nullptr; + + switch (cont_type) + { + case (nn::hac::nca::TYPE_PROGRAM): + str = "Program"; + break; + case (nn::hac::nca::TYPE_META): + str = "Meta"; + break; + case (nn::hac::nca::TYPE_CONTROL): + str = "Control"; + break; + case (nn::hac::nca::TYPE_MANUAL): + str = "Manual"; + break; + case (nn::hac::nca::TYPE_DATA): + str = "Data"; + break; + case (nn::hac::nca::TYPE_PUBLIC_DATA): + str = "PublicData"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* NcaProcess::getEncryptionTypeStr(nn::hac::nca::EncryptionType enc_type) const +{ + const char* str = nullptr; + + switch (enc_type) + { + case (nn::hac::nca::CRYPT_AUTO): + str = "Auto"; + break; + case (nn::hac::nca::CRYPT_NONE): + str = "None"; + break; + case (nn::hac::nca::CRYPT_AESXTS): + str = "AesXts"; + break; + case (nn::hac::nca::CRYPT_AESCTR): + str = "AesCtr"; + break; + case (nn::hac::nca::CRYPT_AESCTREX): + str = "AesCtrEx"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* NcaProcess::getHashTypeStr(nn::hac::nca::HashType hash_type) const +{ + const char* str = nullptr; + + switch (hash_type) + { + case (nn::hac::nca::HASH_AUTO): + str = "Auto"; + break; + case (nn::hac::nca::HASH_NONE): + str = "None"; + break; + case (nn::hac::nca::HASH_HIERARCHICAL_SHA256): + str = "HierarchicalSha256"; + break; + case (nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY): + str = "HierarchicalIntegrity"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* NcaProcess::getFormatTypeStr(nn::hac::nca::FormatType format_type) const +{ + const char* str = nullptr; + + switch (format_type) + { + case (nn::hac::nca::FORMAT_ROMFS): + str = "RomFs"; + break; + case (nn::hac::nca::FORMAT_PFS0): + str = "PartitionFs"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* NcaProcess::getKaekIndexStr(nn::hac::nca::KeyAreaEncryptionKeyIndex keak_index) const +{ + const char* str = nullptr; + + switch (keak_index) + { + case (nn::hac::nca::KAEK_IDX_APPLICATION): + str = "Application"; + break; + case (nn::hac::nca::KAEK_IDX_OCEAN): + str = "Ocean"; + break; + case (nn::hac::nca::KAEK_IDX_SYSTEM): + str = "System"; + break; + default: + str = "Unknown"; + break; + } + + return str; +} + +const char* NcaProcess::getContentTypeForMountStr(nn::hac::nca::ContentType cont_type) const +{ + const char* str = nullptr; + + switch (cont_type) + { + case (nn::hac::nca::TYPE_PROGRAM): + str = "program"; + break; + case (nn::hac::nca::TYPE_META): + str = "meta"; + break; + case (nn::hac::nca::TYPE_CONTROL): + str = "control"; + break; + case (nn::hac::nca::TYPE_MANUAL): + str = "manual"; + break; + case (nn::hac::nca::TYPE_DATA): + str = "data"; + break; + case (nn::hac::nca::TYPE_PUBLIC_DATA): + str = "publicdata"; + break; + default: + str = ""; + break; + } + + return str; +} + +const char* NcaProcess::getProgramPartitionNameStr(size_t i) const +{ + const char* str = nullptr; + + switch (i) + { + case (nn::hac::nca::PARTITION_CODE): + str = "code"; + break; + case (nn::hac::nca::PARTITION_DATA): + str = "data"; + break; + case (nn::hac::nca::PARTITION_LOGO): + str = "logo"; + break; + default: + str = ""; + break; + } + + return str; } \ No newline at end of file diff --git a/programs/nstool/source/NcaProcess.h b/programs/nstool/source/NcaProcess.h index e87a408..8716c9f 100644 --- a/programs/nstool/source/NcaProcess.h +++ b/programs/nstool/source/NcaProcess.h @@ -1,123 +1,123 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include "KeyConfiguration.h" - - -#include "common.h" - -class NcaProcess -{ -public: - NcaProcess(); - - void process(); - - // generic - void setInputFile(const fnd::SharedPtr& file); - void setKeyCfg(const KeyConfiguration& keycfg); - void setCliOutputMode(CliOutputMode type); - void setVerifyMode(bool verify); - - // nca specfic - void setPartition0ExtractPath(const std::string& path); - void setPartition1ExtractPath(const std::string& path); - void setPartition2ExtractPath(const std::string& path); - void setPartition3ExtractPath(const std::string& path); - void setListFs(bool list_fs); - -private: - const std::string kModuleName = "NcaProcess"; - const std::string kNpdmExefsPath = "main.npdm"; - - // user options - fnd::SharedPtr mFile; - KeyConfiguration mKeyCfg; - CliOutputMode mCliOutputMode; - bool mVerify; - - struct sExtract - { - std::string path; - bool doExtract; - } mPartitionPath[nn::hac::nca::kPartitionNum]; - - bool mListFs; - - // data - nn::hac::sNcaHeaderBlock mHdrBlock; - fnd::sha::sSha256Hash mHdrHash; - nn::hac::NcaHeader mHdr; - - // crypto - struct sKeys - { - struct sKeyAreaKey - { - byte_t index; - bool decrypted; - fnd::aes::sAes128Key enc; - fnd::aes::sAes128Key dec; - - void operator=(const sKeyAreaKey& other) - { - index = other.index; - decrypted = other.decrypted; - enc = other.enc; - dec = other.dec; - } - - bool operator==(const sKeyAreaKey& other) const - { - return (index == other.index) \ - && (decrypted == other.decrypted) \ - && (enc == other.enc) \ - && (dec == other.dec); - } - - bool operator!=(const sKeyAreaKey& other) const - { - return !(*this == other); - } - }; - fnd::List kak_list; - - sOptional aes_ctr; - } mContentKey; - - struct sPartitionInfo - { - fnd::SharedPtr reader; - std::string fail_reason; - size_t offset; - size_t size; - - // meta data - nn::hac::nca::FormatType format_type; - nn::hac::nca::HashType hash_type; - nn::hac::nca::EncryptionType enc_type; - fnd::LayeredIntegrityMetadata layered_intergrity_metadata; - fnd::aes::sAesIvCtr aes_ctr; - } mPartitions[nn::hac::nca::kPartitionNum]; - - void importHeader(); - void generateNcaBodyEncryptionKeys(); - void generatePartitionConfiguration(); - void validateNcaSignatures(); - void displayHeader(); - void processPartitions(); - - const char* getFormatVersionStr(nn::hac::NcaHeader::FormatVersion format_ver) const; - const char* getDistributionTypeStr(nn::hac::nca::DistributionType dist_type) const; - const char* getContentTypeStr(nn::hac::nca::ContentType cont_type) const; - const char* getEncryptionTypeStr(nn::hac::nca::EncryptionType enc_type) const; - const char* getHashTypeStr(nn::hac::nca::HashType hash_type) const; - const char* getFormatTypeStr(nn::hac::nca::FormatType format_type) const; - const char* getKaekIndexStr(nn::hac::nca::KeyAreaEncryptionKeyIndex keak_index) const; - const char* getContentTypeForMountStr(nn::hac::nca::ContentType cont_type) const; - const char* getProgramPartitionNameStr(size_t i) const; +#pragma once +#include +#include +#include +#include +#include +#include +#include "KeyConfiguration.h" + + +#include "common.h" + +class NcaProcess +{ +public: + NcaProcess(); + + void process(); + + // generic + void setInputFile(const fnd::SharedPtr& file); + void setKeyCfg(const KeyConfiguration& keycfg); + void setCliOutputMode(CliOutputMode type); + void setVerifyMode(bool verify); + + // nca specfic + void setPartition0ExtractPath(const std::string& path); + void setPartition1ExtractPath(const std::string& path); + void setPartition2ExtractPath(const std::string& path); + void setPartition3ExtractPath(const std::string& path); + void setListFs(bool list_fs); + +private: + const std::string kModuleName = "NcaProcess"; + const std::string kNpdmExefsPath = "main.npdm"; + + // user options + fnd::SharedPtr mFile; + KeyConfiguration mKeyCfg; + CliOutputMode mCliOutputMode; + bool mVerify; + + struct sExtract + { + std::string path; + bool doExtract; + } mPartitionPath[nn::hac::nca::kPartitionNum]; + + bool mListFs; + + // data + nn::hac::sContentArchiveHeaderBlock mHdrBlock; + fnd::sha::sSha256Hash mHdrHash; + nn::hac::ContentArchiveHeader mHdr; + + // crypto + struct sKeys + { + struct sKeyAreaKey + { + byte_t index; + bool decrypted; + fnd::aes::sAes128Key enc; + fnd::aes::sAes128Key dec; + + void operator=(const sKeyAreaKey& other) + { + index = other.index; + decrypted = other.decrypted; + enc = other.enc; + dec = other.dec; + } + + bool operator==(const sKeyAreaKey& other) const + { + return (index == other.index) \ + && (decrypted == other.decrypted) \ + && (enc == other.enc) \ + && (dec == other.dec); + } + + bool operator!=(const sKeyAreaKey& other) const + { + return !(*this == other); + } + }; + fnd::List kak_list; + + sOptional aes_ctr; + } mContentKey; + + struct sPartitionInfo + { + fnd::SharedPtr reader; + std::string fail_reason; + size_t offset; + size_t size; + + // meta data + nn::hac::nca::FormatType format_type; + nn::hac::nca::HashType hash_type; + nn::hac::nca::EncryptionType enc_type; + fnd::LayeredIntegrityMetadata layered_intergrity_metadata; + fnd::aes::sAesIvCtr aes_ctr; + } mPartitions[nn::hac::nca::kPartitionNum]; + + void importHeader(); + void generateNcaBodyEncryptionKeys(); + void generatePartitionConfiguration(); + void validateNcaSignatures(); + void displayHeader(); + void processPartitions(); + + const char* getFormatVersionStr(byte_t format_ver) const; + const char* getDistributionTypeStr(nn::hac::nca::DistributionType dist_type) const; + const char* getContentTypeStr(nn::hac::nca::ContentType cont_type) const; + const char* getEncryptionTypeStr(nn::hac::nca::EncryptionType enc_type) const; + const char* getHashTypeStr(nn::hac::nca::HashType hash_type) const; + const char* getFormatTypeStr(nn::hac::nca::FormatType format_type) const; + const char* getKaekIndexStr(nn::hac::nca::KeyAreaEncryptionKeyIndex keak_index) const; + const char* getContentTypeForMountStr(nn::hac::nca::ContentType cont_type) const; + const char* getProgramPartitionNameStr(size_t i) const; }; \ No newline at end of file diff --git a/programs/nstool/source/NroProcess.cpp b/programs/nstool/source/NroProcess.cpp index 20951c4..e6f43e5 100644 --- a/programs/nstool/source/NroProcess.cpp +++ b/programs/nstool/source/NroProcess.cpp @@ -1,172 +1,172 @@ -#include -#include -#include -#include -#include -#include -#include -#include "NroProcess.h" - -NroProcess::NroProcess(): - mFile(), - mCliOutputMode(_BIT(OUTPUT_BASIC)), - mVerify(false) -{ -} - -void NroProcess::process() -{ - importHeader(); - importCodeSegments(); - - if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) - displayHeader(); - - processRoMeta(); - - if (mIsHomebrewNro) - mAssetProc.process(); -} - -void NroProcess::setInputFile(const fnd::SharedPtr& file) -{ - mFile = file; -} - -void NroProcess::setCliOutputMode(CliOutputMode type) -{ - mCliOutputMode = type; -} - -void NroProcess::setVerifyMode(bool verify) -{ - mVerify = verify; -} - -void NroProcess::setInstructionType(nn::hac::meta::InstructionType type) -{ - mRoMeta.setInstructionType(type); -} - -void NroProcess::setListApi(bool listApi) -{ - mRoMeta.setListApi(listApi); -} - -void NroProcess::setListSymbols(bool listSymbols) -{ - mRoMeta.setListSymbols(listSymbols); -} - -void NroProcess::setAssetListFs(bool list) -{ - mAssetProc.setListFs(list); -} - -void NroProcess::setAssetIconExtractPath(const std::string& path) -{ - mAssetProc.setIconExtractPath(path); -} - -void NroProcess::setAssetNacpExtractPath(const std::string& path) -{ - mAssetProc.setNacpExtractPath(path); -} - -void NroProcess::setAssetRomfsExtractPath(const std::string& path) -{ - mAssetProc.setRomfsExtractPath(path); -} - -const RoMetadataProcess& NroProcess::getRoMetadataProcess() const -{ - return mRoMeta; -} - -void NroProcess::importHeader() -{ - fnd::Vec scratch; - - if (*mFile == nullptr) - { - throw fnd::Exception(kModuleName, "No file reader set."); - } - - if ((*mFile)->size() < sizeof(nn::hac::sNroHeader)) - { - throw fnd::Exception(kModuleName, "Corrupt NRO: file too small"); - } - - scratch.alloc(sizeof(nn::hac::sNroHeader)); - (*mFile)->read(scratch.data(), 0, scratch.size()); - - mHdr.fromBytes(scratch.data(), scratch.size()); - - // setup homebrew extension - nn::hac::sNroHeader* raw_hdr = (nn::hac::sNroHeader*)scratch.data(); - if (((le_uint64_t*)raw_hdr->reserved_0)->get() == nn::hac::nro::kNroHomebrewStructMagic && (*mFile)->size() > mHdr.getNroSize()) - { - mIsHomebrewNro = true; - mAssetProc.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getNroSize(), (*mFile)->size() - mHdr.getNroSize())); - mAssetProc.setCliOutputMode(mCliOutputMode); - mAssetProc.setVerifyMode(mVerify); - } - else - mIsHomebrewNro = false; -} - -void NroProcess::importCodeSegments() -{ - mTextBlob.alloc(mHdr.getTextInfo().size); - (*mFile)->read(mTextBlob.data(), mHdr.getTextInfo().memory_offset, mTextBlob.size()); - mRoBlob.alloc(mHdr.getRoInfo().size); - (*mFile)->read(mRoBlob.data(), mHdr.getRoInfo().memory_offset, mRoBlob.size()); - mDataBlob.alloc(mHdr.getDataInfo().size); - (*mFile)->read(mDataBlob.data(), mHdr.getDataInfo().memory_offset, mDataBlob.size()); -} - -void NroProcess::displayHeader() -{ - std::cout << "[NRO Header]" << std::endl; - std::cout << " RoCrt: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRoCrt().data, nn::hac::nro::kRoCrtSize, false, "") << std::endl; - std::cout << " ModuleId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getModuleId().data, nn::hac::nro::kModuleIdSize, false, "") << std::endl; - std::cout << " NroSize: 0x" << std::hex << mHdr.getNroSize() << std::endl; - std::cout << " Program Sections:" << std::endl; - std::cout << " .text:" << std::endl; - std::cout << " Offset: 0x" << std::hex << mHdr.getTextInfo().memory_offset << std::endl; - std::cout << " Size: 0x" << std::hex << mHdr.getTextInfo().size << std::endl; - std::cout << " .ro:" << std::endl; - std::cout << " Offset: 0x" << std::hex << mHdr.getRoInfo().memory_offset << std::endl; - std::cout << " Size: 0x" << std::hex << mHdr.getRoInfo().size << std::endl; - if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " .api_info:" << std::endl; - std::cout << " Offset: 0x" << std::hex << mHdr.getRoEmbeddedInfo().memory_offset << std::endl; - std::cout << " Size: 0x" << std::hex << mHdr.getRoEmbeddedInfo().size << std::endl; - std::cout << " .dynstr:" << std::endl; - std::cout << " Offset: 0x" << std::hex << mHdr.getRoDynStrInfo().memory_offset << std::endl; - std::cout << " Size: 0x" << std::hex << mHdr.getRoDynStrInfo().size << std::endl; - std::cout << " .dynsym:" << std::endl; - std::cout << " Offset: 0x" << std::hex << mHdr.getRoDynSymInfo().memory_offset << std::endl; - std::cout << " Size: 0x" << std::hex << mHdr.getRoDynSymInfo().size << std::endl; - } - std::cout << " .data:" << std::endl; - std::cout << " Offset: 0x" << std::hex << mHdr.getDataInfo().memory_offset << std::endl; - std::cout << " Size: 0x" << std::hex << mHdr.getDataInfo().size << std::endl; - std::cout << " .bss:" << std::endl; - std::cout << " Size: 0x" << std::hex << mHdr.getBssSize() << std::endl; -} - -void NroProcess::processRoMeta() -{ - if (mRoBlob.size()) - { - // setup ro metadata - mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().memory_offset, mHdr.getRoEmbeddedInfo().size); - mRoMeta.setDynSym(mHdr.getRoDynSymInfo().memory_offset, mHdr.getRoDynSymInfo().size); - mRoMeta.setDynStr(mHdr.getRoDynStrInfo().memory_offset, mHdr.getRoDynStrInfo().size); - mRoMeta.setRoBinary(mRoBlob); - mRoMeta.setCliOutputMode(mCliOutputMode); - mRoMeta.process(); - } +#include +#include +#include +#include +#include +#include +#include +#include "NroProcess.h" + +NroProcess::NroProcess(): + mFile(), + mCliOutputMode(_BIT(OUTPUT_BASIC)), + mVerify(false) +{ +} + +void NroProcess::process() +{ + importHeader(); + importCodeSegments(); + + if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) + displayHeader(); + + processRoMeta(); + + if (mIsHomebrewNro) + mAssetProc.process(); +} + +void NroProcess::setInputFile(const fnd::SharedPtr& file) +{ + mFile = file; +} + +void NroProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void NroProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +void NroProcess::setInstructionType(nn::hac::meta::InstructionType type) +{ + mRoMeta.setInstructionType(type); +} + +void NroProcess::setListApi(bool listApi) +{ + mRoMeta.setListApi(listApi); +} + +void NroProcess::setListSymbols(bool listSymbols) +{ + mRoMeta.setListSymbols(listSymbols); +} + +void NroProcess::setAssetListFs(bool list) +{ + mAssetProc.setListFs(list); +} + +void NroProcess::setAssetIconExtractPath(const std::string& path) +{ + mAssetProc.setIconExtractPath(path); +} + +void NroProcess::setAssetNacpExtractPath(const std::string& path) +{ + mAssetProc.setNacpExtractPath(path); +} + +void NroProcess::setAssetRomfsExtractPath(const std::string& path) +{ + mAssetProc.setRomfsExtractPath(path); +} + +const RoMetadataProcess& NroProcess::getRoMetadataProcess() const +{ + return mRoMeta; +} + +void NroProcess::importHeader() +{ + fnd::Vec scratch; + + if (*mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + if ((*mFile)->size() < sizeof(nn::hac::sNroHeader)) + { + throw fnd::Exception(kModuleName, "Corrupt NRO: file too small"); + } + + scratch.alloc(sizeof(nn::hac::sNroHeader)); + (*mFile)->read(scratch.data(), 0, scratch.size()); + + mHdr.fromBytes(scratch.data(), scratch.size()); + + // setup homebrew extension + nn::hac::sNroHeader* raw_hdr = (nn::hac::sNroHeader*)scratch.data(); + if (((le_uint64_t*)raw_hdr->reserved_0)->get() == nn::hac::nro::kNroHomebrewStructMagic && (*mFile)->size() > mHdr.getNroSize()) + { + mIsHomebrewNro = true; + mAssetProc.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getNroSize(), (*mFile)->size() - mHdr.getNroSize())); + mAssetProc.setCliOutputMode(mCliOutputMode); + mAssetProc.setVerifyMode(mVerify); + } + else + mIsHomebrewNro = false; +} + +void NroProcess::importCodeSegments() +{ + mTextBlob.alloc(mHdr.getTextInfo().size); + (*mFile)->read(mTextBlob.data(), mHdr.getTextInfo().memory_offset, mTextBlob.size()); + mRoBlob.alloc(mHdr.getRoInfo().size); + (*mFile)->read(mRoBlob.data(), mHdr.getRoInfo().memory_offset, mRoBlob.size()); + mDataBlob.alloc(mHdr.getDataInfo().size); + (*mFile)->read(mDataBlob.data(), mHdr.getDataInfo().memory_offset, mDataBlob.size()); +} + +void NroProcess::displayHeader() +{ + std::cout << "[NRO Header]" << std::endl; + std::cout << " RoCrt: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRoCrt().data, nn::hac::nro::kRoCrtSize, false, "") << std::endl; + std::cout << " ModuleId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getModuleId().data, nn::hac::nro::kModuleIdSize, false, "") << std::endl; + std::cout << " NroSize: 0x" << std::hex << mHdr.getNroSize() << std::endl; + std::cout << " Program Sections:" << std::endl; + std::cout << " .text:" << std::endl; + std::cout << " Offset: 0x" << std::hex << mHdr.getTextInfo().memory_offset << std::endl; + std::cout << " Size: 0x" << std::hex << mHdr.getTextInfo().size << std::endl; + std::cout << " .ro:" << std::endl; + std::cout << " Offset: 0x" << std::hex << mHdr.getRoInfo().memory_offset << std::endl; + std::cout << " Size: 0x" << std::hex << mHdr.getRoInfo().size << std::endl; + if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " .api_info:" << std::endl; + std::cout << " Offset: 0x" << std::hex << mHdr.getRoEmbeddedInfo().memory_offset << std::endl; + std::cout << " Size: 0x" << std::hex << mHdr.getRoEmbeddedInfo().size << std::endl; + std::cout << " .dynstr:" << std::endl; + std::cout << " Offset: 0x" << std::hex << mHdr.getRoDynStrInfo().memory_offset << std::endl; + std::cout << " Size: 0x" << std::hex << mHdr.getRoDynStrInfo().size << std::endl; + std::cout << " .dynsym:" << std::endl; + std::cout << " Offset: 0x" << std::hex << mHdr.getRoDynSymInfo().memory_offset << std::endl; + std::cout << " Size: 0x" << std::hex << mHdr.getRoDynSymInfo().size << std::endl; + } + std::cout << " .data:" << std::endl; + std::cout << " Offset: 0x" << std::hex << mHdr.getDataInfo().memory_offset << std::endl; + std::cout << " Size: 0x" << std::hex << mHdr.getDataInfo().size << std::endl; + std::cout << " .bss:" << std::endl; + std::cout << " Size: 0x" << std::hex << mHdr.getBssSize() << std::endl; +} + +void NroProcess::processRoMeta() +{ + if (mRoBlob.size()) + { + // setup ro metadata + mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().memory_offset, mHdr.getRoEmbeddedInfo().size); + mRoMeta.setDynSym(mHdr.getRoDynSymInfo().memory_offset, mHdr.getRoDynSymInfo().size); + mRoMeta.setDynStr(mHdr.getRoDynStrInfo().memory_offset, mHdr.getRoDynStrInfo().size); + mRoMeta.setRoBinary(mRoBlob); + mRoMeta.setCliOutputMode(mCliOutputMode); + mRoMeta.process(); + } } \ No newline at end of file diff --git a/programs/nstool/source/NroProcess.h b/programs/nstool/source/NroProcess.h index c0610b3..a1f67fa 100644 --- a/programs/nstool/source/NroProcess.h +++ b/programs/nstool/source/NroProcess.h @@ -1,53 +1,53 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include "AssetProcess.h" - -#include "common.h" -#include "RoMetadataProcess.h" - -class NroProcess -{ -public: - NroProcess(); - - void process(); - - void setInputFile(const fnd::SharedPtr& file); - void setCliOutputMode(CliOutputMode type); - void setVerifyMode(bool verify); - - void setInstructionType(nn::hac::meta::InstructionType type); - void setListApi(bool listApi); - void setListSymbols(bool listSymbols); - - // for homebrew NROs with Asset blobs appended - void setAssetListFs(bool list); - void setAssetIconExtractPath(const std::string& path); - void setAssetNacpExtractPath(const std::string& path); - void setAssetRomfsExtractPath(const std::string& path); - - const RoMetadataProcess& getRoMetadataProcess() const; -private: - const std::string kModuleName = "NroProcess"; - - fnd::SharedPtr mFile; - CliOutputMode mCliOutputMode; - bool mVerify; - - nn::hac::NroHeader mHdr; - fnd::Vec mTextBlob, mRoBlob, mDataBlob; - RoMetadataProcess mRoMeta; - bool mIsHomebrewNro; - AssetProcess mAssetProc; - - void importHeader(); - void importCodeSegments(); - void displayHeader(); - void processRoMeta(); +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include "AssetProcess.h" + +#include "common.h" +#include "RoMetadataProcess.h" + +class NroProcess +{ +public: + NroProcess(); + + void process(); + + void setInputFile(const fnd::SharedPtr& file); + void setCliOutputMode(CliOutputMode type); + void setVerifyMode(bool verify); + + void setInstructionType(nn::hac::meta::InstructionType type); + void setListApi(bool listApi); + void setListSymbols(bool listSymbols); + + // for homebrew NROs with Asset blobs appended + void setAssetListFs(bool list); + void setAssetIconExtractPath(const std::string& path); + void setAssetNacpExtractPath(const std::string& path); + void setAssetRomfsExtractPath(const std::string& path); + + const RoMetadataProcess& getRoMetadataProcess() const; +private: + const std::string kModuleName = "NroProcess"; + + fnd::SharedPtr mFile; + CliOutputMode mCliOutputMode; + bool mVerify; + + nn::hac::NroHeader mHdr; + fnd::Vec mTextBlob, mRoBlob, mDataBlob; + RoMetadataProcess mRoMeta; + bool mIsHomebrewNro; + AssetProcess mAssetProc; + + void importHeader(); + void importCodeSegments(); + void displayHeader(); + void processRoMeta(); }; \ No newline at end of file diff --git a/programs/nstool/source/NsoProcess.cpp b/programs/nstool/source/NsoProcess.cpp index 7db1e16..3ea00ed 100644 --- a/programs/nstool/source/NsoProcess.cpp +++ b/programs/nstool/source/NsoProcess.cpp @@ -1,237 +1,237 @@ -#include -#include -#include -#include -#include -#include -#include "NsoProcess.h" - -NsoProcess::NsoProcess(): - mFile(), - mCliOutputMode(_BIT(OUTPUT_BASIC)), - mVerify(false) -{ -} - -void NsoProcess::process() -{ - importHeader(); - importCodeSegments(); - if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) - displayNsoHeader(); - - processRoMeta(); -} - -void NsoProcess::setInputFile(const fnd::SharedPtr& file) -{ - mFile = file; -} - -void NsoProcess::setCliOutputMode(CliOutputMode type) -{ - mCliOutputMode = type; -} - -void NsoProcess::setVerifyMode(bool verify) -{ - mVerify = verify; -} - -void NsoProcess::setInstructionType(nn::hac::meta::InstructionType type) -{ - mRoMeta.setInstructionType(type); -} - -void NsoProcess::setListApi(bool listApi) -{ - mRoMeta.setListApi(listApi); -} - -void NsoProcess::setListSymbols(bool listSymbols) -{ - mRoMeta.setListSymbols(listSymbols); -} - -const RoMetadataProcess& NsoProcess::getRoMetadataProcess() const -{ - return mRoMeta; -} - -void NsoProcess::importHeader() -{ - fnd::Vec scratch; - - if (*mFile == nullptr) - { - throw fnd::Exception(kModuleName, "No file reader set."); - } - - if ((*mFile)->size() < sizeof(nn::hac::sNsoHeader)) - { - throw fnd::Exception(kModuleName, "Corrupt NSO: file too small"); - } - - scratch.alloc(sizeof(nn::hac::sNsoHeader)); - (*mFile)->read(scratch.data(), 0, scratch.size()); - - mHdr.fromBytes(scratch.data(), scratch.size()); -} - -void NsoProcess::importCodeSegments() -{ - fnd::Vec scratch; - uint32_t decompressed_len; - fnd::sha::sSha256Hash calc_hash; - - // process text segment - if (mHdr.getTextSegmentInfo().is_compressed) - { - scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size); - (*mFile)->read(scratch.data(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.size()); - mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size); - fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mTextBlob.data(), (uint32_t)mTextBlob.size(), decompressed_len); - if (decompressed_len != mTextBlob.size()) - { - throw fnd::Exception(kModuleName, "NSO text segment failed to decompress"); - } - } - else - { - mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size); - (*mFile)->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size()); - } - if (mHdr.getTextSegmentInfo().is_hashed) - { - fnd::sha::Sha256(mTextBlob.data(), mTextBlob.size(), calc_hash.bytes); - if (calc_hash != mHdr.getTextSegmentInfo().hash) - { - throw fnd::Exception(kModuleName, "NSO text segment failed SHA256 verification"); - } - } - - // process ro segment - if (mHdr.getRoSegmentInfo().is_compressed) - { - scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size); - (*mFile)->read(scratch.data(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.size()); - mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size); - fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mRoBlob.data(), (uint32_t)mRoBlob.size(), decompressed_len); - if (decompressed_len != mRoBlob.size()) - { - throw fnd::Exception(kModuleName, "NSO ro segment failed to decompress"); - } - } - else - { - mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size); - (*mFile)->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size()); - } - if (mHdr.getRoSegmentInfo().is_hashed) - { - fnd::sha::Sha256(mRoBlob.data(), mRoBlob.size(), calc_hash.bytes); - if (calc_hash != mHdr.getRoSegmentInfo().hash) - { - throw fnd::Exception(kModuleName, "NSO ro segment failed SHA256 verification"); - } - } - - // process data segment - if (mHdr.getDataSegmentInfo().is_compressed) - { - scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size); - (*mFile)->read(scratch.data(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.size()); - mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size); - fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mDataBlob.data(), (uint32_t)mDataBlob.size(), decompressed_len); - if (decompressed_len != mDataBlob.size()) - { - throw fnd::Exception(kModuleName, "NSO data segment failed to decompress"); - } - } - else - { - mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size); - (*mFile)->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size()); - } - if (mHdr.getDataSegmentInfo().is_hashed) - { - fnd::sha::Sha256(mDataBlob.data(), mDataBlob.size(), calc_hash.bytes); - if (calc_hash != mHdr.getDataSegmentInfo().hash) - { - throw fnd::Exception(kModuleName, "NSO data segment failed SHA256 verification"); - } - } -} - -void NsoProcess::displayNsoHeader() -{ - std::cout << "[NSO Header]" << std::endl; - std::cout << " ModuleId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getModuleId().data, nn::hac::nso::kModuleIdSize, false, "") << std::endl; - if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT)) - { - std::cout << " Program Segments:" << std::endl; - std::cout << " .module_name:" << std::endl; - std::cout << " FileOffset: 0x" << std::hex << mHdr.getModuleNameInfo().offset << std::endl; - std::cout << " FileSize: 0x" << std::hex << mHdr.getModuleNameInfo().size << std::endl; - std::cout << " .text:" << std::endl; - std::cout << " FileOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.offset << std::endl; - std::cout << " FileSize: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.size << (mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; - std::cout << " .ro:" << std::endl; - std::cout << " FileOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.offset << std::endl; - std::cout << " FileSize: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.size << (mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; - std::cout << " .data:" << std::endl; - std::cout << " FileOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.offset << std::endl; - std::cout << " FileSize: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.size << (mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; - } - std::cout << " Program Sections:" << std::endl; - std::cout << " .text:" << std::endl; - std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.offset << std::endl; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.size << std::endl; - if (mHdr.getTextSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getTextSegmentInfo().hash.bytes, 32, false, "") << std::endl; - } - std::cout << " .ro:" << std::endl; - std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.offset << std::endl; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.size << std::endl; - if (mHdr.getRoSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRoSegmentInfo().hash.bytes, 32, false, "") << std::endl; - } - if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " .api_info:" << std::endl; - std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoEmbeddedInfo().offset << std::endl; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoEmbeddedInfo().size << std::endl; - std::cout << " .dynstr:" << std::endl; - std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoDynStrInfo().offset << std::endl; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoDynStrInfo().size << std::endl; - std::cout << " .dynsym:" << std::endl; - std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoDynSymInfo().offset << std::endl; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoDynSymInfo().size << std::endl; - } - - std::cout << " .data:" << std::endl; - std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.offset << std::endl; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.size << std::endl; - if (mHdr.getDataSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getDataSegmentInfo().hash.bytes, 32, false, "") << std::endl; - } - std::cout << " .bss:" << std::endl; - std::cout << " MemorySize: 0x" << std::hex << mHdr.getBssSize() << std::endl; -} - -void NsoProcess::processRoMeta() -{ - if (mRoBlob.size()) - { - // setup ro metadata - mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().offset, mHdr.getRoEmbeddedInfo().size); - mRoMeta.setDynSym(mHdr.getRoDynSymInfo().offset, mHdr.getRoDynSymInfo().size); - mRoMeta.setDynStr(mHdr.getRoDynStrInfo().offset, mHdr.getRoDynStrInfo().size); - mRoMeta.setRoBinary(mRoBlob); - mRoMeta.setCliOutputMode(mCliOutputMode); - mRoMeta.process(); - } +#include +#include +#include +#include +#include +#include +#include "NsoProcess.h" + +NsoProcess::NsoProcess(): + mFile(), + mCliOutputMode(_BIT(OUTPUT_BASIC)), + mVerify(false) +{ +} + +void NsoProcess::process() +{ + importHeader(); + importCodeSegments(); + if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) + displayNsoHeader(); + + processRoMeta(); +} + +void NsoProcess::setInputFile(const fnd::SharedPtr& file) +{ + mFile = file; +} + +void NsoProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void NsoProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +void NsoProcess::setInstructionType(nn::hac::meta::InstructionType type) +{ + mRoMeta.setInstructionType(type); +} + +void NsoProcess::setListApi(bool listApi) +{ + mRoMeta.setListApi(listApi); +} + +void NsoProcess::setListSymbols(bool listSymbols) +{ + mRoMeta.setListSymbols(listSymbols); +} + +const RoMetadataProcess& NsoProcess::getRoMetadataProcess() const +{ + return mRoMeta; +} + +void NsoProcess::importHeader() +{ + fnd::Vec scratch; + + if (*mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + if ((*mFile)->size() < sizeof(nn::hac::sNsoHeader)) + { + throw fnd::Exception(kModuleName, "Corrupt NSO: file too small"); + } + + scratch.alloc(sizeof(nn::hac::sNsoHeader)); + (*mFile)->read(scratch.data(), 0, scratch.size()); + + mHdr.fromBytes(scratch.data(), scratch.size()); +} + +void NsoProcess::importCodeSegments() +{ + fnd::Vec scratch; + uint32_t decompressed_len; + fnd::sha::sSha256Hash calc_hash; + + // process text segment + if (mHdr.getTextSegmentInfo().is_compressed) + { + scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size); + (*mFile)->read(scratch.data(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.size()); + mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size); + fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mTextBlob.data(), (uint32_t)mTextBlob.size(), decompressed_len); + if (decompressed_len != mTextBlob.size()) + { + throw fnd::Exception(kModuleName, "NSO text segment failed to decompress"); + } + } + else + { + mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size); + (*mFile)->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size()); + } + if (mHdr.getTextSegmentInfo().is_hashed) + { + fnd::sha::Sha256(mTextBlob.data(), mTextBlob.size(), calc_hash.bytes); + if (calc_hash != mHdr.getTextSegmentInfo().hash) + { + throw fnd::Exception(kModuleName, "NSO text segment failed SHA256 verification"); + } + } + + // process ro segment + if (mHdr.getRoSegmentInfo().is_compressed) + { + scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size); + (*mFile)->read(scratch.data(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.size()); + mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size); + fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mRoBlob.data(), (uint32_t)mRoBlob.size(), decompressed_len); + if (decompressed_len != mRoBlob.size()) + { + throw fnd::Exception(kModuleName, "NSO ro segment failed to decompress"); + } + } + else + { + mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size); + (*mFile)->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size()); + } + if (mHdr.getRoSegmentInfo().is_hashed) + { + fnd::sha::Sha256(mRoBlob.data(), mRoBlob.size(), calc_hash.bytes); + if (calc_hash != mHdr.getRoSegmentInfo().hash) + { + throw fnd::Exception(kModuleName, "NSO ro segment failed SHA256 verification"); + } + } + + // process data segment + if (mHdr.getDataSegmentInfo().is_compressed) + { + scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size); + (*mFile)->read(scratch.data(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.size()); + mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size); + fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mDataBlob.data(), (uint32_t)mDataBlob.size(), decompressed_len); + if (decompressed_len != mDataBlob.size()) + { + throw fnd::Exception(kModuleName, "NSO data segment failed to decompress"); + } + } + else + { + mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size); + (*mFile)->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size()); + } + if (mHdr.getDataSegmentInfo().is_hashed) + { + fnd::sha::Sha256(mDataBlob.data(), mDataBlob.size(), calc_hash.bytes); + if (calc_hash != mHdr.getDataSegmentInfo().hash) + { + throw fnd::Exception(kModuleName, "NSO data segment failed SHA256 verification"); + } + } +} + +void NsoProcess::displayNsoHeader() +{ + std::cout << "[NSO Header]" << std::endl; + std::cout << " ModuleId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getModuleId().data, nn::hac::nso::kModuleIdSize, false, "") << std::endl; + if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT)) + { + std::cout << " Program Segments:" << std::endl; + std::cout << " .module_name:" << std::endl; + std::cout << " FileOffset: 0x" << std::hex << mHdr.getModuleNameInfo().offset << std::endl; + std::cout << " FileSize: 0x" << std::hex << mHdr.getModuleNameInfo().size << std::endl; + std::cout << " .text:" << std::endl; + std::cout << " FileOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.offset << std::endl; + std::cout << " FileSize: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.size << (mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; + std::cout << " .ro:" << std::endl; + std::cout << " FileOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.offset << std::endl; + std::cout << " FileSize: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.size << (mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; + std::cout << " .data:" << std::endl; + std::cout << " FileOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.offset << std::endl; + std::cout << " FileSize: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.size << (mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl; + } + std::cout << " Program Sections:" << std::endl; + std::cout << " .text:" << std::endl; + std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.offset << std::endl; + std::cout << " MemorySize: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.size << std::endl; + if (mHdr.getTextSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getTextSegmentInfo().hash.bytes, 32, false, "") << std::endl; + } + std::cout << " .ro:" << std::endl; + std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.offset << std::endl; + std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.size << std::endl; + if (mHdr.getRoSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRoSegmentInfo().hash.bytes, 32, false, "") << std::endl; + } + if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " .api_info:" << std::endl; + std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoEmbeddedInfo().offset << std::endl; + std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoEmbeddedInfo().size << std::endl; + std::cout << " .dynstr:" << std::endl; + std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoDynStrInfo().offset << std::endl; + std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoDynStrInfo().size << std::endl; + std::cout << " .dynsym:" << std::endl; + std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoDynSymInfo().offset << std::endl; + std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoDynSymInfo().size << std::endl; + } + + std::cout << " .data:" << std::endl; + std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.offset << std::endl; + std::cout << " MemorySize: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.size << std::endl; + if (mHdr.getDataSegmentInfo().is_hashed && _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getDataSegmentInfo().hash.bytes, 32, false, "") << std::endl; + } + std::cout << " .bss:" << std::endl; + std::cout << " MemorySize: 0x" << std::hex << mHdr.getBssSize() << std::endl; +} + +void NsoProcess::processRoMeta() +{ + if (mRoBlob.size()) + { + // setup ro metadata + mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().offset, mHdr.getRoEmbeddedInfo().size); + mRoMeta.setDynSym(mHdr.getRoDynSymInfo().offset, mHdr.getRoDynSymInfo().size); + mRoMeta.setDynStr(mHdr.getRoDynStrInfo().offset, mHdr.getRoDynStrInfo().size); + mRoMeta.setRoBinary(mRoBlob); + mRoMeta.setCliOutputMode(mCliOutputMode); + mRoMeta.process(); + } } \ No newline at end of file diff --git a/programs/nstool/source/NsoProcess.h b/programs/nstool/source/NsoProcess.h index ca738b5..9ac4469 100644 --- a/programs/nstool/source/NsoProcess.h +++ b/programs/nstool/source/NsoProcess.h @@ -1,47 +1,47 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "RoMetadataProcess.h" - -class NsoProcess -{ -public: - NsoProcess(); - - void process(); - - void setInputFile(const fnd::SharedPtr& file); - void setCliOutputMode(CliOutputMode type); - void setVerifyMode(bool verify); - - void setInstructionType(nn::hac::meta::InstructionType type); - void setListApi(bool listApi); - void setListSymbols(bool listSymbols); - - const RoMetadataProcess& getRoMetadataProcess() const; -private: - const std::string kModuleName = "NsoProcess"; - - fnd::SharedPtr mFile; - CliOutputMode mCliOutputMode; - bool mVerify; - nn::hac::meta::InstructionType mInstructionType; - bool mListApi; - bool mListSymbols; - - nn::hac::NsoHeader mHdr; - fnd::Vec mTextBlob, mRoBlob, mDataBlob; - RoMetadataProcess mRoMeta; - - void importHeader(); - void importCodeSegments(); - void displayNsoHeader(); - void processRoMeta(); +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "RoMetadataProcess.h" + +class NsoProcess +{ +public: + NsoProcess(); + + void process(); + + void setInputFile(const fnd::SharedPtr& file); + void setCliOutputMode(CliOutputMode type); + void setVerifyMode(bool verify); + + void setInstructionType(nn::hac::meta::InstructionType type); + void setListApi(bool listApi); + void setListSymbols(bool listSymbols); + + const RoMetadataProcess& getRoMetadataProcess() const; +private: + const std::string kModuleName = "NsoProcess"; + + fnd::SharedPtr mFile; + CliOutputMode mCliOutputMode; + bool mVerify; + nn::hac::meta::InstructionType mInstructionType; + bool mListApi; + bool mListSymbols; + + nn::hac::NsoHeader mHdr; + fnd::Vec mTextBlob, mRoBlob, mDataBlob; + RoMetadataProcess mRoMeta; + + void importHeader(); + void importCodeSegments(); + void displayNsoHeader(); + void processRoMeta(); }; \ No newline at end of file diff --git a/programs/nstool/source/PfsProcess.cpp b/programs/nstool/source/PfsProcess.cpp index 999b487..3661fd1 100644 --- a/programs/nstool/source/PfsProcess.cpp +++ b/programs/nstool/source/PfsProcess.cpp @@ -63,7 +63,7 @@ void PfsProcess::setListFs(bool list_fs) mListFs = list_fs; } -const nn::hac::PfsHeader& PfsProcess::getPfsHeader() const +const nn::hac::PartitionFsHeader& PfsProcess::getPfsHeader() const { return mPfs; } @@ -110,16 +110,16 @@ void PfsProcess::displayFs() { for (size_t i = 0; i < mPfs.getFileList().size(); i++) { - const nn::hac::PfsHeader::sFile& file = mPfs.getFileList()[i]; + const nn::hac::PartitionFsHeader::sFile& file = mPfs.getFileList()[i]; std::cout << " " << file.name; if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT)) { switch (mPfs.getFsType()) { - case (nn::hac::PfsHeader::TYPE_PFS0): + case (nn::hac::PartitionFsHeader::TYPE_PFS0): std::cout << std::hex << " (offset=0x" << file.offset << ", size=0x" << file.size << ")"; break; - case (nn::hac::PfsHeader::TYPE_HFS0): + case (nn::hac::PartitionFsHeader::TYPE_HFS0): std::cout << std::hex << " (offset=0x" << file.offset << ", size=0x" << file.size << ", hash_protected_size=0x" << file.hash_protected_size << ")"; break; } @@ -148,7 +148,7 @@ bool PfsProcess::validateHeaderMagic(const nn::hac::sPfsHeader* hdr) void PfsProcess::validateHfs() { fnd::sha::sSha256Hash hash; - const fnd::List& file = mPfs.getFileList(); + const fnd::List& file = mPfs.getFileList(); for (size_t i = 0; i < file.size(); i++) { mCache.alloc(file[i].hash_protected_size); @@ -170,7 +170,7 @@ void PfsProcess::extractFs() fnd::io::makeDirectory(mExtractPath); fnd::SimpleFile outFile; - const fnd::List& file = mPfs.getFileList(); + const fnd::List& file = mPfs.getFileList(); std::string file_path; for (size_t i = 0; i < file.size(); i++) @@ -193,16 +193,16 @@ void PfsProcess::extractFs() } } -const char* PfsProcess::getFsTypeStr(nn::hac::PfsHeader::FsType type) const +const char* PfsProcess::getFsTypeStr(nn::hac::PartitionFsHeader::FsType type) const { const char* str = nullptr; switch (type) { - case (nn::hac::PfsHeader::TYPE_PFS0): + case (nn::hac::PartitionFsHeader::TYPE_PFS0): str = "PFS0"; break; - case (nn::hac::PfsHeader::TYPE_HFS0): + case (nn::hac::PartitionFsHeader::TYPE_HFS0): str = "HFS0"; break; default: diff --git a/programs/nstool/source/PfsProcess.h b/programs/nstool/source/PfsProcess.h index bf9d61c..d49ba9a 100644 --- a/programs/nstool/source/PfsProcess.h +++ b/programs/nstool/source/PfsProcess.h @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include "common.h" @@ -24,7 +24,7 @@ public: void setExtractPath(const std::string& path); void setListFs(bool list_fs); - const nn::hac::PfsHeader& getPfsHeader() const; + const nn::hac::PartitionFsHeader& getPfsHeader() const; private: const std::string kModuleName = "PfsProcess"; @@ -41,7 +41,7 @@ private: fnd::Vec mCache; - nn::hac::PfsHeader mPfs; + nn::hac::PartitionFsHeader mPfs; void importHeader(); void displayHeader(); @@ -51,5 +51,5 @@ private: void validateHfs(); void extractFs(); - const char* getFsTypeStr(nn::hac::PfsHeader::FsType type) const; + const char* getFsTypeStr(nn::hac::PartitionFsHeader::FsType type) const; }; \ No newline at end of file diff --git a/programs/nstool/source/RoMetadataProcess.cpp b/programs/nstool/source/RoMetadataProcess.cpp index 3025fbf..48bcd6f 100644 --- a/programs/nstool/source/RoMetadataProcess.cpp +++ b/programs/nstool/source/RoMetadataProcess.cpp @@ -1,283 +1,283 @@ -#include -#include -#include -#include - -#include "RoMetadataProcess.h" - -RoMetadataProcess::RoMetadataProcess() : - mCliOutputMode(_BIT(OUTPUT_BASIC)), - mInstructionType(nn::hac::meta::INSTR_64BIT), - mListApi(false), - mListSymbols(false), - mApiInfo(), - mDynSym(), - mDynStr(), - mRoBlob(), - mSdkVerApiList(), - mPublicApiList(), - mDebugApiList(), - mPrivateApiList(), - mSymbolList() -{ - -} - -void RoMetadataProcess::process() -{ - importApiList(); - - if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) - displayRoMetaData(); -} - -void RoMetadataProcess::setRoBinary(const fnd::Vec& bin) -{ - mRoBlob = bin; -} - -void RoMetadataProcess::setApiInfo(size_t offset, size_t size) -{ - mApiInfo.offset = offset; - mApiInfo.size = size; -} -void RoMetadataProcess::setDynSym(size_t offset, size_t size) -{ - mDynSym.offset = offset; - mDynSym.size = size; -} -void RoMetadataProcess::setDynStr(size_t offset, size_t size) -{ - mDynStr.offset = offset; - mDynStr.size = size; -} - -void RoMetadataProcess::setCliOutputMode(CliOutputMode type) -{ - mCliOutputMode = type; -} - -void RoMetadataProcess::setInstructionType(nn::hac::meta::InstructionType type) -{ - mInstructionType = type; -} - -void RoMetadataProcess::setListApi(bool listApi) -{ - mListApi = listApi; -} - -void RoMetadataProcess::setListSymbols(bool listSymbols) -{ - mListSymbols = listSymbols; -} - -const std::vector& RoMetadataProcess::getSdkVerApiList() const -{ - return mSdkVerApiList; -} - -const std::vector& RoMetadataProcess::getPublicApiList() const -{ - return mPublicApiList; -} - -const std::vector& RoMetadataProcess::getDebugApiList() const -{ - return mDebugApiList; -} - -const std::vector& RoMetadataProcess::getPrivateApiList() const -{ - return mPrivateApiList; -} - -const fnd::List& RoMetadataProcess::getSymbolList() const -{ - return mSymbolList.getSymbolList(); -} - -void RoMetadataProcess::importApiList() -{ - if (mRoBlob.size() == 0) - { - throw fnd::Exception(kModuleName, "No ro binary set."); - } - - if (mApiInfo.size > 0) - { - std::stringstream list_stream(std::string((char*)mRoBlob.data() + mApiInfo.offset, mApiInfo.size)); - std::string api_str; - - while(std::getline(list_stream, api_str, (char)0x00)) - { - SdkApiString api(api_str); - - if (api.getApiType() == SdkApiString::API_SDK_VERSION) - mSdkVerApiList.push_back(api); - else if (api.getApiType() == SdkApiString::API_MIDDLEWARE) - mPublicApiList.push_back(api); - else if (api.getApiType() == SdkApiString::API_DEBUG) - mDebugApiList.push_back(api); - else if (api.getApiType() == SdkApiString::API_PRIVATE) - mPrivateApiList.push_back(api); - } - } - - if (mDynSym.size > 0) - { - mSymbolList.parseData(mRoBlob.data() + mDynSym.offset, mDynSym.size, mRoBlob.data() + mDynStr.offset, mDynStr.size, mInstructionType == nn::hac::meta::INSTR_64BIT); - } -} - -void RoMetadataProcess::displayRoMetaData() -{ - size_t api_num = mSdkVerApiList.size() + mPublicApiList.size() + mDebugApiList.size() + mPrivateApiList.size(); - - if (api_num > 0 && (mListApi || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))) - { - std::cout << "[SDK API List]" << std::endl; - if (mSdkVerApiList.size() > 0) - { - std::cout << " Sdk Revision: " << mSdkVerApiList[0].getModuleName() << std::endl; - } - if (mPublicApiList.size() > 0) - { - std::cout << " Public APIs:" << std::endl; - for (size_t i = 0; i < mPublicApiList.size(); i++) - { - std::cout << " " << mPublicApiList[i].getModuleName() << " (vender: " << mPublicApiList[i].getVenderName() << ")" << std::endl; - } - } - if (mDebugApiList.size() > 0) - { - std::cout << " Debug APIs:" << std::endl; - for (size_t i = 0; i < mDebugApiList.size(); i++) - { - std::cout << " " << mDebugApiList[i].getModuleName() << " (vender: " << mDebugApiList[i].getVenderName() << ")" << std::endl; - } - } - if (mPrivateApiList.size() > 0) - { - std::cout << " Private APIs:" << std::endl; - for (size_t i = 0; i < mPrivateApiList.size(); i++) - { - std::cout << " " << mPrivateApiList[i].getModuleName() << " (vender: " << mPrivateApiList[i].getVenderName() << ")" << std::endl; - } - } - } - if (mSymbolList.getSymbolList().size() > 0 && (mListSymbols || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))) - { - std::cout << "[Symbol List]" << std::endl; - for (size_t i = 0; i < mSymbolList.getSymbolList().size(); i++) - { - const ElfSymbolParser::sElfSymbol& symbol = mSymbolList.getSymbolList()[i]; - std::cout << " " << symbol.name << " [SHN=" << getSectionIndexStr(symbol.shn_index) << " (" << std::hex << std::setw(4) << std::setfill('0') << symbol.shn_index << ")][STT=" << getSymbolTypeStr(symbol.symbol_type) << "][STB=" << getSymbolBindingStr(symbol.symbol_binding) << "]" << std::endl; - } - } -} - -const char* RoMetadataProcess::getSectionIndexStr(uint16_t shn_index) const -{ - const char* str; - switch (shn_index) - { - case (fnd::elf::SHN_UNDEF): - str = "UNDEF"; - break; - case (fnd::elf::SHN_LOPROC): - str = "LOPROC"; - break; - case (fnd::elf::SHN_HIPROC): - str = "HIPROC"; - break; - case (fnd::elf::SHN_LOOS): - str = "LOOS"; - break; - case (fnd::elf::SHN_HIOS): - str = "HIOS"; - break; - case (fnd::elf::SHN_ABS): - str = "ABS"; - break; - case (fnd::elf::SHN_COMMON): - str = "COMMON"; - break; - default: - str = "UNKNOWN"; - break; - } - return str; -} - -const char* RoMetadataProcess::getSymbolTypeStr(byte_t symbol_type) const -{ - const char* str; - switch (symbol_type) - { - case (fnd::elf::STT_NOTYPE): - str = "NOTYPE"; - break; - case (fnd::elf::STT_OBJECT): - str = "OBJECT"; - break; - case (fnd::elf::STT_FUNC): - str = "FUNC"; - break; - case (fnd::elf::STT_SECTION): - str = "SECTION"; - break; - case (fnd::elf::STT_FILE): - str = "FILE"; - break; - case (fnd::elf::STT_LOOS): - str = "LOOS"; - break; - case (fnd::elf::STT_HIOS): - str = "HIOS"; - break; - case (fnd::elf::STT_LOPROC): - str = "LOPROC"; - break; - case (fnd::elf::STT_HIPROC): - str = "HIPROC"; - break; - default: - str = "UNKNOWN"; - break; - } - return str; -} - -const char* RoMetadataProcess::getSymbolBindingStr(byte_t symbol_binding) const -{ - const char* str; - switch (symbol_binding) - { - case (fnd::elf::STB_LOCAL): - str = "LOCAL"; - break; - case (fnd::elf::STB_GLOBAL): - str = "GLOBAL"; - break; - case (fnd::elf::STB_WEAK): - str = "WEAK"; - break; - case (fnd::elf::STB_LOOS): - str = "LOOS"; - break; - case (fnd::elf::STB_HIOS): - str = "HIOS"; - break; - case (fnd::elf::STB_LOPROC): - str = "LOPROC"; - break; - case (fnd::elf::STB_HIPROC): - str = "HIPROC"; - break; - default: - str = "UNKNOWN"; - break; - } - return str; +#include +#include +#include +#include + +#include "RoMetadataProcess.h" + +RoMetadataProcess::RoMetadataProcess() : + mCliOutputMode(_BIT(OUTPUT_BASIC)), + mInstructionType(nn::hac::meta::INSTR_64BIT), + mListApi(false), + mListSymbols(false), + mApiInfo(), + mDynSym(), + mDynStr(), + mRoBlob(), + mSdkVerApiList(), + mPublicApiList(), + mDebugApiList(), + mPrivateApiList(), + mSymbolList() +{ + +} + +void RoMetadataProcess::process() +{ + importApiList(); + + if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) + displayRoMetaData(); +} + +void RoMetadataProcess::setRoBinary(const fnd::Vec& bin) +{ + mRoBlob = bin; +} + +void RoMetadataProcess::setApiInfo(size_t offset, size_t size) +{ + mApiInfo.offset = offset; + mApiInfo.size = size; +} +void RoMetadataProcess::setDynSym(size_t offset, size_t size) +{ + mDynSym.offset = offset; + mDynSym.size = size; +} +void RoMetadataProcess::setDynStr(size_t offset, size_t size) +{ + mDynStr.offset = offset; + mDynStr.size = size; +} + +void RoMetadataProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void RoMetadataProcess::setInstructionType(nn::hac::meta::InstructionType type) +{ + mInstructionType = type; +} + +void RoMetadataProcess::setListApi(bool listApi) +{ + mListApi = listApi; +} + +void RoMetadataProcess::setListSymbols(bool listSymbols) +{ + mListSymbols = listSymbols; +} + +const std::vector& RoMetadataProcess::getSdkVerApiList() const +{ + return mSdkVerApiList; +} + +const std::vector& RoMetadataProcess::getPublicApiList() const +{ + return mPublicApiList; +} + +const std::vector& RoMetadataProcess::getDebugApiList() const +{ + return mDebugApiList; +} + +const std::vector& RoMetadataProcess::getPrivateApiList() const +{ + return mPrivateApiList; +} + +const fnd::List& RoMetadataProcess::getSymbolList() const +{ + return mSymbolList.getSymbolList(); +} + +void RoMetadataProcess::importApiList() +{ + if (mRoBlob.size() == 0) + { + throw fnd::Exception(kModuleName, "No ro binary set."); + } + + if (mApiInfo.size > 0) + { + std::stringstream list_stream(std::string((char*)mRoBlob.data() + mApiInfo.offset, mApiInfo.size)); + std::string api_str; + + while(std::getline(list_stream, api_str, (char)0x00)) + { + SdkApiString api(api_str); + + if (api.getApiType() == SdkApiString::API_SDK_VERSION) + mSdkVerApiList.push_back(api); + else if (api.getApiType() == SdkApiString::API_MIDDLEWARE) + mPublicApiList.push_back(api); + else if (api.getApiType() == SdkApiString::API_DEBUG) + mDebugApiList.push_back(api); + else if (api.getApiType() == SdkApiString::API_PRIVATE) + mPrivateApiList.push_back(api); + } + } + + if (mDynSym.size > 0) + { + mSymbolList.parseData(mRoBlob.data() + mDynSym.offset, mDynSym.size, mRoBlob.data() + mDynStr.offset, mDynStr.size, mInstructionType == nn::hac::meta::INSTR_64BIT); + } +} + +void RoMetadataProcess::displayRoMetaData() +{ + size_t api_num = mSdkVerApiList.size() + mPublicApiList.size() + mDebugApiList.size() + mPrivateApiList.size(); + + if (api_num > 0 && (mListApi || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))) + { + std::cout << "[SDK API List]" << std::endl; + if (mSdkVerApiList.size() > 0) + { + std::cout << " Sdk Revision: " << mSdkVerApiList[0].getModuleName() << std::endl; + } + if (mPublicApiList.size() > 0) + { + std::cout << " Public APIs:" << std::endl; + for (size_t i = 0; i < mPublicApiList.size(); i++) + { + std::cout << " " << mPublicApiList[i].getModuleName() << " (vender: " << mPublicApiList[i].getVenderName() << ")" << std::endl; + } + } + if (mDebugApiList.size() > 0) + { + std::cout << " Debug APIs:" << std::endl; + for (size_t i = 0; i < mDebugApiList.size(); i++) + { + std::cout << " " << mDebugApiList[i].getModuleName() << " (vender: " << mDebugApiList[i].getVenderName() << ")" << std::endl; + } + } + if (mPrivateApiList.size() > 0) + { + std::cout << " Private APIs:" << std::endl; + for (size_t i = 0; i < mPrivateApiList.size(); i++) + { + std::cout << " " << mPrivateApiList[i].getModuleName() << " (vender: " << mPrivateApiList[i].getVenderName() << ")" << std::endl; + } + } + } + if (mSymbolList.getSymbolList().size() > 0 && (mListSymbols || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))) + { + std::cout << "[Symbol List]" << std::endl; + for (size_t i = 0; i < mSymbolList.getSymbolList().size(); i++) + { + const ElfSymbolParser::sElfSymbol& symbol = mSymbolList.getSymbolList()[i]; + std::cout << " " << symbol.name << " [SHN=" << getSectionIndexStr(symbol.shn_index) << " (" << std::hex << std::setw(4) << std::setfill('0') << symbol.shn_index << ")][STT=" << getSymbolTypeStr(symbol.symbol_type) << "][STB=" << getSymbolBindingStr(symbol.symbol_binding) << "]" << std::endl; + } + } +} + +const char* RoMetadataProcess::getSectionIndexStr(uint16_t shn_index) const +{ + const char* str; + switch (shn_index) + { + case (fnd::elf::SHN_UNDEF): + str = "UNDEF"; + break; + case (fnd::elf::SHN_LOPROC): + str = "LOPROC"; + break; + case (fnd::elf::SHN_HIPROC): + str = "HIPROC"; + break; + case (fnd::elf::SHN_LOOS): + str = "LOOS"; + break; + case (fnd::elf::SHN_HIOS): + str = "HIOS"; + break; + case (fnd::elf::SHN_ABS): + str = "ABS"; + break; + case (fnd::elf::SHN_COMMON): + str = "COMMON"; + break; + default: + str = "UNKNOWN"; + break; + } + return str; +} + +const char* RoMetadataProcess::getSymbolTypeStr(byte_t symbol_type) const +{ + const char* str; + switch (symbol_type) + { + case (fnd::elf::STT_NOTYPE): + str = "NOTYPE"; + break; + case (fnd::elf::STT_OBJECT): + str = "OBJECT"; + break; + case (fnd::elf::STT_FUNC): + str = "FUNC"; + break; + case (fnd::elf::STT_SECTION): + str = "SECTION"; + break; + case (fnd::elf::STT_FILE): + str = "FILE"; + break; + case (fnd::elf::STT_LOOS): + str = "LOOS"; + break; + case (fnd::elf::STT_HIOS): + str = "HIOS"; + break; + case (fnd::elf::STT_LOPROC): + str = "LOPROC"; + break; + case (fnd::elf::STT_HIPROC): + str = "HIPROC"; + break; + default: + str = "UNKNOWN"; + break; + } + return str; +} + +const char* RoMetadataProcess::getSymbolBindingStr(byte_t symbol_binding) const +{ + const char* str; + switch (symbol_binding) + { + case (fnd::elf::STB_LOCAL): + str = "LOCAL"; + break; + case (fnd::elf::STB_GLOBAL): + str = "GLOBAL"; + break; + case (fnd::elf::STB_WEAK): + str = "WEAK"; + break; + case (fnd::elf::STB_LOOS): + str = "LOOS"; + break; + case (fnd::elf::STB_HIOS): + str = "HIOS"; + break; + case (fnd::elf::STB_LOPROC): + str = "LOPROC"; + break; + case (fnd::elf::STB_HIPROC): + str = "HIPROC"; + break; + default: + str = "UNKNOWN"; + break; + } + return str; } \ No newline at end of file diff --git a/programs/nstool/source/RoMetadataProcess.h b/programs/nstool/source/RoMetadataProcess.h index 616a43e..71dab32 100644 --- a/programs/nstool/source/RoMetadataProcess.h +++ b/programs/nstool/source/RoMetadataProcess.h @@ -1,68 +1,68 @@ -#pragma once -#include -#include -#include -#include - -#include - -#include "common.h" -#include "SdkApiString.h" -#include "ElfSymbolParser.h" - -class RoMetadataProcess -{ -public: - RoMetadataProcess(); - - void process(); - - void setRoBinary(const fnd::Vec& bin); - void setApiInfo(size_t offset, size_t size); - void setDynSym(size_t offset, size_t size); - void setDynStr(size_t offset, size_t size); - - void setCliOutputMode(CliOutputMode type); - - void setInstructionType(nn::hac::meta::InstructionType type); - void setListApi(bool listApi); - void setListSymbols(bool listSymbols); - - const std::vector& getSdkVerApiList() const; - const std::vector& getPublicApiList() const; - const std::vector& getDebugApiList() const; - const std::vector& getPrivateApiList() const; - const fnd::List& getSymbolList() const; -private: - const std::string kModuleName = "RoMetadataProcess"; - - CliOutputMode mCliOutputMode; - nn::hac::meta::InstructionType mInstructionType; - bool mListApi; - bool mListSymbols; - - struct sLayout - { - sLayout() : offset(0), size(0) {} - size_t offset; - size_t size; - }; - - sLayout mApiInfo; - sLayout mDynSym; - sLayout mDynStr; - fnd::Vec mRoBlob; - std::vector mSdkVerApiList; - std::vector mPublicApiList; - std::vector mDebugApiList; - std::vector mPrivateApiList; - - ElfSymbolParser mSymbolList; - - void importApiList(); - void displayRoMetaData(); - - const char* getSectionIndexStr(uint16_t shn_index) const; - const char* getSymbolTypeStr(byte_t symbol_type) const; - const char* getSymbolBindingStr(byte_t symbol_binding) const; +#pragma once +#include +#include +#include +#include + +#include + +#include "common.h" +#include "SdkApiString.h" +#include "ElfSymbolParser.h" + +class RoMetadataProcess +{ +public: + RoMetadataProcess(); + + void process(); + + void setRoBinary(const fnd::Vec& bin); + void setApiInfo(size_t offset, size_t size); + void setDynSym(size_t offset, size_t size); + void setDynStr(size_t offset, size_t size); + + void setCliOutputMode(CliOutputMode type); + + void setInstructionType(nn::hac::meta::InstructionType type); + void setListApi(bool listApi); + void setListSymbols(bool listSymbols); + + const std::vector& getSdkVerApiList() const; + const std::vector& getPublicApiList() const; + const std::vector& getDebugApiList() const; + const std::vector& getPrivateApiList() const; + const fnd::List& getSymbolList() const; +private: + const std::string kModuleName = "RoMetadataProcess"; + + CliOutputMode mCliOutputMode; + nn::hac::meta::InstructionType mInstructionType; + bool mListApi; + bool mListSymbols; + + struct sLayout + { + sLayout() : offset(0), size(0) {} + size_t offset; + size_t size; + }; + + sLayout mApiInfo; + sLayout mDynSym; + sLayout mDynStr; + fnd::Vec mRoBlob; + std::vector mSdkVerApiList; + std::vector mPublicApiList; + std::vector mDebugApiList; + std::vector mPrivateApiList; + + ElfSymbolParser mSymbolList; + + void importApiList(); + void displayRoMetaData(); + + const char* getSectionIndexStr(uint16_t shn_index) const; + const char* getSymbolTypeStr(byte_t symbol_type) const; + const char* getSymbolBindingStr(byte_t symbol_binding) const; }; \ No newline at end of file diff --git a/programs/nstool/source/RomfsProcess.h b/programs/nstool/source/RomfsProcess.h index 9edb32c..14e2e52 100644 --- a/programs/nstool/source/RomfsProcess.h +++ b/programs/nstool/source/RomfsProcess.h @@ -1,134 +1,134 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" - -class RomfsProcess -{ -public: - struct sDirectory; - struct sFile; - - struct sDirectory - { - std::string name; - fnd::List dir_list; - fnd::List file_list; - - void operator=(const sDirectory& other) - { - name = other.name; - dir_list = other.dir_list; - file_list = other.file_list; - } - - bool operator==(const sDirectory& other) const - { - return (name == other.name) \ - && (dir_list == other.dir_list) \ - && (file_list == other.file_list); - } - - bool operator!=(const sDirectory& other) const - { - return !operator==(other); - } - - bool operator==(const std::string& other) const - { - return (name == other); - } - }; - - struct sFile - { - std::string name; - uint64_t offset; - uint64_t size; - - void operator=(const sFile& other) - { - name = other.name; - offset = other.offset; - size = other.size; - } - - bool operator==(const sFile& other) const - { - return (name == other.name) \ - && (offset == other.offset) \ - && (size == other.size); - } - - bool operator!=(const sFile& other) const - { - return !operator==(other); - } - - bool operator==(const std::string& other) const - { - return (name == other); - } - }; - - RomfsProcess(); - - void process(); - - // generic - void setInputFile(const fnd::SharedPtr& file); - void setCliOutputMode(CliOutputMode type); - void setVerifyMode(bool verify); - - // romfs specific - void setMountPointName(const std::string& mount_name); - void setExtractPath(const std::string& path); - void setListFs(bool list_fs); - - const sDirectory& getRootDir() const; -private: - const std::string kModuleName = "RomfsProcess"; - static const size_t kCacheSize = 0x10000; - - fnd::SharedPtr mFile; - CliOutputMode mCliOutputMode; - bool mVerify; - - std::string mExtractPath; - bool mExtract; - std::string mMountName; - bool mListFs; - - fnd::Vec mCache; - - size_t mDirNum; - size_t mFileNum; - nn::hac::sRomfsHeader mHdr; - fnd::Vec mDirNodes; - fnd::Vec mFileNodes; - sDirectory mRootDir; - - inline nn::hac::sRomfsDirEntry* get_dir_node(uint32_t offset) { return (nn::hac::sRomfsDirEntry*)(mDirNodes.data() + offset); } - inline nn::hac::sRomfsFileEntry* get_file_node(uint32_t offset) { return (nn::hac::sRomfsFileEntry*)(mFileNodes.data() + offset); } - - - void printTab(size_t tab) const; - void displayFile(const sFile& file, size_t tab) const; - void displayDir(const sDirectory& dir, size_t tab) const; - - void displayHeader(); - void displayFs(); - - void extractDir(const std::string& path, const sDirectory& dir); - void extractFs(); - - bool validateHeaderLayout(const nn::hac::sRomfsHeader* hdr) const; - void importDirectory(uint32_t dir_offset, sDirectory& dir); - void resolveRomfs(); +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +class RomfsProcess +{ +public: + struct sDirectory; + struct sFile; + + struct sDirectory + { + std::string name; + fnd::List dir_list; + fnd::List file_list; + + void operator=(const sDirectory& other) + { + name = other.name; + dir_list = other.dir_list; + file_list = other.file_list; + } + + bool operator==(const sDirectory& other) const + { + return (name == other.name) \ + && (dir_list == other.dir_list) \ + && (file_list == other.file_list); + } + + bool operator!=(const sDirectory& other) const + { + return !operator==(other); + } + + bool operator==(const std::string& other) const + { + return (name == other); + } + }; + + struct sFile + { + std::string name; + uint64_t offset; + uint64_t size; + + void operator=(const sFile& other) + { + name = other.name; + offset = other.offset; + size = other.size; + } + + bool operator==(const sFile& other) const + { + return (name == other.name) \ + && (offset == other.offset) \ + && (size == other.size); + } + + bool operator!=(const sFile& other) const + { + return !operator==(other); + } + + bool operator==(const std::string& other) const + { + return (name == other); + } + }; + + RomfsProcess(); + + void process(); + + // generic + void setInputFile(const fnd::SharedPtr& file); + void setCliOutputMode(CliOutputMode type); + void setVerifyMode(bool verify); + + // romfs specific + void setMountPointName(const std::string& mount_name); + void setExtractPath(const std::string& path); + void setListFs(bool list_fs); + + const sDirectory& getRootDir() const; +private: + const std::string kModuleName = "RomfsProcess"; + static const size_t kCacheSize = 0x10000; + + fnd::SharedPtr mFile; + CliOutputMode mCliOutputMode; + bool mVerify; + + std::string mExtractPath; + bool mExtract; + std::string mMountName; + bool mListFs; + + fnd::Vec mCache; + + size_t mDirNum; + size_t mFileNum; + nn::hac::sRomfsHeader mHdr; + fnd::Vec mDirNodes; + fnd::Vec mFileNodes; + sDirectory mRootDir; + + inline nn::hac::sRomfsDirEntry* get_dir_node(uint32_t offset) { return (nn::hac::sRomfsDirEntry*)(mDirNodes.data() + offset); } + inline nn::hac::sRomfsFileEntry* get_file_node(uint32_t offset) { return (nn::hac::sRomfsFileEntry*)(mFileNodes.data() + offset); } + + + void printTab(size_t tab) const; + void displayFile(const sFile& file, size_t tab) const; + void displayDir(const sDirectory& dir, size_t tab) const; + + void displayHeader(); + void displayFs(); + + void extractDir(const std::string& path, const sDirectory& dir); + void extractFs(); + + bool validateHeaderLayout(const nn::hac::sRomfsHeader* hdr) const; + void importDirectory(uint32_t dir_offset, sDirectory& dir); + void resolveRomfs(); }; \ No newline at end of file diff --git a/programs/nstool/source/UserSettings.cpp b/programs/nstool/source/UserSettings.cpp index 955e9ee..186eb33 100644 --- a/programs/nstool/source/UserSettings.cpp +++ b/programs/nstool/source/UserSettings.cpp @@ -1,1032 +1,1032 @@ -#include "UserSettings.h" -#include "version.h" -#include "PkiValidator.h" -#include "KeyConfiguration.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -UserSettings::UserSettings() -{} - -void UserSettings::parseCmdArgs(const std::vector& arg_list) -{ - sCmdArgs args; - populateCmdArgs(arg_list, args); - populateKeyset(args); - populateUserSettings(args); - if (_HAS_BIT(mOutputMode, OUTPUT_KEY_DATA)) - dumpKeyConfig(); -} - -void UserSettings::showHelp() -{ - printf("%s v%d.%d.%d (C) %s\n", APP_NAME, VER_MAJOR, VER_MINOR, VER_PATCH, AUTHORS); - printf("Built: %s %s\n\n", __TIME__, __DATE__); - - printf("Usage: %s [options... ] \n", BIN_NAME); - printf("\n General Options:\n"); - printf(" -d, --dev Use devkit keyset.\n"); - printf(" -k, --keyset Specify keyset file.\n"); - printf(" -t, --type Specify input file type. [xci, pfs, romfs, nca, meta, cnmt, nso, nro, nacp, aset, cert, tik]\n"); - printf(" -y, --verify Verify file.\n"); - printf("\n Output Options:\n"); - printf(" --showkeys Show keys generated.\n"); - printf(" --showlayout Show layout metadata.\n"); - printf(" -v, --verbose Verbose output.\n"); - printf("\n XCI (GameCard Image)\n"); - printf(" %s [--listfs] [--update --logo --normal --secure ] <.xci file>\n", BIN_NAME); - printf(" --listfs Print file system in embedded partitions.\n"); - printf(" --update Extract \"update\" partition to directory.\n"); - printf(" --logo Extract \"logo\" partition to directory.\n"); - printf(" --normal Extract \"normal\" partition to directory.\n"); - printf(" --secure Extract \"secure\" partition to directory.\n"); - printf("\n PFS0/HFS0 (PartitionFs), RomFs, NSP (Ninendo Submission Package)\n"); - printf(" %s [--listfs] [--fsdir ] \n", BIN_NAME); - printf(" --listfs Print file system.\n"); - printf(" --fsdir Extract file system to directory.\n"); - printf("\n NCA (Nintendo Content Archive)\n"); - printf(" %s [--listfs] [--bodykey --titlekey ] [--part0 ...] <.nca file>\n", BIN_NAME); - printf(" --listfs Print file system in embedded partitions.\n"); - printf(" --titlekey Specify title key extracted from ticket.\n"); - printf(" --bodykey Specify body encryption key.\n"); - printf(" --tik Specify ticket to source title key.\n"); - printf(" --cert Specify certificate chain to verify ticket.\n"); - printf(" --part0 Extract \"partition 0\" to directory.\n"); - printf(" --part1 Extract \"partition 1\" to directory.\n"); - printf(" --part2 Extract \"partition 2\" to directory.\n"); - printf(" --part3 Extract \"partition 3\" to directory.\n"); - printf("\n NSO (Nintendo Software Object), NRO (Nintendo Relocatable Object)\n"); - printf(" %s [--listapi --listsym] [--insttype ] \n", BIN_NAME); - printf(" --listapi Print SDK API List.\n"); - printf(" --listsym Print Code Symbols.\n"); - printf(" --insttype Specify instruction type [64bit|32bit] (64bit is assumed).\n"); - printf("\n ASET (Homebrew Asset Blob)\n"); - printf(" %s [--listfs] [--icon --nacp --fsdir ] \n", BIN_NAME); - printf(" --listfs Print filesystem in embedded RomFS partition.\n"); - printf(" --icon Extract icon partition to file.\n"); - printf(" --nacp Extract NACP partition to file.\n"); - printf(" --fsdir Extract RomFS partition to directory.\n"); - -} - -const std::string UserSettings::getInputPath() const -{ - return mInputPath; -} - -const KeyConfiguration& UserSettings::getKeyCfg() const -{ - return mKeyCfg; -} - -FileType UserSettings::getFileType() const -{ - return mFileType; -} - -bool UserSettings::isVerifyFile() const -{ - return mVerifyFile; -} - -CliOutputMode UserSettings::getCliOutputMode() const -{ - return mOutputMode; -} - -bool UserSettings::isListFs() const -{ - return mListFs; -} - -bool UserSettings::isListApi() const -{ - return mListApi; -} -bool UserSettings::isListSymbols() const -{ - return mListSymbols; -} - -nn::hac::meta::InstructionType UserSettings::getInstType() const -{ - return mInstructionType; -} - -const sOptional& UserSettings::getXciUpdatePath() const -{ - return mXciUpdatePath; -} - -const sOptional& UserSettings::getXciLogoPath() const -{ - return mXciLogoPath; -} - -const sOptional& UserSettings::getXciNormalPath() const -{ - return mXciNormalPath; -} - -const sOptional& UserSettings::getXciSecurePath() const -{ - return mXciSecurePath; -} - -const sOptional& UserSettings::getFsPath() const -{ - return mFsPath; -} - -const sOptional& UserSettings::getNcaPart0Path() const -{ - return mNcaPart0Path; -} - -const sOptional& UserSettings::getNcaPart1Path() const -{ - return mNcaPart1Path; -} - -const sOptional& UserSettings::getNcaPart2Path() const -{ - return mNcaPart2Path; -} - -const sOptional& UserSettings::getNcaPart3Path() const -{ - return mNcaPart3Path; -} - -const sOptional& UserSettings::getAssetIconPath() const -{ - return mAssetIconPath; -} - -const sOptional& UserSettings::getAssetNacpPath() const -{ - return mAssetNacpPath; -} - -const fnd::List>& UserSettings::getCertificateChain() const -{ - return mCertChain; -} - -void UserSettings::populateCmdArgs(const std::vector& arg_list, sCmdArgs& cmd_args) -{ - // show help text - if (arg_list.size() < 2) - { - showHelp(); - throw fnd::Exception(kModuleName, "Not enough arguments."); - } - - cmd_args.input_path = arg_list.back(); - - for (size_t i = 1; i < arg_list.size(); i++) - { - if (arg_list[i] == "-h" || arg_list[i] == "--help") - { - showHelp(); - throw fnd::Exception(kModuleName, "Nothing to do."); - } - } - - for (size_t i = 1; i+1 < arg_list.size(); i++) - { - bool hasParamter = arg_list[i+1][0] != '-' && i+2 < arg_list.size(); - - if (arg_list[i] == "-d" || arg_list[i] == "--dev") - { - if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); - cmd_args.devkit_keys = true; - } - - else if (arg_list[i] == "-y" || arg_list[i] == "--verify") - { - if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); - cmd_args.verify_file = true; - } - - else if (arg_list[i] == "--showkeys") - { - if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); - cmd_args.show_keys = true; - } - - else if (arg_list[i] == "--showlayout") - { - if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); - cmd_args.show_layout = true; - } - - else if (arg_list[i] == "-v" || arg_list[i] == "--verbose") - { - if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); - cmd_args.verbose_output = true; - } - - else if (arg_list[i] == "-k" || arg_list[i] == "--keyset") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.keyset_path = arg_list[i+1]; - } - - else if (arg_list[i] == "-t" || arg_list[i] == "--type") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.file_type = arg_list[i+1]; - } - - else if (arg_list[i] == "--listfs") - { - if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); - cmd_args.list_fs = true; - } - - else if (arg_list[i] == "--update") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.update_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--normal") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.normal_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--secure") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.secure_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--logo") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.logo_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--fsdir") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.fs_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--titlekey") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.nca_titlekey = arg_list[i+1]; - } - - else if (arg_list[i] == "--bodykey") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.nca_bodykey = arg_list[i+1]; - } - - else if (arg_list[i] == "--tik") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.ticket_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--cert") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.cert_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--part0") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.part0_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--part1") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.part1_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--part2") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.part2_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--part3") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.part3_path = arg_list[i+1]; - } - - else if (arg_list[i] == "--listapi") - { - if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); - cmd_args.list_api = true; - } - - else if (arg_list[i] == "--listsym") - { - if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); - cmd_args.list_sym = true; - } - - else if (arg_list[i] == "--insttype") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.inst_type = arg_list[i + 1]; - } - - else if (arg_list[i] == "--icon") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.asset_icon_path = arg_list[i + 1]; - } - - else if (arg_list[i] == "--nacp") - { - if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); - cmd_args.asset_nacp_path = arg_list[i + 1]; - } - - else - { - throw fnd::Exception(kModuleName, arg_list[i] + " is not recognised."); - } - - i += hasParamter; - } -} - -void UserSettings::populateKeyset(sCmdArgs& args) -{ - if (args.keyset_path.isSet) - { - mKeyCfg.importHactoolGenericKeyfile(*args.keyset_path); - } - else - { - // open other resource files in $HOME/.switch/prod.keys (or $HOME/.switch/dev.keys if -d/--dev is set). - std::string keyset_path; - getSwitchPath(keyset_path); - if (keyset_path.empty()) - return; - - fnd::io::appendToPath(keyset_path, kGeneralKeyfileName[args.devkit_keys.isSet]); - - try - { - mKeyCfg.importHactoolGenericKeyfile(keyset_path); - } - catch (const fnd::Exception&) - { - return; - } - - } - - - - if (args.nca_bodykey.isSet) - { - fnd::aes::sAes128Key tmp_key; - fnd::Vec tmp_raw; - fnd::SimpleTextOutput::stringToArray(args.nca_bodykey.var, tmp_raw); - if (tmp_raw.size() != sizeof(fnd::aes::sAes128Key)) - throw fnd::Exception(kModuleName, "Key: \"--bodykey\" has incorrect length"); - memcpy(tmp_key.key, tmp_raw.data(), 16); - mKeyCfg.addNcaExternalContentKey(kDummyRightsIdForUserBodyKey, tmp_key); - } - - if (args.nca_titlekey.isSet) - { - fnd::aes::sAes128Key tmp_key; - fnd::Vec tmp_raw; - fnd::SimpleTextOutput::stringToArray(args.nca_titlekey.var, tmp_raw); - if (tmp_raw.size() != sizeof(fnd::aes::sAes128Key)) - throw fnd::Exception(kModuleName, "Key: \"--titlekey\" has incorrect length"); - memcpy(tmp_key.key, tmp_raw.data(), 16); - mKeyCfg.addNcaExternalContentKey(kDummyRightsIdForUserTitleKey, tmp_key); - } - - // import certificate chain - if (args.cert_path.isSet) - { - fnd::SimpleFile cert_file; - fnd::Vec cert_raw; - nn::pki::SignedData cert; - - cert_file.open(args.cert_path.var, fnd::SimpleFile::Read); - cert_raw.alloc(cert_file.size()); - cert_file.read(cert_raw.data(), cert_raw.size()); - - for (size_t i = 0; i < cert_raw.size(); i+= cert.getBytes().size()) - { - cert.fromBytes(cert_raw.data() + i, cert_raw.size() - i); - mCertChain.addElement(cert); - } - } - - // get titlekey from ticket - if (args.ticket_path.isSet) - { - fnd::SimpleFile tik_file; - fnd::Vec tik_raw; - nn::pki::SignedData tik; - - // open and import ticket - tik_file.open(args.ticket_path.var, fnd::SimpleFile::Read); - tik_raw.alloc(tik_file.size()); - tik_file.read(tik_raw.data(), tik_raw.size()); - tik.fromBytes(tik_raw.data(), tik_raw.size()); - - // validate ticket signature - if (mCertChain.size() > 0) - { - PkiValidator pki_validator; - fnd::Vec tik_hash; - - switch (nn::pki::sign::getHashAlgo(tik.getSignature().getSignType())) - { - case (nn::pki::sign::HASH_ALGO_SHA1): - tik_hash.alloc(fnd::sha::kSha1HashLen); - fnd::sha::Sha1(tik.getBody().getBytes().data(), tik.getBody().getBytes().size(), tik_hash.data()); - break; - case (nn::pki::sign::HASH_ALGO_SHA256): - tik_hash.alloc(fnd::sha::kSha256HashLen); - fnd::sha::Sha256(tik.getBody().getBytes().data(), tik.getBody().getBytes().size(), tik_hash.data()); - break; - } - - try - { - pki_validator.setKeyCfg(mKeyCfg); - pki_validator.addCertificates(mCertChain); - pki_validator.validateSignature(tik.getBody().getIssuer(), tik.getSignature().getSignType(), tik.getSignature().getSignature(), tik_hash); - } - catch (const fnd::Exception& e) - { - std::cout << "[WARNING] Ticket signature could not be validated (" << e.error() << ")" << std::endl; - } - - } - - // extract title key - if (tik.getBody().getTitleKeyEncType() == nn::es::ticket::AES128_CBC) - { - fnd::aes::sAes128Key enc_title_key; - memcpy(enc_title_key.key, tik.getBody().getEncTitleKey(), 16); - fnd::aes::sAes128Key common_key, external_content_key; - if (mKeyCfg.getETicketCommonKey(nn::hac::NcaUtils::getMasterKeyRevisionFromKeyGeneration(tik.getBody().getCommonKeyId()), common_key) == true) - { - nn::hac::AesKeygen::generateKey(external_content_key.key, tik.getBody().getEncTitleKey(), common_key.key); - mKeyCfg.addNcaExternalContentKey(tik.getBody().getRightsId(), external_content_key); - } - else - { - std::cout << "[WARNING] Titlekey not imported from ticket because commonkey was not available" << std::endl; - } - } - else - { - std::cout << "[WARNING] Titlekey not imported from ticket because it is personalised" << std::endl; - } - } -} - -void UserSettings::populateUserSettings(sCmdArgs& args) -{ - // check invalid input - if (args.input_path.isSet == false) - throw fnd::Exception(kModuleName, "No input file specified"); - - // save arguments - mInputPath = *args.input_path; - mVerifyFile = args.verify_file.isSet; - mListFs = args.list_fs.isSet; - mXciUpdatePath = args.update_path; - mXciNormalPath = args.normal_path; - mXciSecurePath = args.secure_path; - mXciLogoPath = args.logo_path; - - mFsPath = args.fs_path; - mNcaPart0Path = args.part0_path; - mNcaPart1Path = args.part1_path; - mNcaPart2Path = args.part2_path; - mNcaPart3Path = args.part3_path; - - // determine the architecture type for NSO/NRO - if (args.inst_type.isSet) - mInstructionType = getInstructionTypeFromString(*args.inst_type); - else - mInstructionType = nn::hac::meta::INSTR_64BIT; // default 64bit - - mListApi = args.list_api.isSet; - mListSymbols = args.list_sym.isSet; - - mAssetIconPath = args.asset_icon_path; - mAssetNacpPath = args.asset_nacp_path; - - // determine output mode - mOutputMode = _BIT(OUTPUT_BASIC); - if (args.verbose_output.isSet) - { - mOutputMode |= _BIT(OUTPUT_KEY_DATA); - mOutputMode |= _BIT(OUTPUT_LAYOUT); - mOutputMode |= _BIT(OUTPUT_EXTENDED); - } - if (args.show_keys.isSet) - { - mOutputMode |= _BIT(OUTPUT_KEY_DATA); - } - if (args.show_layout.isSet) - { - mOutputMode |= _BIT(OUTPUT_LAYOUT); - } - - // determine input file type - if (args.file_type.isSet) - mFileType = getFileTypeFromString(*args.file_type); - else - mFileType = determineFileTypeFromFile(mInputPath); - - // check is the input file could be identified - if (mFileType == FILE_INVALID) - throw fnd::Exception(kModuleName, "Unknown file type."); -} - -FileType UserSettings::getFileTypeFromString(const std::string& type_str) -{ - std::string str = type_str; - std::transform(str.begin(), str.end(), str.begin(), ::tolower); - - FileType type; - if (str == "xci") - type = FILE_XCI; - else if (str == "nsp") - type = FILE_NSP; - else if (str == "partitionfs" || str == "hashedpartitionfs" \ - || str == "pfs" || str == "pfs0" \ - || str == "hfs" || str == "hfs0") - type = FILE_PARTITIONFS; - else if (str == "romfs") - type = FILE_ROMFS; - else if (str == "nca") - type = FILE_NCA; - else if (str == "meta") - type = FILE_META; - else if (str == "cnmt") - type = FILE_CNMT; - else if (str == "nso") - type = FILE_NSO; - else if (str == "nro") - type = FILE_NRO; - else if (str == "nacp") - type = FILE_NACP; - else if (str == "cert") - type = FILE_PKI_CERT; - else if (str == "tik") - type = FILE_ES_TIK; - else if (str == "aset" || str == "asset") - type = FILE_HB_ASSET; - else - type = FILE_INVALID; - - return type; -} - -FileType UserSettings::determineFileTypeFromFile(const std::string& path) -{ - static const size_t kMaxReadSize = 0x5000; - FileType file_type = FILE_INVALID; - fnd::SimpleFile file; - fnd::Vec scratch; - - // open file - file.open(path, file.Read); - - // read file - scratch.alloc(_MIN(kMaxReadSize, file.size())); - file.read(scratch.data(), 0, scratch.size()); - // close file - file.close(); - - // _TYPE_PTR resolves to a pointer of type 'st' located at scratch.data() -#define _TYPE_PTR(st) ((st*)(scratch.data())) -#define _ASSERT_SIZE(sz) (scratch.size() >= (sz)) - - // test npdm - if (_ASSERT_SIZE(sizeof(nn::hac::sXciHeaderPage)) && _TYPE_PTR(nn::hac::sXciHeaderPage)->header.st_magic.get() == nn::hac::xci::kXciStructMagic) - file_type = FILE_XCI; - // test pfs0 - else if (_ASSERT_SIZE(sizeof(nn::hac::sPfsHeader)) && _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.get() == nn::hac::pfs::kPfsStructMagic) - file_type = FILE_PARTITIONFS; - // test hfs0 - else if (_ASSERT_SIZE(sizeof(nn::hac::sPfsHeader)) && _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.get() == nn::hac::pfs::kHashedPfsStructMagic) - file_type = FILE_PARTITIONFS; - // test romfs - else if (_ASSERT_SIZE(sizeof(nn::hac::sRomfsHeader)) && _TYPE_PTR(nn::hac::sRomfsHeader)->header_size.get() == sizeof(nn::hac::sRomfsHeader) && _TYPE_PTR(nn::hac::sRomfsHeader)->sections[1].offset.get() == (_TYPE_PTR(nn::hac::sRomfsHeader)->sections[0].offset.get() + _TYPE_PTR(nn::hac::sRomfsHeader)->sections[0].size.get())) - file_type = FILE_ROMFS; - // test npdm - else if (_ASSERT_SIZE(sizeof(nn::hac::sMetaHeader)) && _TYPE_PTR(nn::hac::sMetaHeader)->st_magic.get() == nn::hac::meta::kMetaStructMagic) - file_type = FILE_META; - // test nca - else if (determineValidNcaFromSample(scratch)) - file_type = FILE_NCA; - // test nso - else if (_ASSERT_SIZE(sizeof(nn::hac::sNsoHeader)) && _TYPE_PTR(nn::hac::sNsoHeader)->st_magic.get() == nn::hac::nso::kNsoStructMagic) - file_type = FILE_NSO; - // test nso - else if (_ASSERT_SIZE(sizeof(nn::hac::sNroHeader)) && _TYPE_PTR(nn::hac::sNroHeader)->st_magic.get() == nn::hac::nro::kNroStructMagic) - file_type = FILE_NRO; - // test pki certificate - else if (determineValidEsCertFromSample(scratch)) - file_type = FILE_PKI_CERT; - // test ticket - else if (determineValidEsTikFromSample(scratch)) - file_type = FILE_ES_TIK; - // test hb asset - else if (_ASSERT_SIZE(sizeof(nn::hac::sAssetHeader)) && _TYPE_PTR(nn::hac::sAssetHeader)->st_magic.get() == nn::hac::aset::kAssetStructMagic) - file_type = FILE_HB_ASSET; - - // do heuristics - // test cnmt - else if (determineValidCnmtFromSample(scratch)) - file_type = FILE_CNMT; - // test nacp - else if (determineValidNacpFromSample(scratch)) - file_type = FILE_NACP; - - - // else unrecognised - else - file_type = FILE_INVALID; - -#undef _ASSERT_SIZE -#undef _TYPE_PTR - - return file_type; -} - -bool UserSettings::determineValidNcaFromSample(const fnd::Vec& sample) const -{ - // prepare decrypted NCA data - byte_t nca_raw[nn::hac::nca::kHeaderSize]; - nn::hac::sNcaHeader* nca_header = (nn::hac::sNcaHeader*)(nca_raw + nn::hac::NcaUtils::sectorToOffset(1)); - - if (sample.size() < nn::hac::nca::kHeaderSize) - return false; - - fnd::aes::sAesXts128Key header_key; - mKeyCfg.getNcaHeaderKey(header_key); - nn::hac::NcaUtils::decryptNcaHeader(sample.data(), nca_raw, header_key); - - if (nca_header->st_magic.get() != nn::hac::nca::kNca2StructMagic && nca_header->st_magic.get() != nn::hac::nca::kNca3StructMagic) - return false; - - return true; -} - -bool UserSettings::determineValidCnmtFromSample(const fnd::Vec& sample) const -{ - if (sample.size() < sizeof(nn::hac::sContentMetaHeader)) - return false; - - const nn::hac::sContentMetaHeader* data = (const nn::hac::sContentMetaHeader*)sample.data(); - - size_t minimum_size = sizeof(nn::hac::sContentMetaHeader) + data->exhdr_size.get() + data->content_count.get() * sizeof(nn::hac::sContentInfo) + data->content_meta_count.get() * sizeof(nn::hac::sContentMetaInfo) + nn::hac::cnmt::kDigestLen; - - if (sample.size() < minimum_size) - return false; - - if (data->type == nn::hac::cnmt::METATYPE_APPLICATION) - { - const nn::hac::sApplicationMetaExtendedHeader* meta = (const nn::hac::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader)); - if ((meta->patch_id.get() & data->id.get()) != data->id.get()) - return false; - } - else if (data->type == nn::hac::cnmt::METATYPE_PATCH) - { - const nn::hac::sPatchMetaExtendedHeader* meta = (const nn::hac::sPatchMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader)); - if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) - return false; - - minimum_size += meta->extended_data_size.get(); - } - else if (data->type == nn::hac::cnmt::METATYPE_ADD_ON_CONTENT) - { - const nn::hac::sAddOnContentMetaExtendedHeader* meta = (const nn::hac::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader)); - if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) - return false; - } - else if (data->type == nn::hac::cnmt::METATYPE_DELTA) - { - const nn::hac::sDeltaMetaExtendedHeader* meta = (const nn::hac::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader)); - if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) - return false; - - minimum_size += meta->extended_data_size.get(); - } - - if (sample.size() != minimum_size) - return false; - - return true; -} - -bool UserSettings::determineValidNacpFromSample(const fnd::Vec& sample) const -{ - if (sample.size() != sizeof(nn::hac::sApplicationControlProperty)) - return false; - - const nn::hac::sApplicationControlProperty* data = (const nn::hac::sApplicationControlProperty*)sample.data(); - - if (data->logo_type > nn::hac::nacp::LOGO_Nintendo) - return false; - - if (data->display_version[0] == 0) - return false; - - if (data->user_account_save_data_size.get() == 0 && data->user_account_save_data_journal_size.get() != 0) - return false; - - if (data->user_account_save_data_journal_size.get() == 0 && data->user_account_save_data_size.get() != 0) - return false; - - if (data->supported_language_flag.get() == 0) - return false; - - return true; -} - -bool UserSettings::determineValidEsCertFromSample(const fnd::Vec& sample) const -{ - nn::pki::SignatureBlock sign; - - try - { - sign.fromBytes(sample.data(), sample.size()); - } - catch (...) - { - return false; - } - - 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) - return false; - - return true; -} - -bool UserSettings::determineValidEsTikFromSample(const fnd::Vec& sample) const -{ - nn::pki::SignatureBlock sign; - - try - { - sign.fromBytes(sample.data(), sample.size()); - } - catch (...) - { - return false; - } - - if (sign.isLittleEndian() == false) - return false; - - if (sign.getSignType() != nn::pki::sign::SIGN_ID_RSA2048_SHA256) - return false; - - return true; -} - -nn::hac::meta::InstructionType UserSettings::getInstructionTypeFromString(const std::string & type_str) -{ - std::string str = type_str; - std::transform(str.begin(), str.end(), str.begin(), ::tolower); - - nn::hac::meta::InstructionType type; - if (str == "32bit") - type = nn::hac::meta::INSTR_32BIT; - else if (str == "64bit") - type = nn::hac::meta::INSTR_64BIT; - else - throw fnd::Exception(kModuleName, "Unsupported instruction type: " + str); - - return type; -} - -void UserSettings::getHomePath(std::string& path) const -{ - // open other resource files in $HOME/.switch/prod.keys (or $HOME/.switch/dev.keys if -d/--dev is set). - path.clear(); - if (path.empty()) fnd::io::getEnvironVar(path, "HOME"); - if (path.empty()) fnd::io::getEnvironVar(path, "USERPROFILE"); - if (path.empty()) return; -} - -void UserSettings::getSwitchPath(std::string& path) const -{ - std::string home; - home.clear(); - getHomePath(home); - if (home.empty()) - return; - - path.clear(); - fnd::io::appendToPath(path, home); - fnd::io::appendToPath(path, kHomeSwitchDirStr); -} - -void UserSettings::dumpKeyConfig() const -{ - fnd::aes::sAes128Key aes_key; - fnd::aes::sAesXts128Key aesxts_key; - fnd::rsa::sRsa2048Key rsa2048_key; - fnd::rsa::sRsa4096Key rsa4096_key; - - const std::string kKeyIndex[kMasterKeyNum] = {"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"}; - - - std::cout << "[KeyConfiguration]" << std::endl; - std::cout << " NCA Keys:" << std::endl; - if (mKeyCfg.getNcaHeader0SignKey(rsa2048_key) == true) - dumpRsa2048Key(rsa2048_key, "Header Signature[0] Key", 2); - if (mKeyCfg.getNcaHeaderKey(aesxts_key) == true) - dumpAesXtsKey(aesxts_key, "Header Encryption Key", 2); - - for (size_t i = 0; i < kMasterKeyNum; i++) - { - if (mKeyCfg.getNcaKeyAreaEncryptionKey(i,0, aes_key) == true) - dumpAesKey(aes_key, "KeyAreaEncryptionKey-Application-" + kKeyIndex[i], 2); - if (mKeyCfg.getNcaKeyAreaEncryptionKey(i,1, aes_key) == true) - dumpAesKey(aes_key, "KeyAreaEncryptionKey-Ocean-" + kKeyIndex[i], 2); - if (mKeyCfg.getNcaKeyAreaEncryptionKey(i,2, aes_key) == true) - dumpAesKey(aes_key, "KeyAreaEncryptionKey-System-" + kKeyIndex[i], 2); - } - - for (size_t i = 0; i < kMasterKeyNum; i++) - { - if (mKeyCfg.getNcaKeyAreaEncryptionKeyHw(i,0, aes_key) == true) - dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-Application-" + kKeyIndex[i], 2); - if (mKeyCfg.getNcaKeyAreaEncryptionKeyHw(i,1, aes_key) == true) - dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-Ocean-" + kKeyIndex[i], 2); - if (mKeyCfg.getNcaKeyAreaEncryptionKeyHw(i,2, aes_key) == true) - dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-System-" + kKeyIndex[i], 2); - } - - std::cout << " XCI Keys:" << std::endl; - if (mKeyCfg.getXciHeaderSignKey(rsa2048_key) == true) - dumpRsa2048Key(rsa2048_key, "Header Signature Key", 2); - if (mKeyCfg.getXciHeaderKey(aes_key) == true) - dumpAesKey(aes_key, "Extended Header Encryption Key", 2); - - - if (mKeyCfg.getAcidSignKey(rsa2048_key) == true) - dumpRsa2048Key(rsa2048_key, "ACID Signer Key", 1); - - - std::cout << " Package1 Keys:" << std::endl; - for (size_t i = 0; i < kMasterKeyNum; i++) - { - if (mKeyCfg.getPkg1Key(i, aes_key) == true) - dumpAesKey(aes_key, "EncryptionKey-" + kKeyIndex[i], 2); - } - - std::cout << " Package2 Keys:" << std::endl; - if (mKeyCfg.getPkg2SignKey(rsa2048_key) == true) - dumpRsa2048Key(rsa2048_key, "Signature Key", 2); - for (size_t i = 0; i < kMasterKeyNum; i++) - { - if (mKeyCfg.getPkg2Key(i, aes_key) == true) - dumpAesKey(aes_key, "EncryptionKey-" + kKeyIndex[i], 2); - } - - std::cout << " ETicket Keys:" << std::endl; - for (size_t i = 0; i < kMasterKeyNum; i++) - { - if (mKeyCfg.getETicketCommonKey(i, aes_key) == true) - dumpAesKey(aes_key, "CommonKey-" + kKeyIndex[i], 2); - } - - if (mKeyCfg.getPkiRootSignKey("Root", rsa4096_key) == true) - dumpRsa4096Key(rsa4096_key, "NNPKI Root Key", 1); -} - -void UserSettings::dumpRsa2048Key(const fnd::rsa::sRsa2048Key& key, const std::string& name, size_t indent) const -{ - std::string indent_str; - - indent_str.clear(); - for (size_t i = 0; i < indent; i++) - { - indent_str += " "; - } - - std::cout << indent_str << name << ":" << std::endl; - if (key.modulus[0] != 0x00 && key.modulus[1] != 0x00) - { - std::cout << indent_str << " Modulus:" << std::endl; - for (size_t i = 0; i < 0x10; i++) - { - std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.modulus + i * 0x10, 0x10, true, ":") << std::endl; - } - } - if (key.priv_exponent[0] != 0x00 && key.priv_exponent[1] != 0x00) - { - std::cout << indent_str << " Private Exponent:" << std::endl; - for (size_t i = 0; i < 0x10; i++) - { - std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.priv_exponent + i * 0x10, 0x10, true, ":") << std::endl; - } - } -} - -void UserSettings::dumpRsa4096Key(const fnd::rsa::sRsa4096Key& key, const std::string& name, size_t indent) const -{ - std::string indent_str; - - indent_str.clear(); - for (size_t i = 0; i < indent; i++) - { - indent_str += " "; - } - - std::cout << indent_str << name << ":" << std::endl; - if (key.modulus[0] != 0x00 && key.modulus[1] != 0x00) - { - std::cout << indent_str << " Modulus:" << std::endl; - for (size_t i = 0; i < 0x20; i++) - { - std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.modulus + i * 0x10, 0x10, true, ":") << std::endl; - } - } - if (key.priv_exponent[0] != 0x00 && key.priv_exponent[1] != 0x00) - { - std::cout << indent_str << " Private Exponent:" << std::endl; - for (size_t i = 0; i < 0x20; i++) - { - std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.priv_exponent + i * 0x10, 0x10, true, ":") << std::endl; - } - } -} - -void UserSettings::dumpAesKey(const fnd::aes::sAes128Key& key, const std::string& name, size_t indent) const -{ - std::string indent_str; - - indent_str.clear(); - for (size_t i = 0; i < indent; i++) - { - indent_str += " "; - } - - std::cout << indent_str << name << ":" << std::endl; - std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.key, 0x10, true, ":") << std::endl; -} - -void UserSettings::dumpAesXtsKey(const fnd::aes::sAesXts128Key& key, const std::string& name, size_t indent) const -{ - std::string indent_str; - - indent_str.clear(); - for (size_t i = 0; i < indent; i++) - { - indent_str += " "; - } - - std::cout << indent_str << name << ":" << std::endl; - std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.key[0], 0x20, true, ":") << std::endl; +#include "UserSettings.h" +#include "version.h" +#include "PkiValidator.h" +#include "KeyConfiguration.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +UserSettings::UserSettings() +{} + +void UserSettings::parseCmdArgs(const std::vector& arg_list) +{ + sCmdArgs args; + populateCmdArgs(arg_list, args); + populateKeyset(args); + populateUserSettings(args); + if (_HAS_BIT(mOutputMode, OUTPUT_KEY_DATA)) + dumpKeyConfig(); +} + +void UserSettings::showHelp() +{ + printf("%s v%d.%d.%d (C) %s\n", APP_NAME, VER_MAJOR, VER_MINOR, VER_PATCH, AUTHORS); + printf("Built: %s %s\n\n", __TIME__, __DATE__); + + printf("Usage: %s [options... ] \n", BIN_NAME); + printf("\n General Options:\n"); + printf(" -d, --dev Use devkit keyset.\n"); + printf(" -k, --keyset Specify keyset file.\n"); + printf(" -t, --type Specify input file type. [xci, pfs, romfs, nca, meta, cnmt, nso, nro, nacp, aset, cert, tik]\n"); + printf(" -y, --verify Verify file.\n"); + printf("\n Output Options:\n"); + printf(" --showkeys Show keys generated.\n"); + printf(" --showlayout Show layout metadata.\n"); + printf(" -v, --verbose Verbose output.\n"); + printf("\n XCI (GameCard Image)\n"); + printf(" %s [--listfs] [--update --logo --normal --secure ] <.xci file>\n", BIN_NAME); + printf(" --listfs Print file system in embedded partitions.\n"); + printf(" --update Extract \"update\" partition to directory.\n"); + printf(" --logo Extract \"logo\" partition to directory.\n"); + printf(" --normal Extract \"normal\" partition to directory.\n"); + printf(" --secure Extract \"secure\" partition to directory.\n"); + printf("\n PFS0/HFS0 (PartitionFs), RomFs, NSP (Ninendo Submission Package)\n"); + printf(" %s [--listfs] [--fsdir ] \n", BIN_NAME); + printf(" --listfs Print file system.\n"); + printf(" --fsdir Extract file system to directory.\n"); + printf("\n NCA (Nintendo Content Archive)\n"); + printf(" %s [--listfs] [--bodykey --titlekey ] [--part0 ...] <.nca file>\n", BIN_NAME); + printf(" --listfs Print file system in embedded partitions.\n"); + printf(" --titlekey Specify title key extracted from ticket.\n"); + printf(" --bodykey Specify body encryption key.\n"); + printf(" --tik Specify ticket to source title key.\n"); + printf(" --cert Specify certificate chain to verify ticket.\n"); + printf(" --part0 Extract \"partition 0\" to directory.\n"); + printf(" --part1 Extract \"partition 1\" to directory.\n"); + printf(" --part2 Extract \"partition 2\" to directory.\n"); + printf(" --part3 Extract \"partition 3\" to directory.\n"); + printf("\n NSO (Nintendo Software Object), NRO (Nintendo Relocatable Object)\n"); + printf(" %s [--listapi --listsym] [--insttype ] \n", BIN_NAME); + printf(" --listapi Print SDK API List.\n"); + printf(" --listsym Print Code Symbols.\n"); + printf(" --insttype Specify instruction type [64bit|32bit] (64bit is assumed).\n"); + printf("\n ASET (Homebrew Asset Blob)\n"); + printf(" %s [--listfs] [--icon --nacp --fsdir ] \n", BIN_NAME); + printf(" --listfs Print filesystem in embedded RomFS partition.\n"); + printf(" --icon Extract icon partition to file.\n"); + printf(" --nacp Extract NACP partition to file.\n"); + printf(" --fsdir Extract RomFS partition to directory.\n"); + +} + +const std::string UserSettings::getInputPath() const +{ + return mInputPath; +} + +const KeyConfiguration& UserSettings::getKeyCfg() const +{ + return mKeyCfg; +} + +FileType UserSettings::getFileType() const +{ + return mFileType; +} + +bool UserSettings::isVerifyFile() const +{ + return mVerifyFile; +} + +CliOutputMode UserSettings::getCliOutputMode() const +{ + return mOutputMode; +} + +bool UserSettings::isListFs() const +{ + return mListFs; +} + +bool UserSettings::isListApi() const +{ + return mListApi; +} +bool UserSettings::isListSymbols() const +{ + return mListSymbols; +} + +nn::hac::meta::InstructionType UserSettings::getInstType() const +{ + return mInstructionType; +} + +const sOptional& UserSettings::getXciUpdatePath() const +{ + return mXciUpdatePath; +} + +const sOptional& UserSettings::getXciLogoPath() const +{ + return mXciLogoPath; +} + +const sOptional& UserSettings::getXciNormalPath() const +{ + return mXciNormalPath; +} + +const sOptional& UserSettings::getXciSecurePath() const +{ + return mXciSecurePath; +} + +const sOptional& UserSettings::getFsPath() const +{ + return mFsPath; +} + +const sOptional& UserSettings::getNcaPart0Path() const +{ + return mNcaPart0Path; +} + +const sOptional& UserSettings::getNcaPart1Path() const +{ + return mNcaPart1Path; +} + +const sOptional& UserSettings::getNcaPart2Path() const +{ + return mNcaPart2Path; +} + +const sOptional& UserSettings::getNcaPart3Path() const +{ + return mNcaPart3Path; +} + +const sOptional& UserSettings::getAssetIconPath() const +{ + return mAssetIconPath; +} + +const sOptional& UserSettings::getAssetNacpPath() const +{ + return mAssetNacpPath; +} + +const fnd::List>& UserSettings::getCertificateChain() const +{ + return mCertChain; +} + +void UserSettings::populateCmdArgs(const std::vector& arg_list, sCmdArgs& cmd_args) +{ + // show help text + if (arg_list.size() < 2) + { + showHelp(); + throw fnd::Exception(kModuleName, "Not enough arguments."); + } + + cmd_args.input_path = arg_list.back(); + + for (size_t i = 1; i < arg_list.size(); i++) + { + if (arg_list[i] == "-h" || arg_list[i] == "--help") + { + showHelp(); + throw fnd::Exception(kModuleName, "Nothing to do."); + } + } + + for (size_t i = 1; i+1 < arg_list.size(); i++) + { + bool hasParamter = arg_list[i+1][0] != '-' && i+2 < arg_list.size(); + + if (arg_list[i] == "-d" || arg_list[i] == "--dev") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.devkit_keys = true; + } + + else if (arg_list[i] == "-y" || arg_list[i] == "--verify") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.verify_file = true; + } + + else if (arg_list[i] == "--showkeys") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.show_keys = true; + } + + else if (arg_list[i] == "--showlayout") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.show_layout = true; + } + + else if (arg_list[i] == "-v" || arg_list[i] == "--verbose") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.verbose_output = true; + } + + else if (arg_list[i] == "-k" || arg_list[i] == "--keyset") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.keyset_path = arg_list[i+1]; + } + + else if (arg_list[i] == "-t" || arg_list[i] == "--type") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.file_type = arg_list[i+1]; + } + + else if (arg_list[i] == "--listfs") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.list_fs = true; + } + + else if (arg_list[i] == "--update") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.update_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--normal") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.normal_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--secure") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.secure_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--logo") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.logo_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--fsdir") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.fs_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--titlekey") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.nca_titlekey = arg_list[i+1]; + } + + else if (arg_list[i] == "--bodykey") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.nca_bodykey = arg_list[i+1]; + } + + else if (arg_list[i] == "--tik") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.ticket_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--cert") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.cert_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--part0") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.part0_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--part1") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.part1_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--part2") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.part2_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--part3") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.part3_path = arg_list[i+1]; + } + + else if (arg_list[i] == "--listapi") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.list_api = true; + } + + else if (arg_list[i] == "--listsym") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.list_sym = true; + } + + else if (arg_list[i] == "--insttype") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.inst_type = arg_list[i + 1]; + } + + else if (arg_list[i] == "--icon") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.asset_icon_path = arg_list[i + 1]; + } + + else if (arg_list[i] == "--nacp") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.asset_nacp_path = arg_list[i + 1]; + } + + else + { + throw fnd::Exception(kModuleName, arg_list[i] + " is not recognised."); + } + + i += hasParamter; + } +} + +void UserSettings::populateKeyset(sCmdArgs& args) +{ + if (args.keyset_path.isSet) + { + mKeyCfg.importHactoolGenericKeyfile(*args.keyset_path); + } + else + { + // open other resource files in $HOME/.switch/prod.keys (or $HOME/.switch/dev.keys if -d/--dev is set). + std::string keyset_path; + getSwitchPath(keyset_path); + if (keyset_path.empty()) + return; + + fnd::io::appendToPath(keyset_path, kGeneralKeyfileName[args.devkit_keys.isSet]); + + try + { + mKeyCfg.importHactoolGenericKeyfile(keyset_path); + } + catch (const fnd::Exception&) + { + return; + } + + } + + + + if (args.nca_bodykey.isSet) + { + fnd::aes::sAes128Key tmp_key; + fnd::Vec tmp_raw; + fnd::SimpleTextOutput::stringToArray(args.nca_bodykey.var, tmp_raw); + if (tmp_raw.size() != sizeof(fnd::aes::sAes128Key)) + throw fnd::Exception(kModuleName, "Key: \"--bodykey\" has incorrect length"); + memcpy(tmp_key.key, tmp_raw.data(), 16); + mKeyCfg.addNcaExternalContentKey(kDummyRightsIdForUserBodyKey, tmp_key); + } + + if (args.nca_titlekey.isSet) + { + fnd::aes::sAes128Key tmp_key; + fnd::Vec tmp_raw; + fnd::SimpleTextOutput::stringToArray(args.nca_titlekey.var, tmp_raw); + if (tmp_raw.size() != sizeof(fnd::aes::sAes128Key)) + throw fnd::Exception(kModuleName, "Key: \"--titlekey\" has incorrect length"); + memcpy(tmp_key.key, tmp_raw.data(), 16); + mKeyCfg.addNcaExternalContentKey(kDummyRightsIdForUserTitleKey, tmp_key); + } + + // import certificate chain + if (args.cert_path.isSet) + { + fnd::SimpleFile cert_file; + fnd::Vec cert_raw; + nn::pki::SignedData cert; + + cert_file.open(args.cert_path.var, fnd::SimpleFile::Read); + cert_raw.alloc(cert_file.size()); + cert_file.read(cert_raw.data(), cert_raw.size()); + + for (size_t i = 0; i < cert_raw.size(); i+= cert.getBytes().size()) + { + cert.fromBytes(cert_raw.data() + i, cert_raw.size() - i); + mCertChain.addElement(cert); + } + } + + // get titlekey from ticket + if (args.ticket_path.isSet) + { + fnd::SimpleFile tik_file; + fnd::Vec tik_raw; + nn::pki::SignedData tik; + + // open and import ticket + tik_file.open(args.ticket_path.var, fnd::SimpleFile::Read); + tik_raw.alloc(tik_file.size()); + tik_file.read(tik_raw.data(), tik_raw.size()); + tik.fromBytes(tik_raw.data(), tik_raw.size()); + + // validate ticket signature + if (mCertChain.size() > 0) + { + PkiValidator pki_validator; + fnd::Vec tik_hash; + + switch (nn::pki::sign::getHashAlgo(tik.getSignature().getSignType())) + { + case (nn::pki::sign::HASH_ALGO_SHA1): + tik_hash.alloc(fnd::sha::kSha1HashLen); + fnd::sha::Sha1(tik.getBody().getBytes().data(), tik.getBody().getBytes().size(), tik_hash.data()); + break; + case (nn::pki::sign::HASH_ALGO_SHA256): + tik_hash.alloc(fnd::sha::kSha256HashLen); + fnd::sha::Sha256(tik.getBody().getBytes().data(), tik.getBody().getBytes().size(), tik_hash.data()); + break; + } + + try + { + pki_validator.setKeyCfg(mKeyCfg); + pki_validator.addCertificates(mCertChain); + pki_validator.validateSignature(tik.getBody().getIssuer(), tik.getSignature().getSignType(), tik.getSignature().getSignature(), tik_hash); + } + catch (const fnd::Exception& e) + { + std::cout << "[WARNING] Ticket signature could not be validated (" << e.error() << ")" << std::endl; + } + + } + + // extract title key + if (tik.getBody().getTitleKeyEncType() == nn::es::ticket::AES128_CBC) + { + fnd::aes::sAes128Key enc_title_key; + memcpy(enc_title_key.key, tik.getBody().getEncTitleKey(), 16); + fnd::aes::sAes128Key common_key, external_content_key; + if (mKeyCfg.getETicketCommonKey(nn::hac::ContentArchiveUtils::getMasterKeyRevisionFromKeyGeneration(tik.getBody().getCommonKeyId()), common_key) == true) + { + nn::hac::AesKeygen::generateKey(external_content_key.key, tik.getBody().getEncTitleKey(), common_key.key); + mKeyCfg.addNcaExternalContentKey(tik.getBody().getRightsId(), external_content_key); + } + else + { + std::cout << "[WARNING] Titlekey not imported from ticket because commonkey was not available" << std::endl; + } + } + else + { + std::cout << "[WARNING] Titlekey not imported from ticket because it is personalised" << std::endl; + } + } +} + +void UserSettings::populateUserSettings(sCmdArgs& args) +{ + // check invalid input + if (args.input_path.isSet == false) + throw fnd::Exception(kModuleName, "No input file specified"); + + // save arguments + mInputPath = *args.input_path; + mVerifyFile = args.verify_file.isSet; + mListFs = args.list_fs.isSet; + mXciUpdatePath = args.update_path; + mXciNormalPath = args.normal_path; + mXciSecurePath = args.secure_path; + mXciLogoPath = args.logo_path; + + mFsPath = args.fs_path; + mNcaPart0Path = args.part0_path; + mNcaPart1Path = args.part1_path; + mNcaPart2Path = args.part2_path; + mNcaPart3Path = args.part3_path; + + // determine the architecture type for NSO/NRO + if (args.inst_type.isSet) + mInstructionType = getInstructionTypeFromString(*args.inst_type); + else + mInstructionType = nn::hac::meta::INSTR_64BIT; // default 64bit + + mListApi = args.list_api.isSet; + mListSymbols = args.list_sym.isSet; + + mAssetIconPath = args.asset_icon_path; + mAssetNacpPath = args.asset_nacp_path; + + // determine output mode + mOutputMode = _BIT(OUTPUT_BASIC); + if (args.verbose_output.isSet) + { + mOutputMode |= _BIT(OUTPUT_KEY_DATA); + mOutputMode |= _BIT(OUTPUT_LAYOUT); + mOutputMode |= _BIT(OUTPUT_EXTENDED); + } + if (args.show_keys.isSet) + { + mOutputMode |= _BIT(OUTPUT_KEY_DATA); + } + if (args.show_layout.isSet) + { + mOutputMode |= _BIT(OUTPUT_LAYOUT); + } + + // determine input file type + if (args.file_type.isSet) + mFileType = getFileTypeFromString(*args.file_type); + else + mFileType = determineFileTypeFromFile(mInputPath); + + // check is the input file could be identified + if (mFileType == FILE_INVALID) + throw fnd::Exception(kModuleName, "Unknown file type."); +} + +FileType UserSettings::getFileTypeFromString(const std::string& type_str) +{ + std::string str = type_str; + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + + FileType type; + if (str == "gc" || str == "gamecard" || str == "xci") + type = FILE_GC; + else if (str == "nsp") + type = FILE_NSP; + else if (str == "partitionfs" || str == "hashedpartitionfs" \ + || str == "pfs" || str == "pfs0" \ + || str == "hfs" || str == "hfs0") + type = FILE_PARTITIONFS; + else if (str == "romfs") + type = FILE_ROMFS; + else if (str == "nca" || str == "contentarchive") + type = FILE_NCA; + else if (str == "meta" || str == "npdm") + type = FILE_META; + else if (str == "cnmt") + type = FILE_CNMT; + else if (str == "nso") + type = FILE_NSO; + else if (str == "nro") + type = FILE_NRO; + else if (str == "nacp") + type = FILE_NACP; + else if (str == "cert") + type = FILE_PKI_CERT; + else if (str == "tik") + type = FILE_ES_TIK; + else if (str == "aset" || str == "asset") + type = FILE_HB_ASSET; + else + type = FILE_INVALID; + + return type; +} + +FileType UserSettings::determineFileTypeFromFile(const std::string& path) +{ + static const size_t kMaxReadSize = 0x5000; + FileType file_type = FILE_INVALID; + fnd::SimpleFile file; + fnd::Vec scratch; + + // open file + file.open(path, file.Read); + + // read file + scratch.alloc(_MIN(kMaxReadSize, file.size())); + file.read(scratch.data(), 0, scratch.size()); + // close file + file.close(); + + // _TYPE_PTR resolves to a pointer of type 'st' located at scratch.data() +#define _TYPE_PTR(st) ((st*)(scratch.data())) +#define _ASSERT_SIZE(sz) (scratch.size() >= (sz)) + + // test npdm + if (_ASSERT_SIZE(sizeof(nn::hac::sGcHeaderPage)) && _TYPE_PTR(nn::hac::sGcHeaderPage)->header.st_magic.get() == nn::hac::gc::kGcHeaderStructMagic) + file_type = FILE_GC; + // test pfs0 + else if (_ASSERT_SIZE(sizeof(nn::hac::sPfsHeader)) && _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.get() == nn::hac::pfs::kPfsStructMagic) + file_type = FILE_PARTITIONFS; + // test hfs0 + else if (_ASSERT_SIZE(sizeof(nn::hac::sPfsHeader)) && _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.get() == nn::hac::pfs::kHashedPfsStructMagic) + file_type = FILE_PARTITIONFS; + // test romfs + else if (_ASSERT_SIZE(sizeof(nn::hac::sRomfsHeader)) && _TYPE_PTR(nn::hac::sRomfsHeader)->header_size.get() == sizeof(nn::hac::sRomfsHeader) && _TYPE_PTR(nn::hac::sRomfsHeader)->sections[1].offset.get() == (_TYPE_PTR(nn::hac::sRomfsHeader)->sections[0].offset.get() + _TYPE_PTR(nn::hac::sRomfsHeader)->sections[0].size.get())) + file_type = FILE_ROMFS; + // test npdm + else if (_ASSERT_SIZE(sizeof(nn::hac::sMetaHeader)) && _TYPE_PTR(nn::hac::sMetaHeader)->st_magic.get() == nn::hac::meta::kMetaStructMagic) + file_type = FILE_META; + // test nca + else if (determineValidNcaFromSample(scratch)) + file_type = FILE_NCA; + // test nso + else if (_ASSERT_SIZE(sizeof(nn::hac::sNsoHeader)) && _TYPE_PTR(nn::hac::sNsoHeader)->st_magic.get() == nn::hac::nso::kNsoStructMagic) + file_type = FILE_NSO; + // test nso + else if (_ASSERT_SIZE(sizeof(nn::hac::sNroHeader)) && _TYPE_PTR(nn::hac::sNroHeader)->st_magic.get() == nn::hac::nro::kNroStructMagic) + file_type = FILE_NRO; + // test pki certificate + else if (determineValidEsCertFromSample(scratch)) + file_type = FILE_PKI_CERT; + // test ticket + else if (determineValidEsTikFromSample(scratch)) + file_type = FILE_ES_TIK; + // test hb asset + else if (_ASSERT_SIZE(sizeof(nn::hac::sAssetHeader)) && _TYPE_PTR(nn::hac::sAssetHeader)->st_magic.get() == nn::hac::aset::kAssetStructMagic) + file_type = FILE_HB_ASSET; + + // do heuristics + // test cnmt + else if (determineValidCnmtFromSample(scratch)) + file_type = FILE_CNMT; + // test nacp + else if (determineValidNacpFromSample(scratch)) + file_type = FILE_NACP; + + + // else unrecognised + else + file_type = FILE_INVALID; + +#undef _ASSERT_SIZE +#undef _TYPE_PTR + + return file_type; +} + +bool UserSettings::determineValidNcaFromSample(const fnd::Vec& sample) const +{ + // prepare decrypted NCA data + byte_t nca_raw[nn::hac::nca::kHeaderSize]; + nn::hac::sContentArchiveHeader* nca_header = (nn::hac::sContentArchiveHeader*)(nca_raw + nn::hac::ContentArchiveUtils::sectorToOffset(1)); + + if (sample.size() < nn::hac::nca::kHeaderSize) + return false; + + fnd::aes::sAesXts128Key header_key; + mKeyCfg.getContentArchiveHeaderKey(header_key); + nn::hac::ContentArchiveUtils::decryptContentArchiveHeader(sample.data(), nca_raw, header_key); + + if (nca_header->st_magic.get() != nn::hac::nca::kNca2StructMagic && nca_header->st_magic.get() != nn::hac::nca::kNca3StructMagic) + return false; + + return true; +} + +bool UserSettings::determineValidCnmtFromSample(const fnd::Vec& sample) const +{ + if (sample.size() < sizeof(nn::hac::sContentMetaHeader)) + return false; + + const nn::hac::sContentMetaHeader* data = (const nn::hac::sContentMetaHeader*)sample.data(); + + size_t minimum_size = sizeof(nn::hac::sContentMetaHeader) + data->exhdr_size.get() + data->content_count.get() * sizeof(nn::hac::sContentInfo) + data->content_meta_count.get() * sizeof(nn::hac::sContentMetaInfo) + nn::hac::cnmt::kDigestLen; + + if (sample.size() < minimum_size) + return false; + + if (data->type == nn::hac::cnmt::METATYPE_APPLICATION) + { + const nn::hac::sApplicationMetaExtendedHeader* meta = (const nn::hac::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader)); + if ((meta->patch_id.get() & data->id.get()) != data->id.get()) + return false; + } + else if (data->type == nn::hac::cnmt::METATYPE_PATCH) + { + const nn::hac::sPatchMetaExtendedHeader* meta = (const nn::hac::sPatchMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader)); + if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) + return false; + + minimum_size += meta->extended_data_size.get(); + } + else if (data->type == nn::hac::cnmt::METATYPE_ADD_ON_CONTENT) + { + const nn::hac::sAddOnContentMetaExtendedHeader* meta = (const nn::hac::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader)); + if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) + return false; + } + else if (data->type == nn::hac::cnmt::METATYPE_DELTA) + { + const nn::hac::sDeltaMetaExtendedHeader* meta = (const nn::hac::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader)); + if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) + return false; + + minimum_size += meta->extended_data_size.get(); + } + + if (sample.size() != minimum_size) + return false; + + return true; +} + +bool UserSettings::determineValidNacpFromSample(const fnd::Vec& sample) const +{ + if (sample.size() != sizeof(nn::hac::sApplicationControlProperty)) + return false; + + const nn::hac::sApplicationControlProperty* data = (const nn::hac::sApplicationControlProperty*)sample.data(); + + if (data->logo_type > nn::hac::nacp::LOGO_Nintendo) + return false; + + if (data->display_version[0] == 0) + return false; + + if (data->user_account_save_data_size.get() == 0 && data->user_account_save_data_journal_size.get() != 0) + return false; + + if (data->user_account_save_data_journal_size.get() == 0 && data->user_account_save_data_size.get() != 0) + return false; + + if (data->supported_language_flag.get() == 0) + return false; + + return true; +} + +bool UserSettings::determineValidEsCertFromSample(const fnd::Vec& sample) const +{ + nn::pki::SignatureBlock sign; + + try + { + sign.fromBytes(sample.data(), sample.size()); + } + catch (...) + { + return false; + } + + 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) + return false; + + return true; +} + +bool UserSettings::determineValidEsTikFromSample(const fnd::Vec& sample) const +{ + nn::pki::SignatureBlock sign; + + try + { + sign.fromBytes(sample.data(), sample.size()); + } + catch (...) + { + return false; + } + + if (sign.isLittleEndian() == false) + return false; + + if (sign.getSignType() != nn::pki::sign::SIGN_ID_RSA2048_SHA256) + return false; + + return true; +} + +nn::hac::meta::InstructionType UserSettings::getInstructionTypeFromString(const std::string & type_str) +{ + std::string str = type_str; + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + + nn::hac::meta::InstructionType type; + if (str == "32bit") + type = nn::hac::meta::INSTR_32BIT; + else if (str == "64bit") + type = nn::hac::meta::INSTR_64BIT; + else + throw fnd::Exception(kModuleName, "Unsupported instruction type: " + str); + + return type; +} + +void UserSettings::getHomePath(std::string& path) const +{ + // open other resource files in $HOME/.switch/prod.keys (or $HOME/.switch/dev.keys if -d/--dev is set). + path.clear(); + if (path.empty()) fnd::io::getEnvironVar(path, "HOME"); + if (path.empty()) fnd::io::getEnvironVar(path, "USERPROFILE"); + if (path.empty()) return; +} + +void UserSettings::getSwitchPath(std::string& path) const +{ + std::string home; + home.clear(); + getHomePath(home); + if (home.empty()) + return; + + path.clear(); + fnd::io::appendToPath(path, home); + fnd::io::appendToPath(path, kHomeSwitchDirStr); +} + +void UserSettings::dumpKeyConfig() const +{ + fnd::aes::sAes128Key aes_key; + fnd::aes::sAesXts128Key aesxts_key; + fnd::rsa::sRsa2048Key rsa2048_key; + fnd::rsa::sRsa4096Key rsa4096_key; + + const std::string kKeyIndex[kMasterKeyNum] = {"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"}; + + + std::cout << "[KeyConfiguration]" << std::endl; + std::cout << " NCA Keys:" << std::endl; + if (mKeyCfg.getContentArchiveHeader0SignKey(rsa2048_key) == true) + dumpRsa2048Key(rsa2048_key, "Header Signature[0] Key", 2); + if (mKeyCfg.getContentArchiveHeaderKey(aesxts_key) == true) + dumpAesXtsKey(aesxts_key, "Header Encryption Key", 2); + + for (size_t i = 0; i < kMasterKeyNum; i++) + { + if (mKeyCfg.getNcaKeyAreaEncryptionKey(i,0, aes_key) == true) + dumpAesKey(aes_key, "KeyAreaEncryptionKey-Application-" + kKeyIndex[i], 2); + if (mKeyCfg.getNcaKeyAreaEncryptionKey(i,1, aes_key) == true) + dumpAesKey(aes_key, "KeyAreaEncryptionKey-Ocean-" + kKeyIndex[i], 2); + if (mKeyCfg.getNcaKeyAreaEncryptionKey(i,2, aes_key) == true) + dumpAesKey(aes_key, "KeyAreaEncryptionKey-System-" + kKeyIndex[i], 2); + } + + for (size_t i = 0; i < kMasterKeyNum; i++) + { + if (mKeyCfg.getNcaKeyAreaEncryptionKeyHw(i,0, aes_key) == true) + dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-Application-" + kKeyIndex[i], 2); + if (mKeyCfg.getNcaKeyAreaEncryptionKeyHw(i,1, aes_key) == true) + dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-Ocean-" + kKeyIndex[i], 2); + if (mKeyCfg.getNcaKeyAreaEncryptionKeyHw(i,2, aes_key) == true) + dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-System-" + kKeyIndex[i], 2); + } + + std::cout << " XCI Keys:" << std::endl; + if (mKeyCfg.getXciHeaderSignKey(rsa2048_key) == true) + dumpRsa2048Key(rsa2048_key, "Header Signature Key", 2); + if (mKeyCfg.getXciHeaderKey(aes_key) == true) + dumpAesKey(aes_key, "Extended Header Encryption Key", 2); + + + if (mKeyCfg.getAcidSignKey(rsa2048_key) == true) + dumpRsa2048Key(rsa2048_key, "ACID Signer Key", 1); + + + std::cout << " Package1 Keys:" << std::endl; + for (size_t i = 0; i < kMasterKeyNum; i++) + { + if (mKeyCfg.getPkg1Key(i, aes_key) == true) + dumpAesKey(aes_key, "EncryptionKey-" + kKeyIndex[i], 2); + } + + std::cout << " Package2 Keys:" << std::endl; + if (mKeyCfg.getPkg2SignKey(rsa2048_key) == true) + dumpRsa2048Key(rsa2048_key, "Signature Key", 2); + for (size_t i = 0; i < kMasterKeyNum; i++) + { + if (mKeyCfg.getPkg2Key(i, aes_key) == true) + dumpAesKey(aes_key, "EncryptionKey-" + kKeyIndex[i], 2); + } + + std::cout << " ETicket Keys:" << std::endl; + for (size_t i = 0; i < kMasterKeyNum; i++) + { + if (mKeyCfg.getETicketCommonKey(i, aes_key) == true) + dumpAesKey(aes_key, "CommonKey-" + kKeyIndex[i], 2); + } + + if (mKeyCfg.getPkiRootSignKey("Root", rsa4096_key) == true) + dumpRsa4096Key(rsa4096_key, "NNPKI Root Key", 1); +} + +void UserSettings::dumpRsa2048Key(const fnd::rsa::sRsa2048Key& key, const std::string& name, size_t indent) const +{ + std::string indent_str; + + indent_str.clear(); + for (size_t i = 0; i < indent; i++) + { + indent_str += " "; + } + + std::cout << indent_str << name << ":" << std::endl; + if (key.modulus[0] != 0x00 && key.modulus[1] != 0x00) + { + std::cout << indent_str << " Modulus:" << std::endl; + for (size_t i = 0; i < 0x10; i++) + { + std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.modulus + i * 0x10, 0x10, true, ":") << std::endl; + } + } + if (key.priv_exponent[0] != 0x00 && key.priv_exponent[1] != 0x00) + { + std::cout << indent_str << " Private Exponent:" << std::endl; + for (size_t i = 0; i < 0x10; i++) + { + std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.priv_exponent + i * 0x10, 0x10, true, ":") << std::endl; + } + } +} + +void UserSettings::dumpRsa4096Key(const fnd::rsa::sRsa4096Key& key, const std::string& name, size_t indent) const +{ + std::string indent_str; + + indent_str.clear(); + for (size_t i = 0; i < indent; i++) + { + indent_str += " "; + } + + std::cout << indent_str << name << ":" << std::endl; + if (key.modulus[0] != 0x00 && key.modulus[1] != 0x00) + { + std::cout << indent_str << " Modulus:" << std::endl; + for (size_t i = 0; i < 0x20; i++) + { + std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.modulus + i * 0x10, 0x10, true, ":") << std::endl; + } + } + if (key.priv_exponent[0] != 0x00 && key.priv_exponent[1] != 0x00) + { + std::cout << indent_str << " Private Exponent:" << std::endl; + for (size_t i = 0; i < 0x20; i++) + { + std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.priv_exponent + i * 0x10, 0x10, true, ":") << std::endl; + } + } +} + +void UserSettings::dumpAesKey(const fnd::aes::sAes128Key& key, const std::string& name, size_t indent) const +{ + std::string indent_str; + + indent_str.clear(); + for (size_t i = 0; i < indent; i++) + { + indent_str += " "; + } + + std::cout << indent_str << name << ":" << std::endl; + std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.key, 0x10, true, ":") << std::endl; +} + +void UserSettings::dumpAesXtsKey(const fnd::aes::sAesXts128Key& key, const std::string& name, size_t indent) const +{ + std::string indent_str; + + indent_str.clear(); + for (size_t i = 0; i < indent; i++) + { + indent_str += " "; + } + + std::cout << indent_str << name << ":" << std::endl; + std::cout << indent_str << " " << fnd::SimpleTextOutput::arrayToString(key.key[0], 0x20, true, ":") << std::endl; } \ No newline at end of file diff --git a/programs/nstool/source/UserSettings.h b/programs/nstool/source/UserSettings.h index 935c0c5..33143b8 100644 --- a/programs/nstool/source/UserSettings.h +++ b/programs/nstool/source/UserSettings.h @@ -1,134 +1,134 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include "common.h" -#include "KeyConfiguration.h" - -class UserSettings -{ -public: - UserSettings(); - - void parseCmdArgs(const std::vector& arg_list); - void showHelp(); - - // generic options - const std::string getInputPath() const; - const KeyConfiguration& getKeyCfg() const; - FileType getFileType() const; - bool isVerifyFile() const; - CliOutputMode getCliOutputMode() const; - - // specialised toggles - bool isListFs() const; - bool isListApi() const; - bool isListSymbols() const; - nn::hac::meta::InstructionType getInstType() const; - - // specialised paths - const sOptional& getXciUpdatePath() const; - const sOptional& getXciLogoPath() const; - const sOptional& getXciNormalPath() const; - const sOptional& getXciSecurePath() const; - const sOptional& getFsPath() const; - const sOptional& getNcaPart0Path() const; - const sOptional& getNcaPart1Path() const; - const sOptional& getNcaPart2Path() const; - const sOptional& getNcaPart3Path() const; - const sOptional& getAssetIconPath() const; - const sOptional& getAssetNacpPath() const; - const fnd::List>& getCertificateChain() const; - -private: - const std::string kModuleName = "UserSettings"; - - const std::string kHomeSwitchDirStr = ".switch"; - const std::string kGeneralKeyfileName[2] = { "prod.keys", "dev.keys" }; - const std::string kTitleKeyfileName = "title.keys"; - - - struct sCmdArgs - { - sCmdArgs() {} - sOptional input_path; - sOptional devkit_keys; - sOptional keyset_path; - sOptional file_type; - sOptional verify_file; - sOptional show_keys; - sOptional show_layout; - sOptional verbose_output; - sOptional list_fs; - sOptional update_path; - sOptional logo_path; - sOptional normal_path; - sOptional secure_path; - sOptional fs_path; - sOptional nca_titlekey; - sOptional nca_bodykey; - sOptional ticket_path; - sOptional cert_path; - sOptional part0_path; - sOptional part1_path; - sOptional part2_path; - sOptional part3_path; - sOptional list_api; - sOptional list_sym; - sOptional inst_type; - sOptional asset_icon_path; - sOptional asset_nacp_path; - }; - - std::string mInputPath; - FileType mFileType; - KeyConfiguration mKeyCfg; - bool mVerifyFile; - CliOutputMode mOutputMode; - - bool mListFs; - sOptional mXciUpdatePath; - sOptional mXciLogoPath; - sOptional mXciNormalPath; - sOptional mXciSecurePath; - sOptional mFsPath; - - sOptional mNcaPart0Path; - sOptional mNcaPart1Path; - sOptional mNcaPart2Path; - sOptional mNcaPart3Path; - - sOptional mAssetIconPath; - sOptional mAssetNacpPath; - - fnd::List> mCertChain; - - bool mListApi; - bool mListSymbols; - nn::hac::meta::InstructionType mInstructionType; - - void populateCmdArgs(const std::vector& arg_list, sCmdArgs& cmd_args); - void populateKeyset(sCmdArgs& args); - void populateUserSettings(sCmdArgs& args); - FileType getFileTypeFromString(const std::string& type_str); - FileType determineFileTypeFromFile(const std::string& path); - bool determineValidNcaFromSample(const fnd::Vec& sample) const; - bool determineValidCnmtFromSample(const fnd::Vec& sample) const; - bool determineValidNacpFromSample(const fnd::Vec& sample) const; - bool determineValidEsCertFromSample(const fnd::Vec& sample) const; - bool determineValidEsTikFromSample(const fnd::Vec& sample) const; - nn::hac::meta::InstructionType getInstructionTypeFromString(const std::string& type_str); - void getHomePath(std::string& path) const; - void getSwitchPath(std::string& path) const; - - void dumpKeyConfig() const; - void dumpRsa2048Key(const fnd::rsa::sRsa2048Key& key, const std::string& name, size_t indent) const; - void dumpRsa4096Key(const fnd::rsa::sRsa4096Key& key, const std::string& name, size_t indent) const; - void dumpAesKey(const fnd::aes::sAes128Key& key, const std::string& name, size_t indent) const; - void dumpAesXtsKey(const fnd::aes::sAesXts128Key& key, const std::string& name, size_t indent) const; +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "KeyConfiguration.h" + +class UserSettings +{ +public: + UserSettings(); + + void parseCmdArgs(const std::vector& arg_list); + void showHelp(); + + // generic options + const std::string getInputPath() const; + const KeyConfiguration& getKeyCfg() const; + FileType getFileType() const; + bool isVerifyFile() const; + CliOutputMode getCliOutputMode() const; + + // specialised toggles + bool isListFs() const; + bool isListApi() const; + bool isListSymbols() const; + nn::hac::meta::InstructionType getInstType() const; + + // specialised paths + const sOptional& getXciUpdatePath() const; + const sOptional& getXciLogoPath() const; + const sOptional& getXciNormalPath() const; + const sOptional& getXciSecurePath() const; + const sOptional& getFsPath() const; + const sOptional& getNcaPart0Path() const; + const sOptional& getNcaPart1Path() const; + const sOptional& getNcaPart2Path() const; + const sOptional& getNcaPart3Path() const; + const sOptional& getAssetIconPath() const; + const sOptional& getAssetNacpPath() const; + const fnd::List>& getCertificateChain() const; + +private: + const std::string kModuleName = "UserSettings"; + + const std::string kHomeSwitchDirStr = ".switch"; + const std::string kGeneralKeyfileName[2] = { "prod.keys", "dev.keys" }; + const std::string kTitleKeyfileName = "title.keys"; + + + struct sCmdArgs + { + sCmdArgs() {} + sOptional input_path; + sOptional devkit_keys; + sOptional keyset_path; + sOptional file_type; + sOptional verify_file; + sOptional show_keys; + sOptional show_layout; + sOptional verbose_output; + sOptional list_fs; + sOptional update_path; + sOptional logo_path; + sOptional normal_path; + sOptional secure_path; + sOptional fs_path; + sOptional nca_titlekey; + sOptional nca_bodykey; + sOptional ticket_path; + sOptional cert_path; + sOptional part0_path; + sOptional part1_path; + sOptional part2_path; + sOptional part3_path; + sOptional list_api; + sOptional list_sym; + sOptional inst_type; + sOptional asset_icon_path; + sOptional asset_nacp_path; + }; + + std::string mInputPath; + FileType mFileType; + KeyConfiguration mKeyCfg; + bool mVerifyFile; + CliOutputMode mOutputMode; + + bool mListFs; + sOptional mXciUpdatePath; + sOptional mXciLogoPath; + sOptional mXciNormalPath; + sOptional mXciSecurePath; + sOptional mFsPath; + + sOptional mNcaPart0Path; + sOptional mNcaPart1Path; + sOptional mNcaPart2Path; + sOptional mNcaPart3Path; + + sOptional mAssetIconPath; + sOptional mAssetNacpPath; + + fnd::List> mCertChain; + + bool mListApi; + bool mListSymbols; + nn::hac::meta::InstructionType mInstructionType; + + void populateCmdArgs(const std::vector& arg_list, sCmdArgs& cmd_args); + void populateKeyset(sCmdArgs& args); + void populateUserSettings(sCmdArgs& args); + FileType getFileTypeFromString(const std::string& type_str); + FileType determineFileTypeFromFile(const std::string& path); + bool determineValidNcaFromSample(const fnd::Vec& sample) const; + bool determineValidCnmtFromSample(const fnd::Vec& sample) const; + bool determineValidNacpFromSample(const fnd::Vec& sample) const; + bool determineValidEsCertFromSample(const fnd::Vec& sample) const; + bool determineValidEsTikFromSample(const fnd::Vec& sample) const; + nn::hac::meta::InstructionType getInstructionTypeFromString(const std::string& type_str); + void getHomePath(std::string& path) const; + void getSwitchPath(std::string& path) const; + + void dumpKeyConfig() const; + void dumpRsa2048Key(const fnd::rsa::sRsa2048Key& key, const std::string& name, size_t indent) const; + void dumpRsa4096Key(const fnd::rsa::sRsa4096Key& key, const std::string& name, size_t indent) const; + void dumpAesKey(const fnd::aes::sAes128Key& key, const std::string& name, size_t indent) const; + void dumpAesXtsKey(const fnd::aes::sAesXts128Key& key, const std::string& name, size_t indent) const; }; \ No newline at end of file diff --git a/programs/nstool/source/common.h b/programs/nstool/source/common.h index 0df08c7..7b34922 100644 --- a/programs/nstool/source/common.h +++ b/programs/nstool/source/common.h @@ -1,60 +1,60 @@ -#pragma once -#include -#include -#include -#include -#include - -static const size_t kMasterKeyNum = 0x20; -static const size_t kNcaKeakNum = nn::hac::nca::kKeyAreaEncryptionKeyNum; - -enum FileType -{ - FILE_XCI, - FILE_NSP, - FILE_PARTITIONFS, - FILE_ROMFS, - FILE_NCA, - FILE_META, - FILE_CNMT, - FILE_NSO, - FILE_NRO, - FILE_NACP, - FILE_PKI_CERT, - FILE_ES_TIK, - FILE_HB_ASSET, - FILE_INVALID = -1, -}; - -enum CliOutputModeFlag -{ - OUTPUT_BASIC, - OUTPUT_LAYOUT, - OUTPUT_KEY_DATA, - OUTPUT_EXTENDED -}; - -typedef byte_t CliOutputMode; - -template -struct sOptional -{ - bool isSet; - T var; - inline sOptional() : isSet(false) {} - inline sOptional(const T& other) : isSet(true), var(other) {} - inline sOptional(const sOptional& other) : isSet(other.isSet), var(other.var) {} - inline const T& operator=(const T& other) { isSet = true; var = other; return var; } - inline const sOptional& operator=(const sOptional& other) - { - isSet = other.isSet; - if (isSet) { - var = other.var; - } - return *this; - } - inline T& operator*() { return var; } -}; - -const byte_t kDummyRightsIdForUserTitleKey[nn::hac::nca::kRightsIdLen] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +#pragma once +#include +#include +#include +#include +#include + +static const size_t kMasterKeyNum = 0x20; +static const size_t kNcaKeakNum = nn::hac::nca::kKeyAreaEncryptionKeyNum; + +enum FileType +{ + FILE_GC, + FILE_NSP, + FILE_PARTITIONFS, + FILE_ROMFS, + FILE_NCA, + FILE_META, + FILE_CNMT, + FILE_NSO, + FILE_NRO, + FILE_NACP, + FILE_PKI_CERT, + FILE_ES_TIK, + FILE_HB_ASSET, + FILE_INVALID = -1, +}; + +enum CliOutputModeFlag +{ + OUTPUT_BASIC, + OUTPUT_LAYOUT, + OUTPUT_KEY_DATA, + OUTPUT_EXTENDED +}; + +typedef byte_t CliOutputMode; + +template +struct sOptional +{ + bool isSet; + T var; + inline sOptional() : isSet(false) {} + inline sOptional(const T& other) : isSet(true), var(other) {} + inline sOptional(const sOptional& other) : isSet(other.isSet), var(other.var) {} + inline const T& operator=(const T& other) { isSet = true; var = other; return var; } + inline const sOptional& operator=(const sOptional& other) + { + isSet = other.isSet; + if (isSet) { + var = other.var; + } + return *this; + } + inline T& operator*() { return var; } +}; + +const byte_t kDummyRightsIdForUserTitleKey[nn::hac::nca::kRightsIdLen] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const byte_t kDummyRightsIdForUserBodyKey[nn::hac::nca::kRightsIdLen] = {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe}; \ No newline at end of file diff --git a/programs/nstool/source/main.cpp b/programs/nstool/source/main.cpp index 4f1776a..9141874 100644 --- a/programs/nstool/source/main.cpp +++ b/programs/nstool/source/main.cpp @@ -1,228 +1,228 @@ -#include -#include -#include -#include -#include "UserSettings.h" -#include "XciProcess.h" -#include "PfsProcess.h" -#include "RomfsProcess.h" -#include "NcaProcess.h" -#include "MetaProcess.h" -#include "CnmtProcess.h" -#include "NsoProcess.h" -#include "NroProcess.h" -#include "NacpProcess.h" -#include "PkiCertProcess.h" -#include "EsTikProcess.h" -#include "AssetProcess.h" - -#ifdef _WIN32 -int wmain(int argc, wchar_t** argv) -#else -int main(int argc, char** argv) -#endif -{ - std::vector args; - for (size_t i = 0; i < (size_t)argc; i++) - { -#ifdef _WIN32 - args.push_back(fnd::StringConv::ConvertChar16ToChar8(std::u16string((char16_t*)argv[i]))); -#else - args.push_back(argv[i]); -#endif - } - - UserSettings user_set; - try { - user_set.parseCmdArgs(args); - - fnd::SharedPtr inputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read)); - - if (user_set.getFileType() == FILE_XCI) - { - XciProcess xci; - - xci.setInputFile(inputFile); - - xci.setKeyCfg(user_set.getKeyCfg()); - xci.setCliOutputMode(user_set.getCliOutputMode()); - xci.setVerifyMode(user_set.isVerifyFile()); - - if (user_set.getXciUpdatePath().isSet) - xci.setPartitionForExtract(nn::hac::xci::kUpdatePartitionStr, user_set.getXciUpdatePath().var); - if (user_set.getXciLogoPath().isSet) - xci.setPartitionForExtract(nn::hac::xci::kLogoPartitionStr, user_set.getXciLogoPath().var); - if (user_set.getXciNormalPath().isSet) - xci.setPartitionForExtract(nn::hac::xci::kNormalPartitionStr, user_set.getXciNormalPath().var); - if (user_set.getXciSecurePath().isSet) - xci.setPartitionForExtract(nn::hac::xci::kSecurePartitionStr, user_set.getXciSecurePath().var); - xci.setListFs(user_set.isListFs()); - - xci.process(); - } - else if (user_set.getFileType() == FILE_PARTITIONFS || user_set.getFileType() == FILE_NSP) - { - PfsProcess pfs; - - pfs.setInputFile(inputFile); - pfs.setCliOutputMode(user_set.getCliOutputMode()); - pfs.setVerifyMode(user_set.isVerifyFile()); - - if (user_set.getFsPath().isSet) - pfs.setExtractPath(user_set.getFsPath().var); - pfs.setListFs(user_set.isListFs()); - - pfs.process(); - } - else if (user_set.getFileType() == FILE_ROMFS) - { - RomfsProcess romfs; - - romfs.setInputFile(inputFile); - romfs.setCliOutputMode(user_set.getCliOutputMode()); - romfs.setVerifyMode(user_set.isVerifyFile()); - - if (user_set.getFsPath().isSet) - romfs.setExtractPath(user_set.getFsPath().var); - romfs.setListFs(user_set.isListFs()); - - romfs.process(); - } - else if (user_set.getFileType() == FILE_NCA) - { - NcaProcess nca; - - nca.setInputFile(inputFile); - nca.setKeyCfg(user_set.getKeyCfg()); - nca.setCliOutputMode(user_set.getCliOutputMode()); - nca.setVerifyMode(user_set.isVerifyFile()); - - - if (user_set.getNcaPart0Path().isSet) - nca.setPartition0ExtractPath(user_set.getNcaPart0Path().var); - if (user_set.getNcaPart1Path().isSet) - nca.setPartition1ExtractPath(user_set.getNcaPart1Path().var); - if (user_set.getNcaPart2Path().isSet) - nca.setPartition2ExtractPath(user_set.getNcaPart2Path().var); - if (user_set.getNcaPart3Path().isSet) - nca.setPartition3ExtractPath(user_set.getNcaPart3Path().var); - nca.setListFs(user_set.isListFs()); - - nca.process(); - } - else if (user_set.getFileType() == FILE_META) - { - MetaProcess npdm; - - npdm.setInputFile(inputFile); - npdm.setKeyCfg(user_set.getKeyCfg()); - npdm.setCliOutputMode(user_set.getCliOutputMode()); - npdm.setVerifyMode(user_set.isVerifyFile()); - - npdm.process(); - } - else if (user_set.getFileType() == FILE_CNMT) - { - CnmtProcess cnmt; - - cnmt.setInputFile(inputFile); - cnmt.setCliOutputMode(user_set.getCliOutputMode()); - cnmt.setVerifyMode(user_set.isVerifyFile()); - - cnmt.process(); - } - else if (user_set.getFileType() == FILE_NSO) - { - NsoProcess obj; - - obj.setInputFile(inputFile); - obj.setCliOutputMode(user_set.getCliOutputMode()); - obj.setVerifyMode(user_set.isVerifyFile()); - - obj.setInstructionType(user_set.getInstType()); - obj.setListApi(user_set.isListApi()); - obj.setListSymbols(user_set.isListSymbols()); - - obj.process(); - } - else if (user_set.getFileType() == FILE_NRO) - { - NroProcess obj; - - obj.setInputFile(inputFile); - obj.setCliOutputMode(user_set.getCliOutputMode()); - obj.setVerifyMode(user_set.isVerifyFile()); - - obj.setInstructionType(user_set.getInstType()); - obj.setListApi(user_set.isListApi()); - obj.setListSymbols(user_set.isListSymbols()); - - if (user_set.getAssetIconPath().isSet) - obj.setAssetIconExtractPath(user_set.getAssetIconPath().var); - if (user_set.getAssetNacpPath().isSet) - obj.setAssetNacpExtractPath(user_set.getAssetNacpPath().var); - - if (user_set.getFsPath().isSet) - obj.setAssetRomfsExtractPath(user_set.getFsPath().var); - obj.setAssetListFs(user_set.isListFs()); - - obj.process(); - } - else if (user_set.getFileType() == FILE_NACP) - { - NacpProcess nacp; - - nacp.setInputFile(inputFile); - nacp.setCliOutputMode(user_set.getCliOutputMode()); - nacp.setVerifyMode(user_set.isVerifyFile()); - - nacp.process(); - } - else if (user_set.getFileType() == FILE_PKI_CERT) - { - PkiCertProcess cert; - - cert.setInputFile(inputFile); - cert.setKeyCfg(user_set.getKeyCfg()); - cert.setCliOutputMode(user_set.getCliOutputMode()); - cert.setVerifyMode(user_set.isVerifyFile()); - - cert.process(); - } - else if (user_set.getFileType() == FILE_ES_TIK) - { - EsTikProcess tik; - - tik.setInputFile(inputFile); - tik.setKeyCfg(user_set.getKeyCfg()); - tik.setCertificateChain(user_set.getCertificateChain()); - tik.setCliOutputMode(user_set.getCliOutputMode()); - tik.setVerifyMode(user_set.isVerifyFile()); - - tik.process(); - } - else if (user_set.getFileType() == FILE_HB_ASSET) - { - AssetProcess obj; - - obj.setInputFile(inputFile); - obj.setCliOutputMode(user_set.getCliOutputMode()); - obj.setVerifyMode(user_set.isVerifyFile()); - - if (user_set.getAssetIconPath().isSet) - obj.setIconExtractPath(user_set.getAssetIconPath().var); - if (user_set.getAssetNacpPath().isSet) - obj.setNacpExtractPath(user_set.getAssetNacpPath().var); - - if (user_set.getFsPath().isSet) - obj.setRomfsExtractPath(user_set.getFsPath().var); - obj.setListFs(user_set.isListFs()); - - obj.process(); - } - } - catch (const fnd::Exception& e) { - printf("\n\n%s\n", e.what()); - } - return 0; +#include +#include +#include +#include +#include "UserSettings.h" +#include "GameCardProcess.h" +#include "PfsProcess.h" +#include "RomfsProcess.h" +#include "NcaProcess.h" +#include "MetaProcess.h" +#include "CnmtProcess.h" +#include "NsoProcess.h" +#include "NroProcess.h" +#include "NacpProcess.h" +#include "PkiCertProcess.h" +#include "EsTikProcess.h" +#include "AssetProcess.h" + +#ifdef _WIN32 +int wmain(int argc, wchar_t** argv) +#else +int main(int argc, char** argv) +#endif +{ + std::vector args; + for (size_t i = 0; i < (size_t)argc; i++) + { +#ifdef _WIN32 + args.push_back(fnd::StringConv::ConvertChar16ToChar8(std::u16string((char16_t*)argv[i]))); +#else + args.push_back(argv[i]); +#endif + } + + UserSettings user_set; + try { + user_set.parseCmdArgs(args); + + fnd::SharedPtr inputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read)); + + if (user_set.getFileType() == FILE_GC) + { + GameCardProcess xci; + + xci.setInputFile(inputFile); + + xci.setKeyCfg(user_set.getKeyCfg()); + xci.setCliOutputMode(user_set.getCliOutputMode()); + xci.setVerifyMode(user_set.isVerifyFile()); + + if (user_set.getXciUpdatePath().isSet) + xci.setPartitionForExtract(nn::hac::gc::kUpdatePartitionStr, user_set.getXciUpdatePath().var); + if (user_set.getXciLogoPath().isSet) + xci.setPartitionForExtract(nn::hac::gc::kLogoPartitionStr, user_set.getXciLogoPath().var); + if (user_set.getXciNormalPath().isSet) + xci.setPartitionForExtract(nn::hac::gc::kNormalPartitionStr, user_set.getXciNormalPath().var); + if (user_set.getXciSecurePath().isSet) + xci.setPartitionForExtract(nn::hac::gc::kSecurePartitionStr, user_set.getXciSecurePath().var); + xci.setListFs(user_set.isListFs()); + + xci.process(); + } + else if (user_set.getFileType() == FILE_PARTITIONFS || user_set.getFileType() == FILE_NSP) + { + PfsProcess pfs; + + pfs.setInputFile(inputFile); + pfs.setCliOutputMode(user_set.getCliOutputMode()); + pfs.setVerifyMode(user_set.isVerifyFile()); + + if (user_set.getFsPath().isSet) + pfs.setExtractPath(user_set.getFsPath().var); + pfs.setListFs(user_set.isListFs()); + + pfs.process(); + } + else if (user_set.getFileType() == FILE_ROMFS) + { + RomfsProcess romfs; + + romfs.setInputFile(inputFile); + romfs.setCliOutputMode(user_set.getCliOutputMode()); + romfs.setVerifyMode(user_set.isVerifyFile()); + + if (user_set.getFsPath().isSet) + romfs.setExtractPath(user_set.getFsPath().var); + romfs.setListFs(user_set.isListFs()); + + romfs.process(); + } + else if (user_set.getFileType() == FILE_NCA) + { + NcaProcess nca; + + nca.setInputFile(inputFile); + nca.setKeyCfg(user_set.getKeyCfg()); + nca.setCliOutputMode(user_set.getCliOutputMode()); + nca.setVerifyMode(user_set.isVerifyFile()); + + + if (user_set.getNcaPart0Path().isSet) + nca.setPartition0ExtractPath(user_set.getNcaPart0Path().var); + if (user_set.getNcaPart1Path().isSet) + nca.setPartition1ExtractPath(user_set.getNcaPart1Path().var); + if (user_set.getNcaPart2Path().isSet) + nca.setPartition2ExtractPath(user_set.getNcaPart2Path().var); + if (user_set.getNcaPart3Path().isSet) + nca.setPartition3ExtractPath(user_set.getNcaPart3Path().var); + nca.setListFs(user_set.isListFs()); + + nca.process(); + } + else if (user_set.getFileType() == FILE_META) + { + MetaProcess npdm; + + npdm.setInputFile(inputFile); + npdm.setKeyCfg(user_set.getKeyCfg()); + npdm.setCliOutputMode(user_set.getCliOutputMode()); + npdm.setVerifyMode(user_set.isVerifyFile()); + + npdm.process(); + } + else if (user_set.getFileType() == FILE_CNMT) + { + CnmtProcess cnmt; + + cnmt.setInputFile(inputFile); + cnmt.setCliOutputMode(user_set.getCliOutputMode()); + cnmt.setVerifyMode(user_set.isVerifyFile()); + + cnmt.process(); + } + else if (user_set.getFileType() == FILE_NSO) + { + NsoProcess obj; + + obj.setInputFile(inputFile); + obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setVerifyMode(user_set.isVerifyFile()); + + obj.setInstructionType(user_set.getInstType()); + obj.setListApi(user_set.isListApi()); + obj.setListSymbols(user_set.isListSymbols()); + + obj.process(); + } + else if (user_set.getFileType() == FILE_NRO) + { + NroProcess obj; + + obj.setInputFile(inputFile); + obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setVerifyMode(user_set.isVerifyFile()); + + obj.setInstructionType(user_set.getInstType()); + obj.setListApi(user_set.isListApi()); + obj.setListSymbols(user_set.isListSymbols()); + + if (user_set.getAssetIconPath().isSet) + obj.setAssetIconExtractPath(user_set.getAssetIconPath().var); + if (user_set.getAssetNacpPath().isSet) + obj.setAssetNacpExtractPath(user_set.getAssetNacpPath().var); + + if (user_set.getFsPath().isSet) + obj.setAssetRomfsExtractPath(user_set.getFsPath().var); + obj.setAssetListFs(user_set.isListFs()); + + obj.process(); + } + else if (user_set.getFileType() == FILE_NACP) + { + NacpProcess nacp; + + nacp.setInputFile(inputFile); + nacp.setCliOutputMode(user_set.getCliOutputMode()); + nacp.setVerifyMode(user_set.isVerifyFile()); + + nacp.process(); + } + else if (user_set.getFileType() == FILE_PKI_CERT) + { + PkiCertProcess cert; + + cert.setInputFile(inputFile); + cert.setKeyCfg(user_set.getKeyCfg()); + cert.setCliOutputMode(user_set.getCliOutputMode()); + cert.setVerifyMode(user_set.isVerifyFile()); + + cert.process(); + } + else if (user_set.getFileType() == FILE_ES_TIK) + { + EsTikProcess tik; + + tik.setInputFile(inputFile); + tik.setKeyCfg(user_set.getKeyCfg()); + tik.setCertificateChain(user_set.getCertificateChain()); + tik.setCliOutputMode(user_set.getCliOutputMode()); + tik.setVerifyMode(user_set.isVerifyFile()); + + tik.process(); + } + else if (user_set.getFileType() == FILE_HB_ASSET) + { + AssetProcess obj; + + obj.setInputFile(inputFile); + obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setVerifyMode(user_set.isVerifyFile()); + + if (user_set.getAssetIconPath().isSet) + obj.setIconExtractPath(user_set.getAssetIconPath().var); + if (user_set.getAssetNacpPath().isSet) + obj.setNacpExtractPath(user_set.getAssetNacpPath().var); + + if (user_set.getFsPath().isSet) + obj.setRomfsExtractPath(user_set.getFsPath().var); + obj.setListFs(user_set.isListFs()); + + obj.process(); + } + } + catch (const fnd::Exception& e) { + printf("\n\n%s\n", e.what()); + } + return 0; } \ No newline at end of file