/* * Hash the buffer and place the result in *shaStateP. */ void sha_hash(shaState * shaStateP, const char *buffer, int bufferLen) { sha_clear(shaStateP); sha_update(shaStateP, buffer, bufferLen); sha_finish(shaStateP); }
/* static bool checkFileHash(wchar_t *path, uint8_t *checkhash) { FIL fil; uint8_t *buf; uint8_t hash[32]; size_t size; mbedtls_sha256_context ctx; if (!FileOpen(&fil, path, false) || ((FileGetSize(&fil)) == 0 && (FileClose(&fil) || true))) return false; buf = __builtin_alloca(BUF_SIZE); mbedtls_sha256_init(&ctx); mbedtls_sha256_starts(&ctx, 0); while ((size = FileRead2(&fil, buf, BUF_SIZE))) mbedtls_sha256_update(&ctx, buf, size); FileClose(&fil); mbedtls_sha256_finish(&ctx, hash); return !memcmp(hash, checkhash, sizeof(hash)); } */ uint_fast8_t tmdValidateChunk(tmd_data *data, wchar_t *path, uint_fast16_t content_index, uint_fast8_t drive) { //validates loaded tmd content chunk records FIL fil; size_t size; wchar_t apppath[_MAX_LFN + 1]; uint8_t hash[SHA_256_SIZE]; uint8_t *buf = __builtin_alloca(BUF_SIZE); uint_fast16_t content_count; content_count = __builtin_bswap16(data->header.content_count); if (!data->content_chunk && (data->content_chunk = __builtin_alloca(content_count * sizeof(tmd_content_chunk))) && !tmdPreloadChunk(data, path, content_index) ) return 0; for (uint_fast16_t info_index = 0, chunk_index = 0; chunk_index < content_count; info_index++) { for (uint_fast16_t chunk_count = __builtin_bswap16(data->content_info[info_index].content_command_count); chunk_count > 0; chunk_index++, chunk_count--) { if (content_index == CONTENT_INDEX_ALL || content_index == data->content_chunk[chunk_index].content_index) { sha_start(SHA_256_MODE, NULL); swprintf(apppath, _MAX_LFN + 1, L"%.*ls/%08lx%s", wcsrchr(path, L'/') - path, path, __builtin_bswap32(data->content_chunk[chunk_index].content_id), APP_EXT); size = __builtin_bswap32(data->content_chunk[chunk_index].content_size_lo); if (FileOpen(&fil, apppath, 0) && (FileGetSize(&fil) == size || (FileClose(&fil) && 0))) { while ((size = FileRead2(&fil, buf, BUF_SIZE))) sha_update(buf, size); } else if (!(apppath[wcslen(apppath) - strlen(APP_EXT)] = 0) && FileOpen(&fil, apppath, 0) && (FileGetSize(&fil) == size || (FileClose(&fil) && 0)) ) { aes_key Key = {&(aes_key_data){{0}}, AES_CNT_INPUT_BE_NORMAL, 0x2C, NORMALKEY}; getTitleKey2(&Key, data->header.title_id, drive); aes_ctr ctr = {{{0}}, AES_CNT_INPUT_BE_NORMAL}; aes_set_key(&Key); while ((size = FileRead2(&fil, buf, BUF_SIZE))) { aes(buf, buf, size, &ctr, AES_CBC_DECRYPT_MODE | AES_CNT_INPUT_BE_NORMAL | AES_CNT_OUTPUT_BE_NORMAL); sha_update(buf, size); } } else return 0; FileClose(&fil); sha_finish(hash); if (memcmp(hash, data->content_chunk[chunk_index].content_hash, sizeof(hash))) return 0; } } } return 1; }