The Content Scrambling System (CSS)

CSS Modes


Decrypting Stream Data (Mode 1)

A DVD sector contains 2048 bytes (the same as a CD-ROM sector). Each sector has an MPEG-2 PACK header which is followed by either stream data (MPEG-2, AC-3, etc.) or other information (PCI and DSI). An introduction to this top-level format can be found here, or in Part 1 of the MPEG-2 specification (but note that DVD uses 2048-byte PACKs which is larger than the official maximum).

If a sector contains stream data, the PACK header is followed by a stream header which contains 2 bits for the encryption type. These bits are set to 00 for no encryption, and 01 for CSS encryption. (According to the source for css-auth, 10 is an unknown/reserved code and 11 is CPRM encryption).

Note that it is incorrect to look at these bits if the PACK is not stream data - most (all?) open-source CSS decryptors fail in this respect. Non-stream data can never be encrypted, since it lacks the header which specifies the encryption type.

Once you have a sector which needs decrypting using CSS, and the correct title key, the procedure is as follows:

  1. XOR the title key with a "salt" sequence - this is the bytes at offset 0x54 to 0x58 in the sector
  2. Initialize LFSR #1, LFSR #2 and CC
  3. Decrypt bytes 0x080 to 0x7FF in the sector, in that order

The LFSRs are run in mode 1 (H1 = 0xFF, H2 = 0x00) and each byte is decrypted using the following algorithm:

	P = TABLE[C] ^ LFSRBYTE
This decryption algorithm can be specified in C++ as follows:

	unsigned char salted_key[5];
	for (int ii = 0; ii < 5; ii++)
	{
	    salted_key[ii] = key[ii] ^ sector[0x54 + ii];
	}

	InitLFSRs(salted_key);

	for (int ii = 0x080; ii < 0x800; ii++)
	{
	    sector[ii] = css_table[sector[ii]] ^ GetLFSRBYTE(0xFF, 0x00);
	}
And the CSS table is this:

	33  73  3B  26  63  23  6B  76  3E  7E  36  2B  6E  2E  66  7B
	D3  93  DB  06  43  03  4B  96  DE  9E  D6  0B  4E  0E  46  9B
	57  17  5F  82  C7  87  CF  12  5A  1A  52  8F  CA  8A  C2  1F
	D9  99  D1  00  49  09  41  90  D8  98  D0  01  48  08  40  91
	3D  7D  35  24  6D  2D  65  74  3C  7C  34  25  6C  2C  64  75
	DD  9D  D5  04  4D  0D  45  94  DC  9C  D4  05  4C  0C  44  95
	59  19  51  80  C9  89  C1  10  58  18  50  81  C8  88  C0  11
	D7  97  DF  02  47  07  4F  92  DA  9A  D2  0F  4A  0A  42  9F
	53  13  5B  86  C3  83  CB  16  5E  1E  56  8B  CE  8E  C6  1B
	B3  F3  BB  A6  E3  A3  EB  F6  BE  FE  B6  AB  EE  AE  E6  FB
	37  77  3F  22  67  27  6F  72  3A  7A  32  2F  6A  2A  62  7F
	B9  F9  B1  A0  E9  A9  E1  F0  B8  F8  B0  A1  E8  A8  E0  F1
	5D  1D  55  84  CD  8D  C5  14  5C  1C  54  85  CC  8C  C4  15
	BD  FD  B5  A4  ED  AD  E5  F4  BC  FC  B4  A5  EC  AC  E4  F5
	39  79  31  20  69  29  61  70  38  78  30  21  68  28  60  71
	B7  F7  BF  A2  E7  A7  EF  F2  BA  FA  B2  AF  EA  AA  E2  FF

Calculating the Response to a Challenge (Mode 3)

The DVD challenge-response protocol is used by a DVD player to authenticate itself with a drive (in theory it also works to authenticate the drive with the DVD player, although a player could easily not care).

The protocol uses three different key types and 32 different variants to calculate a 5-byte response from a 10-byte challenge. The key types are called KEY1, KEY2 and BUSKEY. See Drive Authentication for details of how these keys are used.

