int SetMediaSize(u8 *mediaSize, cci_settings *set) { char *str = set->rsf->CardInfo.MediaSize; if(!str) set->romInfo.mediaSize = (u64)GB*2; else{ if(strcasecmp(str,"128MB") == 0) set->romInfo.mediaSize = (u64)MB*128; else if(strcasecmp(str,"256MB") == 0) set->romInfo.mediaSize = (u64)MB*256; else if(strcasecmp(str,"512MB") == 0) set->romInfo.mediaSize = (u64)MB*512; else if(strcasecmp(str,"1GB") == 0) set->romInfo.mediaSize = (u64)GB*1; else if(strcasecmp(str,"2GB") == 0) set->romInfo.mediaSize = (u64)GB*2; else if(strcasecmp(str,"4GB") == 0) set->romInfo.mediaSize = (u64)GB*4; else if(strcasecmp(str,"8GB") == 0) set->romInfo.mediaSize = (u64)GB*8; //else if(strcasecmp(str,"16GB") == 0) set->romInfo.mediaSize = (u64)GB*16; //else if(strcasecmp(str,"32GB") == 0) set->romInfo.mediaSize = (u64)GB*32; else { fprintf(stderr,"[CCI ERROR] Invalid MediaSize: %s\n",str); return INVALID_RSF_OPT; } } u32_to_u8(mediaSize,(set->romInfo.mediaSize/set->romInfo.blockSize),LE); return 0; }
int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff) { for(int i = 0; i < ctx->fileCount; i++){ if(i == 0) ctx->fileOffset[i] = 0; else ctx->fileOffset[i] = align((ctx->fileOffset[i-1]+ctx->fileSize[i-1]),ctx->blockSize); memcpy(ctx->fileHdr[i].name,ctx->fileName[i],8); u32_to_u8(ctx->fileHdr[i].offset,ctx->fileOffset[i],LE); u32_to_u8(ctx->fileHdr[i].size,ctx->fileSize[i],LE); ctr_sha(ctx->file[i],ctx->fileSize[i],ctx->fileHashes[9-i],CTR_SHA_256); } memcpy(outbuff,ctx->fileHdr,sizeof(exefs_filehdr)*10); memcpy(outbuff+0xc0,ctx->fileHashes,0x20*10); return 0; }
int GenerateTicket(USER_CONTEXT *ctx) { if(ctx->flags[verbose]) { printf("[+] Generating Ticket\n"); } ctx->cia_section[tik].size = (sizeof(TICKET_STRUCTURE)+ sizeof(TIK_2048_SIG_CONTEXT)); ctx->cia_section[tik].buffer = malloc(ctx->cia_section[tik].size); if(ctx->cia_section[tik].buffer == NULL){ printf("[!] Failed to allocated memory for ticket\n"); return 1; } TICKET_STRUCTURE ticket; TIK_2048_SIG_CONTEXT sig; memset(&sig,0x0,sizeof(TIK_2048_SIG_CONTEXT)); memset(&ticket,0x0,sizeof(TICKET_STRUCTURE)); if(ctx->flags[verbose]) { printf(" > Collecting Data\n"); } ticket.TicketFormatVersion = ctx->core.ticket_format_ver; ticket.ca_crl_version = ctx->core.ca_crl_version; ticket.signer_crl_version = ctx->core.signer_crl_version; ticket.CommonKeyID = ctx->keys.common_key_id; memcpy(ticket.Issuer,ctx->core.TicketIssuer,0x40); memcpy(ticket.TicketID,ctx->core.TicketID,0x8); memcpy(ticket.DeviceID,ctx->core.DeviceID,0x4); memcpy(ticket.TitleID,ctx->core.TitleID,0x8); memcpy(ticket.TicketVersion,ctx->core.TicketVersion,0x2); if(ctx->flags[verbose]) { printf(" > Encrypting Titlekey\n"); } if(EncryptTitleKey(ticket.EncryptedTitleKey,ctx->keys.title_key,ctx->keys.common_key,ctx->core.TitleID) != 0){ printf("[!] Failed to encrypt titlekey\n"); return Fail; } if(ctx->flags[showkeys]) memdump(stdout,"\n[+] Encrypted Title Key: ",ticket.EncryptedTitleKey,0x10); if(SetStaticData(dev,ticket.StaticData) != 0){ printf("[!] ERROR in Generating Ticket\n"); return Fail; } if(ctx->flags[verbose]) { printf(" > Signing Ticket\n"); } u32_to_u8(sig.sig_type,RSA_2048_SHA256,BE); u8 hash[0x20]; ctr_sha(&ticket,sizeof(TICKET_STRUCTURE),hash,CTR_SHA_256); if(ctr_rsa(hash,sig.data,ctx->keys.ticket.n,ctx->keys.ticket.d,RSA_2048_SHA256,CTR_RSA_SIGN) != Good){ printf("[!] Failed to sign ticket\n"); return ticket_gen_fail; } if(ctx->flags[info]){ memdump(stdout,"[+] Ticket Signature: ",sig.data,0x100); } memcpy(ctx->cia_section[tik].buffer,&sig,sizeof(TIK_2048_SIG_CONTEXT)); memcpy((ctx->cia_section[tik].buffer + sizeof(TIK_2048_SIG_CONTEXT)),&ticket,sizeof(TICKET_STRUCTURE)); return 0; }
static char * print_chars(const widechar *buffer, int length) { static uint8_t result_buf[BUFSIZE]; size_t result_len = BUFSIZE - 1; #ifdef WIDECHARS_ARE_UCS4 u32_to_u8(buffer, length, result_buf, &result_len); #else u16_to_u8(buffer, length, result_buf, &result_len); #endif result_buf[result_len] = 0; return result_buf; }
int SetupTMDContentRecord(u8 *content_record, cia_settings *ciaset) { for(int i = 0; i < ciaset->content.count; i++){ tmd_content_chunk *ptr = (tmd_content_chunk*)(content_record+sizeof(tmd_content_chunk)*i); u32_to_u8(ptr->contentID,ciaset->content.id[i],BE); u16_to_u8(ptr->contentIndex,ciaset->content.index[i],BE); u16_to_u8(ptr->contentFlags,ciaset->content.flags[i],BE); u64_to_u8(ptr->contentSize,ciaset->content.size[i],BE); memcpy(ptr->contentHash,ciaset->content.hash[i],0x20); } return 0; }
int SetCardInfoNotes(cardinfo_hdr *hdr, cci_settings *set) { u64_to_u8(hdr->notes.mediaSizeUsed,set->romInfo.usedSize,LE); u32_to_u8(hdr->notes.unknown,0,LE); if(set->options.tmdHdr){ u64_to_u8(hdr->notes.cverTitleId,GetTmdTitleId(set->options.tmdHdr),LE); u16_to_u8(hdr->notes.cverTitleId,GetTmdVersion(set->options.tmdHdr),LE); } return 0; }
int SetWriteableAddress(cardinfo_hdr *hdr, cci_settings *set) { if(set->romInfo.mediaType != mediatype_CARD2){ // Can only be set for Card2 Media u32_to_u8(hdr->writableAddress,(u32)-1,LE); return 0; } char *str = set->rsf->CardInfo.WritableAddress; set->romInfo.card2SaveOffset = -1; if(str){ if(strncmp(str,"0x",2) != 0){ fprintf(stderr,"[CCI ERROR] WritableAddress requires a Hexadecimal value\n"); return INVALID_RSF_OPT; } set->romInfo.card2SaveOffset = strtoull(str,NULL,16); } else{ if ((set->romInfo.mediaSize / 2) < set->romInfo.saveSize || set->romInfo.saveSize > (u64)(2047*MB)){ u64 saveDataSize = set->romInfo.saveSize / KB; fprintf(stderr,"[CCI ERROR] Too large SavedataSize %"PRIu64"K\n",saveDataSize); return SAVE_DATA_TOO_LARGE; } if(set->options.closeAlignWR) set->romInfo.card2SaveOffset = align(set->romInfo.usedSize, set->romInfo.blockSize); // invalid for "real" chips else{ u64 unusedSize = GetCciUnusedSize(set->romInfo.mediaSize,set->romInfo.mediaType); // Some value related to the physical implementation of gamecards if(unusedSize > 0) set->romInfo.card2SaveOffset = set->romInfo.mediaSize - unusedSize - set->romInfo.saveSize; // Nintendo's method for calculating writable region offset else{ fprintf(stderr,"[CCI WARNING] Nintendo does not support CARD2 for the current MediaSize, aligning save offset after last NCCH\n"); set->romInfo.card2SaveOffset = align(set->romInfo.usedSize, set->romInfo.blockSize); // invalid for "real" chips } } } u32_to_u8(hdr->writableAddress,(u32)(set->romInfo.card2SaveOffset/set->romInfo.blockSize),LE); return 0; }
static void print_widechars(widechar *buffer, int length) { uint8_t *result_buf; size_t result_len; #ifdef WIDECHARS_ARE_UCS4 result_buf = u32_to_u8(buffer, length, NULL, &result_len); #else result_buf = u16_to_u8(buffer, length, NULL, &result_len); #endif fprintf(stderr, "%.*s", (int)result_len, result_buf); free(result_buf); }
void SetCciNcchInfo(cci_hdr *hdr, cci_settings *set) { u64 ncchSize,ncchOffset; ncchOffset = NCCH0_OFFSET; for(int i = 0; i < CCI_MAX_CONTENT; i++){ if(set->content.active[i]){ set->content.cOffset[i] = ncchOffset; ncchSize = align(set->content.dSize[i],set->romInfo.blockSize); u32_to_u8(hdr->offset_sizeTable[i].offset,(ncchOffset/set->romInfo.blockSize),LE); u32_to_u8(hdr->offset_sizeTable[i].size,(ncchSize/set->romInfo.blockSize),LE); u64_to_u8(hdr->ncchIdTable[i],set->content.titleId[i],LE); ncchOffset += ncchSize; } } set->romInfo.usedSize = ncchOffset; return; }
int SetCardInfoBitmask(cardinfo_hdr *hdr, cci_settings *set) { u32 bitmask = 0; char *str = set->rsf->CardInfo.CardType; if(!str) bitmask |= 0; else{ if(strcasecmp(str,"s1") == 0) bitmask |= 0; else if(strcasecmp(str,"s2") == 0) bitmask |= 0x20; else { fprintf(stderr,"[CCI ERROR] Invalid CardType: %s\n",str); return INVALID_RSF_OPT; } } str = set->rsf->CardInfo.CryptoType; if(!str) { if(set->options.useExternalSdkCardInfo) bitmask |= (3*0x40); else bitmask |= 0; } else{ int val = strtol(str,NULL,10); if(val < 0 || val > 3) { fprintf(stderr,"[CCI ERROR] Invalid CryptoType: %s\n",str); return INVALID_RSF_OPT; } if(val != 3) fprintf(stderr,"[CCI WARNING] Card crypto type = '%d'\n",val); bitmask |= val * 0x40; } u32_to_u8(hdr->cardInfoBitmask,bitmask,BE); return 0; }
int main(int argc, char **argv) { uint8_t *charbuf; size_t charlen; widechar inbuf[BUFSIZE]; widechar transbuf[BUFSIZE]; widechar outbuf[BUFSIZE]; int outputPos[BUFSIZE]; int inputPos[BUFSIZE]; int inlen; int translen; int outlen; int cursorPos = -1; int realInlen = 0; int optc; set_program_name(argv[0]); while ((optc = getopt_long(argc, argv, "hv", longopts, NULL)) != -1) { switch (optc) { /* --help and --version exit immediately, per GNU coding standards. */ case 'v': version_etc( stdout, program_name, PACKAGE_NAME, VERSION, AUTHORS, (char *)NULL); exit(EXIT_SUCCESS); break; case 'h': print_help(); exit(EXIT_SUCCESS); break; default: fprintf(stderr, "Try `%s --help' for more information.\n", program_name); exit(EXIT_FAILURE); break; } } if (optind < argc) { /* Print error message and exit. */ fprintf(stderr, "%s: extra operand: %s\n", program_name, argv[optind]); fprintf(stderr, "Try `%s --help' for more information.\n", program_name); exit(EXIT_FAILURE); } validTable = NULL; enteredCursorPos = -1; mode = 0; while (1) { getCommands(); printf("Type something, press enter, and view the results.\n"); printf("A blank line returns to command entry.\n"); if (minimalist) while (1) { translen = outputSize; outlen = outputSize; inlen = getInput(); if (inlen == 0) break; if (!(realInlen = _lou_extParseChars(inputBuffer, inbuf))) break; inlen = realInlen; if (!lou_translateString( table, inbuf, &inlen, transbuf, &translen, NULL, NULL, 0)) break; transbuf[translen] = 0; printf("Translation:\n"); #ifdef WIDECHARS_ARE_UCS4 charbuf = u32_to_u8(transbuf, translen, NULL, &charlen); #else charbuf = u16_to_u8(transbuf, translen, NULL, &charlen); #endif printf("%.*s\n", (int)charlen, charbuf); free(charbuf); if (showSizes) printf("input length = %d; output length = %d\n", inlen, translen); lou_backTranslateString( table, transbuf, &translen, outbuf, &outlen, NULL, NULL, 0); printf("Back-translation:\n"); #ifdef WIDECHARS_ARE_UCS4 charbuf = u32_to_u8(outbuf, outlen, NULL, &charlen); #else charbuf = u16_to_u8(outbuf, outlen, NULL, &charlen); #endif printf("%.*s\n", (int)charlen, charbuf); free(charbuf); if (showSizes) printf("input length = %d; output length = %d.\n", translen, outlen); if (outlen == realInlen) { int k; for (k = 0; k < realInlen; k++) if (inbuf[k] != outbuf[k]) break; if (k == realInlen) printf("Perfect roundtrip!\n"); } } else while (1) { memset(emphasis, 0, sizeof(formtype) * BUFSIZE); { size_t k = 0; for (k = 0; k < strlen(enteredEmphasis); k++) emphasis[k] = (formtype)enteredEmphasis[k] - '0'; emphasis[k] = 0; } strcpy(spacing, enteredSpacing); cursorPos = enteredCursorPos; inlen = getInput(); if (inlen == 0) break; outlen = outputSize; if (backOnly) { if (!(translen = _lou_extParseChars(inputBuffer, transbuf))) break; inlen = realInlen; } else { translen = outputSize; if (!(realInlen = _lou_extParseChars(inputBuffer, inbuf))) break; inlen = realInlen; if (!lou_translate(table, inbuf, &inlen, transbuf, &translen, emphasis, spacing, &outputPos[0], &inputPos[0], &cursorPos, mode)) break; transbuf[translen] = 0; if (mode & dotsIO) { printf("Translation dot patterns:\n"); printf("%s\n", _lou_showDots(transbuf, translen)); } else { printf("Translation:\n"); #ifdef WIDECHARS_ARE_UCS4 charbuf = u32_to_u8(transbuf, translen, NULL, &charlen); #else charbuf = u16_to_u8(transbuf, translen, NULL, &charlen); #endif printf("%.*s\n", (int)charlen, charbuf); free(charbuf); if (showSizes) printf("input length = %d; output length = %d\n", inlen, translen); } } if (cursorPos != -1) printf("Cursor position: %d\n", cursorPos); if (enteredSpacing[0]) printf("Returned spacing: %s\n", spacing); if (showPositions) { printf("Output positions:\n"); for (int k = 0; k < inlen; k++) printf("%d ", outputPos[k]); printf("\n"); printf("Input positions:\n"); for (int k = 0; k < translen; k++) printf("%d ", inputPos[k]); printf("\n"); } if (!forwardOnly) { if (!lou_backTranslate(table, transbuf, &translen, outbuf, &outlen, emphasis, spacing, &outputPos[0], &inputPos[0], &cursorPos, mode)) break; printf("Back-translation:\n"); #ifdef WIDECHARS_ARE_UCS4 charbuf = u32_to_u8(outbuf, outlen, NULL, &charlen); #else charbuf = u16_to_u8(outbuf, outlen, NULL, &charlen); #endif printf("%.*s\n", (int)charlen, charbuf); free(charbuf); if (showSizes) printf("input length = %d; output length = %d\n", translen, outlen); if (cursorPos != -1) printf("Cursor position: %d\n", cursorPos); if (enteredSpacing[0]) printf("Returned spacing: %s\n", spacing); if (showPositions) { printf("Output positions:\n"); for (int k = 0; k < translen; k++) printf("%d ", outputPos[k]); printf("\n"); printf("Input positions:\n"); for (int k = 0; k < outlen; k++) printf("%d ", inputPos[k]); printf("\n"); } } if (!(forwardOnly || backOnly)) { if (outlen == realInlen) { int k; for (k = 0; k < realInlen; k++) if (inbuf[k] != outbuf[k]) break; if (k == realInlen) printf("Perfect roundtrip!\n"); } } } } lou_free(); exit(EXIT_SUCCESS); }
int SetupNcch(ncch_settings *set, romfs_buildctx *romfs) { u64 ncchSize = 0; u64 exhdrSize,acexSize,logoSize,plnRgnSize,exefsSize,romfsSize; u64 exhdrOffset,acexOffset,logoOffset,plnRgnOffset,exefsOffset,romfsOffset; u32 exefsHashSize,romfsHashSize; ncchSize += sizeof(ncch_hdr); // Sig+Hdr // Sizes for NCCH hdr if(set->sections.exhdr.size){ exhdrSize = set->sections.exhdr.size; exhdrOffset = ncchSize; ncchSize += exhdrSize; } else exhdrSize = 0; if(set->sections.acexDesc.size){ acexSize = set->sections.acexDesc.size; acexOffset = ncchSize; ncchSize += acexSize; } else acexSize = 0; if(set->sections.logo.size){ logoSize = set->sections.logo.size; logoOffset = align(ncchSize,set->options.blockSize); ncchSize = logoOffset + logoSize; } else logoSize = 0; if(set->sections.plainRegion.size){ plnRgnSize = align(set->sections.plainRegion.size,set->options.blockSize); plnRgnOffset = align(ncchSize,set->options.blockSize); ncchSize = plnRgnOffset + plnRgnSize; } else plnRgnSize = 0; if(set->sections.exeFs.size){ exefsHashSize = align(sizeof(exefs_hdr),set->options.blockSize); exefsSize = align(set->sections.exeFs.size,set->options.blockSize); exefsOffset = align(ncchSize,set->options.blockSize); ncchSize = exefsOffset + exefsSize; } else exefsSize = 0; if(romfs->romfsSize){ romfsHashSize = align(romfs->romfsHeaderSize,set->options.blockSize); romfsSize = align(romfs->romfsSize,set->options.blockSize); //romfsOffset = align(ncchSize,set->options.blockSize); // Old makerom method, SDK 2.x and prior romfsOffset = align(ncchSize,0x1000); ncchSize = romfsOffset + romfsSize; } else romfsSize = 0; // Aligning Total NCCH Size ncchSize = align(ncchSize,set->options.blockSize); u8 *ncch = calloc(1,ncchSize); if(!ncch){ fprintf(stderr,"[NCCH ERROR] Not enough memory\n"); return MEM_ERROR; } // Setting up hdr\n"); ncch_hdr *hdr = (ncch_hdr*)ncch; int ret = SetCommonHeaderBasicData(set,hdr); if(ret != 0){ free(ncch); return ret; } u32_to_u8(hdr->ncchSize,ncchSize/set->options.blockSize,LE); // Copy already built sections to ncch if(exhdrSize){ memcpy((u8*)(ncch+exhdrOffset),set->sections.exhdr.buffer,set->sections.exhdr.size); free(set->sections.exhdr.buffer); set->sections.exhdr.buffer = NULL; u32_to_u8(hdr->exhdrSize,exhdrSize,LE); } if(acexSize){ memcpy((u8*)(ncch+acexOffset),set->sections.acexDesc.buffer,set->sections.acexDesc.size); free(set->sections.acexDesc.buffer); set->sections.acexDesc.buffer = NULL; } if(logoSize){ memcpy((u8*)(ncch+logoOffset),set->sections.logo.buffer,set->sections.logo.size); free(set->sections.logo.buffer); set->sections.logo.buffer = NULL; u32_to_u8(hdr->logoOffset,logoOffset/set->options.blockSize,LE); u32_to_u8(hdr->logoSize,logoSize/set->options.blockSize,LE); } if(plnRgnSize){ memcpy((u8*)(ncch+plnRgnOffset),set->sections.plainRegion.buffer,set->sections.plainRegion.size); free(set->sections.plainRegion.buffer); set->sections.plainRegion.buffer = NULL; u32_to_u8(hdr->plainRegionOffset,plnRgnOffset/set->options.blockSize,LE); u32_to_u8(hdr->plainRegionSize,plnRgnSize/set->options.blockSize,LE); } if(exefsSize){ memcpy((u8*)(ncch+exefsOffset),set->sections.exeFs.buffer,set->sections.exeFs.size); free(set->sections.exeFs.buffer); set->sections.exeFs.buffer = NULL; u32_to_u8(hdr->exefsOffset,exefsOffset/set->options.blockSize,LE); u32_to_u8(hdr->exefsSize,exefsSize/set->options.blockSize,LE); u32_to_u8(hdr->exefsHashSize,exefsHashSize/set->options.blockSize,LE); } // Point Romfs CTX to output buffer, if exists\n"); if(romfsSize){ romfs->output = ncch + romfsOffset; u32_to_u8(hdr->romfsOffset,romfsOffset/set->options.blockSize,LE); u32_to_u8(hdr->romfsSize,romfsSize/set->options.blockSize,LE); u32_to_u8(hdr->romfsHashSize,romfsHashSize/set->options.blockSize,LE); } set->out->buffer = ncch; set->out->size = ncchSize; GetNcchInfo(&set->cryptoDetails,hdr); return 0; }
int check_base(const char *tableList, const char *input, const char *expected, optional_test_params in) { int i, retval = 0; int direction = in.direction; const int *expected_inputPos = in.expected_inputPos; const int *expected_outputPos = in.expected_outputPos; if (in.direction < 0 || in.direction > 2) { fprintf(stderr, "Invalid direction.\n"); return 1; } if (in.direction != 0 && in.typeform != NULL) { // Currently, in backward translation, nothing is done with the initial value of // the typeform argument, and on return it always contains all zeros, so it // doesn't make any sense to use typeforms in backward translation tests. fprintf(stderr, "typeforms only supported with testmode 'forward'\n"); return 1; } if (in.direction == 2 && in.cursorPos >= 0) { fprintf(stderr, "cursorPos not supported with testmode 'bothDirections'\n"); return 1; } if (in.direction == 2 && in.max_outlen >= 0) { fprintf(stderr, "maxOutputLength not supported with testmode 'bothDirections'\n"); return 1; } if (in.real_inlen >= 0 && in.max_outlen < 0) { fprintf(stderr, "realInputLength not supported when maxOutputLength is not specified\n"); return 1; } while (1) { widechar *inbuf, *outbuf, *expectedbuf; int inlen = strlen(input); int actualInlen; const int outlen_multiplier = 4 + sizeof(widechar) * 2; int outlen = inlen * outlen_multiplier; int expectedlen = strlen(expected); int funcStatus = 0; formtype *typeformbuf = NULL; int *inputPos = NULL; int *outputPos = NULL; int cursorPos = 0; inbuf = malloc(sizeof(widechar) * inlen); outbuf = malloc(sizeof(widechar) * outlen); expectedbuf = malloc(sizeof(widechar) * expectedlen); if (in.typeform != NULL) { typeformbuf = malloc(outlen * sizeof(formtype)); memcpy(typeformbuf, in.typeform, inlen * sizeof(formtype)); } if (in.cursorPos >= 0) { cursorPos = in.cursorPos; } if (in.max_outlen >= 0) { outlen = in.max_outlen; } inlen = _lou_extParseChars(input, inbuf); if (!inlen) { fprintf(stderr, "Cannot parse input string.\n"); retval = 1; goto fail; } if (in.real_inlen > inlen) { fprintf(stderr, "expected realInputLength (%d) may not exceed total input length " "(%d)\n", in.real_inlen, inlen); return 1; } if (expected_inputPos) { inputPos = malloc(sizeof(int) * outlen); } if (expected_outputPos) { outputPos = malloc(sizeof(int) * inlen); } actualInlen = inlen; // Note that this loop is not strictly needed to make the current tests pass, but // in the general case it is needed because it is theoretically possible that we // provided a too short output buffer. for (int k = 1; k <= 3; k++) { if (direction == 1) { funcStatus = lou_backTranslate(tableList, inbuf, &actualInlen, outbuf, &outlen, typeformbuf, NULL, outputPos, inputPos, &cursorPos, in.mode); } else { funcStatus = lou_translate(tableList, inbuf, &actualInlen, outbuf, &outlen, typeformbuf, NULL, outputPos, inputPos, &cursorPos, in.mode); } if (!funcStatus) { fprintf(stderr, "Translation failed.\n"); retval = 1; goto fail; } if (in.max_outlen >= 0 || inlen == actualInlen) { break; } else if (k < 3) { // Hm, something is not quite right. Try again with a larger outbuf free(outbuf); outlen = inlen * outlen_multiplier * (k + 1); outbuf = malloc(sizeof(widechar) * outlen); if (expected_inputPos) { free(inputPos); inputPos = malloc(sizeof(int) * outlen); } fprintf(stderr, "Warning: For %s: returned inlen (%d) differs from passed inlen " "(%d) " "using outbuf of size %d. Trying again with bigger outbuf " "(%d).\n", input, actualInlen, inlen, inlen * outlen_multiplier * k, outlen); actualInlen = inlen; } } expectedlen = _lou_extParseChars(expected, expectedbuf); for (i = 0; i < outlen && i < expectedlen && expectedbuf[i] == outbuf[i]; i++) ; if (i < outlen || i < expectedlen) { retval = 1; if (in.diagnostics) { outbuf[outlen] = 0; fprintf(stderr, "Input: '%s'\n", input); /* Print the original typeform not the typeformbuf, as the * latter has been modified by the translation and contains some * information about outbuf */ if (in.typeform != NULL) print_typeform(in.typeform, inlen); if (in.cursorPos >= 0) fprintf(stderr, "Cursor: %d\n", in.cursorPos); fprintf(stderr, "Expected: '%s' (length %d)\n", expected, expectedlen); fprintf(stderr, "Received: '"); print_widechars(outbuf, outlen); fprintf(stderr, "' (length %d)\n", outlen); uint8_t *expected_utf8; uint8_t *out_utf8; size_t expected_utf8_len; size_t out_utf8_len; #ifdef WIDECHARS_ARE_UCS4 expected_utf8 = u32_to_u8(&expectedbuf[i], 1, NULL, &expected_utf8_len); out_utf8 = u32_to_u8(&outbuf[i], 1, NULL, &out_utf8_len); #else expected_utf8 = u16_to_u8(&expectedbuf[i], 1, NULL, &expected_utf8_len); out_utf8 = u16_to_u8(&outbuf[i], 1, NULL, &out_utf8_len); #endif if (i < outlen && i < expectedlen) { fprintf(stderr, "Diff: Expected '%.*s' but received '%.*s' in index %d\n", (int)expected_utf8_len, expected_utf8, (int)out_utf8_len, out_utf8, i); } else if (i < expectedlen) { fprintf(stderr, "Diff: Expected '%.*s' but received nothing in index " "%d\n", (int)expected_utf8_len, expected_utf8, i); } else { fprintf(stderr, "Diff: Expected nothing but received '%.*s' in index " "%d\n", (int)out_utf8_len, out_utf8, i); } free(expected_utf8); free(out_utf8); } } if (expected_inputPos) { int error_printed = 0; for (i = 0; i < outlen; i++) { if (expected_inputPos[i] != inputPos[i]) { if (!error_printed) { // Print only once fprintf(stderr, "Input position failure:\n"); error_printed = 1; } fprintf(stderr, "Expected %d, received %d in index %d\n", expected_inputPos[i], inputPos[i], i); retval = 1; } } } if (expected_outputPos) { int error_printed = 0; for (i = 0; i < inlen; i++) { if (expected_outputPos[i] != outputPos[i]) { if (!error_printed) { // Print only once fprintf(stderr, "Output position failure:\n"); error_printed = 1; } fprintf(stderr, "Expected %d, received %d in index %d\n", expected_outputPos[i], outputPos[i], i); retval = 1; } } } if ((in.expected_cursorPos >= 0) && (cursorPos != in.expected_cursorPos)) { fprintf(stderr, "Cursor position failure:\n"); fprintf(stderr, "Initial:%d Expected:%d Actual:%d \n", in.cursorPos, in.expected_cursorPos, cursorPos); retval = 1; } if (in.max_outlen < 0 && inlen != actualInlen) { fprintf(stderr, "Unexpected error happened: input length is not the same before as " "after the translation:\n"); fprintf(stderr, "Before: %d After: %d \n", inlen, actualInlen); retval = 1; } else if (actualInlen > inlen) { fprintf(stderr, "Unexpected error happened: returned input length (%d) exceeds " "total input length (%d)\n", actualInlen, inlen); retval = 1; } else if (in.real_inlen >= 0 && in.real_inlen != actualInlen) { fprintf(stderr, "Real input length failure:\n"); fprintf(stderr, "Expected: %d, received: %d\n", in.real_inlen, actualInlen); retval = 1; } fail: free(inbuf); free(outbuf); free(expectedbuf); free(typeformbuf); free(inputPos); free(outputPos); if (direction == 2) { const char *tmp = input; input = expected; expected = tmp; expected_inputPos = in.expected_outputPos; expected_outputPos = in.expected_inputPos; direction = 1; continue; } else { break; } } return retval; }
/** Check if a string is hyphenated as expected. * * @return 0 if the hyphenation is as expected and 1 otherwise. */ int check_hyphenation(const char *tableList, const char *str, const char *expected) { widechar *inbuf; widechar *hyphenatedbuf = NULL; uint8_t *hyphenated = NULL; char *hyphens = NULL; int inlen = strlen(str); size_t hyphenatedlen = inlen * 2; int retval = 0; inbuf = malloc(sizeof(widechar) * inlen); inlen = _lou_extParseChars(str, inbuf); if (!inlen) { fprintf(stderr, "Cannot parse input string.\n"); retval = 1; goto fail; } hyphens = calloc(inlen + 1, sizeof(char)); if (!lou_hyphenate(tableList, inbuf, inlen, hyphens, 0)) { fprintf(stderr, "Hyphenation failed.\n"); retval = 1; goto fail; } if (hyphens[0] != '0') { fprintf(stderr, "Unexpected output from lou_hyphenate.\n"); retval = 1; goto fail; } hyphenatedbuf = malloc(sizeof(widechar) * hyphenatedlen); int i = 0; int j = 0; hyphenatedbuf[i++] = inbuf[j++]; for (; j < inlen; j++) { if (hyphens[j] != '0') hyphenatedbuf[i++] = (widechar)'-'; hyphenatedbuf[i++] = inbuf[j]; } #ifdef WIDECHARS_ARE_UCS4 hyphenated = u32_to_u8(hyphenatedbuf, i, NULL, &hyphenatedlen); #else hyphenated = u16_to_u8(hyphenatedbuf, i, NULL, &hyphenatedlen); #endif if (!hyphenated) { fprintf(stderr, "Unexpected error during UTF-8 encoding\n"); free(hyphenatedbuf); retval = 2; goto fail; } if (strlen(expected) != hyphenatedlen || strncmp(expected, (const char *)hyphenated, hyphenatedlen)) { fprintf(stderr, "Input: '%s'\n", str); fprintf(stderr, "Expected: '%s'\n", expected); fprintf(stderr, "Received: '%.*s'\n", (int)hyphenatedlen, hyphenated); retval = 1; } free(hyphenatedbuf); free(hyphenated); fail: free(inbuf); free(hyphens); return retval; }
int SignTMDHeader(tmd_hdr *hdr, tmd_signature *sig, keys_struct *keys) { memset(sig,0,sizeof(tmd_signature)); u32_to_u8(sig->sigType,RSA_2048_SHA256,BE); return ctr_sig((u8*)hdr,sizeof(tmd_hdr),sig->data,keys->rsa.cpPub,keys->rsa.cpPvt,RSA_2048_SHA256,CTR_RSA_SIGN); }
int main(int argc, char *argv[]) { if(argc < 2){ help(argv[0]); return 1; } int action = 0; int i = 1; while(!action){ if(i == argc) break; if(strcmp(argv[i],"-i") == 0 || strncmp(argv[i],"--image=",8) == 0) action = image; if(strcmp(argv[i],"-d") == 0 || strncmp(argv[i],"--FSdir=",8) == 0) action = fs; if(strcmp(argv[i],"-g") == 0 || strncmp(argv[i],"--genextdata=",13) == 0) action = generate; i++; } if(action == 0){ printf("[!] Nothing to do\n"); help(argv[0]); return ARG_ERROR; } if(action == image){ ExtdataContext *extdata = malloc(sizeof(ExtdataContext)); InitaliseExtdataContext(extdata); char *input = NULL; char *output = NULL; int DB_Mode = -1; u8 Extract = False; extdata->PrintInfo = False; extdata->Verbose = False; extdata->OverrideActiveDIFI = False; u8 result = 0; for(i = 1; i < argc; i++){ if(strcmp(argv[i],"-i") == 0 && input == NULL && i < argc-1){ input = argv[i+1]; } else if(strncmp(argv[i],"--image=",8) == 0 && input == NULL){ input = (char*)(argv[i]+8); } else if(strcmp(argv[i],"-x") == 0 && output == NULL && i < argc-1 && Extract == False){ Extract = True; output = argv[i+1]; } else if(strncmp(argv[i],"--extract=",10) == 0 && output == NULL && Extract == False){ Extract = True; output = (char*)(argv[i]+10); } else if(strcmp(argv[i],"-a") == 0 && i < argc-1){ extdata->OverrideActiveDIFI = True; extdata->DIFIPartition = strtol(argv[i+1],NULL,10); } else if(strncmp(argv[i],"--forcedifi=",12) == 0){ extdata->OverrideActiveDIFI = True; extdata->DIFIPartition = strtol((argv[i]+12),NULL,10); } else if(strcmp(argv[i],"-p") == 0 || strcmp(argv[i],"--info") == 0){ extdata->PrintInfo = True; } else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){ extdata->Verbose = True; } else if(strcmp(argv[i],"-l") == 0 || strcmp(argv[i],"--listDB") == 0){ DB_Mode = DB_Normal; } else if(strcmp(argv[i],"-0") == 0 || strcmp(argv[i],"--listTID") == 0){ DB_Mode = DB_ByTID; } } if(input == NULL){ printf("[!] No input extdata image was specified\n"); FreeExtdataContext(extdata); help(argv[0]); return ARG_ERROR; } if(Extract == False && extdata->PrintInfo == False && extdata->Verbose == False && DB_Mode == -1){ printf("[!] Nothing to do\n"); FreeExtdataContext(extdata); help(argv[0]); return ARG_ERROR; } if(extdata->OverrideActiveDIFI && extdata->DIFIPartition != 0 && extdata->DIFIPartition != 1){ printf("[!] Invalid DIFI partition: %d\n",extdata->DIFIPartition); FreeExtdataContext(extdata); help(argv[0]); return ARG_ERROR; } FILE *fp = fopen(input,"rb"); if(fp == NULL){ printf("[!] Failed to open '%s'\n",input); FreeExtdataContext(extdata); return IO_ERROR; } fclose(fp); extdata->extdata.size = GetFileSize_u64(input); extdata->extdata.buffer = malloc(extdata->extdata.size); if(extdata->extdata.buffer == NULL){ printf("[!] Failed to allocate memory for extdata image\n"); FreeExtdataContext(extdata); return MEM_ERROR; } fp = fopen(input,"rb"); ReadFile_64(extdata->extdata.buffer,extdata->extdata.size,0,fp); fclose(fp); result = GetExtdataContext(extdata); if(result != 0){ printf("[!] Failed to interprete extdata image (%d)\n",result); FreeExtdataContext(extdata); return 1; } if(extdata->Files.Count > 0){ u8* embedded_data = extdata->extdata.buffer + extdata->Files.Data[0].offset; // Extracting Data if(extdata->Files.Count == 1 && Extract){ fp = fopen(output,"wb"); if(fp == NULL){ printf("[!] Failed to create '%s'\n",output); FreeExtdataContext(extdata); return IO_ERROR; } if(extdata->Verbose) printf("[+] Writing data to '%s'\n",output); WriteBuffer(embedded_data,extdata->Files.Data[0].size,0,fp); fclose(fp); } // Displaying DB... if possible if(DB_Mode >= 0){ if(extdata->ExtdataType == RawIVFC && extdata->Files.Count == 1 && IsTitleDB(embedded_data)){ result = ProcessTitleDB(embedded_data,DB_Mode); if(result){ printf("[!] Failed to read DB (%d)\n",result); } } else{ printf("[!] No valid Title Database in extdata\n"); } } } else{ printf("[!] No data exists embedded in extdata\n"); } FreeExtdataContext(extdata); } else if(action == fs){ VSXEContext *vsxe_ctx = malloc(sizeof(VSXEContext)); ExtdataContext *vsxe = malloc(sizeof(ExtdataContext)); char *input = NULL; char *output = NULL; char cwd[IO_PATH_LEN]; char VSXE_image_path[IO_PATH_LEN]; memset(vsxe_ctx,0,sizeof(VSXEContext)); memset(&cwd,0,IO_PATH_LEN); memset(&VSXE_image_path,0,IO_PATH_LEN); memset(vsxe,0,sizeof(ExtdataContext)); if(getcwdir(cwd,IO_PATH_LEN) == NULL){ printf("[!] Could not store Current Working Directory\n"); return IO_ERROR; } for(i = 1; i < argc; i++){ if(strcmp(argv[i],"-d") == 0 && input == NULL && i < argc-1){ input = argv[i+1]; } else if(strncmp(argv[i],"--FSdir=",8) == 0 && input == NULL){ input = (char*)(argv[i]+8); } else if(strcmp(argv[i],"-x") == 0 && output == NULL && i < argc-1){ vsxe_ctx->Flags[vsxe_extract] = True; output = argv[i+1]; } else if(strncmp(argv[i],"--extractFS=",12) == 0 && output == NULL){ vsxe_ctx->Flags[vsxe_extract] = True; output = (char*)(argv[i]+12); } else if(strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--showFS") == 0){ vsxe_ctx->Flags[vsxe_show_fs] = True; } else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){ vsxe_ctx->Flags[vsxe_verbose] = True; } else if(strcmp(argv[i],"-f") == 0 || strcmp(argv[i],"--FStable") == 0){ vsxe_ctx->Flags[vsxe_fstable] = True; } else if(strcmp(argv[i],"-a") == 0 && i < argc-1){ vsxe->OverrideActiveDIFI = True; vsxe->DIFIPartition = strtol(argv[i+1],NULL,10); } else if(strncmp(argv[i],"--forcedifi=",12) == 0){ vsxe->OverrideActiveDIFI = True; vsxe->DIFIPartition = strtol((argv[i]+12),NULL,10); } } if(input == NULL){ printf("[!] No Extdata FS directory was specified\n"); free(vsxe_ctx); FreeExtdataContext(vsxe); return ARG_ERROR; } if(vsxe_ctx->Flags[vsxe_extract] && output == NULL){ printf("[!] No Output directory was specified\n"); free(vsxe_ctx); FreeExtdataContext(vsxe); return ARG_ERROR; } if(vsxe_ctx->Flags[vsxe_show_fs] == False && vsxe_ctx->Flags[vsxe_extract] == False && vsxe_ctx->Flags[vsxe_fstable] == False){ printf("[!] Nothing to do\n"); free(vsxe_ctx); FreeExtdataContext(vsxe); return ARG_ERROR; } #ifdef _WIN32 vsxe_ctx->platform = WIN_32; #else vsxe_ctx->platform = UNIX; #endif // Storing Input Directory vsxe_ctx->input = malloc(IO_PATH_LEN); if(vsxe_ctx->input == NULL){ printf("[!] Failed to allocate memory for input path\n"); free(vsxe_ctx); FreeExtdataContext(vsxe); return MEM_ERROR; } chdir(input); if(getcwdir(vsxe_ctx->input,IO_PATH_LEN) == NULL){ printf("[!] Could not store input Directory\n"); free(vsxe_ctx->input); free(vsxe_ctx); FreeExtdataContext(vsxe); return IO_ERROR; } chdir(cwd); // Storing Output Directory vsxe_ctx->output = malloc(IO_PATH_LEN); if(vsxe_ctx->output == NULL){ printf("[!] Failed to allocate memory for output path\n"); free(vsxe_ctx->input); free(vsxe_ctx); FreeExtdataContext(vsxe); return MEM_ERROR; } chdir(output); if(getcwdir(vsxe_ctx->output,IO_PATH_LEN) == NULL){ printf("[!] Could not store output Directory\n"); free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); return IO_ERROR; } chdir(cwd); // Getting path to VSXE FS Image sprintf(VSXE_image_path,"%s%c00000001.dec",vsxe_ctx->input,vsxe_ctx->platform); FILE *fp = fopen(VSXE_image_path,"rb"); if(fp == NULL){ printf("[!] Could not open '%s'\n",VSXE_image_path); free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); return IO_ERROR; } fclose(fp); vsxe->extdata.size = GetFileSize_u64(VSXE_image_path); vsxe->extdata.buffer = malloc(vsxe->extdata.size); if(vsxe->extdata.buffer == NULL){ printf("[!] Failed to allocate memory for VSXE FST Image\n"); free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); return MEM_ERROR; } // Getting VSXE FST Image fp = fopen(VSXE_image_path,"rb"); ReadFile_64(vsxe->extdata.buffer,vsxe->extdata.size,0,fp); fclose(fp); u8 result = GetExtdataContext(vsxe); if(result){ printf("[!] Failed to obtain VSXE FST from image '%s' (%d)\n",VSXE_image_path,result); free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); return result; } if(vsxe->Files.Count > 0){ u8 *vsxe_offset = vsxe->extdata.buffer + vsxe->Files.Data[0].offset; if(vsxe->ExtdataType == RawIVFC && vsxe->Files.Count == 1 && IsVSXEFileSystem(vsxe_offset)){ vsxe_ctx->vsxe = vsxe_offset; result = ProcessExtData_FS(vsxe_ctx); if(result){ printf("[!] Failed to read VSXE FST (%d)\n",result); } } else{ printf("[!] No valid VSXE FST exists in '%s'\n",output); } } else{ printf("[!] No data exists embedded in extdata\n"); } free(vsxe_ctx->input); free(vsxe_ctx->output); free(vsxe_ctx); FreeExtdataContext(vsxe); } else if(action == generate){ // Extdata Gen COMPONENT_STRUCT sourcedata; memset(&sourcedata,0,sizeof(COMPONENT_STRUCT)); COMPONENT_STRUCT outdata; memset(&outdata,0,sizeof(COMPONENT_STRUCT)); char *input = NULL; char *output = NULL; char *extdatatype = NULL; u32 activeDIFI = 0; u8 type = 0; u8 Verbose = False; u8 UniqueExtdataID[8]; memset(&UniqueExtdataID,0,8); u8 GenMAC = False; for(i = 1; i < argc; i++){ if(strcmp(argv[i],"-1") == 0 || strcmp(argv[i],"-2") == 0 || strncmp(argv[i],"--keyX=",6) == 0 || strncmp(argv[i],"--keyY=",6) == 0){ GenMAC = True; } else if(strcmp(argv[i],"-g") == 0 && input == NULL && i < argc-1){ input = argv[i+1]; } else if(strncmp(argv[i],"--genextdata=",13) == 0 && input == NULL){ input = (char*)(argv[i]+13); } else if(strcmp(argv[i],"-o") == 0 && output == NULL && i < argc-1){ output = argv[i+1]; } else if(strncmp(argv[i],"--outimage=",11) == 0 && output == NULL){ output = (char*)(argv[i]+11); } else if(strcmp(argv[i],"-t") == 0 && extdatatype == NULL && i < argc-1){ extdatatype = argv[i+1]; } else if(strncmp(argv[i],"--type=",7) == 0 && extdatatype == NULL){ extdatatype = (char*)(argv[i]+7); } else if(strcmp(argv[i],"-a") == 0 && i < argc-1){ activeDIFI = strtol(argv[i+1],NULL,10); } else if(strncmp(argv[i],"--activedifi=",13) == 0){ activeDIFI = strtol((argv[i]+13),NULL,10); } else if(strcmp(argv[i],"-u") == 0 && i < argc-1){ if(strlen(argv[i+1]) == 16) char_to_u8_array(UniqueExtdataID,argv[i+1],8,BE,16); else printf("[!] Invalid length for Extdata Unique ID (expected 16 hex characters)\n"); } else if(strncmp(argv[i],"--uniqueID=",11) == 0){ if(strlen((argv[i]+11)) == 16) char_to_u8_array(UniqueExtdataID,(argv[i]+11),8,BE,16); else printf("[!] Invalid length for Extdata Unique ID (expected 16 hex characters)\n"); } else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){ Verbose = True; } } if(input == NULL){ printf("[!] No input image was specified\n"); help(argv[0]); return ARG_ERROR; } if(output == NULL){ printf("[!] No output extdata image was specified\n"); help(argv[0]); return ARG_ERROR; } if(extdatatype == NULL){ printf("[!] No extdata type was specified\n"); help(argv[0]); return ARG_ERROR; } // MAC Gen AESMAC_CTX *aes_ctx = malloc(sizeof(AESMAC_CTX)); memset(aes_ctx,0,sizeof(AESMAC_CTX)); u8 KeyX[0x10]; u8 KeyY[0x10]; memset(&KeyX,0,0x10); memset(&KeyY,0,0x10); aes_ctx->Verbose = Verbose; if(strcmp(extdatatype,"DATA") == 0){ type = BUILD_DATA; aes_ctx->type = mac_extdata; } else if(strcmp(extdatatype,"FS") == 0){ type = BUILD_FS; aes_ctx->type = mac_extdata; } else if(strcmp(extdatatype,"TDB") == 0){ type = BUILD_DB; aes_ctx->type = mac_title_db; } else if(strcmp(extdatatype,"IDB") == 0){ type = BUILD_DB; aes_ctx->type = mac_import_db; } if(type == 0){ printf("[!] Invalid Extdata type '%s'\n",extdatatype); help(argv[0]); free(aes_ctx); return ARG_ERROR; } if(GenMAC){ for(i = 1; i < argc; i++){ if(strcmp(argv[i],"-1") == 0 && i < argc-1){ if(strlen(argv[i+1]) == 32) char_to_u8_array(KeyX,argv[i+1],16,BE,16); else{ printf("[!] Invalid length for KeyX (expected 32 hex characters)\n"); help(argv[0]); free(aes_ctx); return ARG_ERROR; } } else if(strncmp(argv[i],"--keyX=",7) == 0){ if(strlen((argv[i]+7)) == 32) char_to_u8_array(KeyX,(argv[i]+7),16,BE,16); else{ printf("[!] Invalid length for KeyX (expected 32 hex characters)\n"); help(argv[0]); free(aes_ctx); return ARG_ERROR; } } else if(strcmp(argv[i],"-2") == 0 && i < argc-1){ if(strlen(argv[i+1]) == 32) char_to_u8_array(KeyY,argv[i+1],16,BE,16); else{ printf("[!] Invalid length for KeyY (expected 32 hex characters)\n"); help(argv[0]); free(aes_ctx); return ARG_ERROR; } } else if(strncmp(argv[i],"--keyY=",7) == 0){ if(strlen((argv[i]+7)) == 32) char_to_u8_array(KeyY,(argv[i]+7),16,BE,16); else{ printf("[!] Invalid length for KeyY (expected 32 hex characters)\n"); help(argv[0]); free(aes_ctx); return ARG_ERROR; } } else if(strcmp(argv[i],"-3") == 0 && i < argc-1){ u32_to_u8(aes_ctx->subdir_id,strtol(argv[i+1],NULL,16),BE); } else if(strncmp(argv[i],"--SubDirID=",11) == 0){ u32_to_u8(aes_ctx->subdir_id,strtol((argv[i]+11),NULL,16),BE); } else if(strcmp(argv[i],"-4") == 0 && i < argc-1){ u32_to_u8(aes_ctx->image_id,strtol(argv[i+1],NULL,16),BE); } else if(strncmp(argv[i],"--ImageID=",10) == 0){ u32_to_u8(aes_ctx->image_id,strtol((argv[i]+11),NULL,16),BE); } else if(strcmp(argv[i],"-5") == 0 || strcmp(argv[i],"--IsQuotaDat") == 0){ aes_ctx->is_quote_dat = 1; } } if(aes_ctx->is_quote_dat == 1){ memset(aes_ctx->image_id,0,4); memset(aes_ctx->subdir_id,0,4); } } //Extdata creation FILE *outfile = fopen(output,"wb"); if(outfile == NULL){ printf("[!] Failed to create '%s'\n",output); free(aes_ctx); return IO_ERROR; } FILE *infile = fopen(input,"rb"); if(infile == NULL){ printf("[!] Failed to open '%s'\n",input); free(aes_ctx); free(sourcedata.buffer); return IO_ERROR; } fclose(infile); sourcedata.size = GetFileSize_u64(input); sourcedata.buffer = malloc(sourcedata.size); if(sourcedata.buffer == NULL){ printf("[!] Failed to allocate memory to generate Extdata\n"); free(aes_ctx); return MEM_ERROR; } infile = fopen(input,"rb"); ReadFile_64(sourcedata.buffer,sourcedata.size,0,infile); fclose(infile); u8 result = CreateExtdata(&outdata,&sourcedata,type,activeDIFI,UniqueExtdataID); if(result){ free(aes_ctx); free(sourcedata.buffer); if(outdata.size > 0){ free(outdata.buffer); } return result; } if(GenMAC){ if(Verbose) printf("[+] Generating AES MAC\n"); memcpy(aes_ctx->header,(outdata.buffer+0x100),0x100); GenAESMAC(KeyX,KeyY,aes_ctx); memcpy(outdata.buffer,aes_ctx->aesmac,16); } if(Verbose) printf("[+] Writing '%s'\n",output); WriteBuffer(outdata.buffer,outdata.size,0,outfile); if(outdata.size > 0) free(outdata.buffer); if(sourcedata.size > 0)free(sourcedata.buffer); free(aes_ctx); fclose(outfile); } return 0; }
/** * gnutls_utf8_password_normalize: * @password: contain the UTF-8 formatted password * @plen: the length of the provided password * @out: the result in an null-terminated allocated string * @flags: should be zero * * This function will convert the provided UTF-8 password according * to the normalization rules in RFC7613. * * If the flag %GNUTLS_UTF8_IGNORE_ERRS is specified, any UTF-8 encoding * errors will be ignored, and in that case the output will be a copy of the input. * * Returns: %GNUTLS_E_INVALID_UTF8_STRING on invalid UTF-8 data, or 0 on success. * * Since: 3.5.7 **/ int gnutls_utf8_password_normalize(const unsigned char *password, unsigned plen, gnutls_datum_t *out, unsigned flags) { size_t ucs4_size = 0, nrm_size = 0; size_t final_size = 0; uint8_t *final = NULL; uint32_t *ucs4 = NULL; uint32_t *nrm = NULL; uint8_t *nrmu8 = NULL; int ret; if (plen == 0) { out->data = (uint8_t*)gnutls_strdup(""); out->size = 0; if (out->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); return 0; } /* check for invalid UTF-8 */ if (u8_check((uint8_t*)password, plen) != NULL) { gnutls_assert(); if (flags & GNUTLS_UTF8_IGNORE_ERRS) { raw_copy: out->data = gnutls_malloc(plen+1); if (out->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); out->size = plen; memcpy(out->data, password, plen); out->data[plen] = 0; return 0; } else { return GNUTLS_E_INVALID_UTF8_STRING; } } /* convert to UTF-32 */ ucs4 = u8_to_u32((uint8_t*)password, plen, NULL, &ucs4_size); if (ucs4 == NULL) { gnutls_assert(); ret = GNUTLS_E_PARSING_ERROR; goto fail; } ret = check_for_valid_freeformclass(ucs4, ucs4_size); if (ret < 0) { gnutls_assert(); if (flags & GNUTLS_UTF8_IGNORE_ERRS) { free(ucs4); goto raw_copy; } if (ret == GNUTLS_E_INVALID_UTF8_STRING) ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* normalize to NFC */ nrm = u32_normalize(UNINORM_NFC, ucs4, ucs4_size, NULL, &nrm_size); if (nrm == NULL) { gnutls_assert(); ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* convert back to UTF-8 */ final_size = 0; nrmu8 = u32_to_u8(nrm, nrm_size, NULL, &final_size); if (nrmu8 == NULL) { gnutls_assert(); ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* copy to output with null terminator */ final = gnutls_malloc(final_size+1);
int PrepAESMAC(AESMAC_CTX *ctx) { u8 savegame_type[6][8] = {"CTR-EXT0","CTR-SYS0","CTR-NOR0","CTR-SAV0","CTR-SIGN","CTR-9DB0"}; memset(ctx->hash,0,0x20); if(ctx->type == 0) return Fail; else if(ctx->type == mac_import_db){ db_sha256_block finalblock; memset(&finalblock,0,sizeof(db_sha256_block)); memcpy(finalblock.savegame_type,savegame_type[CTR_9DB0],8); u32_to_u8(finalblock.db_id,0x3,LE); memcpy(finalblock.diff_header,ctx->header,0x100); ctr_sha(&finalblock,sizeof(db_sha256_block),ctx->hash,CTR_SHA_256); } else if(ctx->type == mac_title_db){ db_sha256_block finalblock; memset(&finalblock,0,sizeof(db_sha256_block)); memcpy(finalblock.savegame_type,savegame_type[CTR_9DB0],8); u32_to_u8(finalblock.db_id,0x2,LE); memcpy(finalblock.diff_header,ctx->header,0x100); ctr_sha(&finalblock,sizeof(db_sha256_block),ctx->hash,CTR_SHA_256); } else if(ctx->type == mac_extdata){ extdata_sha256_block finalblock; memset(&finalblock,0,sizeof(extdata_sha256_block)); memcpy(finalblock.savegame_type,savegame_type[CTR_EXT0],8); endian_memcpy(finalblock.image_id,ctx->image_id,4,LE); endian_memcpy(finalblock.subdir_id,ctx->subdir_id,4,LE); u32_to_u8(finalblock.unknown,ctx->is_quote_dat,LE); endian_memcpy(finalblock.image_id_dup,ctx->image_id,4,LE); endian_memcpy(finalblock.subdir_id_dup,ctx->subdir_id,4,LE); memcpy(finalblock.diff_header,ctx->header,0x100); ctr_sha(&finalblock,sizeof(extdata_sha256_block),ctx->hash,CTR_SHA_256); } else if(ctx->type == mac_sys_save){ sys_savedata_sha256_block finalblock; memset(&finalblock,0,sizeof(sys_savedata_sha256_block)); memcpy(finalblock.savegame_type,savegame_type[CTR_SYS0],8); endian_memcpy(finalblock.save_id,ctx->saveid,8,LE); memcpy(finalblock.disa_header,ctx->header,0x100); ctr_sha(&finalblock,sizeof(sys_savedata_sha256_block),ctx->hash,CTR_SHA_256); } else if(ctx->type == mac_sd_save){ sdcard_savegame_sha256_block finalblock; memset(&finalblock,0,sizeof(sdcard_savegame_sha256_block)); memcpy(finalblock.savegame_type,savegame_type[CTR_SIGN],8); endian_memcpy(finalblock.program_id,ctx->programid,8,LE); // Generating CTR_SAV0 hash ctr_sav0_sha256_block pre_block; memset(&pre_block,0,sizeof(ctr_sav0_sha256_block)); memcpy(pre_block.savegame_type,savegame_type[CTR_SAV0],8); memcpy(pre_block.disa_header,ctx->header,0x100); ctr_sha(&pre_block,sizeof(ctr_sav0_sha256_block),finalblock.ctr_sav0_block_hash,CTR_SHA_256); // ctr_sha(&finalblock,sizeof(sdcard_savegame_sha256_block),ctx->hash,CTR_SHA_256); } else if(ctx->type == mac_card_save){ gamecard_savegame_sha256_block finalblock; memset(&finalblock,0,sizeof(gamecard_savegame_sha256_block)); memcpy(finalblock.savegame_type,savegame_type[CTR_SAV0],8); // Generating CTR_NOR0 hash ctr_nor0_sha256_block pre_block; memset(&pre_block,0,sizeof(ctr_nor0_sha256_block)); memcpy(pre_block.savegame_type,savegame_type[CTR_NOR0],8); memcpy(pre_block.disa_header,ctx->header,0x100); ctr_sha(&pre_block,sizeof(ctr_nor0_sha256_block),finalblock.ctr_nor0_block_hash,CTR_SHA_256); // ctr_sha(&finalblock,sizeof(gamecard_savegame_sha256_block),ctx->hash,CTR_SHA_256); } else return Fail; return 0; }
static inline u8 dispatch_t192(t192 a193, u32 a194) { return u32_to_u8(a194); }