| 687 | } |
| 688 | |
| 689 | bool SCEDecrypter::DecryptData() |
| 690 | { |
| 691 | aes_context aes; |
| 692 | |
| 693 | // Calculate the total data size. |
| 694 | for (unsigned int i = 0; i < meta_hdr.section_count; i++) |
| 695 | { |
| 696 | data_buf_length += ::narrow<u32>(meta_shdr[i].data_size); |
| 697 | } |
| 698 | |
| 699 | // Allocate a buffer to store decrypted data. |
| 700 | data_buf = std::make_unique<u8[]>(data_buf_length); |
| 701 | |
| 702 | // Set initial offset. |
| 703 | u32 data_buf_offset = 0; |
| 704 | |
| 705 | // Parse the metadata section headers to find the offsets of encrypted data. |
| 706 | for (unsigned int i = 0; i < meta_hdr.section_count; i++) |
| 707 | { |
| 708 | usz ctr_nc_off = 0; |
| 709 | u8 ctr_stream_block[0x10]; |
| 710 | u8 data_key[0x10]; |
| 711 | u8 data_iv[0x10]; |
| 712 | |
| 713 | // Check if this is an encrypted section. |
| 714 | if (meta_shdr[i].encrypted == 3) |
| 715 | { |
| 716 | // Make sure the key and iv are not out of boundaries. |
| 717 | if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count)) |
| 718 | { |
| 719 | // Get the key and iv from the previously stored key buffer. |
| 720 | memcpy(data_key, data_keys.get() + meta_shdr[i].key_idx * 0x10, 0x10); |
| 721 | memcpy(data_iv, data_keys.get() + meta_shdr[i].iv_idx * 0x10, 0x10); |
| 722 | |
| 723 | // Allocate a buffer to hold the data. |
| 724 | auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size); |
| 725 | |
| 726 | // Seek to the section data offset and read the encrypted data. |
| 727 | sce_f.seek(meta_shdr[i].data_offset); |
| 728 | sce_f.read(buf.get(), meta_shdr[i].data_size); |
| 729 | |
| 730 | // Zero out our ctr nonce. |
| 731 | memset(ctr_stream_block, 0, sizeof(ctr_stream_block)); |
| 732 | |
| 733 | // Perform AES-CTR encryption on the data blocks. |
| 734 | aes_setkey_enc(&aes, data_key, 128); |
| 735 | aes_crypt_ctr(&aes, meta_shdr[i].data_size, &ctr_nc_off, data_iv, ctr_stream_block, buf.get(), buf.get()); |
| 736 | |
| 737 | // Copy the decrypted data. |
| 738 | memcpy(data_buf.get() + data_buf_offset, buf.get(), meta_shdr[i].data_size); |
| 739 | } |
| 740 | } |
| 741 | else |
| 742 | { |
| 743 | auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size); |
| 744 | sce_f.seek(meta_shdr[i].data_offset); |
| 745 | sce_f.read(buf.get(), meta_shdr[i].data_size); |
| 746 | memcpy(data_buf.get() + data_buf_offset, buf.get(), meta_shdr[i].data_size); |
no test coverage detected