The calculation procedure works as follows:

  1. The challenge string is permuted (rearranged) depending on the key type
  2. A CSS key is created from the first 5 bytes of the permuted string
  3. The key is salted with the constant sequence F4 10 45 A3 E2 and the LFSRs are initialized
  4. The response is initialized from the last 5 bytes of the permuted string
  5. A mix byte is determined depending on the key type and the CSS variant
  6. The response is scrambled six times using the LFSRs running in mode 3 (H1 = H2 = 0xFF)
The scrambling function uses three primitives, which I call "mix", "xor" and "mess". These are easiest to describe directly in C++:

	void mix(unsigned char RSP[5], unsigned char MIXBYTE)
	{
	    unsigned char lastbyte = 0;
	    for (int ii = 0; ii < 5; ii++)
	    {
	        unsigned char temp = mix1[RSP[ii] ^ GetLFSRBYTE(0xFF, 0xFF)];
	        temp = mix2[temp ^ MIXBYTE] ^ lastbyte;
	        lastbyte = RSP[ii];
	        RSP[ii] = temp;
	    }
	}
	
	void xor(unsigned char RSP[5])
	{
	    RSP[0] ^= RSP[4];
	}

	void mess(unsigned char RSP[5])
	{
	    for (int ii = 0; ii < 5; ii++)
	    {
	        RSP[ii] = mess[RSP[ii]];
	    }
	}
Once these functions are derived, the total response calculation is as follows:

	// permute challenge string into key and initial response
	for (int ii = 0; ii < 5; ii++)
	{
	    key[ii] = challenge[challenge_permute[KEYTYPE][ii]] ^ salt[ii];
	    response[ii] = challenge[challenge_permute[KEYTYPE][ii + 5]];
	}

	InitLFSRs(key);

	unsigned char MIXBYTE = variant[translate_variant[KEYTYPE][VARIANT]];

	// step 1
	mix(response, MIXBYTE);
	xor(response);
	// step 2
	mix(response, MIXBYTE);
	xor(response);
	// step 3
	mix(response, MIXBYTE);
	mess(response)
	xor(response);
	// step 4
	mix(response, MIXBYTE);
	mess(response)
	xor(response);
	// step 5
	mix(response, MIXBYTE);
	xor(response);
	// step 6
	mix(response, MIXBYTE);
As you can see, the algorithm is complicated, and uses more tables. These tables are defined here:

salt

	F4  10  45  A3  E2
	
mix1

	C4  CD  CE  CB  C8  C9  CA  CF  CC  C5  C6  C3  C0  C1  C2  C7
	14  1D  1E  1B  18  19  1A  1F  1C  15  16  13  10  11  12  17
	24  2D  2E  2B  28  29  2A  2F  2C  25  26  23  20  21  22  27
	34  3D  3E  3B  38  39  3A  3F  3C  35  36  33  30  31  32  37
	04  0D  0E  0B  08  09  0A  0F  0C  05  06  03  00  01  02  07
	D4  DD  DE  DB  D8  D9  DA  DF  DC  D5  D6  D3  D0  D1  D2  D7
	E4  ED  EE  EB  E8  E9  EA  EF  EC  E5  E6  E3  E0  E1  E2  E7
	F4  FD  FE  FB  F8  F9  FA  FF  FC  F5  F6  F3  F0  F1  F2  F7
	44  4D  4E  4B  48  49  4A  4F  4C  45  46  43  40  41  42  47
	94  9D  9E  9B  98  99  9A  9F  9C  95  96  93  90  91  92  97
	A4  AD  AE  AB  A8  A9  AA  AF  AC  A5  A6  A3  A0  A1  A2  A7
	B4  BD  BE  BB  B8  B9  BA  BF  BC  B5  B6  B3  B0  B1  B2  B7
	84  8D  8E  8B  88  89  8A  8F  8C  85  86  83  80  81  82  87
	54  5D  5E  5B  58  59  5A  5F  5C  55  56  53  50  51  52  57
	64  6D  6E  6B  68  69  6A  6F  6C  65  66  63  60  61  62  67
	74  7D  7E  7B  78  79  7A  7F  7C  75  76  73  70  71  72  77

