| 623 | } |
| 624 | |
| 625 | bool SCEDecrypter::LoadMetadata(const u8 erk[32], const u8 riv[16]) |
| 626 | { |
| 627 | aes_context aes; |
| 628 | const auto metadata_info = std::make_unique<u8[]>(sizeof(meta_info)); |
| 629 | const auto metadata_headers_size = sce_hdr.se_hsize - (sizeof(sce_hdr) + sce_hdr.se_meta + sizeof(meta_info)); |
| 630 | const auto metadata_headers = std::make_unique<u8[]>(metadata_headers_size); |
| 631 | |
| 632 | // Locate and read the encrypted metadata info. |
| 633 | sce_f.seek(sce_hdr.se_meta + sizeof(sce_hdr)); |
| 634 | sce_f.read(metadata_info.get(), sizeof(meta_info)); |
| 635 | |
| 636 | // Locate and read the encrypted metadata header and section header. |
| 637 | sce_f.seek(sce_hdr.se_meta + sizeof(sce_hdr) + sizeof(meta_info)); |
| 638 | sce_f.read(metadata_headers.get(), metadata_headers_size); |
| 639 | |
| 640 | // Copy the necessary parameters. |
| 641 | u8 metadata_key[0x20]; |
| 642 | u8 metadata_iv[0x10]; |
| 643 | memcpy(metadata_key, erk, 0x20); |
| 644 | memcpy(metadata_iv, riv, 0x10); |
| 645 | |
| 646 | // Check DEBUG flag. |
| 647 | if ((sce_hdr.se_flags & 0x8000) != 0x8000) |
| 648 | { |
| 649 | // Decrypt the metadata info. |
| 650 | aes_setkey_dec(&aes, metadata_key, 256); // AES-256 |
| 651 | aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(meta_info), metadata_iv, metadata_info.get(), metadata_info.get()); |
| 652 | } |
| 653 | |
| 654 | // Load the metadata info. |
| 655 | meta_info.Load(metadata_info.get()); |
| 656 | |
| 657 | // If the padding is not NULL for the key or iv fields, the metadata info |
| 658 | // is not properly decrypted. |
| 659 | if ((meta_info.key_pad[0] != 0x00) || |
| 660 | (meta_info.iv_pad[0] != 0x00)) |
| 661 | { |
| 662 | self_log.error("Failed to decrypt SCE metadata info!"); |
| 663 | return false; |
| 664 | } |
| 665 | |
| 666 | // Perform AES-CTR encryption on the metadata headers. |
| 667 | usz ctr_nc_off = 0; |
| 668 | u8 ctr_stream_block[0x10]; |
| 669 | aes_setkey_enc(&aes, meta_info.key, 128); |
| 670 | aes_crypt_ctr(&aes, metadata_headers_size, &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.get(), metadata_headers.get()); |
| 671 | |
| 672 | // Load the metadata header. |
| 673 | meta_hdr.Load(metadata_headers.get()); |
| 674 | |
| 675 | // Load the metadata section headers. |
| 676 | meta_shdr.clear(); |
| 677 | for (unsigned int i = 0; i < meta_hdr.section_count; i++) |
| 678 | { |
| 679 | meta_shdr.emplace_back(); |
| 680 | meta_shdr.back().Load(metadata_headers.get() + sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i); |
| 681 | } |
| 682 |
no test coverage detected