Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > General > Decrypting

Reply
 
Thread Tools Search this Thread Display Modes
Old 15th November 2007, 00:08   #261  |  Link
Geremia
Registered User
 
Join Date: Feb 2007
Posts: 71
wel.....all these informations about xbox360 hd-dvd were not meant to be public because they are not already usefull.
Geremia is offline   Reply With Quote
Old 27th December 2018, 03:26   #262  |  Link
MartyMcNuts
Registered User
 
Join Date: Aug 2018
Posts: 15
Hi all, I know this is an old thread and I have read it a few times over, which does provide some general information on how Subset-Differences work, however there doesn't seem to be anything with more detail. What I am trying to do is test a bunch of "possible device keys" against a MKB_RO.inf file to calculate a "processing key" for that MKB. I already understand the rest of the procedure to calculate the "media key" and the "VUK" but need assistance with the device key to processing key step.

So,according to the AACS specs (3.2.3 - 3.2.5), each subset-difference is encoded with 5 bytes. The first byte is the U mask and the last 4 bytes are the UV number (most significant byte first). So for example, I have a subset-difference 0B 00 00 0A 00, (0B) is the U Mask and (00 00 0A 00) is the UV Number. Now, that (first byte) is treated as a number, the number of low-order 0-bits in the mask. For example, the value 01 denotes a mask of FFFFFFFE; value 0A denotes a mask of FFFFFC00.

Question 1. How is this u_mask calculated?



From the AACS Specs, "For conciseness, the path number and the “v” mask are encoded in a single 32-bit number, referred to as the uv number. The mask for v is given by the first lower-order 1-bit in the uv number. That bit, and all lower-order 0-bits, are zero bits in the “v” mask."

The first sentence there I understand. The rest doesn't make sense to me, however, by using the code:

long v_mask = 0xFFFFFFFF;
while ((uv & ~v_mask) == 0) v_mask <<= 1;

to calculate the v_mask, for the example subset-difference "0B 00 00 0A 00", use the UV number, "00 00 0A 00" the v_mask equals "FF FF FC 00"

Parts I don't understand are:

"As a result, the u mask always has more 0 bits than the v mask. The subset-difference is the subtree rooted at node u minus the sub-tree rooted at node v."

Question 2: Can someone please show me this using the example subset-difference above?



From the AACS specs "A subset-difference applies to a device if the u node is on a path from the device’s node to the root of the tree, but the v node is not. This is simple to calculate using the uv number, the appropriate mask, and the device node number (D_node). By definition, a device “D_node” is on a path to a “uv” number with mask “m” if and only if:

(D_node & m) == (uv & m)

Thus, a subset-difference applies if and only if:

((D_node & u_mask ) == (uv & u_mask)) and ((D_node & v_mask) != (uv & v_mask))

Question 3: Where does this D_node come from?


AACS specs CONTINUED: The device searches through the Explicit Subset-Difference Record fields, looking at the identified subset-differences, until it finds the one that applies to it. At that point the device either has the Device Key, or is able to derive the subsidiary Device Key, associated with that subset-difference. It finds the appropriate stored Device Key as follows: assuming the Explicit Subset-Difference Record value is uv, u_mask, and v_mask, and the stored Device Key has uv’, m’u, and m’v, the appropriate Device Key is the one that meets the following condition:

(u_mask == m’u) and ((uv & m’v) == (uv’ & m’v))

If m’v equals v_mask, the starting Device Key is the final Device Key, and is used directly to derive the Processing Key, as described above. Usually, however, the starting Device Key’s node is further up in the tree, and the actual Device Key will have to be derived. The device does that as follows:

1. Initialization. m = the stored v mask m’v. Dk = the starting Device Key.
2. Use AES-G3 on Dk, as described above, to determine a left subsidiary Device Key, a Processing Key, and a right subsidiary Device Key.
3. Look at the most significant zero bit in m. If the corresponding bit in the incoming uv number is 0, Dk = left subsidiary Device Key from step 2. Otherwise, Dk = right subsidiary Device Key from step 2.
4. Iteration. Arithmetic shift m right one bit. If it does not equal the incoming v mask mv, repeat starting at step 2.

I understand steps 2 and 4. I do not understand steps 1 and 3.

Question 4: Since we are not an authentic device, how can we know / calculate / obtain the UV, u-mask and v_mask from a device key?
Question 5: If we cannot know these, how do we work around that?


