1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-08 11:51:48 +00:00

Remove support for NPDM patching.

This commit is contained in:
Pablo Curiel 2022-06-26 03:34:31 +02:00
parent d3b007d9af
commit ce4034852c
10 changed files with 24 additions and 278 deletions

View file

@ -53,7 +53,6 @@ static options_t options[] = {
{ "set download distribution type", 0 },
{ "remove console specific data", 1 },
{ "remove titlekey crypto (overrides previous option)", 0 },
{ "change acid rsa key/sig", 0 },
{ "disable linked account requirement", 0 },
{ "enable screenshots", 0 },
{ "enable video capture", 0 },
@ -135,13 +134,12 @@ static void nspDump(TitleInfo *title_info, u64 free_space)
bool set_download_type = (options[0].val == 1);
bool remove_console_data = (options[1].val == 1);
bool remove_titlekey_crypto = (options[2].val == 1);
bool change_acid_rsa = (options[3].val == 1);
bool patch_sua = (options[4].val == 1);
bool patch_screenshot = (options[5].val == 1);
bool patch_video_capture = (options[6].val == 1);
bool patch_hdcp = (options[7].val == 1);
bool append_authoringtool_data = (options[8].val == 1);
UsbHsFsDevice *ums_device = (options[9].val == 0 ? NULL : &(ums_devices[options[8].val - 1]));
bool patch_sua = (options[3].val == 1);
bool patch_screenshot = (options[4].val == 1);
bool patch_video_capture = (options[5].val == 1);
bool patch_hdcp = (options[6].val == 1);
bool append_authoringtool_data = (options[7].val == 1);
UsbHsFsDevice *ums_device = (options[8].val == 0 ? NULL : &(ums_devices[options[8].val - 1]));
bool success = false;
if (ums_device && ums_device->write_protect)
@ -211,7 +209,7 @@ static void nspDump(TitleInfo *title_info, u64 free_space)
}
// determine if we should initialize programinfo ctx
if (change_acid_rsa || append_authoringtool_data)
if (append_authoringtool_data)
{
program_count = titleGetContentCountByType(title_info, NcmContentType_Program);
if (program_count && !(program_info_ctx = calloc(program_count, sizeof(ProgramInfoContext))))
@ -317,12 +315,6 @@ static void nspDump(TitleInfo *title_info, u64 free_space)
goto end;
}
if (change_acid_rsa && !programInfoGenerateNcaPatch(cur_program_info_ctx))
{
consolePrint("program info nca patch failed (%s)\n", cur_nca_ctx->content_id_str);
goto end;
}
if (append_authoringtool_data && !programInfoGenerateAuthoringToolXml(cur_program_info_ctx))
{
consolePrint("program info xml failed (%s)\n", cur_nca_ctx->content_id_str);
@ -615,9 +607,6 @@ static void nspDump(TitleInfo *title_info, u64 free_space)
case NcmContentType_Meta:
cnmtWriteNcaPatch(&cnmt_ctx, buf, blksize, offset);
break;
case NcmContentType_Program:
programInfoWriteNcaPatch((ProgramInfoContext*)cur_nca_ctx->content_type_ctx, buf, blksize, offset);
break;
case NcmContentType_Control:
nacpWriteNcaPatch((NacpContext*)cur_nca_ctx->content_type_ctx, buf, blksize, offset);
break;

View file

@ -61,7 +61,6 @@ static options_t options[] = {
{ "set download distribution type", false },
{ "remove console specific data", true },
{ "remove titlekey crypto (overrides previous option)", false },
{ "change acid rsa key/sig", false },
{ "disable linked account requirement", false },
{ "enable screenshots", false },
{ "enable video capture", false },
@ -127,12 +126,11 @@ static void dump_thread_func(void *arg)
bool set_download_type = options[0].val;
bool remove_console_data = options[1].val;
bool remove_titlekey_crypto = options[2].val;
bool change_acid_rsa = options[3].val;
bool patch_sua = options[4].val;
bool patch_screenshot = options[5].val;
bool patch_video_capture = options[6].val;
bool patch_hdcp = options[7].val;
bool append_authoringtool_data = options[8].val;
bool patch_sua = options[3].val;
bool patch_screenshot = options[4].val;
bool patch_video_capture = options[5].val;
bool patch_hdcp = options[6].val;
bool append_authoringtool_data = options[7].val;
bool success = false;
u8 *buf = NULL;
@ -197,7 +195,7 @@ static void dump_thread_func(void *arg)
}
// determine if we should initialize programinfo ctx
if (change_acid_rsa || append_authoringtool_data)
if (append_authoringtool_data)
{
program_count = titleGetContentCountByType(title_info, NcmContentType_Program);
if (program_count && !(program_info_ctx = calloc(program_count, sizeof(ProgramInfoContext))))
@ -303,12 +301,6 @@ static void dump_thread_func(void *arg)
goto end;
}
if (change_acid_rsa && !programInfoGenerateNcaPatch(cur_program_info_ctx))
{
consolePrint("program info nca patch failed (%s)\n", cur_nca_ctx->content_id_str);
goto end;
}
if (append_authoringtool_data && !programInfoGenerateAuthoringToolXml(cur_program_info_ctx))
{
consolePrint("program info xml failed (%s)\n", cur_nca_ctx->content_id_str);
@ -592,9 +584,6 @@ static void dump_thread_func(void *arg)
case NcmContentType_Meta:
cnmtWriteNcaPatch(&cnmt_ctx, buf, blksize, offset);
break;
case NcmContentType_Program:
programInfoWriteNcaPatch((ProgramInfoContext*)cur_nca_ctx->content_type_ctx, buf, blksize, offset);
break;
case NcmContentType_Control:
nacpWriteNcaPatch((NacpContext*)cur_nca_ctx->content_type_ctx, buf, blksize, offset);
break;

View file

@ -599,13 +599,8 @@ typedef struct {
NXDT_ASSERT(NpdmKernelCapabilityDescriptorEntry, 0x4);
typedef struct {
NcaContext *nca_ctx; ///< Pointer to the NCA context for the Program NCA from which NPDM data is retrieved.
PartitionFileSystemContext *pfs_ctx; ///< PartitionFileSystemContext for the Program NCA FS section #0, which is where the NPDM is stored.
PartitionFileSystemEntry *pfs_entry; ///< PartitionFileSystemEntry for the NPDM in the Program NCA FS section #0. Used to generate a NcaHierarchicalSha256Patch if needed.
NcaHierarchicalSha256Patch nca_patch; ///< NcaHierarchicalSha256Patch generated if NPDM modifications are needed. Used to seamlessly replace Program NCA data while writing it.
///< Bear in mind that generating a patch modifies the NCA context.
u8 *raw_data; ///< Pointer to a dynamically allocated buffer that holds the raw NPDM.
u64 raw_data_size; ///< Raw NPDM size. Kept here for convenience - this is part of 'pfs_entry'.
u64 raw_data_size; ///< Raw NPDM size.
NpdmMetaHeader *meta_header; ///< Pointer to the NpdmMetaHeader within 'raw_data'.
NpdmAcidHeader *acid_header; ///< Pointer to the NpdmAcidHeader within 'raw_data'.
NpdmFsAccessControlDescriptor *acid_fac_descriptor; ///< Pointer to the NpdmFsAccessControlDescriptor within the NPDM ACID section.
@ -620,26 +615,18 @@ typedef struct {
/// Initializes a NpdmContext using a previously initialized PartitionFileSystemContext (which must belong to the ExeFS from a Program NCA).
bool npdmInitializeContext(NpdmContext *out, PartitionFileSystemContext *pfs_ctx);
/// Changes the ACID public key from the NPDM in the input NpdmContext, updates the ACID signature from the NCA header in the underlying NCA context and generates a Partition FS entry patch.
bool npdmGenerateNcaPatch(NpdmContext *npdm_ctx);
/// Writes data from the Partition FS entry patch in the input NpdmContext to the provided buffer.
void npdmWriteNcaPatch(NpdmContext *npdm_ctx, void *buf, u64 buf_size, u64 buf_offset);
/// Helper inline functions.
NX_INLINE void npdmFreeContext(NpdmContext *npdm_ctx)
{
if (!npdm_ctx) return;
pfsFreeEntryPatch(&(npdm_ctx->nca_patch));
if (npdm_ctx->raw_data) free(npdm_ctx->raw_data);
memset(npdm_ctx, 0, sizeof(NpdmContext));
}
NX_INLINE bool npdmIsValidContext(NpdmContext *npdm_ctx)
{
return (npdm_ctx && npdm_ctx->nca_ctx && npdm_ctx->pfs_ctx && npdm_ctx->pfs_entry && npdm_ctx->raw_data && npdm_ctx->raw_data_size && npdm_ctx->meta_header && npdm_ctx->acid_header && \
npdm_ctx->acid_fac_descriptor && \
return (npdm_ctx && npdm_ctx->raw_data && npdm_ctx->raw_data_size && npdm_ctx->meta_header && npdm_ctx->acid_header && npdm_ctx->acid_fac_descriptor && \
((npdm_ctx->acid_header->srv_access_control_size && npdm_ctx->acid_sac_descriptor) || (!npdm_ctx->acid_header->srv_access_control_size && !npdm_ctx->acid_sac_descriptor)) && \
((npdm_ctx->acid_header->kernel_capability_size && npdm_ctx->acid_kc_descriptor) || (!npdm_ctx->acid_header->kernel_capability_size && !npdm_ctx->acid_kc_descriptor)) && \
npdm_ctx->aci_header && npdm_ctx->aci_fac_data && \

View file

@ -34,7 +34,7 @@ extern "C" {
typedef struct {
NcaContext *nca_ctx; ///< Pointer to the NCA context for the Program NCA from which program data (NPDM / NSO) is retrieved.
PartitionFileSystemContext pfs_ctx; ///< PartitionFileSystemContext for the Program NCA ExeFS, which is where program data (NPDM / NSO) is stored.
NpdmContext npdm_ctx; ///< NpdmContext for the NPDM stored in Program NCA ExeFS. Holds its own NcaHierarchicalSha256Patch that may be applied to the Program NCA if needed.
NpdmContext npdm_ctx; ///< NpdmContext for the NPDM stored in Program NCA ExeFS.
u32 nso_count; ///< Number of NSOs stored in Program NCA FS section #0.
NsoContext *nso_ctx; ///< Pointer to a dynamically allocated buffer that holds 'nso_count' NSO contexts.
char *authoring_tool_xml; ///< Pointer to a dynamically allocated, NULL-terminated buffer that holds AuthoringTool-like XML data.
@ -71,18 +71,7 @@ NX_INLINE void programInfoFreeContext(ProgramInfoContext *program_info_ctx)
NX_INLINE bool programInfoIsValidContext(ProgramInfoContext *program_info_ctx)
{
return (program_info_ctx && program_info_ctx->nca_ctx && npdmIsValidContext(&(program_info_ctx->npdm_ctx)) && program_info_ctx->npdm_ctx.pfs_ctx == &(program_info_ctx->pfs_ctx) && \
program_info_ctx->nso_count && program_info_ctx->nso_ctx);
}
NX_INLINE bool programInfoGenerateNcaPatch(ProgramInfoContext *program_info_ctx)
{
return (programInfoIsValidContext(program_info_ctx) && npdmGenerateNcaPatch(&(program_info_ctx->npdm_ctx)));
}
NX_INLINE void programInfoWriteNcaPatch(ProgramInfoContext *program_info_ctx, void *buf, u64 buf_size, u64 buf_offset)
{
if (program_info_ctx) npdmWriteNcaPatch(&(program_info_ctx->npdm_ctx), buf, buf_size, buf_offset);
return (program_info_ctx && program_info_ctx->nca_ctx && npdmIsValidContext(&(program_info_ctx->npdm_ctx)) && program_info_ctx->nso_count && program_info_ctx->nso_ctx);
}
#ifdef __cplusplus

View file

@ -2,7 +2,6 @@
* rsa.c
*
* Copyright (c) 2018-2019, SciresM.
* Copyright (c) 2018-2019, The-4n.
* Copyright (c) 2020-2022, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
@ -36,19 +35,10 @@ extern "C" {
#define RSA2048_SIG_SIZE RSA2048_BYTES
#define RSA2048_PUBKEY_SIZE RSA2048_BYTES
/// Returns a pointer to the RSA-2048 public key that can be used to verify signatures generated by rsa2048GenerateSha256BasedPssSignature().
/// Suitable to replace the ACID public key in a NPDM.
const u8 *rsa2048GetCustomPublicKey(void);
/// Verifies a RSA-2048-PSS with SHA-256 signature.
/// The provided signature and modulus should have sizes of at least RSA2048_SIG_SIZE and RSA2048_PUBKEY_SIZE, respectively.
bool rsa2048VerifySha256BasedPssSignature(const void *data, size_t data_size, const void *signature, const void *modulus, const void *public_exponent, size_t public_exponent_size);
/// Generates a RSA-2048-PSS with SHA-256 signature using a custom RSA-2048 private key.
/// Suitable to replace the ACID signature in a Program NCA header.
/// Destination buffer size should be at least RSA2048_SIG_SIZE.
bool rsa2048GenerateSha256BasedPssSignature(void *dst, const void *src, size_t size);
/// Performs RSA-2048-OAEP decryption.
/// Suitable to decrypt the titlekey block from tickets with personalized crypto.
/// The provided signature and modulus should have sizes of at least RSA2048_SIG_SIZE and RSA2048_PUBKEY_SIZE, respectively.

View file

@ -13,7 +13,6 @@
"set_download_distribution": false,
"remove_console_data": true,
"remove_titlekey_crypto": false,
"replace_acid_key_sig": false,
"disable_linked_account_requirement": false,
"enable_screenshots": false,
"enable_video_capture": false,

View file

@ -216,7 +216,7 @@ end:
static bool configValidateJsonNspObject(const struct json_object *obj)
{
bool ret = false, set_download_distribution_found = false, remove_console_data_found = false, remove_titlekey_crypto_found = false, replace_acid_key_sig_found = false;
bool ret = false, set_download_distribution_found = false, remove_console_data_found = false, remove_titlekey_crypto_found = false;
bool disable_linked_account_requirement_found = false, enable_screenshots_found = false, enable_video_capture_found = false, disable_hdcp_found = false, append_authoringtool_data_found = false, lookup_checksum_found = false;
if (!jsonValidateObject(obj)) goto end;
@ -226,7 +226,6 @@ static bool configValidateJsonNspObject(const struct json_object *obj)
CONFIG_VALIDATE_FIELD(Boolean, set_download_distribution);
CONFIG_VALIDATE_FIELD(Boolean, remove_console_data);
CONFIG_VALIDATE_FIELD(Boolean, remove_titlekey_crypto);
CONFIG_VALIDATE_FIELD(Boolean, replace_acid_key_sig);
CONFIG_VALIDATE_FIELD(Boolean, disable_linked_account_requirement);
CONFIG_VALIDATE_FIELD(Boolean, enable_screenshots);
CONFIG_VALIDATE_FIELD(Boolean, enable_video_capture);
@ -236,7 +235,7 @@ static bool configValidateJsonNspObject(const struct json_object *obj)
goto end;
}
ret = (set_download_distribution_found && remove_console_data_found && remove_titlekey_crypto_found && replace_acid_key_sig_found && disable_linked_account_requirement_found && \
ret = (set_download_distribution_found && remove_console_data_found && remove_titlekey_crypto_found && disable_linked_account_requirement_found && \
enable_screenshots_found && enable_video_capture_found && disable_hdcp_found && append_authoringtool_data_found && lookup_checksum_found);
end:

View file

@ -28,6 +28,7 @@ bool npdmInitializeContext(NpdmContext *out, PartitionFileSystemContext *pfs_ctx
NcaContext *nca_ctx = NULL;
u64 cur_offset = 0;
bool success = false, dump_meta_header = false, dump_acid_header = false, dump_aci_header = false;
PartitionFileSystemEntry *pfs_entry = NULL;
if (!out || !pfs_ctx || !pfs_ctx->nca_fs_ctx || !(nca_ctx = (NcaContext*)pfs_ctx->nca_fs_ctx->nca_ctx) || nca_ctx->content_type != NcmContentType_Program || !pfs_ctx->offset || !pfs_ctx->size || \
!pfs_ctx->is_exefs || pfs_ctx->header_size <= sizeof(PartitionFileSystemHeader) || !pfs_ctx->header)
@ -40,9 +41,7 @@ bool npdmInitializeContext(NpdmContext *out, PartitionFileSystemContext *pfs_ctx
npdmFreeContext(out);
/* Get 'main.npdm' file entry. */
out->nca_ctx = nca_ctx;
out->pfs_ctx = pfs_ctx;
if (!(out->pfs_entry = pfsGetEntryByName(out->pfs_ctx, "main.npdm")))
if (!(pfs_entry = pfsGetEntryByName(pfs_ctx, "main.npdm")))
{
LOG_MSG("'main.npdm' entry unavailable in ExeFS!");
goto end;
@ -51,14 +50,14 @@ bool npdmInitializeContext(NpdmContext *out, PartitionFileSystemContext *pfs_ctx
//LOG_MSG("Found 'main.npdm' entry in Program NCA \"%s\".", nca_ctx->content_id_str);
/* Check raw NPDM size. */
if (!out->pfs_entry->size)
if (!pfs_entry->size)
{
LOG_MSG("Invalid raw NPDM size!");
goto end;
}
/* Allocate memory for the raw NPDM data. */
out->raw_data_size = out->pfs_entry->size;
out->raw_data_size = pfs_entry->size;
if (!(out->raw_data = malloc(out->raw_data_size)))
{
LOG_MSG("Failed to allocate memory for the raw NPDM data!");
@ -66,7 +65,7 @@ bool npdmInitializeContext(NpdmContext *out, PartitionFileSystemContext *pfs_ctx
}
/* Read raw NPDM data into memory buffer. */
if (!pfsReadEntryData(out->pfs_ctx, out->pfs_entry, out->raw_data, out->raw_data_size, 0))
if (!pfsReadEntryData(pfs_ctx, pfs_entry, out->raw_data, out->raw_data_size, 0))
{
LOG_MSG("Failed to read raw NPDM data!");
goto end;
@ -287,62 +286,3 @@ end:
return success;
}
bool npdmGenerateNcaPatch(NpdmContext *npdm_ctx)
{
if (!npdmIsValidContext(npdm_ctx) || npdm_ctx->nca_ctx->content_type != NcmContentType_Program)
{
LOG_MSG("Invalid parameters!");
return false;
}
NcaContext *nca_ctx = npdm_ctx->nca_ctx;
/* Check if we really need to generate this patch. */
if (!ncaIsHeaderDirty(nca_ctx))
{
LOG_MSG("Skipping NPDM patching - NCA header hasn't been modified.");
return true;
}
/* Update NPDM ACID public key. */
memcpy(npdm_ctx->acid_header->public_key, rsa2048GetCustomPublicKey(), RSA2048_PUBKEY_SIZE);
/* Generate Partition FS entry patch. */
if (!pfsGenerateEntryPatch(npdm_ctx->pfs_ctx, npdm_ctx->pfs_entry, npdm_ctx->raw_data, npdm_ctx->raw_data_size, 0, &(npdm_ctx->nca_patch)))
{
LOG_MSG("Failed to generate Partition FS entry patch!");
return false;
}
/* Update NCA ACID signature. */
if (!rsa2048GenerateSha256BasedPssSignature(nca_ctx->header.acid_signature, &(nca_ctx->header.magic), NCA_SIGNATURE_AREA_SIZE))
{
LOG_MSG("Failed to generate RSA-2048-PSS NCA ACID signature!");
return false;
}
/* Update NCA content type context patch status. */
nca_ctx->content_type_ctx_patch = true;
return true;
}
void npdmWriteNcaPatch(NpdmContext *npdm_ctx, void *buf, u64 buf_size, u64 buf_offset)
{
NcaContext *nca_ctx = NULL;
NcaHierarchicalSha256Patch *nca_patch = (npdm_ctx ? &(npdm_ctx->nca_patch) : NULL);
/* Using npdmIsValidContext() here would probably take up precious CPU cycles. */
if (!nca_patch || nca_patch->written || !(nca_ctx = npdm_ctx->nca_ctx) || nca_ctx->content_type != NcmContentType_Program || !nca_ctx->content_type_ctx_patch) return;
/* Attempt to write Partition FS entry patch. */
pfsWriteEntryPatchToMemoryBuffer(npdm_ctx->pfs_ctx, nca_patch, buf, buf_size, buf_offset);
/* Check if we need to update the NCA content type context patch status. */
if (nca_patch->written)
{
nca_ctx->content_type_ctx_patch = false;
LOG_MSG("NPDM Partition FS entry patch successfully written to NCA \"%s\"!", nca_ctx->content_id_str);
}
}

View file

@ -2,7 +2,6 @@
* rsa.c
*
* Copyright (c) 2018-2019, SciresM.
* Copyright (c) 2018-2019, The-4n.
* Copyright (c) 2020-2022, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
@ -29,65 +28,6 @@
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/pk.h>
/* Global variables. */
/// Self-generated private key.
static const char g_rsa2048CustomPrivateKey[] = "-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEowIBAAKCAQEAvVRzt+8mE7oE4RkmSh3ws4CGlBj7uhHkfwCpPFsn4TNVdLRo\r\n"
"YYY17jQYWTtcOYPMcHxwUpgJyspGN8QGXEkJqY8jILv2eO0jBGtg7Br2afUBp6/x\r\n"
"BOMT2RlYVX6H4a1UA19Hzmcn+T1hdDwS6oBYpi8rJSm0+q+yB34dueNkVsk4eKbj\r\n"
"CNNKFi+XgyNBi41d57SPCrkcm/9tkagRorE8vLcFPcXcYOjdXH3L4XTXq7sxxytA\r\n"
"I66erfSc4XunkoLifcbfMOB3gjGCoQs6GfaiAU3TwxewQ7hdoqvj5Gm9VyHqzeDF\r\n"
"5mUTlmed2I6m4ELxbV1b0lUguR5ZEzwXwiVWxwIDAQABAoIBADvLYkijFOmCBGx7\r\n"
"HualkhF+9AHt6gKYCAw8Tzaqq2uqZMDZAWZblsjGVzJHVxcrEvQruOW88srDG24d\r\n"
"UMzwnEaa2ENMWclTS43nw9KNqWlJYd5t6LbcaLZWFNnbflq9/RybiPgdCDjlM9Qb\r\n"
"7PV214iUuRGhnHDX8GgBYq4ErPnjQ7+Gv1ducpMYjZencLWCl4fFX86U0/MU0+Qf\r\n"
"jKGegQTnk52aaeScbDOjjx5h+m0hkDNSfsmXTlvJt2c8wy/Yx+leVgCPjMC1nbft\r\n"
"Ob1TlpjuEAKBOGt4+DkWwVmIlxilmx9wCTZnwvPKd7A0e0FGsdHnQienPrMqlgbl\r\n"
"JPYwJuECgYEA6yLZHTfX3ebpzcdQQqmuHZtbOcs+EGRy24gAzd+9vCGKf0VtKSl9\r\n"
"3oA3XBOe2C2TgSgbWFZ7v/2efWRjgwJta0BQlpkzkh6NUQa2LI2M3zgZwHCZ7Ihr\r\n"
"skG73qZsMHOOv7VQz/wDp6AZNasfz21Mcyh4uFzpkb3NKLXqsJ9LeG8CgYEAziEb\r\n"
"yBCuhCKq7YZt/cHlbCbi7HbCYbub0isOCUtV0qPsX+kVZdPS+oGLPq1905JKdAe9\r\n"
"O+4SltCw6qn9RgYnCCVQ47SGHg7KO8Z5vdcNUiDvsQ+jNFlmM5QBuf1UV/Y+DV/Q\r\n"
"fZdA06OeYxkfPuBMtjdS9qMKwm3OsCkiQasWQykCgYAqALieAoq6JfSgALmyntLu\r\n"
"kQDzyv2UOg1Wb+4M2KnxAGDYKVO9pZ7Jb0f0V8DpRwLxcHOqDRDgE/MK3TL1hSp8\r\n"
"nSmILWfL8081KSjDvqlqeoAHI1YrrZbnadyggkQTR6E5V69O5+rTN8MpFh+Bkzmz\r\n"
"3IfsDxTeJvSOECkTUfFOWwKBgQDG/id3yMLxRRaGH5TnuNvmwNOpPC0DdL5E8tOm\r\n"
"HVhI9X8oSDgkCY5Pz+fBJnOmYEAIK8B/rqG7ftSMdnbPtvjPYFbqvEgNlHGfq0e0\r\n"
"AXwWoT1ETbhcvUFw4Z2ZE/rswAe/mZQI6o/mwLoTKRmE9byY3Gf3OgcVFDTI060C\r\n"
"gEwJoQKBgHpOmtGum3JuLpPc+PTXZOe29tdWndkFWktjPoow60d+NO2jpTFuEpmW\r\n"
"XRW35vXI8PqMCmHOQ8YU59aMN9juAnsJmPUxbAW5fZfvVwWUo0cTOenfT6syrEYO\r\n"
"n5NEG+mY4WZaOFRNiZu8+4aJI1yycXMyA22iKcU8+nN/sMAJs3Nx\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
/// Self-generated public key.
/// Used to verify signatures generated with g_rsa2048CustomPrivateKey.
static const u8 g_rsa2048CustomPublicKey[] = {
0xBD, 0x54, 0x73, 0xB7, 0xEF, 0x26, 0x13, 0xBA, 0x04, 0xE1, 0x19, 0x26, 0x4A, 0x1D, 0xF0, 0xB3,
0x80, 0x86, 0x94, 0x18, 0xFB, 0xBA, 0x11, 0xE4, 0x7F, 0x00, 0xA9, 0x3C, 0x5B, 0x27, 0xE1, 0x33,
0x55, 0x74, 0xB4, 0x68, 0x61, 0x86, 0x35, 0xEE, 0x34, 0x18, 0x59, 0x3B, 0x5C, 0x39, 0x83, 0xCC,
0x70, 0x7C, 0x70, 0x52, 0x98, 0x09, 0xCA, 0xCA, 0x46, 0x37, 0xC4, 0x06, 0x5C, 0x49, 0x09, 0xA9,
0x8F, 0x23, 0x20, 0xBB, 0xF6, 0x78, 0xED, 0x23, 0x04, 0x6B, 0x60, 0xEC, 0x1A, 0xF6, 0x69, 0xF5,
0x01, 0xA7, 0xAF, 0xF1, 0x04, 0xE3, 0x13, 0xD9, 0x19, 0x58, 0x55, 0x7E, 0x87, 0xE1, 0xAD, 0x54,
0x03, 0x5F, 0x47, 0xCE, 0x67, 0x27, 0xF9, 0x3D, 0x61, 0x74, 0x3C, 0x12, 0xEA, 0x80, 0x58, 0xA6,
0x2F, 0x2B, 0x25, 0x29, 0xB4, 0xFA, 0xAF, 0xB2, 0x07, 0x7E, 0x1D, 0xB9, 0xE3, 0x64, 0x56, 0xC9,
0x38, 0x78, 0xA6, 0xE3, 0x08, 0xD3, 0x4A, 0x16, 0x2F, 0x97, 0x83, 0x23, 0x41, 0x8B, 0x8D, 0x5D,
0xE7, 0xB4, 0x8F, 0x0A, 0xB9, 0x1C, 0x9B, 0xFF, 0x6D, 0x91, 0xA8, 0x11, 0xA2, 0xB1, 0x3C, 0xBC,
0xB7, 0x05, 0x3D, 0xC5, 0xDC, 0x60, 0xE8, 0xDD, 0x5C, 0x7D, 0xCB, 0xE1, 0x74, 0xD7, 0xAB, 0xBB,
0x31, 0xC7, 0x2B, 0x40, 0x23, 0xAE, 0x9E, 0xAD, 0xF4, 0x9C, 0xE1, 0x7B, 0xA7, 0x92, 0x82, 0xE2,
0x7D, 0xC6, 0xDF, 0x30, 0xE0, 0x77, 0x82, 0x31, 0x82, 0xA1, 0x0B, 0x3A, 0x19, 0xF6, 0xA2, 0x01,
0x4D, 0xD3, 0xC3, 0x17, 0xB0, 0x43, 0xB8, 0x5D, 0xA2, 0xAB, 0xE3, 0xE4, 0x69, 0xBD, 0x57, 0x21,
0xEA, 0xCD, 0xE0, 0xC5, 0xE6, 0x65, 0x13, 0x96, 0x67, 0x9D, 0xD8, 0x8E, 0xA6, 0xE0, 0x42, 0xF1,
0x6D, 0x5D, 0x5B, 0xD2, 0x55, 0x20, 0xB9, 0x1E, 0x59, 0x13, 0x3C, 0x17, 0xC2, 0x25, 0x56, 0xC7
};
/* Function prototypes. */
const u8 *rsa2048GetCustomPublicKey(void)
{
return g_rsa2048CustomPublicKey;
}
bool rsa2048VerifySha256BasedPssSignature(const void *data, size_t data_size, const void *signature, const void *modulus, const void *public_exponent, size_t public_exponent_size)
{
if (!data || !data_size || !signature || !modulus || !public_exponent || !public_exponent_size)
@ -131,72 +71,6 @@ end:
return ret;
}
bool rsa2048GenerateSha256BasedPssSignature(void *dst, const void *src, size_t size)
{
if (!dst || !src || !size)
{
LOG_MSG("Invalid parameters!");
return false;
}
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_pk_context pk;
size_t olen = 0;
int mbedtls_ret = 0;
const char *pers = __func__;
u8 hash[SHA256_HASH_SIZE] = {0}, buf[MBEDTLS_MPI_MAX_SIZE] = {0};
bool ret = false;
/* Initialize contexts. */
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_pk_init(&pk);
/* Calculate SHA-256 checksum for the input data. */
sha256CalculateHash(hash, src, size);
/* Seed the random number generator. */
mbedtls_ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const u8*)pers, strlen(pers));
if (mbedtls_ret != 0)
{
LOG_MSG("mbedtls_ctr_drbg_seed failed! (%d).", mbedtls_ret);
goto end;
}
/* Parse private key. */
mbedtls_ret = mbedtls_pk_parse_key(&pk, (const u8*)g_rsa2048CustomPrivateKey, strlen(g_rsa2048CustomPrivateKey) + 1, NULL, 0);
if (mbedtls_ret != 0)
{
LOG_MSG("mbedtls_pk_parse_key failed! (%d).", mbedtls_ret);
goto end;
}
/* Set RSA padding. */
mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
/* Calculate hash signature. */
mbedtls_ret = mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, hash, 0, buf, &olen, mbedtls_ctr_drbg_random, &ctr_drbg);
if (mbedtls_ret != 0 || olen < RSA2048_SIG_SIZE)
{
LOG_MSG("mbedtls_pk_sign failed! (%d, %lu).", mbedtls_ret, olen);
goto end;
}
/* Copy signature to output buffer. */
memcpy(dst, buf, RSA2048_SIG_SIZE);
ret = true;
end:
mbedtls_pk_free(&pk);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
return ret;
}
bool rsa2048OaepDecrypt(void *dst, size_t dst_size, const void *signature, const void *modulus, const void *public_exponent, size_t public_exponent_size, const void *private_exponent, \
size_t private_exponent_size, const void *label, size_t label_size, size_t *out_size)
{

View file

@ -36,11 +36,6 @@ list of top level functions designed to alter nca data in order of (possible) us
* ncaRemoveTitlekeyCrypto (can be used with digital titles + game updates in gamecards)
* programInfoGenerateNcaPatch (Program)
* calls npdmGenerateNcaPatch
* calls pfsGenerateEntryPatch
* calls ncaGenerateHierarchicalSha256Patch
* nacpGenerateNcaPatch (Control)
* calls romfsGenerateFileEntryPatch
* calls ncaGenerateHierarchicalSha256Patch / ncaGenerateHierarchicalIntegrityPatch
@ -62,11 +57,6 @@ list of top level functions designed to alter nca data in order of (possible) us
* calls pfsWriteEntryPatchToMemoryBuffer
* calls ncaWriteHierarchicalSha256PatchToMemoryBuffer
* programInfoWriteNcaPatch (writes ndpm patch)
* calls npdmWriteNcaPatch
* calls pfsWriteEntryPatchToMemoryBuffer
* calls ncaWriteHierarchicalSha256PatchToMemoryBuffer
* nacpWriteNcaPatch (writes nacp patch)
* calls romfsWriteFileEntryPatchToMemoryBuffer
* calls ncaWriteHierarchicalSha256PatchToMemoryBuffer / ncaWriteHierarchicalIntegrityPatchToMemoryBuffer