mirror of
https://github.com/GerbilSoft/rvthtool.git
synced 2025-06-18 19:45:35 -04:00
[nusresign, wadresign] Use TCHAR printf() functions where possible.
This lets us consolidate sets of fputs() and printf()-style functions into a single printf(), which reduces code size. Note that it will definitely increase the size on Windows due to more UTF-16 strings. - Converted some more printf()-style functions to fputs()-style. gcc does this automatically if possible, but MSVC does not. - Updated copyright years. [nusresign] main.c: Remove a few extra leading spaces in print_help(). [nusresign] resign-nus.cpp: - Removed a line of debugging code. - Ticket type change from Disc to Installable should be on stdout, not stderr. TODO: There's a few more functions that need TCHAR conversions, but they require changing more code elsewhere. Code size differences: (64-bit Gentoo Linux, gcc-12.1.0, release build, no LTO) [NOTE: Windows builds will increase due to more TCHAR usage.] text data bss dec hex filename 3151 160 0 3311 cef main.c.o [wadresign, before] 3132 160 0 3292 cdc main.c.o [wadresign, after] -19 0 0 -19 -13 Difference text data bss dec hex filename 6581 0 0 6581 19b5 print-info.c.o [wadresign, before] 6146 0 0 6146 1802 print-info.c.o [wadresign, after] -435 0 0 -435 -1b3 Difference text data bss dec hex filename 14164 8 0 14172 375c resign-wad.cpp.o [wadresign, before] 11888 8 0 11896 2e78 resign-wad.cpp.o [wadresign, after] -2276 0 0 -2276 -8e4 Difference text data bss dec hex filename 2561 96 0 2657 a61 main.c.o [nusresign, before] 2526 96 0 2622 a3e main.c.o [nusresign, after] -35 0 0 -35 -23 Difference text data bss dec hex filename 8787 8 0 8795 225b print-info.cpp.o [nusresign, before] 8574 8 0 8582 2186 print-info.cpp.o [nusresign, after] -213 0 0 -213 -d5 Difference text data bss dec hex filename 5374 8 0 5382 1506 resign-nus.cpp.o [nusresign, before] 5341 8 0 5349 14e5 resign-nus.cpp.o [nusresign, after] -33 0 0 -33 -21 Difference
This commit is contained in:
parent
6eafbf3ff4
commit
37833e42e9
@ -65,34 +65,30 @@ static void ATTR_PRINTF(2, 3) print_error(const TCHAR *argv0, const TCHAR *fmt,
|
||||
*/
|
||||
static void print_help(const TCHAR *argv0)
|
||||
{
|
||||
fputs("This program is licensed under the GNU GPL v2.\n"
|
||||
"For more information, visit: http://www.gnu.org/licenses/\n"
|
||||
"\n", stdout);
|
||||
_fputts(_T("This program is licensed under the GNU GPL v2.\n")
|
||||
_T("For more information, visit: http://www.gnu.org/licenses/\n")
|
||||
_T("\n"), stdout);
|
||||
|
||||
fputs("Syntax: ", stdout);
|
||||
_fputts(argv0, stdout);
|
||||
fputs(" [options] [command]\n"
|
||||
"\n"
|
||||
"Supported commands:\n"
|
||||
"\n"
|
||||
"info nusdir/\n"
|
||||
"- Print information about the specified NUS directory.\n"
|
||||
"\n"
|
||||
"resign nusdir/\n"
|
||||
" - Resigns the specified NUS directory in place.\n"
|
||||
" Default converts Retail NUS to Debug, and Debug NUS to retail.\n"
|
||||
"\n"
|
||||
"verify nusdir/\n"
|
||||
" - Verify the content hashes.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
"\n"
|
||||
" -k, --recrypt=KEY Recrypt the WAD using the specified KEY:\n"
|
||||
" default, retail, debug\n"
|
||||
" Recrypting to retail will blank out the signatures.\n"
|
||||
" -h, --help Display this help and exit.\n"
|
||||
"\n"
|
||||
, stdout);
|
||||
_tprintf(_T("Syntax: %s [options] [command]\n\n"), argv0);
|
||||
_fputts(_T("Supported commands:\n")
|
||||
_T("\n")
|
||||
_T("info nusdir/\n")
|
||||
_T("- Print information about the specified NUS directory.\n")
|
||||
_T("\n")
|
||||
_T("resign nusdir/\n")
|
||||
_T("- Resigns the specified NUS directory in place.\n")
|
||||
_T(" Default converts Retail NUS to Debug, and Debug NUS to retail.\n")
|
||||
_T("\n")
|
||||
_T("verify nusdir/\n")
|
||||
_T(" - Verify the content hashes.\n")
|
||||
_T("\n")
|
||||
_T("Options:\n")
|
||||
_T("\n")
|
||||
_T(" -k, --recrypt=KEY Recrypt the WAD using the specified KEY:\n")
|
||||
_T(" default, retail, debug\n")
|
||||
_T(" Recrypting to retail will blank out the signatures.\n")
|
||||
_T(" -h, --help Display this help and exit.\n")
|
||||
_T("\n"), stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,15 +129,15 @@ int RVTH_CDECL _tmain(int argc, TCHAR *argv[])
|
||||
// Set the C locale.
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
puts("NUS Resigner v" VERSION_STRING "\n"
|
||||
"Copyright (c) 2018-2020 by David Korth.");
|
||||
_fputts(_T("NUS Resigner v") _T(VERSION_STRING) _T("\n")
|
||||
_T("Copyright (c) 2018-2022 by David Korth.\n")
|
||||
#ifdef RP_GIT_VERSION
|
||||
puts(RP_GIT_VERSION);
|
||||
# ifdef RP_GIT_DESCRIBE
|
||||
puts(RP_GIT_DESCRIBE);
|
||||
# endif
|
||||
_T(RP_GIT_VERSION) _T("\n")
|
||||
# ifdef RP_GIT_DESCRIBE
|
||||
_T(RP_GIT_DESCRIBE) _T("\n")
|
||||
# endif
|
||||
#endif
|
||||
putchar('\n');
|
||||
_T("\n"), stdout);
|
||||
|
||||
// Using Unicode getopt() for Windows:
|
||||
// - https://www.codeproject.com/Articles/157001/Full-getopt-Port-for-Unicode-and-Multibyte-Microso
|
||||
|
@ -2,7 +2,7 @@
|
||||
* RVT-H Tool: WAD Resigner *
|
||||
* print-info.c: Print WAD information. *
|
||||
* *
|
||||
* Copyright (c) 2018-2020 by David Korth. *
|
||||
* Copyright (c) 2018-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
@ -19,14 +19,14 @@
|
||||
#include <nettle/sha1.h>
|
||||
#include <nettle/sha2.h>
|
||||
|
||||
// C includes.
|
||||
// C includes
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// C++ includes.
|
||||
// C++ includes
|
||||
#include <memory>
|
||||
#include <string>
|
||||
using std::tstring;
|
||||
@ -107,11 +107,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("- *** ERROR opening ", stderr);
|
||||
_fputts(cidbuf, stderr);
|
||||
fputs(".app: ", stderr);
|
||||
_fputts(_tcserror(err), stderr);
|
||||
putchar('\n');
|
||||
_ftprintf(stderr, _T("- *** ERROR opening %s.app: %s\n"), cidbuf, _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
@ -128,11 +124,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("- *** ERROR opening ", stderr);
|
||||
_fputts(cidbuf, stderr);
|
||||
fputs(".h3: ", stderr);
|
||||
_fputts(_tcserror(err), stderr);
|
||||
putchar('\n');
|
||||
_ftprintf(stderr, _T("- *** ERROR opening %s.h3: %s\n"), cidbuf, _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
@ -145,9 +137,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
|
||||
// Invalid size.
|
||||
fclose(f_h3);
|
||||
fclose(f_content);
|
||||
fputs("- *** ERROR opening ", stderr);
|
||||
_fputts(cidbuf, stderr);
|
||||
fputs(".h3: Size is incorrect\n", stderr);
|
||||
_ftprintf(stderr, _T("- *** ERROR opening %s.h3: Size is incorrect\n"), cidbuf);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -162,11 +152,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
|
||||
err = EIO;
|
||||
}
|
||||
fclose(f_content);
|
||||
fputs("- *** ERROR opening ", stderr);
|
||||
_fputts(cidbuf, stderr);
|
||||
fputs(".h3: ", stderr);
|
||||
_fputts(_tcserror(err), stderr);
|
||||
putchar('\n');
|
||||
_ftprintf(stderr, _T("- *** ERROR opening %s.h3: %s\n"), cidbuf, _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
}
|
||||
@ -244,19 +230,19 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
|
||||
// Finalize the SHA-1 and compare it.
|
||||
uint8_t digest[SHA1_DIGEST_SIZE];
|
||||
sha1_digest(&sha1, sizeof(digest), digest);
|
||||
fputs("- Expected SHA-1: ", stdout);
|
||||
_fputts(_T("- Expected SHA-1: "), stdout);
|
||||
for (size_t size = 0; size < sizeof(entry->sha1_hash); size++) {
|
||||
printf("%02x", entry->sha1_hash[size]);
|
||||
_tprintf(_T("%02x"), entry->sha1_hash[size]);
|
||||
}
|
||||
putchar('\n');
|
||||
printf("- Actual SHA-1: ");
|
||||
_fputtc(_T('\n'), stdout);
|
||||
_fputts(_T("- Actual SHA-1: "), stdout);
|
||||
for (size_t size = 0; size < sizeof(digest); size++) {
|
||||
printf("%02x", digest[size]);
|
||||
_tprintf(_T("%02x"), digest[size]);
|
||||
}
|
||||
if (!memcmp(digest, entry->sha1_hash, SHA1_DIGEST_SIZE)) {
|
||||
fputs(" [OK]\n", stdout);
|
||||
_fputts(_T(" [OK]\n"), stdout);
|
||||
} else {
|
||||
fputs(" [ERROR]\n", stdout);
|
||||
_fputts(_T(" [ERROR]\n"), stdout);
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
@ -384,7 +370,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
|
||||
bool showH4status = true;
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
if (bad_hash[i] != 0) {
|
||||
printf("- ERROR: %u H%u hash(es) were incorrect.\n", bad_hash[i], i);
|
||||
_tprintf(_T("- ERROR: %u H%u hash(es) were incorrect.\n"), bad_hash[i], i);
|
||||
showH4status = false;
|
||||
ret = 1;
|
||||
}
|
||||
@ -396,24 +382,24 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
|
||||
sha1_init(&sha1_h4);
|
||||
sha1_update(&sha1_h4, hash_h3_len, hash_h3.get());
|
||||
sha1_digest(&sha1_h4, sizeof(digest), digest);
|
||||
fputs("- Expected SHA-1: ", stdout);
|
||||
_fputts(_T("- Expected SHA-1: "), stdout);
|
||||
for (size_t size = 0; size < sizeof(entry->sha1_hash); size++) {
|
||||
printf("%02x", entry->sha1_hash[size]);
|
||||
_tprintf(_T("%02x"), entry->sha1_hash[size]);
|
||||
}
|
||||
fputs(" (H4)\n", stdout);
|
||||
printf("- Actual SHA-1: ");
|
||||
_fputts(_T(" (H4)\n"), stdout);
|
||||
_fputts(_T("- Actual SHA-1: "), stdout);
|
||||
for (size_t size = 0; size < sizeof(digest); size++) {
|
||||
printf("%02x", digest[size]);
|
||||
}
|
||||
if (showH4status) {
|
||||
if (!memcmp(digest, entry->sha1_hash, SHA1_DIGEST_SIZE)) {
|
||||
fputs(" [OK] (H4)\n", stdout);
|
||||
_fputts(_T(" [OK] (H4)\n"), stdout);
|
||||
} else {
|
||||
fputs(" [ERROR] (H4)\n", stdout);
|
||||
_fputts(_T(" [ERROR] (H4)\n"), stdout);
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
fputs(" (H4)\n", stdout);
|
||||
_fputts(_T(" (H4)\n"), stdout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,7 +433,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR opening ticket file: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR opening ticket file: %s\n"), _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
@ -459,7 +445,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR opening TMD file: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR opening TMD file: %s\n"), _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
@ -469,12 +455,12 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
if (tik_size < sizeof(WUP_Ticket)) {
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
fprintf(stderr, "*** ERROR reading ticket file: Too small.\n");
|
||||
_fputts(_T("*** ERROR reading ticket file: Too small.\n"), stderr);
|
||||
return -EIO;
|
||||
} else if (tik_size > (64*1024)) {
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
fprintf(stderr, "*** ERROR reading ticket file: Too big.\n");
|
||||
_fputts(_T("*** ERROR reading ticket file: Too big.\n"), stderr);
|
||||
return -EIO;
|
||||
}
|
||||
fseeko(f_tmd, 0, SEEK_END);
|
||||
@ -482,12 +468,12 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
if (tmd_size < (sizeof(WUP_TMD_Header) + sizeof(WUP_TMD_ContentInfoTable))) {
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
fprintf(stderr, "*** ERROR reading TMD file: Too small.\n");
|
||||
_fputts(_T("*** ERROR reading TMD file: Too small.\n"), stderr);
|
||||
return -EIO;
|
||||
} else if (tmd_size > (128*1024)) {
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
fprintf(stderr, "*** ERROR reading TMD file: Too big.\n");
|
||||
_fputts(_T("*** ERROR reading TMD file: Too big.\n"), stderr);
|
||||
return -EIO;
|
||||
}
|
||||
rewind(f_tik);
|
||||
@ -509,13 +495,13 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
_tprintf(_T("%s:\n"), nus_dir);
|
||||
// FIXME: Get the actual Wii U application type.
|
||||
//printf("Type: %08x\n", be32_to_cpu(pTmdHeader->rvl.title_type));
|
||||
printf("- Title ID: %08X-%08X\n", be32_to_cpu(pTmdHeader->rvl.title_id.hi), be32_to_cpu(pTmdHeader->rvl.title_id.lo));
|
||||
_tprintf(_T("- Title ID: %08X-%08X\n"), be32_to_cpu(pTmdHeader->rvl.title_id.hi), be32_to_cpu(pTmdHeader->rvl.title_id.lo));
|
||||
|
||||
// TODO: Figure out where the game ID is stored.
|
||||
|
||||
// Title version (TODO: Wii U changes?)
|
||||
uint16_t title_version = be16_to_cpu(pTmdHeader->rvl.title_version);
|
||||
printf("- Title version: %u.%u (v%u)\n",
|
||||
_tprintf(_T("- Title version: %u.%u (v%u)\n"),
|
||||
title_version >> 8, title_version & 0xFF, title_version);
|
||||
|
||||
// OS version
|
||||
@ -528,29 +514,30 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
os_version = (uint8_t)ios_tid_lo;
|
||||
}
|
||||
}
|
||||
printf("- OS version: OSv%u\n", os_version);
|
||||
_tprintf(_T("- OS version: OSv%u\n"), os_version);
|
||||
|
||||
// Determine the encryption key in use.
|
||||
// NOTE: May use CTR since CTR and WUP have the same certificates.
|
||||
RVL_Cert_Issuer issuer_ticket = cert_get_issuer_from_name(pTicket->issuer);
|
||||
RVL_AES_Keys_e encKey;
|
||||
const char *s_encKey;
|
||||
const TCHAR *s_encKey;
|
||||
switch (issuer_ticket) {
|
||||
default: // TODO: Show an error instead?
|
||||
case CTR_CERT_ISSUER_PPKI_TICKET:
|
||||
case WUP_CERT_ISSUER_PPKI_TICKET:
|
||||
encKey = WUP_KEY_RETAIL;
|
||||
s_encKey = "Retail";
|
||||
s_encKey = _T("Retail");
|
||||
break;
|
||||
case CTR_CERT_ISSUER_DPKI_TICKET:
|
||||
case WUP_CERT_ISSUER_DPKI_TICKET:
|
||||
encKey = WUP_KEY_DEBUG;
|
||||
s_encKey = "Debug";
|
||||
s_encKey = _T("Debug");
|
||||
break;
|
||||
}
|
||||
printf("- Encryption: %s\n", s_encKey);
|
||||
_tprintf(_T("- Encryption: %s\n"), s_encKey);
|
||||
|
||||
// Check the ticket issuer and signature.
|
||||
// FIXME: TCHAR version.
|
||||
// NOTE: The ticket might have a certificate chain appended,
|
||||
// so we'll only check the actual ticket data.
|
||||
const char *const s_issuer_ticket = issuer_type(issuer_ticket);
|
||||
@ -559,6 +546,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
s_issuer_ticket, RVL_SigStatus_toString_stsAppend(sig_status_ticket));
|
||||
|
||||
// Check the TMD issuer and signature.
|
||||
// FIXME: TCHAR version.
|
||||
// NOTE: TMD signature only covers the TMD header.
|
||||
// We'll need to check the content info hash afterwards.
|
||||
const char *const s_issuer_tmd = issuer_type(cert_get_issuer_from_name(pTmdHeader->rvl.issuer));
|
||||
@ -617,7 +605,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
printf("- TMD Signature: %s%s\n",
|
||||
s_issuer_tmd, RVL_SigStatus_toString_stsAppend(sig_status_tmd));
|
||||
|
||||
putchar('\n');
|
||||
_fputtc(_T('\n'), stdout);
|
||||
|
||||
// Decrypted title key for contents verification.
|
||||
uint8_t title_key[16];
|
||||
@ -674,15 +662,15 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
// TODO: Show the actual table index, or just the
|
||||
// index field in the entry?
|
||||
uint16_t content_index = be16_to_cpu(p->index);
|
||||
printf("#%d: ID=%08x, type=%04X, size=%u",
|
||||
_tprintf(_T("#%d: ID=%08x, type=%04X, size=%u"),
|
||||
be16_to_cpu(p->index),
|
||||
be32_to_cpu(p->content_id),
|
||||
be16_to_cpu(p->type),
|
||||
(uint32_t)be64_to_cpu(p->size));
|
||||
if (content_index == boot_index) {
|
||||
fputs(", bootable", stdout);
|
||||
_fputts(_T(", bootable"), stdout);
|
||||
}
|
||||
putchar('\n');
|
||||
_fputtc(_T('\n'), stdout);
|
||||
|
||||
if (verify) {
|
||||
// Verify the content.
|
||||
@ -695,7 +683,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
|
||||
}
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
_fputtc(_T('\n'), stdout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* RVT-H Tool: NUS Resigner *
|
||||
* resign-nus.cpp: Re-sign an NUS directory. (Wii U) *
|
||||
* *
|
||||
* Copyright (c) 2018-2020 by David Korth. *
|
||||
* Copyright (c) 2018-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
#include "libwiicrypto/sig_tools.h"
|
||||
#include "libwiicrypto/wiiu_structs.h"
|
||||
|
||||
// C includes.
|
||||
// C includes
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
@ -25,7 +25,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// C++ includes.
|
||||
// C++ includes
|
||||
#include <memory>
|
||||
#include <string>
|
||||
using std::tstring;
|
||||
@ -154,7 +154,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR opening ticket file: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR opening ticket file: %s\n"), _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR opening TMD file: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR opening TMD file: %s\n"), _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
@ -176,12 +176,12 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
if (tik_size < sizeof(WUP_Ticket)) {
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
fprintf(stderr, "*** ERROR reading ticket file: Too small.\n");
|
||||
_fputts(_T("*** ERROR reading ticket file: Too small.\n"), stderr);
|
||||
return -EIO;
|
||||
} else if (tik_size > (64*1024)) {
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
fprintf(stderr, "*** ERROR reading ticket file: Too big.\n");
|
||||
_fputts(_T("*** ERROR reading ticket file: Too big.\n"), stderr);
|
||||
return -EIO;
|
||||
}
|
||||
fseeko(f_tmd, 0, SEEK_END);
|
||||
@ -189,12 +189,12 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
if (tmd_size < (sizeof(WUP_TMD_Header) + sizeof(WUP_TMD_ContentInfoTable))) {
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
fprintf(stderr, "*** ERROR reading TMD file: Too small.\n");
|
||||
_fputts(_T("*** ERROR reading TMD file: Too small.\n"), stderr);
|
||||
return -EIO;
|
||||
} else if (tmd_size > (128*1024)) {
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
fprintf(stderr, "*** ERROR reading TMD file: Too big.\n");
|
||||
_fputts(_T("*** ERROR reading TMD file: Too big.\n"), stderr);
|
||||
return -EIO;
|
||||
}
|
||||
rewind(f_tik);
|
||||
@ -214,21 +214,20 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
// NOTE: Not checking the TMD key. Assuming it's the same as Ticket.
|
||||
// NOTE: Need to check for 3DS
|
||||
RVL_CryptoType_e src_key; // TODO: WUP constants?
|
||||
const char *s_fromKey;
|
||||
const TCHAR *s_fromKey;
|
||||
switch (cert_get_issuer_from_name(pTicket->issuer)) {
|
||||
case CTR_CERT_ISSUER_PPKI_TICKET:
|
||||
case WUP_CERT_ISSUER_PPKI_TICKET:
|
||||
src_key = RVL_CryptoType_Retail;
|
||||
s_fromKey = "retail";
|
||||
s_fromKey = _T("retail");
|
||||
break;
|
||||
case CTR_CERT_ISSUER_DPKI_TICKET:
|
||||
case WUP_CERT_ISSUER_DPKI_TICKET:
|
||||
src_key = RVL_CryptoType_Debug;
|
||||
s_fromKey = "debug";
|
||||
s_fromKey = _T("debug");
|
||||
break;
|
||||
default:
|
||||
fputs("*** ERROR: NUS ticket has an unknown issuer.\n", stderr);
|
||||
printf("issuer: %s == %d\n", pTicket->issuer, cert_get_issuer_from_name(pTicket->issuer));
|
||||
_fputts(_T("*** ERROR: NUS ticket has an unknown issuer.\n"), stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -241,7 +240,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
} else {
|
||||
// If the specified key matches the current key, fail.
|
||||
if (recrypt_key == src_key) {
|
||||
fputs("*** ERROR: Cannot recrypt to the same key.\n", stderr);
|
||||
_fputts(_T("*** ERROR: Cannot recrypt to the same key.\n"), stderr);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
@ -249,7 +248,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
// Determine the new issuers.
|
||||
RVL_Cert_Issuer issuer_ca, issuer_xs, issuer_cp, issuer_sp;
|
||||
const char *s_issuer_xs, *s_issuer_cp;
|
||||
const char *s_toKey;
|
||||
const TCHAR *s_toKey;
|
||||
RVL_AES_Keys_e toKey;
|
||||
RVL_PKI toPki;
|
||||
switch (recrypt_key) {
|
||||
@ -258,7 +257,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
issuer_xs = WUP_CERT_ISSUER_PPKI_TICKET;
|
||||
issuer_cp = WUP_CERT_ISSUER_PPKI_TMD;
|
||||
issuer_sp = RVL_CERT_ISSUER_UNKNOWN;
|
||||
s_toKey = "retail";
|
||||
s_toKey = _T("retail");
|
||||
toKey = WUP_KEY_RETAIL;
|
||||
toPki = WUP_PKI_PPKI;
|
||||
break;
|
||||
@ -267,7 +266,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
issuer_xs = WUP_CERT_ISSUER_DPKI_TICKET;
|
||||
issuer_cp = WUP_CERT_ISSUER_DPKI_TMD;
|
||||
issuer_sp = WUP_CERT_ISSUER_DPKI_SP;
|
||||
s_toKey = "debug";
|
||||
s_toKey = _T("debug");
|
||||
toKey = WUP_KEY_DEBUG;
|
||||
toPki = WUP_PKI_DPKI;
|
||||
break;
|
||||
@ -279,7 +278,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
s_issuer_xs = RVL_Cert_Issuers[issuer_xs];
|
||||
s_issuer_cp = RVL_Cert_Issuers[issuer_cp];
|
||||
|
||||
printf("Converting NUS from %s to %s...\n", s_fromKey, s_toKey);
|
||||
_tprintf(_T("Converting NUS from %s to %s...\n"), s_fromKey, s_toKey);
|
||||
|
||||
/** Ticket fixups **/
|
||||
|
||||
@ -289,11 +288,11 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
case 0x10004:
|
||||
break;
|
||||
case 0x30004:
|
||||
fprintf(stderr, "*** Changing ticket signature type from Disc to Installable.\n");
|
||||
_fputts(_T("*** Changing ticket signature type from Disc to Installable.\n"), stdout);
|
||||
pTicket->signature_type = cpu_to_be32(0x10004);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "*** ERROR: Ticket has unsupported signature type: 0x%08X\n",
|
||||
_ftprintf(stderr, _T("*** ERROR: Ticket has unsupported signature type: 0x%08X\n"),
|
||||
be32_to_cpu(pTicket->signature_type));
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
@ -303,11 +302,11 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
case 0x10004:
|
||||
break;
|
||||
case 0x30004:
|
||||
fprintf(stderr, "*** Changing TMD signature type from Disc to Installable.\n");
|
||||
_fputts(_T("*** Changing TMD signature type from Disc to Installable.\n"), stdout);
|
||||
pTmdHeader->rvl.signature_type = cpu_to_be32(0x10004);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "*** ERROR: TMD has unsupported signature type: 0x%08X\n",
|
||||
_ftprintf(stderr, _T("*** ERROR: TMD has unsupported signature type: 0x%08X\n"),
|
||||
be32_to_cpu(pTmdHeader->rvl.signature_type));
|
||||
fclose(f_tik);
|
||||
fclose(f_tmd);
|
||||
@ -395,7 +394,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR: Unable to write title.cert: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR: Unable to write title.cert: %s\n"), _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
@ -420,6 +419,6 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
|
||||
|
||||
fclose(f_cert);
|
||||
|
||||
printf("NUS resigning complete.\n");
|
||||
_fputts(_T("NUS resigning complete.\n"), stdout);
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "config.version.h"
|
||||
#include "git.h"
|
||||
|
||||
// C includes.
|
||||
// C includes
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
@ -20,16 +20,16 @@
|
||||
#include "libwiicrypto/sig_tools.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "libwiicrypto/win32/secoptions.h"
|
||||
# include "libwiicrypto/win32/secoptions.h"
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "print-info.h"
|
||||
#include "resign-wad.hpp"
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define ATTR_PRINTF(fmt, args) __attribute__ ((format (printf, (fmt), (args))))
|
||||
# define ATTR_PRINTF(fmt, args) __attribute__ ((format (printf, (fmt), (args))))
|
||||
#else
|
||||
# define ATTR_PRINTF(fmt, args)
|
||||
# define ATTR_PRINTF(fmt, args)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -59,38 +59,34 @@ static void ATTR_PRINTF(2, 3) print_error(const TCHAR *argv0, const TCHAR *fmt,
|
||||
*/
|
||||
static void print_help(const TCHAR *argv0)
|
||||
{
|
||||
fputs("This program is licensed under the GNU GPL v2.\n"
|
||||
"For more information, visit: http://www.gnu.org/licenses/\n"
|
||||
"\n", stdout);
|
||||
_fputts(_T("This program is licensed under the GNU GPL v2.\n")
|
||||
_T("For more information, visit: http://www.gnu.org/licenses/\n")
|
||||
_T("\n"), stdout);
|
||||
|
||||
fputs("Syntax: ", stdout);
|
||||
_fputts(argv0, stdout);
|
||||
fputs(" [options] [command]\n"
|
||||
"\n"
|
||||
"Supported commands:\n"
|
||||
"\n"
|
||||
"info file.wad\n"
|
||||
"- Print information about the specified WAD file.\n"
|
||||
"\n"
|
||||
"resign source.wad dest.wad\n"
|
||||
"- Resigns source.wad and creates dest.wad using the new key.\n"
|
||||
" Default converts Retail/Korean WADs to Debug, and\n"
|
||||
" Debug WADs to Retail. The format isn't changed unless\n"
|
||||
" the --format parameter is specified.\n"
|
||||
"\n"
|
||||
"verify file.wad\n"
|
||||
"- Verify the content hashes.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
"\n"
|
||||
" -k, --recrypt=KEY Recrypt the WAD using the specified KEY:\n"
|
||||
" default, retail, korean, vWii, debug\n"
|
||||
" Recrypting to retail will use fakesigning.\n"
|
||||
" -f, --format=FMT Use the specified format FMT:\n"
|
||||
" default, wad, bwf\n"
|
||||
" -h, --help Display this help and exit.\n"
|
||||
"\n"
|
||||
, stdout);
|
||||
_tprintf(_T("Syntax: %s [options] [command]\n\n"), argv0);
|
||||
_fputts(_T("Supported commands:\n")
|
||||
_T("\n")
|
||||
_T("info file.wad\n")
|
||||
_T("- Print information about the specified WAD file.\n")
|
||||
_T("\n")
|
||||
_T("resign source.wad dest.wad\n")
|
||||
_T("- Resigns source.wad and creates dest.wad using the new key.\n")
|
||||
_T(" Default converts Retail/Korean WADs to Debug, and\n")
|
||||
_T(" Debug WADs to Retail. The format isn't changed unless\n")
|
||||
_T(" the --format parameter is specified.\n")
|
||||
_T("\n")
|
||||
_T("verify file.wad\n")
|
||||
_T("- Verify the content hashes.\n")
|
||||
_T("\n")
|
||||
_T("Options:\n")
|
||||
_T("\n")
|
||||
_T(" -k, --recrypt=KEY Recrypt the WAD using the specified KEY:\n")
|
||||
_T(" default, retail, korean, vWii, debug\n")
|
||||
_T(" Recrypting to retail will use fakesigning.\n")
|
||||
_T(" -f, --format=FMT Use the specified format FMT:\n")
|
||||
_T(" default, wad, bwf\n")
|
||||
_T(" -h, --help Display this help and exit.\n")
|
||||
_T("\n"), stdout);
|
||||
}
|
||||
|
||||
int RVTH_CDECL _tmain(int argc, TCHAR *argv[])
|
||||
@ -118,15 +114,15 @@ int RVTH_CDECL _tmain(int argc, TCHAR *argv[])
|
||||
// Set the C locale.
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
puts("WAD Resigner v" VERSION_STRING "\n"
|
||||
"Copyright (c) 2018-2019 by David Korth.");
|
||||
_fputts(_T("WAD Resigner v") _T(VERSION_STRING) _T("\n")
|
||||
_T("Copyright (c) 2018-2022 by David Korth.\n")
|
||||
#ifdef RP_GIT_VERSION
|
||||
puts(RP_GIT_VERSION);
|
||||
# ifdef RP_GIT_DESCRIBE
|
||||
puts(RP_GIT_DESCRIBE);
|
||||
# endif
|
||||
_T(RP_GIT_VERSION) _T("\n")
|
||||
# ifdef RP_GIT_DESCRIBE
|
||||
_T(RP_GIT_DESCRIBE) _T("\n")
|
||||
# endif
|
||||
#endif
|
||||
putchar('\n');
|
||||
_T("\n"), stdout);
|
||||
|
||||
// Using Unicode getopt() for Windows:
|
||||
// - https://www.codeproject.com/Articles/157001/Full-getopt-Port-for-Unicode-and-Multibyte-Microso
|
||||
|
@ -2,7 +2,7 @@
|
||||
* RVT-H Tool: WAD Resigner *
|
||||
* print-info.c: Print WAD information. *
|
||||
* *
|
||||
* Copyright (c) 2018-2020 by David Korth. *
|
||||
* Copyright (c) 2018-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
// Nettle SHA-1
|
||||
#include <nettle/sha1.h>
|
||||
|
||||
// C includes.
|
||||
// C includes
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@ -74,9 +74,9 @@ static const char *issuer_type(RVL_Cert_Issuer issuer)
|
||||
* @param pIsBWF [out] `bool` to store if the WAD file is a BroadOn WAD file or not.
|
||||
* @return WAD file type as a string, or NULL on error.
|
||||
*/
|
||||
const char *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF)
|
||||
const TCHAR *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF)
|
||||
{
|
||||
const char *s_wad_type = NULL;
|
||||
const TCHAR *s_wad_type = NULL;
|
||||
const WAD_Header *const header = (const WAD_Header*)buf;
|
||||
if (buf_len < sizeof(Wii_WAD_Header)) {
|
||||
// Not enough data...
|
||||
@ -94,17 +94,17 @@ const char *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF)
|
||||
|
||||
*pIsBWF = false;
|
||||
if (header->wad.type == cpu_to_be32(WII_WAD_TYPE_Is)) {
|
||||
s_wad_type = "Installable";
|
||||
s_wad_type = _T("Installable");
|
||||
} else if (header->wad.type == cpu_to_be32(WII_WAD_TYPE_ib)) {
|
||||
s_wad_type = "Boot2";
|
||||
s_wad_type = _T("Boot2");
|
||||
} else if (header->wad.type == cpu_to_be32(WII_WAD_TYPE_Bk)) {
|
||||
s_wad_type = "Backup";
|
||||
s_wad_type = _T("Backup");
|
||||
} else {
|
||||
// This might be a BroadOn WAD.
|
||||
if (header->bwf.ticket_size == cpu_to_be32(sizeof(RVL_Ticket))) {
|
||||
// Ticket size is correct.
|
||||
// This is probably a BroadOn WAD.
|
||||
s_wad_type = "BroadOn WAD Format";
|
||||
s_wad_type = _T("BroadOn WAD Format");
|
||||
*pIsBWF = true;
|
||||
}
|
||||
}
|
||||
@ -225,19 +225,19 @@ static int verify_content(FILE *f_wad, RVL_AES_Keys_e encKey,
|
||||
|
||||
// Finalize the SHA-1 and compare it.
|
||||
sha1_digest(&sha1, sizeof(digest), digest);
|
||||
fputs("- Expected SHA-1: ", stdout);
|
||||
_fputts(_T("- Expected SHA-1: "), stdout);
|
||||
for (size = 0; size < sizeof(content->sha1_hash); size++) {
|
||||
printf("%02x", content->sha1_hash[size]);
|
||||
_tprintf(_T("%02x"), content->sha1_hash[size]);
|
||||
}
|
||||
putchar('\n');
|
||||
printf("- Actual SHA-1: ");
|
||||
_fputtc(_T('\n'), stdout);
|
||||
_fputts(_T("- Actual SHA-1: "), stdout);
|
||||
for (size = 0; size < sizeof(digest); size++) {
|
||||
printf("%02x", digest[size]);
|
||||
_tprintf(_T("%02x"), digest[size]);
|
||||
}
|
||||
if (!memcmp(digest, content->sha1_hash, SHA1_DIGEST_SIZE)) {
|
||||
fputs(" [OK]\n", stdout);
|
||||
_fputts(_T(" [OK]\n"), stdout);
|
||||
} else {
|
||||
fputs(" [ERROR]\n", stdout);
|
||||
_fputts(_T(" [ERROR]\n"), stdout);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
{
|
||||
int ret;
|
||||
size_t size;
|
||||
const char *s_wad_type = NULL;
|
||||
const TCHAR *s_wad_type = NULL;
|
||||
bool isBWF = false;
|
||||
WAD_Header header;
|
||||
WAD_Info_t wadInfo;
|
||||
@ -281,8 +281,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
|
||||
// Encryption key
|
||||
RVL_AES_Keys_e encKey;
|
||||
const char *s_encKey;
|
||||
const char *s_invalidKey = NULL;
|
||||
const TCHAR *s_encKey;
|
||||
const TCHAR *s_invalidKey = NULL;
|
||||
|
||||
// Contents
|
||||
unsigned int nbr_cont, nbr_cont_actual;
|
||||
@ -295,9 +295,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
size = fread(&header, 1, sizeof(header), f_wad);
|
||||
if (size != sizeof(header)) {
|
||||
int err = errno;
|
||||
fputs("*** ERROR reading WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "': %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR reading WAD file '%s': %s\n"),
|
||||
wad_filename, _tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -307,9 +306,7 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
s_wad_type = identify_wad_type((const uint8_t*)&header, sizeof(header), &isBWF);
|
||||
if (!s_wad_type) {
|
||||
// Unrecognized WAD type.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "' is not valid.\n");
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' is not valid.\n"), wad_filename);
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
@ -322,41 +319,31 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
}
|
||||
if (ret != 0) {
|
||||
// Unable to get WAD information.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "' is not valid.");
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' is not valid.\n"), wad_filename);
|
||||
ret = 2;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Verify the ticket and TMD sizes.
|
||||
if (wadInfo.ticket_size < sizeof(RVL_Ticket)) {
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "' ticket size is too small. (%u; should be %u)\n",
|
||||
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ticket size is too small. (%u; should be %u)\n"),
|
||||
wad_filename, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
ret = 3;
|
||||
goto end;
|
||||
} else if (wadInfo.ticket_size > WAD_TICKET_SIZE_MAX) {
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "' ticket size is too big. (%u; should be %u)\n",
|
||||
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ticket size is too big. (%u; should be %u)\n"),
|
||||
wad_filename, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
ret = 4;
|
||||
goto end;
|
||||
} else if (wadInfo.tmd_size < sizeof(RVL_TMD_Header)) {
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "' TMD size is too small. (%u; should be at least %u)\n",
|
||||
wadInfo.tmd_size, (uint32_t)sizeof(RVL_TMD_Header));
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' TMD size is too small. (%u; should be at least %u)\n"),
|
||||
wad_filename, wadInfo.tmd_size, (uint32_t)sizeof(RVL_TMD_Header));
|
||||
ret = 5;
|
||||
goto end;
|
||||
} else if (wadInfo.tmd_size > WAD_TMD_SIZE_MAX) {
|
||||
// Too big.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "' TMD size is too big. (%u; should be less than 1 MB)\n",
|
||||
wadInfo.tmd_size);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' TMD size is too big. (%u; should be less than 1 MiB)\n"),
|
||||
wad_filename, wadInfo.tmd_size);
|
||||
ret = 6;
|
||||
goto end;
|
||||
}
|
||||
@ -364,7 +351,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
// Load the ticket and TMD.
|
||||
ticket_u8 = malloc(wadInfo.ticket_size);
|
||||
if (!ticket_u8) {
|
||||
fprintf(stderr, "*** ERROR: Unable to allocate %u bytes for the ticket.\n", wadInfo.ticket_size);
|
||||
_ftprintf(stderr, _T("*** ERROR: Unable to allocate %u bytes for the ticket.\n"),
|
||||
wadInfo.ticket_size);
|
||||
ret = 7;
|
||||
goto end;
|
||||
}
|
||||
@ -372,9 +360,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
size = fread(ticket_u8, 1, wadInfo.ticket_size, f_wad);
|
||||
if (size != wadInfo.ticket_size) {
|
||||
// Read error.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fputs("': Unable to read the ticket.\n", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s': Unable to read the ticket.\n"),
|
||||
wad_filename);
|
||||
ret = 8;
|
||||
goto end;
|
||||
}
|
||||
@ -382,7 +369,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
|
||||
tmd_u8 = malloc(wadInfo.tmd_size);
|
||||
if (!tmd_u8) {
|
||||
fprintf(stderr, "*** ERROR: Unable to allocate %u bytes for the TMD.\n", wadInfo.tmd_size);
|
||||
_ftprintf(stderr, _T("*** ERROR: Unable to allocate %u bytes for the TMD.\n"),
|
||||
wadInfo.tmd_size);
|
||||
ret = 9;
|
||||
goto end;
|
||||
}
|
||||
@ -390,9 +378,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
size = fread(tmd_u8, 1, wadInfo.tmd_size, f_wad);
|
||||
if (size != wadInfo.tmd_size) {
|
||||
// Read error.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fputs("': Unable to read the TMD.\n", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s': Unable to read the TMD.\n"),
|
||||
wad_filename);
|
||||
ret = 10;
|
||||
goto end;
|
||||
}
|
||||
@ -400,8 +387,10 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
|
||||
// NOTE: Using TMD for most information.
|
||||
_tprintf(_T("%s:\n"), wad_filename);
|
||||
printf("Type: %s\n", s_wad_type);
|
||||
printf("- Title ID: %08X-%08X\n", be32_to_cpu(tmdHeader->title_id.hi), be32_to_cpu(tmdHeader->title_id.lo));
|
||||
_tprintf(_T("Type: %s\n"), s_wad_type);
|
||||
_tprintf(_T("- Title ID: %08X-%08X\n"),
|
||||
be32_to_cpu(tmdHeader->title_id.hi),
|
||||
be32_to_cpu(tmdHeader->title_id.lo));
|
||||
|
||||
// Game ID, but only if all characters are alphanumeric.
|
||||
if (ISALNUM(tmdHeader->title_id.u8[4]) &&
|
||||
@ -409,13 +398,14 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
ISALNUM(tmdHeader->title_id.u8[6]) &&
|
||||
ISALNUM(tmdHeader->title_id.u8[7]))
|
||||
{
|
||||
// TODO: _tprintf()?
|
||||
printf("- Game ID: %.4s\n",
|
||||
(const char*)&tmdHeader->title_id.u8[4]);
|
||||
}
|
||||
|
||||
// Title version
|
||||
title_version = be16_to_cpu(tmdHeader->title_version);
|
||||
printf("- Title version: %u.%u (v%u)\n",
|
||||
_tprintf(_T("- Title version: %u.%u (v%u)\n"),
|
||||
(unsigned int)(title_version >> 8),
|
||||
(unsigned int)(title_version & 0xFF),
|
||||
title_version);
|
||||
@ -428,7 +418,7 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
ios_version = (uint8_t)ios_tid_lo;
|
||||
}
|
||||
}
|
||||
printf("- IOS version: %u\n", ios_version);
|
||||
_tprintf(_T("- IOS version: %u\n"), ios_version);
|
||||
|
||||
// Determine the encryption key in use.
|
||||
issuer_ticket = cert_get_issuer_from_name(ticket->issuer);
|
||||
@ -439,26 +429,26 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
switch (ticket->common_key_index) {
|
||||
case 0:
|
||||
encKey = RVL_KEY_RETAIL;
|
||||
s_encKey = "Retail";
|
||||
s_encKey = _T("Retail");
|
||||
break;
|
||||
case 1:
|
||||
encKey = RVL_KEY_KOREAN;
|
||||
s_encKey = "Korean";
|
||||
s_encKey = _T("Korean");
|
||||
break;
|
||||
case 2:
|
||||
encKey = vWii_KEY_RETAIL;
|
||||
s_encKey = "vWii";
|
||||
s_encKey = _T("vWii");
|
||||
break;
|
||||
default: {
|
||||
// NOTE: A good number of retail WADs have an
|
||||
// incorrect common key index for some reason.
|
||||
if (ticket->title_id.u8[7] == 'K') {
|
||||
s_invalidKey = "Korean";
|
||||
s_encKey = "Korean";
|
||||
s_invalidKey = _T("Korean");
|
||||
s_encKey = _T("Korean");
|
||||
encKey = RVL_KEY_KOREAN;
|
||||
} else {
|
||||
s_invalidKey = "retail";
|
||||
s_encKey = "Retail";
|
||||
s_invalidKey = _T("retail");
|
||||
s_encKey = _T("Retail");
|
||||
encKey = RVL_KEY_RETAIL;
|
||||
}
|
||||
break;
|
||||
@ -472,50 +462,48 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
// FIXME: How to handle invalid indexes?
|
||||
// For now, assume it's the same as debug.
|
||||
encKey = RVL_KEY_DEBUG;
|
||||
s_encKey = "Debug";
|
||||
s_encKey = _T("Debug");
|
||||
break;
|
||||
case 1:
|
||||
encKey = RVL_KEY_KOREAN_DEBUG;
|
||||
s_encKey = "Korean (Debug)";
|
||||
s_encKey = _T("Korean (Debug)");
|
||||
break;
|
||||
case 2:
|
||||
encKey = vWii_KEY_DEBUG;
|
||||
s_encKey = "vWii (Debug)";
|
||||
s_encKey = _T("vWii (Debug)");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
printf("- Encryption: %s\n", s_encKey);
|
||||
_tprintf(_T("- Encryption: %s\n"), s_encKey);
|
||||
|
||||
// Check the ticket issuer and signature.
|
||||
// FIXME: TCHAR version.
|
||||
s_issuer_ticket = issuer_type(issuer_ticket);
|
||||
sig_status_ticket = sig_verify(ticket_u8, wadInfo.ticket_size);
|
||||
printf("- Ticket Signature: %s%s\n",
|
||||
s_issuer_ticket, RVL_SigStatus_toString_stsAppend(sig_status_ticket));
|
||||
|
||||
// Check the TMD issuer and signature.
|
||||
// FIXME: TCHAR version.
|
||||
s_issuer_tmd = issuer_type(cert_get_issuer_from_name(tmdHeader->issuer));
|
||||
sig_status_tmd = sig_verify(tmd_u8, wadInfo.tmd_size);
|
||||
printf("- TMD Signature: %s%s\n",
|
||||
s_issuer_tmd, RVL_SigStatus_toString_stsAppend(sig_status_tmd));
|
||||
|
||||
putchar('\n');
|
||||
_fputtc(_T('\n'), stdout);
|
||||
|
||||
if (wadInfo.ticket_size > sizeof(RVL_Ticket)) {
|
||||
fputs("*** WARNING: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "' ticket size is too big. (%u; should be %u)\n\n",
|
||||
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
_ftprintf(stderr, _T("*** WARNING: WAD file '%s' ticket size is too big. (%u; should be %u)\n\n"),
|
||||
wad_filename, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
}
|
||||
if (s_invalidKey) {
|
||||
// Invalid common key index for retail.
|
||||
// NOTE: A good number of retail WADs have an
|
||||
// incorrect common key index for some reason.
|
||||
fputs("*** WARNING: WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "': Invalid common key index %u.\n",
|
||||
ticket->common_key_index);
|
||||
fprintf(stderr, "*** Assuming %s common key based on game ID.\n\n", s_invalidKey);
|
||||
_ftprintf(stderr, _T("*** WARNING: WAD file '%s': Invalid common key index %u.\n"),
|
||||
wad_filename, ticket->common_key_index);
|
||||
_ftprintf(stderr, _T("*** Assuming %s common key based on game ID.\n\n"), s_invalidKey);
|
||||
}
|
||||
|
||||
// Print the contents.
|
||||
@ -539,15 +527,15 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
// index field in the entry?
|
||||
const uint32_t content_size = (uint32_t)be64_to_cpu(content->size);
|
||||
uint16_t content_index = be16_to_cpu(content->index);
|
||||
printf("#%d: ID=%08x, type=%04X, size=%u",
|
||||
_tprintf(_T("#%d: ID=%08x, type=%04X, size=%u"),
|
||||
content_index,
|
||||
be32_to_cpu(content->content_id),
|
||||
be16_to_cpu(content->type),
|
||||
content_size);
|
||||
if (content_index == boot_index) {
|
||||
fputs(", bootable", stdout);
|
||||
_fputts(_T(", bootable"), stdout);
|
||||
}
|
||||
putchar('\n');
|
||||
_fputtc(_T('\n'), stdout);
|
||||
|
||||
if (verify) {
|
||||
// Verify the content.
|
||||
@ -555,9 +543,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
int vret = verify_content(f_wad, encKey, ticket, content, content_addr);
|
||||
if (vret < 0) {
|
||||
// Read error.
|
||||
fprintf(stderr, "*** ERROR reading content #%d: ", content_index);
|
||||
_fputts(_tcserror(-vret), stderr);
|
||||
putchar('\n');
|
||||
_ftprintf(stderr, _T("*** ERROR reading content #%d: %s\n"),
|
||||
content_index, _tcserror(-vret));
|
||||
ret = 1;
|
||||
} else if (vret > 0) {
|
||||
if (ret == 0 && encKey == vWii_KEY_RETAIL) {
|
||||
@ -565,9 +552,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
vret = verify_content(f_wad, RVL_KEY_RETAIL, ticket, content, content_addr);
|
||||
if (vret < 0) {
|
||||
// Read error.
|
||||
fprintf(stderr, "*** ERROR reading content #%d: ", content_index);
|
||||
_fputts(_tcserror(-vret), stderr);
|
||||
putchar('\n');
|
||||
_ftprintf(stderr, _T("*** ERROR reading content #%d: %s\n"),
|
||||
content_index, _tcserror(-vret));
|
||||
} else if (vret == 0) {
|
||||
vWii_crypt_error = true;
|
||||
}
|
||||
@ -601,9 +587,10 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
}
|
||||
|
||||
if (vWii_crypt_error) {
|
||||
putchar('\n');
|
||||
printf("*** WARNING: This WAD file should be encrypted using the vWii common\n"
|
||||
" key, but it's actually encrypted with the retail common key.\n");
|
||||
_fputtc(_T('\n'), stdout);
|
||||
_fputts(_T("*** WARNING: This WAD file should be encrypted using the vWii common\n")
|
||||
_T(" key, but it's actually encrypted with the retail common key.\n"),
|
||||
stdout);
|
||||
// FIXME: Add a way to fix this and indicate how to fix it.
|
||||
}
|
||||
|
||||
@ -611,12 +598,12 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
|
||||
{
|
||||
const int diff = (int)(data_size_actual - wadInfo.data_size);
|
||||
if (diff != 0) {
|
||||
putchar('\n');
|
||||
printf("*** WARNING: The data size in the WAD header does not match the\n"
|
||||
" actual content data size.\n"
|
||||
" Expected: 0x%08X, actual: 0x%08X (difference: %c0x%0X)\n",
|
||||
wadInfo.data_size, data_size_actual,
|
||||
(diff < 0 ? '-' : '+'), (unsigned int)abs(diff));
|
||||
_fputtc(_T('\n'), stdout);
|
||||
_tprintf(_T("*** WARNING: The data size in the WAD header does not match the\n")
|
||||
_T(" actual content data size.\n")
|
||||
_T(" Expected: 0x%08X, actual: 0x%08X (difference: %c0x%0X)\n"),
|
||||
wadInfo.data_size, data_size_actual,
|
||||
(diff < 0 ? '-' : '+'), (unsigned int)abs(diff));
|
||||
// FIXME: Add a way to fix this and indicate how to fix it.
|
||||
}
|
||||
}
|
||||
@ -641,9 +628,8 @@ int print_wad_info(const TCHAR *wad_filename, bool verify)
|
||||
FILE *f_wad = _tfopen(wad_filename, _T("rb"));
|
||||
if (!f_wad) {
|
||||
int err = errno;
|
||||
fputs("*** ERROR opening WAD file '", stderr);
|
||||
_fputts(wad_filename, stderr);
|
||||
fprintf(stderr, "': %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR opening WAD file '%s': %s"),
|
||||
wad_filename, _tcserror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* RVT-H Tool: WAD Resigner *
|
||||
* print-info.h: Print WAD information. *
|
||||
* *
|
||||
* Copyright (c) 2018-2020 by David Korth. *
|
||||
* Copyright (c) 2018-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
@ -32,7 +32,7 @@ extern "C" {
|
||||
* @param pIsBWF [out] `bool` to store if the WAD file is a BroadOn WAD file or not.
|
||||
* @return WAD file type as a string, or NULL on error.
|
||||
*/
|
||||
const char *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF);
|
||||
const TCHAR *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF);
|
||||
|
||||
/**
|
||||
* 'info' command. (internal function)
|
||||
|
@ -88,7 +88,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
RVL_TMD_Header *tmdHeader;
|
||||
|
||||
// Key names
|
||||
const char *s_fromKey, *s_toKey;
|
||||
const TCHAR *s_fromKey, *s_toKey;
|
||||
|
||||
// Files
|
||||
FILE *f_src_wad = NULL, *f_dest_wad = NULL;
|
||||
@ -141,9 +141,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("*** ERROR reading WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fprintf(stderr, "': %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR reading WAD file '%s': %s\n"),
|
||||
src_wad, _tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -154,9 +153,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
// it's a BroadOn WAD or not.
|
||||
if (identify_wad_type((const uint8_t*)&srcHeader, sizeof(srcHeader), &isSrcBwf) == NULL) {
|
||||
// Unrecognized WAD type.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fputs("' is not valid.\n", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' is not valid."), src_wad);
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
@ -169,49 +166,37 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
}
|
||||
if (ret != 0) {
|
||||
// Unable to get WAD information.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fputs("' is not valid.", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' is not valid."), src_wad);
|
||||
ret = 2;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Verify the various sizes.
|
||||
if (wadInfo.ticket_size < sizeof(RVL_Ticket)) {
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fprintf(stderr, "' ticket size is too small. (%u; should be %u)\n",
|
||||
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ticket size is too small. (%u; should be %u)\n"),
|
||||
src_wad, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
ret = 3;
|
||||
goto end;
|
||||
} else if (wadInfo.ticket_size > WAD_TICKET_SIZE_MAX) {
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fprintf(stderr, "' ticket size is too big. (%u; should be %u)\n",
|
||||
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ticket size is too big. (%u; should be %u)\n"),
|
||||
src_wad, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
|
||||
ret = 4;
|
||||
goto end;
|
||||
} else if (wadInfo.tmd_size < sizeof(RVL_TMD_Header)) {
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fprintf(stderr, "' TMD size is too small. (%u; should be at least %u)\n",
|
||||
wadInfo.tmd_size, (uint32_t)sizeof(RVL_TMD_Header));
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' TMD size is too small. (%u; should be at least %u)\n"),
|
||||
src_wad, wadInfo.tmd_size, (uint32_t)sizeof(RVL_TMD_Header));
|
||||
ret = 5;
|
||||
goto end;
|
||||
} else if (wadInfo.tmd_size > WAD_TMD_SIZE_MAX) {
|
||||
// Too big.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fprintf(stderr, "' TMD size is too big. (%u; should be less than 1 MB)\n",
|
||||
wadInfo.tmd_size);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' TMD size is too big. (%u; should be less than 1 MiB)\n"),
|
||||
src_wad, wadInfo.tmd_size);
|
||||
ret = 6;
|
||||
goto end;
|
||||
} else if (wadInfo.meta_size > WAD_META_SIZE_MAX) {
|
||||
// Too big.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fprintf(stderr, "' metadata size is too big. (%u; should be less than 1 MB)\n",
|
||||
wadInfo.meta_size);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ' metadata size is too big. (%u; should be less than 1 MB)\n"),
|
||||
src_wad, wadInfo.meta_size);
|
||||
ret = 7;
|
||||
goto end;
|
||||
}
|
||||
@ -223,9 +208,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
// Data size is the rest of the file.
|
||||
if (src_file_size < wadInfo.data_address) {
|
||||
// Not valid...
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fputs("' data size is invalid.\n", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' data size is invalid.\n"), src_wad);
|
||||
ret = 8;
|
||||
goto end;
|
||||
}
|
||||
@ -234,16 +217,12 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
// Verify the data size.
|
||||
if (src_file_size < wadInfo.data_address) {
|
||||
// File is too small.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fputs("' data address is invalid.\n", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' data address is invalid.\n"), src_wad);
|
||||
ret = 9;
|
||||
goto end;
|
||||
} else if (src_file_size - wadInfo.data_address < wadInfo.data_size) {
|
||||
// Data size is too small.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fputs("' data size is invalid.\n", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' data size is invalid.\n"), src_wad);
|
||||
ret = 10;
|
||||
goto end;
|
||||
}
|
||||
@ -253,10 +232,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
|
||||
if (wadInfo.data_size > WAD_DATA_SIZE_MAX) {
|
||||
// Maximum of 128 MB.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fprintf(stderr, "' data size is too big. (%u; should be less than 128 MB)\n",
|
||||
wadInfo.data_size);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' data size is too big. (%u; should be less than 128 MiB)\n"),
|
||||
src_wad, wadInfo.data_size);
|
||||
ret = 11;
|
||||
goto end;
|
||||
}
|
||||
@ -266,9 +243,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
size = fread(buf->u8, 1, wadInfo.ticket_size, f_src_wad);
|
||||
if (size != wadInfo.ticket_size) {
|
||||
// Read error.
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fputs("': Unable to read the ticket.\n", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s': Unable to read the ticket.\n"), src_wad);
|
||||
ret = 13;
|
||||
goto end;
|
||||
}
|
||||
@ -280,15 +255,15 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
switch (buf->ticket.common_key_index) {
|
||||
case 0:
|
||||
src_key = RVL_CryptoType_Retail;
|
||||
s_fromKey = "retail";
|
||||
s_fromKey = _T("retail");
|
||||
break;
|
||||
case 1:
|
||||
src_key = RVL_CryptoType_Korean;
|
||||
s_fromKey = "Korean";
|
||||
s_fromKey = _T("Korean");
|
||||
break;
|
||||
case 2:
|
||||
src_key = RVL_CryptoType_vWii;
|
||||
s_fromKey = "vWii";
|
||||
s_fromKey = _T("vWii");
|
||||
break;
|
||||
default: {
|
||||
// NOTE: A good number of retail WADs have an
|
||||
@ -297,10 +272,10 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
// print_wad_info(), so don't print one here.
|
||||
if (buf->ticket.title_id.u8[7] == 'K') {
|
||||
src_key = RVL_CryptoType_Korean;
|
||||
s_fromKey = "Korean";
|
||||
s_fromKey = _T("Korean");
|
||||
} else {
|
||||
src_key = RVL_CryptoType_Retail;
|
||||
s_fromKey = "retail";
|
||||
s_fromKey = _T("retail");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -308,12 +283,10 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
break;
|
||||
case RVL_CERT_ISSUER_DPKI_TICKET:
|
||||
src_key = RVL_CryptoType_Debug;
|
||||
s_fromKey = "debug";
|
||||
s_fromKey = _T("debug");
|
||||
break;
|
||||
default:
|
||||
fputs("*** ERROR: WAD file '", stderr);
|
||||
_fputts(src_wad, stderr);
|
||||
fputs("': Unknown issuer.\n", stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR: WAD file '%s': Unknown issuer.\n"), src_wad);
|
||||
ret = 14;
|
||||
goto end;
|
||||
}
|
||||
@ -335,7 +308,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
default:
|
||||
// Should not happen...
|
||||
assert(!"src_key: Invalid cryptoType.");
|
||||
fputs("*** ERROR: Unable to select encryption key.\n", stderr);
|
||||
_fputts(_T("*** ERROR: Unable to select encryption key.\n"), stderr);
|
||||
ret = 15;
|
||||
goto end;
|
||||
}
|
||||
@ -362,7 +335,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
// Allow the same key only if converting to a different format.
|
||||
if (isSrcBwf == isDestBwf) {
|
||||
// No point in recrypting to the same key and format...
|
||||
fputs("*** ERROR: Cannot recrypt to the same key and format.\n", stderr);
|
||||
_fputts(_T("*** ERROR: Cannot recrypt to the same key and format.\n"), stderr);
|
||||
ret = 16;
|
||||
goto end;
|
||||
}
|
||||
@ -372,37 +345,36 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
switch (recrypt_key) {
|
||||
case RVL_CryptoType_Debug:
|
||||
toKey = RVL_KEY_DEBUG;
|
||||
s_toKey = "debug (realsigned)";
|
||||
s_toKey = _T("debug (realsigned)");
|
||||
break;
|
||||
case RVL_CryptoType_Retail:
|
||||
toKey = RVL_KEY_RETAIL;
|
||||
s_toKey = "retail (fakesigned)";
|
||||
s_toKey = _T("retail (fakesigned)");
|
||||
break;
|
||||
case RVL_CryptoType_Korean:
|
||||
// TODO: Add RVL_CryptoType_Korean_Debug?
|
||||
toKey = RVL_KEY_KOREAN;
|
||||
s_toKey = "Korean (fakesigned)";
|
||||
s_toKey = _T("Korean (fakesigned)");
|
||||
break;
|
||||
case RVL_CryptoType_vWii:
|
||||
// TODO: Add RVL_CryptoType_vWii_Debug?
|
||||
toKey = vWii_KEY_RETAIL;
|
||||
s_toKey = "vWii (fakesigned)";
|
||||
s_toKey = _T("vWii (fakesigned)");
|
||||
break;
|
||||
default:
|
||||
// Invalid key index.
|
||||
// This should not happen...
|
||||
assert(!"recrypt_key: Invalid key index.");
|
||||
fputs("*** ERROR: Invalid recrypt_key value.\n", stderr);
|
||||
_fputts(_T("*** ERROR: Invalid recrypt_key value.\n"), stderr);
|
||||
ret = 17;
|
||||
goto end;
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
printf("Converting from %s to %s [", s_fromKey, s_toKey);
|
||||
fputs(isSrcBwf ? "bwf" : "wad", stdout);
|
||||
fputs("->", stdout);
|
||||
fputs(isDestBwf ? "bwf" : "wad", stdout);
|
||||
fputs("]...\n", stdout);
|
||||
_fputtc(_T('\n'), stdout);
|
||||
_tprintf(_T("Converting from %s to %s [%s->%s]...\n"),
|
||||
s_fromKey, s_toKey,
|
||||
isSrcBwf ? _T("bwf") : _T("wad"),
|
||||
isDestBwf ? _T("bwf") : _T("wad"));
|
||||
|
||||
// Open the destination WAD file.
|
||||
errno = 0;
|
||||
@ -412,9 +384,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("*** ERROR opening destination WAD file '", stderr);
|
||||
_fputts(dest_wad, stderr);
|
||||
fprintf(stderr, "' for write: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR opening destination WAD file '%s' for write: %s\n"),
|
||||
dest_wad, _tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -459,7 +430,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (isSrcBwf) {
|
||||
if (!isDestBwf) {
|
||||
// bwf->wad
|
||||
printf("Converting the BroadOn WAD header to standard WAD format...\n");
|
||||
_tprintf(_T("Converting the BroadOn WAD header to standard WAD format...\n"));
|
||||
data_offset = 0;
|
||||
|
||||
// Type is 'Is' for most WADs, 'ib' for boot2.
|
||||
@ -493,7 +464,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
} else /*if (!isSrcBwf)*/ {
|
||||
if (isDestBwf) {
|
||||
// wad->bwf
|
||||
printf("Converting the standard WAD header to BroadOn WAD format...\n");
|
||||
_tprintf(_T("Converting the standard WAD header to BroadOn WAD format...\n"));
|
||||
|
||||
outHeader.bwf.header_size = cpu_to_be32(sizeof(outHeader));
|
||||
outHeader.bwf.data_offset = cpu_to_be32(data_offset);
|
||||
@ -519,7 +490,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR writing initial destination WAD header: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR writing initial destination WAD header: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -530,7 +502,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
}
|
||||
|
||||
// Write the certificates.
|
||||
printf("Writing certificate chain...\n");
|
||||
_tprintf(_T("Writing certificate chain...\n"));
|
||||
errno = 0;
|
||||
size = fwrite(cert_CA, 1, sizeof(*cert_CA), f_dest_wad);
|
||||
if (size != sizeof(*cert_CA)) {
|
||||
@ -538,7 +510,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR writing destination WAD certificate chain: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD certificate chain: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -549,7 +522,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR writing destination WAD certificate chain: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD certificate chain: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -560,7 +534,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR writing destination WAD certificate chain: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD certificate chain: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -572,7 +547,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR writing destination WAD certificate chain: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD certificate chain: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -588,7 +564,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
assert(wadInfo.crl_size == 0);
|
||||
|
||||
// Recrypt the ticket and TMD.
|
||||
printf("Recrypting the ticket and TMD...\n");
|
||||
_tprintf(_T("Recrypting the ticket and TMD...\n"));
|
||||
|
||||
// Ticket is already loaded, so recrypt and resign it.
|
||||
errno = 0;
|
||||
@ -599,7 +575,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR recrypting the ticket: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR recrypting the ticket: %s\n"), _tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -623,7 +599,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR writing destination WAD ticket: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD ticket: %s\n"), _tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -643,7 +619,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR reading source WAD TMD: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR reading source WAD TMD: %s\n"), _tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -684,7 +660,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR writing destination WAD TMD: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD TMD: %s\n"), _tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -702,7 +678,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR seeking in destination WAD: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR seeking in destination WAD: %s\n"), _tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -719,7 +695,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
const uint32_t content_size = (uint32_t)be64_to_cpu(content->size);
|
||||
uint32_t size_to_copy = ALIGN_BYTES(16, content_size);
|
||||
uint16_t content_index = be16_to_cpu(content->index);
|
||||
printf("Copying WAD content #%d...\n", content_index);
|
||||
_tprintf(_T("Copying WAD content #%d...\n"), content_index);
|
||||
|
||||
// Contents are always physically AES-aligned (16 bytes), but the
|
||||
// data size in the header does not include extra bytes at the end
|
||||
@ -750,7 +726,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR reading source WAD data: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR reading source WAD data: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -762,7 +739,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR writing destination WAD data: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD data: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -777,7 +755,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fprintf(stderr, "*** ERROR reading source WAD data: %s\n", strerror(err));
|
||||
_ftprintf(stderr, _T("*** ERROR reading source WAD data: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -789,9 +768,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("*** ERROR writing destination WAD data: ", stderr);
|
||||
_fputts(_tcserror(err), stderr);
|
||||
fputc('\n', stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD data: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -801,7 +779,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
// Copy the metadata.
|
||||
// FIXME: Copy before the data if the output format is BWF.
|
||||
if (wadInfo.meta_size != 0) {
|
||||
printf("Copying the WAD metadata...\n");
|
||||
_tprintf(_T("Copying the WAD metadata...\n"));
|
||||
|
||||
fseeko(f_src_wad, wadInfo.meta_address, SEEK_SET);
|
||||
errno = 0;
|
||||
@ -811,9 +789,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("*** ERROR reading source WAD metadata: ", stderr);
|
||||
_fputts(_tcserror(err), stderr);
|
||||
fputc('\n', stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR reading source WAD metadata: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -830,9 +807,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("*** ERROR writing destination WAD metadata: ", stderr);
|
||||
_fputts(_tcserror(err), stderr);
|
||||
fputc('\n', stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD metadata: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -858,9 +834,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("*** ERROR writing destination WAD padding: ", stderr);
|
||||
_fputts(_tcserror(err), stderr);
|
||||
fputc('\n', stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD padding: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
@ -869,8 +844,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
|
||||
// Do we need to update the data size?
|
||||
if (likely(!isDestBwf) && unlikely(wadInfo.data_size != data_size_actual)) {
|
||||
fprintf(stderr, "*** Fixing WAD header's data size field:\n"
|
||||
" Old: 0x%08X, New: 0x%08X\n",
|
||||
_ftprintf(stderr, _T("*** Fixing WAD header's data size field:\n")
|
||||
_T(" Old: 0x%08X, New: 0x%08X\n"),
|
||||
wadInfo.data_size, data_size_actual);
|
||||
outHeader.wad.data_size = cpu_to_be32(data_size_actual);
|
||||
}
|
||||
@ -884,14 +859,13 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
|
||||
if (err == 0) {
|
||||
err = EIO;
|
||||
}
|
||||
fputs("*** ERROR writing destination WAD header: ", stderr);
|
||||
_fputts(_tcserror(err), stderr);
|
||||
fputc('\n', stderr);
|
||||
_ftprintf(stderr, _T("*** ERROR writing destination WAD header: %s\n"),
|
||||
_tcserror(err));
|
||||
ret = -err;
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("WAD resigning complete.\n");
|
||||
_tprintf(_T("WAD resigning complete.\n"));
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
|
Loading…
Reference in New Issue
Block a user