Some answers including calculations (or possibly some code?) using the above example subset-difference would be greatly appreciated.

Thanks,
Marty
MartyMcNuts is offline   Reply With Quote
Old 27th December 2018, 06:25   #263  |  Link
mick0
Registered User
 
Join Date: Dec 2017
Posts: 4
Quote:
Originally Posted by MartyMcNuts View Post
Question 1. How is this u_mask calculated?
Question 2: Can someone please show me this using the example subset-difference above?
Question 3: Where does this D_node come from?
Question 4: Since we are not an authentic device, how can we know / calculate / obtain the UV, u-mask and v_mask from a device key?
Question 5: If we cannot know these, how do we work around that?

Some answers including calculations (or possibly some code?) using the above example subset-difference would be greatly appreciated.

Thanks,
Marty
Hi Marty

For questions 1,2,4 and 5 maybe you should see how aacskeys does it?

Also, I'm curious, why do you want to calculate these using your own custom implementation instead of just using aacskeys (available since 2007, open source and runs on Windows/Linux/Mac)?

Aacskeys can calculate and print these for you - all you need to do is to copy-paste device/processing keys you want to test in to ProcessingDeviceKeysSimple.txt and run it in verbose mode (-v). It can try large number of keys in a relatively short time and it doesn't require device_node, UV or u_mask_shift values like libaacs does.

If you are writing a BD player/ripper then why not just use libaacs instead of writing your own AACS implementation?

