Skip to content

Latest commit

 

History

History
45 lines (27 loc) · 5.59 KB

xvd_info.md

File metadata and controls

45 lines (27 loc) · 5.59 KB

What are XVDs?

XVD packages are a secured file format used by the Xbox One to store data, similar to the Xbox 360's STFS packages. XVD files are usually used to store system images/data while XVCs (a slightly modified version of XVDs) are used to store game data.

An XVD file consists of a header containing the hash of the top level hash table, certain metadata about the file (such as content ID, content type, the sandbox ID the package was created for, the product ID that the package belongs to, etc) and also a signature of the header itself which is stored at the beginning of the XVD file, from 0h to 200h.

After the header there's space for an optional embedded XVD (which is usually the GameOS partition that the game inside the XVC is coded against). This embedded XVD is just a copy-paste of the XVD being embedded with no changes made to it.

After the embedded XVD comes an (optional) area for the hash tree: the tree is a multilevel array of hashes, the topmost levels contain the hashes of the blocks in the levels underneath it, with the lowest level of the tree containing hashes of the data blocks (the blocks following the hash tree). The hashes in the hash tree are computed using SHA-256, with the result usually being resized to 18h bytes (but for data block hashes can be slightly modified depending on flags in the XVD header and the XVC region that the data being hashed is located). The full 256-bit hash of the top-most level is stored in the XVD header.

Following the hash tree is another optional area reserved for user data (also known as Persistent Local Storage). This area is for games to store local-only data, although some system XVD packages seem to store data here too.

Finally after the user data comes the actual XVD data. If the file is an XVC the first 3 blocks are reserved for an XVC descriptor (which is never encrypted). This specifies the content ID, any encryption keys used, the chunks used to update packages (if the XVC is using chunk-based updates) and offsets/lengths/keyIDs of the different XVC regions in the file, along with other metadata. XVC regions can be encrypted with any of the keys specified in the XVC descriptor. The region-based encryption also includes the XVC region ID as part of the AES-128-XTS 'tweak' value.

Then comes the actual filesystem data. This data is encrypted with the CIK (can either be the decrypted value of the encrypted CIK in the XVD header if it's an XVD, or the key corresponding to the XVC key GUID)

The filesystem data is just a normal NTFS filesystem containing the files inside the package, other filesystems may be possible but NTFS is the only one observed so far.

Security Overview

From a security standpoint XVDs seem very secure:

  • Each block of data is hashed, with the hash stored in the bottom-most hash tree level
  • Each block in that hash tree level is then hashed with the hash result stored in the level above it
  • This continues, until eventually the number of hashes in the level can fit into one hash block
  • That hash block is then hashed with the result stored in the XVD header
  • The XVD header is then hashed, and the hash signed with Microsoft's private key, the signature is then stored at the beginning of the file.

To make sure the package is authenticated by Microsoft and not tampered with the console just needs to verify the signature of the header-hash, verify the top-most hash tree hash and then verify that each hash in the hash tree matches up with the actual hash. This is similar to the way STFS packages were secured on the Xbox 360, however instead of having the hash tables scattered around the file (as with STFS) they're instead stored before the data actually begins.

The data blocks inside XVD files are also secured with customized AES-128-XTS encryption (the encrypted data is then used for computing the hashes), with XVC packages the Xbox One either retrieves the encryption key over Xbox Live or retrieves it from the game disc, however it seems that the keys from these methods don't work as CIK keys. It's assumed that these keys are obfuscated/encrypted in some way (possibly with the retail ODK in the same way that the encrypted CIK in non-XVC files is encrypted?)

Non-XVC files use an ODK which appears to be static for all XVDs (but differs between retail/devkits), this key is used to decrypt the encrypted CIK in the XVD header, the decrypted CIK is then used to decrypt the XVD data.

Platform Security Processor

The PSP is a self-contained core located on the Xbox CPU die. From official AMD documentation its described as an ARM core, however instead of running TrustZone per AMD's spec it appears to be running MS customized code.

It seems that the PSP handles crypto for certain things, and also may use keyslots in a way similar to the Xbox 360's keyvault, except instead of the actual console OS having access to these keys only code running on the PSP can use them.

The Xbox One HostOS contacts the PSP through the psp.sys driver. For decrypting XVDs it appears to send the header of the XVD to the PSP, which then (assumably) decrypts the CIK field in the header and sends it back, with the OS performing the rest of the decryption.

psp.sys also has commands which seem to read memory from the PSP instead of sending commands to it, the contents of this memory are unknown, but it's possible (albeit unlikely) that the ODK may be in this area of memory.

Acronyms

  • CIK: Content Instance Key, used to encrypt the XVD data, is either stored encrypted in the header or stored outside the package in a license file

  • ODK: Offline Distribution Key, used to decrypt the header's encrypted CIK, and likely any CIK stored outside the package