void Crypto::AesCtr(const u8* in, u32 size, const u8 key[kAes128KeySize], u8 ctr[kAesBlockSize], u8* out) { aes_context ctx; u8 block[kAesBlockSize] = { 0 }; size_t counterOffset = 0; aes_setkey_enc(&ctx, key, 128); aes_crypt_ctr(&ctx, size, &counterOffset, ctr, block, in, out); }
void AesCtrCrypt(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset) { u8 stream[16]; aes_context aes; size_t nc_off = 0; clrmem(&aes,sizeof(aes_context)); aes_setkey_enc(&aes, key, 128); SetAesCtrOffset(ctr,offset); aes_crypt_ctr(&aes, length, &nc_off, ctr, stream, input, output); return; }
static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output ) { #if defined(POLARSSL_CIPHER_MODE_CTR) return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter, stream_block, input, output ); #else ((void) ctx); ((void) length); ((void) nc_off); ((void) nonce_counter); ((void) stream_block); ((void) input); ((void) output); return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); #endif /* POLARSSL_CIPHER_MODE_CTR */ }
bool SELFDecrypter::LoadMetadata() { aes_context aes; u32 metadata_info_size = sizeof(meta_info); u8 *metadata_info = (u8 *)malloc(metadata_info_size); u32 metadata_headers_size = sce_hdr.se_hsize - (sizeof(sce_hdr) + sce_hdr.se_meta + sizeof(meta_info)); u8 *metadata_headers = (u8 *)malloc(metadata_headers_size); // Locate and read the encrypted metadata info. self_f.Seek(sce_hdr.se_meta + sizeof(sce_hdr)); self_f.Read(metadata_info, metadata_info_size); // Locate and read the encrypted metadata header and section header. self_f.Seek(sce_hdr.se_meta + sizeof(sce_hdr) + metadata_info_size); self_f.Read(metadata_headers, metadata_headers_size); // Find the right keyset from the key vault. SELF_KEY keyset = key_v.FindSelfKey(app_info.self_type, sce_hdr.se_flags, app_info.version); // Copy the necessary parameters. u8 metadata_key[0x20]; u8 metadata_iv[0x10]; memcpy(metadata_key, keyset.erk, 0x20); memcpy(metadata_iv, keyset.riv, 0x10); // Check DEBUG flag. if ((sce_hdr.se_flags & 0x8000) != 0x8000) { // Decrypt the NPDRM layer. if (!DecryptNPDRM(metadata_info, metadata_info_size)) return false; // Decrypt the metadata info. aes_setkey_dec(&aes, metadata_key, 256); // AES-256 aes_crypt_cbc(&aes, AES_DECRYPT, metadata_info_size, metadata_iv, metadata_info, metadata_info); } // Load the metadata info. meta_info.Load(metadata_info); // If the padding is not NULL for the key or iv fields, the metadata info // is not properly decrypted. if ((meta_info.key_pad[0] != 0x00) || (meta_info.iv_pad[0] != 0x00)) { LOG_ERROR(LOADER, "SELF: Failed to decrypt metadata info!"); return false; } // Perform AES-CTR encryption on the metadata headers. size_t ctr_nc_off = 0; u8 ctr_stream_block[0x10]; aes_setkey_enc(&aes, meta_info.key, 128); aes_crypt_ctr(&aes, metadata_headers_size, &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers, metadata_headers); // Load the metadata header. meta_hdr.Load(metadata_headers); // Load the metadata section headers. meta_shdr.clear(); for (unsigned int i = 0; i < meta_hdr.section_count; i++) { meta_shdr.emplace_back(); meta_shdr.back().Load(metadata_headers + sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i); } // Copy the decrypted data keys. data_keys_length = meta_hdr.key_count * 0x10; data_keys = (u8 *) malloc (data_keys_length); memcpy(data_keys, metadata_headers + sizeof(meta_hdr) + meta_hdr.section_count * sizeof(MetadataSectionHeader), data_keys_length); return true; }
bool SELFDecrypter::DecryptData() { aes_context aes; // Calculate the total data size. for (unsigned int i = 0; i < meta_hdr.section_count; i++) { if (meta_shdr[i].encrypted == 3) { if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count)) data_buf_length += meta_shdr[i].data_size; } } // Allocate a buffer to store decrypted data. data_buf = (u8*)malloc(data_buf_length); // Set initial offset. u32 data_buf_offset = 0; // Parse the metadata section headers to find the offsets of encrypted data. for (unsigned int i = 0; i < meta_hdr.section_count; i++) { size_t ctr_nc_off = 0; u8 ctr_stream_block[0x10]; u8 data_key[0x10]; u8 data_iv[0x10]; // Check if this is an encrypted section. if (meta_shdr[i].encrypted == 3) { // Make sure the key and iv are not out of boundaries. if((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count)) { // Get the key and iv from the previously stored key buffer. memcpy(data_key, data_keys + meta_shdr[i].key_idx * 0x10, 0x10); memcpy(data_iv, data_keys + meta_shdr[i].iv_idx * 0x10, 0x10); // Allocate a buffer to hold the data. u8 *buf = (u8 *)malloc(meta_shdr[i].data_size); // Seek to the section data offset and read the encrypted data. self_f.Seek(meta_shdr[i].data_offset); self_f.Read(buf, meta_shdr[i].data_size); // Zero out our ctr nonce. memset(ctr_stream_block, 0, sizeof(ctr_stream_block)); // Perform AES-CTR encryption on the data blocks. aes_setkey_enc(&aes, data_key, 128); aes_crypt_ctr(&aes, meta_shdr[i].data_size, &ctr_nc_off, data_iv, ctr_stream_block, buf, buf); // Copy the decrypted data. memcpy(data_buf + data_buf_offset, buf, meta_shdr[i].data_size); // Advance the buffer's offset. data_buf_offset += meta_shdr[i].data_size; // Release the temporary buffer. free(buf); } } } return true; }
bool SCEDecrypter::LoadMetadata(const u8 erk[32], const u8 riv[16]) { aes_context aes; const auto metadata_info = std::make_unique<u8[]>(sizeof(meta_info)); const auto metadata_headers_size = sce_hdr.se_hsize - (sizeof(sce_hdr) + sce_hdr.se_meta + sizeof(meta_info)); const auto metadata_headers = std::make_unique<u8[]>(metadata_headers_size); // Locate and read the encrypted metadata info. sce_f.seek(sce_hdr.se_meta + sizeof(sce_hdr)); sce_f.read(metadata_info.get(), sizeof(meta_info)); // Locate and read the encrypted metadata header and section header. sce_f.seek(sce_hdr.se_meta + sizeof(sce_hdr) + sizeof(meta_info)); sce_f.read(metadata_headers.get(), metadata_headers_size); // Copy the necessary parameters. u8 metadata_key[0x20]; u8 metadata_iv[0x10]; memcpy(metadata_key, erk, 0x20); memcpy(metadata_iv, riv, 0x10); // Check DEBUG flag. if ((sce_hdr.se_flags & 0x8000) != 0x8000) { // Decrypt the metadata info. aes_setkey_dec(&aes, metadata_key, 256); // AES-256 aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(meta_info), metadata_iv, metadata_info.get(), metadata_info.get()); } // Load the metadata info. meta_info.Load(metadata_info.get()); // If the padding is not NULL for the key or iv fields, the metadata info // is not properly decrypted. if ((meta_info.key_pad[0] != 0x00) || (meta_info.iv_pad[0] != 0x00)) { LOG_ERROR(LOADER, "SELF: Failed to decrypt metadata info!"); return false; } // Perform AES-CTR encryption on the metadata headers. size_t ctr_nc_off = 0; u8 ctr_stream_block[0x10]; aes_setkey_enc(&aes, meta_info.key, 128); aes_crypt_ctr(&aes, metadata_headers_size, &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.get(), metadata_headers.get()); // Load the metadata header. meta_hdr.Load(metadata_headers.get()); // Load the metadata section headers. meta_shdr.clear(); for (unsigned int i = 0; i < meta_hdr.section_count; i++) { meta_shdr.emplace_back(); meta_shdr.back().Load(metadata_headers.get() + sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i); } // Copy the decrypted data keys. data_keys_length = meta_hdr.key_count * 0x10; data_keys = std::make_unique<u8[]>(data_keys_length); memcpy(data_keys.get(), metadata_headers.get() + sizeof(meta_hdr) + meta_hdr.section_count * sizeof(MetadataSectionHeader), data_keys_length); return true; }