For reference here is a list of currently known device keys you can use with aacskeys (libaacs/KEYDB.cfg compatible format).
Code:
| DK | DEVICE_KEY 0xAA856A1BA814AB99FFDEBA6AEFBE1C04 | DEVICE_NODE 0x0018 | KEY_UV 0x00000001 | KEY_U_MASK_SHIFT 0x17 ; MKBv01
| DK | DEVICE_KEY 0x810827A76E5B2CC1685E3217A23E2186 | DEVICE_NODE 0x0100 | KEY_UV 0x00000100 | KEY_U_MASK_SHIFT 0x17 ; MKBv01-MKBv12
| DK | DEVICE_KEY 0x44145A846F19D096F2C84A2E50C5C4F5 | DEVICE_NODE 0x0200 | KEY_UV 0x00000280 | KEY_U_MASK_SHIFT 0x09 ; MKBv14-MKBv16
| DK | DEVICE_KEY 0xEB55A475080FBCF18534EFA0839A7373 | DEVICE_NODE 0x0340 | KEY_UV 0x00000340 | KEY_U_MASK_SHIFT 0x08 ; MKBv17-MKBv19
| DK | DEVICE_KEY 0xFB4AC39009E82113D45ECF4B7EAEA467 | DEVICE_NODE 0x0388 | KEY_UV 0x00000384 | KEY_U_MASK_SHIFT 0x07 ; MKBv20-MKBv21
| DK | DEVICE_KEY 0x8BF4FBD91A7FB7DB8576D1E5A15A8544 | DEVICE_NODE 0x0388 | KEY_UV 0x00000384 | KEY_U_MASK_SHIFT 0x05 ; MKBv22-MKBv30
| DK | DEVICE_KEY 0xA088BC72424478EACAF237A9E258351E | DEVICE_NODE 0x0400 | KEY_UV 0x00000200 | KEY_U_MASK_SHIFT 0x17 ; MKBv01-MKBv23
| DK | DEVICE_KEY 0x5FB86EF127C19C171E799F61C27BDC2A | DEVICE_NODE 0x0800 | KEY_UV 0x00000400 | KEY_U_MASK_SHIFT 0x17 ; MKBv01-MKBv48
| DK | DEVICE_KEY 0x6C02A9C4DF6DE9314F6F4BB44677BD67 | DEVICE_NODE 0x0600 | KEY_UV 0x00000500 | KEY_U_MASK_SHIFT 0x0A ; MKBv24-MKBv35
| DK | DEVICE_KEY 0x4D84E4D6D434A08D6EF0B523B6D891B2 | DEVICE_NODE 0x0700 | KEY_UV 0x00000680 | KEY_U_MASK_SHIFT 0x09 ; MKBv36-MKBv43
| DK | DEVICE_KEY 0xF2F56575C0C5448042298FA9B316AB9A | DEVICE_NODE 0x0710 | KEY_UV 0x00000714 | KEY_U_MASK_SHIFT 0x04 ; MKBv44-MKBv51
| DK | DEVICE_KEY 0x31A194B61D3119D2B09DC0D8B9A73A00 | DEVICE_NODE 0x0880 | KEY_UV 0x00000840 | KEY_U_MASK_SHIFT 0x0B ; MKBv49-MKBv52
| DK | DEVICE_KEY 0x25F9782764D026413C3D4868F891E81E | DEVICE_NODE 0x0884 | KEY_UV 0x000008A0 | KEY_U_MASK_SHIFT 0x07 ; MKBv53-MKBv54
| DK | DEVICE_KEY 0xFDAD855E9A89E5335288AF2805DC0497 | DEVICE_NODE 0x08F0 | KEY_UV 0x000008FC | KEY_U_MASK_SHIFT 0x04 ; MKBv55-MKBv57
| DK | DEVICE_KEY 0x7FD1F7966AD2B0E4F4901205E32A69BA | DEVICE_NODE 0x0A00 | KEY_UV 0x00000900 | KEY_U_MASK_SHIFT 0x0B ; MKBv49-MKBv62
And all currently known processing keys (libaacs/KEYDB.cfg format)
Code:
| PK | 0x09F911029D74E35BD84156C5635688C0 ; MKBv01
| PK | 0x455FE10422CA29C4933F95052B792AB2 ; MKBv03
| PK | 0x973940BB180E83266231EE596CEF65B2 ; MKBv03-MKBv12
| PK | 0xF190A1E8178D80643494394F8031D9C8 ; MKBv04
| PK | 0x7A5F8A09F833F7221BD41FA64C9C7933 ; MKBv06-MKBv08
| PK | 0xC87294CE84F9CCEB5984B547EEC18D66 ; MKBv09
| PK | 0x452F6E403CDF10714E41DFAA257D313F ; MKBv10
| PK | 0x58EBDADF88DCC93304CBBEDB9EE095F6 ; MKBv14-MKBv16
| PK | 0xCC72242D4CC8156B960502805987DED0 ; MKBv14-MKBv23
| PK | 0x465FA8BE828509014D05D2FCCEFF35D2 ; MKBv17
| PK | 0xAD5E546C46D72DC083AEB5686924E1B3 ; MKBv18-MKBv19
| PK | 0x53FCE78ECD352DA50D526B5EE3D3D96B ; MKBv20-MKBv21
| PK | 0xC32238976FF44A51E2D33553CFE85772 ; MKBv22-MKBv30
| PK | 0x3ADE0AB7C9E4270055506C449E8EE6CF ; MKBv24-MKBv48
| PK | 0xD11E3DBA323D37DE3DE0D6A0DC5EC807 ; MKBv24-MKBv25
| PK | 0xAAAF8A16F829DA16A124D837F64EE2D8 ; MKBv26-MKBv28
| PK | 0xC0F535929D59CD071BEE9CB53F0C21C2 ; MKBv30-MKBv35
| PK | 0x99AB6AE0A7E13504CE284B7CA401B26A ; MKBv31-MKBv36
| PK | 0x19DF7DA3A1FB75AC4DC34CCB6AF6A5C7 ; MKBv36-MKBv38
| PK | 0x3FB9D3314AAC7F76581190A624A5C578 ; MKBv39-MKBv43
| PK | 0x186D1BBA19487F6450C1FD5ADA9407E6 ; MKBv44-MKBv51
| PK | 0xF2C416A45D806D964F567B5D7FED209D ; MKBv49-MKBv52
| PK | 0x7A8BAB1B0C66C39D1A2EEE6883E4DD3C ; MKBv53-MKBv54
| PK | 0x1F70D403A6D39B20A3F7131750ACAA22 ; MKBv53-MKBv54
| PK | 0x8FBDD8452146552EF76136B0A348590B ; MKBv55-MKBv57
| PK | 0x0EB5F81CF17405CAFDB97832F5EA11B4 ; MKBv55-MKBv62
mick0 is offline   Reply With Quote
Old 27th December 2018, 07:38   #264  |  Link
MartyMcNuts
Registered User
 
Join Date: Aug 2018
Posts: 15
@mick0,

I thought I'd design my own VUK finder program with GUI, which I have mostly done using a list of processing keys, however, this method only works up to MKBv62.