mix2

	C4  24  14  34  CE  2E  1E  3E  CD  2D  1D  3D  CB  2B  1B  3B
	44  A4  94  B4  4E  AE  9E  BE  4D  AD  9D  BD  4B  AB  9B  BB
	04  E4  D4  F4  0E  EE  DE  FE  0D  ED  DD  FD  0B  EB  DB  FB
	84  64  54  74  8E  6E  5E  7E  8D  6D  5D  7D  8B  6B  5B  7B
	CC  2C  1C  3C  C6  26  16  36  C5  25  15  35  C3  23  13  33
	4C  AC  9C  BC  46  A6  96  B6  45  A5  95  B5  43  A3  93  B3
	0C  EC  DC  FC  06  E6  D6  F6  05  E5  D5  F5  03  E3  D3  F3
	8C  6C  5C  7C  86  66  56  76  85  65  55  75  83  63  53  73
	C8  28  18  38  CA  2A  1A  3A  C9  29  19  39  CF  2F  1F  3F
	48  A8  98  B8  4A  AA  9A  BA  49  A9  99  B9  4F  AF  9F  BF
	08  E8  D8  F8  0A  EA  DA  FA  09  E9  D9  F9  0F  EF  DF  FF
	88  68  58  78  8A  6A  5A  7A  89  69  59  79  8F  6F  5F  7F
	C0  20  10  30  C2  22  12  32  C1  21  11  31  C7  27  17  37
	40  A0  90  B0  42  A2  92  B2  41  A1  91  B1  47  A7  97  B7
	00  E0  D0  F0  02  E2  D2  F2  01  E1  D1  F1  07  E7  D7  F7
	80  60  50  70  82  62  52  72  81  61  51  71  87  67  57  77

mess

	00  81  03  82  06  87  05  84  0C  8D  0F  8E  0A  8B  09  88
	18  99  1B  9A  1E  9F  1D  9C  14  95  17  96  12  93  11  90
	30  B1  33  B2  36  B7  35  B4  3C  BD  3F  BE  3A  BB  39  B8
	28  A9  2B  AA  2E  AF  2D  AC  24  A5  27  A6  22  A3  21  A0
	60  E1  63  E2  66  E7  65  E4  6C  ED  6F  EE  6A  EB  69  E8
	78  F9  7B  FA  7E  FF  7D  FC  74  F5  77  F6  72  F3  71  F0
	50  D1  53  D2  56  D7  55  D4  5C  DD  5F  DE  5A  DB  59  D8
	48  C9  4B  CA  4E  CF  4D  CC  44  C5  47  C6  42  C3  41  C0
	C0  41  C3  42  C6  47  C5  44  CC  4D  CF  4E  CA  4B  C9  48
	D8  59  DB  5A  DE  5F  DD  5C  D4  55  D7  56  D2  53  D1  50
	F0  71  F3  72  F6  77  F5  74  FC  7D  FF  7E  FA  7B  F9  78
	E8  69  EB  6A  EE  6F  ED  6C  E4  65  E7  66  E2  63  E1  60
	A0  21  A3  22  A6  27  A5  24  AC  2D  AF  2E  AA  2B  A9  28
	B8  39  BB  3A  BE  3F  BD  3C  B4  35  B7  36  B2  33  B1  30
	90  11  93  12  96  17  95  14  9C  1D  9F  1E  9A  1B  99  18
	88  09  8B  0A  8E  0F  8D  0C  84  05  87  06  82  03  81  00


challenge_permute

KEY1    01  05  03  00  07  04  02  09  06  08
KEY2    07  09  05  02  04  01  06  00  08  03
BUSKEY  00  08  03  01  07  02  04  06  09  05

variant

	00  01  04  05  10  11  14  15  20  21  24  25  30  31  34  35
	80  81  84  85  90  91  94  95  A0  A1  A4  A5  B0  B1  B4  B5

translate_variant

KEY1    00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F
        10  11  12  13  14  15  16  17  18  19  1A  1B  1C  1D  1E  1F
KEY2    0A  08  0E  0C  0B  09  0F  0D  1A  18  1E  1C  1B  19  1F  1D
        02  00  06  04  03  01  07  05  12  10  16  14  13  11  17  15
BUSKEY  12  1A  16  1E  02  0A  06  0E  10  18  14  1C  00  08  04  0C
        13  1B  17  1F  03  0B  07  0F  11  19  15  1D  01  09  05  0D
The large tables are made up of simple bit operations on the input byte, but this isn't very interesting and I won't go into details.


[Back] [Home] [TinyTed]