I would like to better understand the Device Key to Processing Key method as I want to test possible device keys from PS3 firmware to see if they can calculate the correct processing key for a given MKB (v63 - v66). I had thought about using libaacs but I don't really understand some of the code (especially the part regarding device keys, uv's, v_masks etc) or how to use it. (I am a c# programmer and would like to understand the method so I can then either convert some c++ code to c# or write my own)
MartyMcNuts is offline   Reply With Quote
Old 27th December 2018, 22:55   #265  |  Link
mick0
Registered User
 
Join Date: Dec 2017
Posts: 4
Quote:
Originally Posted by MartyMcNuts View Post
@mick0,

I thought I'd design my own VUK finder program with GUI, which I have mostly done using a list of processing keys, however, this method only works up to MKBv62.

I would like to better understand the Device Key to Processing Key method as I want to test possible device keys from PS3 firmware to see if they can calculate the correct processing key for a given MKB (v63 - v66). I had thought about using libaacs but I don't really understand some of the code (especially the part regarding device keys, uv's, v_masks etc) or how to use it. (I am a c# programmer and would like to understand the method so I can then either convert some c++ code to c# or write my own)
I see.

Unfortunately I can't help you with the calculations.

Also, I'm not sure if there still are people around who actually understands all this, so basically I think your best bet is be to study how libaacs and aacskeys are doing it.
mick0 is offline   Reply With Quote
Old 28th December 2018, 03:12   #266  |  Link
MartyMcNuts
Registered User
 
Join Date: Aug 2018
Posts: 15
mick0,

Yeah, I may have to read up on c++ so I can better understand some of the libaacs code.

Thanks,
Marty
MartyMcNuts is offline   Reply With Quote
Old 8th January 2019, 06:51   #267  |  Link
maetel99
Registered User
 
Join Date: Apr 2018
Posts: 11
Here is some code I wrote to use a device key to determine a processing key via the subset-difference process. This code essentially consolidates the libaacs functions _find_dk(), _calc_mk_dks(), and _calc_v_mask(), along with some macros. The input to the function is a candidate device key and an index into the record arrays for the encrypted media key and subset-differences. The function returns a processing key if the device key is valid, otherwise it returns an error code. I'm not including all the lower-level functions here.

There is some ambiguity in the AACS spec as far as what record array index to start from when testing a candidate device key in the subset-difference tree. My code follows the model used in libaacs in which we simply test every index for a given device key and look for the first one that delivers a valid processing key. Unfortunately, this can be slow since there may be 500+ records to test and each one requires iterating over a subset-difference tree.

Code:
// attempts to derive a processing key from a given device key and subset difference record index
// follows logic from AACS Common Spec section 3.2.4
// sdIdx = index of subset difference record to use
// deviceKey = 16 byte device key to use
// processingKey = 16 byte processing key if sucessful
// mediaKey = 16 byte media key if successful
// returns 0 if found processing key, -1 if no valid key, -2 if device key is revoked
int DeriveProcessingKeyForDeviceKeySubsetRecord(BDAACSMKBStatus *mkbStat, int sdIdx,
    unsigned char *deviceKey, unsigned char *processingKey, unsigned char *mediaKey)
{
    int                 result;
    int32_t             tmvIter;
    uint32_t            m, n, mu, mv, uv, mvIter;
    unsigned char       uvNumber[4], devKey[16], verifyData[16], encDataKey[16], procKey[16], medKey[16];
    
    // get the verification data (MKB record type 0x81)
    BDAACSMKBGetVerificationData(mkbStat, verifyData);
    // get encrypted data key for this subset difference index (MKB record type 0x05)
    BDAACSMKBGetMediaKeyData(mkbStat, sdIdx, encDataKey);
    // get subset diffence data for this index (MKB record type 0x04)
    BDAACSMKBGetSubsetDiffData(mkbStat, sdIdx, &mu, uvNumber);
    
    // check u mask value from record
    // AACS common spec section 3.2.3:
    // if the u mask value is not of the bit form 00xxxxxx, this marks the end of the list
    if ((mu & 0xC0) != 0) {
        // end of the list, device at this record location is revoked
        return -2;
    }
    
    // compute uv from uvNumber in endian independent way
    uv = uvNumber[0];
    uv = (uv << 8) | uvNumber[1];
    uv = (uv << 8) | uvNumber[2];
    uv = (uv << 8) | uvNumber[3];
    if (uv == 0)
        return -1;
    
    // following AACS common spec section 3.2.3, derive v mask mv from the uv number
    // the v mask is given by the first lower-order 1-bit in the uv number
    // that bit, and all lower-order 0-bits, are zero bits in the v mask
    mv = 0xFFFFFFFF;
    while ((uv & ~mv) == 0)
        mv <<= 1;
    // following AACS common spec section 3.2.5.1.5, encoded u-mask value is actually
    // the number of low-order 0-bits in the mask
    mu = 0xFFFFFFFF << mu;
    
    // section 3.2.3: the mu mask always has more trailing 0 bits than the mv mask
    // the deeper the position of a node in the tree, the shorter the sequence of 0-bits
    // in the mask associated to that node, and u is an ancestor of v
    if (mv < mu)
        return -1;
    
    // initialize iterator and starting device key
    mvIter = mv;
    result = -1;
    
    while (mvIter != mu) {
        
        // start with initial device key
        memcpy(devKey, deviceKey, 16);
        
        // repeat subset-difference iteration as needed
        tmvIter = mvIter;
        while (tmvIter != mv) {
            // determine the bit position of the most significant 0 bit in iterator
            // use algorithm from Hacker's Delight, number of trailing zeros
            m = ~tmvIter & (tmvIter - 1);
            n = 1;
            while (m != 0) {
                n <<= 1;
                m >>= 1;
            }
            n >>= 1;
            // determine whether to take a right or a left subsidiary Device Key
            if ((uv & n) == 0) {
                // use left subsidiary Device key
                AACSEncryptAESG3(devKey, devKey, 0, 0);
            }
            else {
                // use right subsidiary Device key
                AACSEncryptAESG3(devKey, 0, 0, devKey);
            }
            
            // arithmetic shift right using signed integer
            tmvIter >>= 1;
        }
        
        // get processing key at this position
        AACSEncryptAESG3(devKey, 0, procKey, 0);
        // attempt to derive media key using this processing key to check if it is valid
        result = AACSDeriveMediaKeyFromProcessKey(procKey, encDataKey, uvNumber, verifyData, medKey);
        if (result == 0) {
            // valid processing key
            if (processingKey)
                memcpy(processingKey, procKey, 16);
            if (mediaKey)
                memcpy(mediaKey, medKey, 16);
            mvIter = mu;
        }
        else
            mvIter <<= 1;
    }
    
    return result;
}
maetel99 is offline   Reply With Quote
Old 10th January 2019, 01:39   #268  |  Link
MartyMcNuts
Registered User
 
Join Date: Aug 2018
Posts: 15
thanks @maetel99.

I'll take a look at your code.
MartyMcNuts is offline   Reply With Quote
Old 10th January 2019, 02:52   #269  |  Link
MartyMcNuts
Registered User
 
Join Date: Aug 2018
Posts: 15
@maetel99,

I have a question regarding your code. The first section where you check the u mask value from record (spec 3.2.3)

if ((mu & 0xC0) != 0) {
// end of the list, device at this record location is revoked
return -2;
}


according to your code, mu is currently unassigned.

uint32_t m, n, mu, mv, uv, mvIter;


Can you please advise what the value of mu is and how you obtain it.

Thanks
MartyMcNuts is offline   Reply With Quote
Old 10th January 2019, 03:28   #270  |  Link
videoh
Registered User
 
Join Date: Jul 2014
Posts: 611
Looks like mu gets set by this call:

// get subset diffence data for this index (MKB record type 0x04)
BDAACSMKBGetSubsetDiffData(mkbStat, sdIdx, &mu, uvNumber);
videoh is offline   Reply With Quote
Old 10th January 2019, 04:13   #271  |  Link
MartyMcNuts
Registered User
 
Join Date: Aug 2018
Posts: 15
Thanks @videoh,

haha Not sure how I missed that!!
MartyMcNuts is offline   Reply With Quote
Old 10th January 2019, 04:19   #272  |  Link
maetel99
Registered User
 
Join Date: Apr 2018
Posts: 11
Quote:
Originally Posted by videoh View Post
Looks like mu gets set by this call:

// get subset diffence data for this index (MKB record type 0x04)
BDAACSMKBGetSubsetDiffData(mkbStat, sdIdx, &mu, uvNumber);
Correct, the initial value of the u-mask is read in from the subset difference record in the MKB file at the specified index.
maetel99 is offline   Reply With Quote
Old 11th January 2019, 03:49   #273  |  Link
videoh
Registered User
 
Join Date: Jul 2014
Posts: 611
Quote:
Originally Posted by MartyMcNuts View Post
haha Not sure how I missed that!!
Those naughty & characters like to hide in plain sight.
videoh is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 02:12.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.