📄 mpeg3css.c
字号:
{
ai.lstk.title_key[i] ^= key[4 - (i % 5)];
}
/* Save the title key */
for(i = 0; i < 5; i++)
{
css->title_key[i] = ai.lstk.title_key[i];
}
return 0;
}
static int get_disk_key(mpeg3_css_t *css, int agid, unsigned char *key)
{
dvd_struct s;
int index, i;
s.type = DVD_STRUCT_DISCKEY;
s.disckey.agid = agid;
memset(s.disckey.value, 0, MPEG3_DVD_PACKET_SIZE);
if(ioctl(css->fd, DVD_READ_STRUCT, &s) < 0)
{
/*perror("get_disk_key"); */
return 1;
}
for(index = 0; index < sizeof s.disckey.value; index ++)
s.disckey.value[index] ^= key[4 - (index%5)];
/* Save disk key */
for(i = 0; i < MPEG3_DVD_PACKET_SIZE; i++)
css->disk_key[i] = s.disckey.value[i];
return 0;
}
static int validate(mpeg3_css_t *css, int lba, int do_title)
{
dvd_authinfo ai;
dvd_struct dvds;
int result = 0;
int i, rv, tries, agid;
memset(&ai, 0, sizeof (ai));
memset(&dvds, 0, sizeof (dvds));
if(get_asf(css)) return 1;
/* Init sequence, request AGID */
for(tries = 1, rv = -1; rv == -1 && tries < 4; tries++)
{
ai.type = DVD_LU_SEND_AGID;
ai.lsa.agid = 0;
rv = ioctl(css->fd, DVD_AUTH, &ai);
if(rv == -1)
{
/* perror("validate: request AGID"); */
ai.type = DVD_INVALIDATE_AGID;
ai.lsa.agid = 0;
ioctl(css->fd, DVD_AUTH, &ai);
}
}
if(tries >= 4) return 1;
for(i = 0; i < 10; i++) css->challenge[i] = i;
/* Send AGID to host */
if(hostauth(css, &ai)) return 1;
/* Get challenge from host */
if(hostauth(css, &ai)) return 1;
agid = ai.lsa.agid;
/* Send challenge to LU */
if(ioctl(css->fd, DVD_AUTH, &ai) < 0) return 1;
/* Get key1 from LU */
if(ioctl(css->fd, DVD_AUTH, &ai) < 0) return 1;
/* Send key1 to host */
if(hostauth(css, &ai)) return 1;
/* Get challenge from LU */
if(ioctl(css->fd, DVD_AUTH, &ai) < 0) return 1;
/* Send challenge to host */
if(hostauth(css, &ai)) return 1;
/* Get key2 from host */
if(hostauth(css, &ai)) return 1;
/* Send key2 to LU */
if(ioctl(css->fd, DVD_AUTH, &ai) < 0)
{
perror("validate: Send key2 to LU");
return 1;
}
if(ai.type == DVD_AUTH_FAILURE)
{
fprintf(stderr, "validate: authorization failed\n");
return 1;
}
memcpy(css->challenge, css->key1.b, 5);
memcpy(css->challenge + 5, css->key2.b, 5);
crypt_bus_key(css, css->varient, css->challenge, &(css->keycheck));
get_asf(css);
if(do_title)
return get_title_key(css, agid, lba, css->keycheck.b);
else
return get_disk_key(css, agid, css->keycheck.b);
return 0;
}
static int validate_path(mpeg3_css_t *css, int do_title)
{
int result = 0;
int lba = 0, file_fd;
if(do_title)
{
if((file_fd = open(css->path, O_RDONLY)) == -1)
{
perror("validate_path: open");
return 1;
}
if(ioctl(file_fd, FIBMAP, &lba) != 0)
{
perror("validate_path: FIBMAP");
close(file_fd);
return 1;
}
close(file_fd);
}
result = mpeg3io_device(css->path, css->device_path);
//printf("validate_path 1 %d\n", result);
if(!result) result = (css->fd = open(css->device_path, O_RDONLY | O_NONBLOCK)) < 0;
//printf("validate_path 2 %d\n", result);
if(!result) result = validate(css, lba, do_title);
//printf("validate_path 3 %d\n", result);
/* Definitely encrypted if we got here. */
if(!result) css->encrypted = 1;
close(css->fd);
return result;
}
/*
*
* this function is only used internally when decrypting title key
*
*/
static void title_key(unsigned char *key, unsigned char *im, unsigned char invert)
{
unsigned int lfsr1_lo, lfsr1_hi, lfsr0, combined;
unsigned char o_lfsr0, o_lfsr1;
unsigned char k[5];
int i;
lfsr1_lo = im[0] | 0x100;
lfsr1_hi = im[1];
lfsr0 = ((im[4] << 17) | (im[3] << 9) | (im[2] << 1)) + 8 - (im[2]&7);
lfsr0 = (bit_reverse[lfsr0 & 0xff] << 24) | (bit_reverse[(lfsr0 >> 8) & 0xff] << 16)
| (bit_reverse[(lfsr0 >> 16) & 0xff] << 8) | bit_reverse[(lfsr0 >> 24) & 0xff];
combined = 0;
for (i = 0; i < 5; ++i) {
o_lfsr1 = lfsr1_bits0[lfsr1_hi] ^ lfsr1_bits1[lfsr1_lo];
lfsr1_hi = lfsr1_lo>>1;
lfsr1_lo = ((lfsr1_lo&1)<<8) ^ o_lfsr1;
o_lfsr1 = bit_reverse[o_lfsr1];
/*o_lfsr0 = (lfsr0>>7)^(lfsr0>>10)^(lfsr0>>11)^(lfsr0>>19);*/
o_lfsr0 = (((((((lfsr0>>8)^lfsr0)>>1)^lfsr0)>>3)^lfsr0)>>7);
lfsr0 = (lfsr0>>8)|(o_lfsr0<<24);
combined += (o_lfsr0 ^ invert) + o_lfsr1;
k[i] = combined & 0xff;
combined >>= 8;
}
key[4] = k[4] ^ csstab1[key[4]] ^ key[3];
key[3] = k[3] ^ csstab1[key[3]] ^ key[2];
key[2] = k[2] ^ csstab1[key[2]] ^ key[1];
key[1] = k[1] ^ csstab1[key[1]] ^ key[0];
key[0] = k[0] ^ csstab1[key[0]] ^ key[4];
key[4] = k[4] ^ csstab1[key[4]] ^ key[3];
key[3] = k[3] ^ csstab1[key[3]] ^ key[2];
key[2] = k[2] ^ csstab1[key[2]] ^ key[1];
key[1] = k[1] ^ csstab1[key[1]] ^ key[0];
key[0] = k[0] ^ csstab1[key[0]];
}
/*
*
* this function decrypts a title key with the specified disk key
*
* tkey: the unobfuscated title key (XORed with BusKey)
* dkey: the unobfuscated disk key (XORed with BusKey)
* 2048 bytes in length (though only 5 bytes are needed, see below)
*
* use the result returned in tkey with css_descramble
*
*/
static int decrypt_title_key(mpeg3_css_t *css, unsigned char *dkey, unsigned char *tkey)
{
unsigned char test[5], pretkey[5];
int i = 0;
for(i = 0; mpeg3_playkeys[i]; i++)
{
memcpy(pretkey, dkey + mpeg3_playkeys[i]->offset, 5);
title_key(pretkey, mpeg3_playkeys[i]->key, 0);
memcpy(test, dkey, 5);
title_key(test, pretkey, 0);
if(memcmp(test, pretkey, 5) == 0)
break;
}
if(!mpeg3_playkeys[i])
{
fprintf(stderr, "mpeg3_decrypttitlekey: Shit - Need key %d\n", i + 1);
return 1;
}
title_key(css->title_key, pretkey, 0xff);
return 0;
}
/*
*
* The descrambling core
*
* sec: encrypted sector (2048 bytes)
* key: decrypted title key obtained from css_decrypttitlekey
*
*/
#define SALTED(i) (key[i] ^ sec[0x54 - offset + (i)])
static void descramble(unsigned char *sec, unsigned char *key, int offset)
{
unsigned int lfsr1_lo, lfsr1_hi, lfsr0, combined;
unsigned char o_lfsr0, o_lfsr1;
unsigned char *end = sec + 0x800 - offset;
if(offset > 0x54)
fprintf(stderr, "mpeg3css.c: descramble: offset > 0x54\n");
lfsr1_lo = SALTED(0) | 0x100;
lfsr1_hi = SALTED(1);
lfsr0 = ((SALTED(4) << 17) | (SALTED(3) << 9) | (SALTED(2) << 1)) + 8 - (SALTED(2) & 7);
lfsr0 = (bit_reverse[lfsr0 & 0xff] << 24) | (bit_reverse[(lfsr0 >> 8) & 0xff] << 16)
| (bit_reverse[(lfsr0 >> 16) & 0xff] << 8) | bit_reverse[(lfsr0 >> 24) & 0xff];
sec += 0x80 - offset;
combined = 0;
while(sec != end)
{
o_lfsr1 = lfsr1_bits0[lfsr1_hi] ^ lfsr1_bits1[lfsr1_lo];
lfsr1_hi = lfsr1_lo >> 1;
lfsr1_lo = ((lfsr1_lo&1) << 8) ^ o_lfsr1;
o_lfsr1 = bit_reverse[o_lfsr1];
/*o_lfsr0 = (lfsr0 >> 7) ^ (lfsr0 >> 10) ^ (lfsr0 >> 11) ^ (lfsr0 >> 19);*/
o_lfsr0 = (((((((lfsr0 >> 8) ^ lfsr0) >> 1) ^ lfsr0) >> 3) ^ lfsr0) >> 7);
lfsr0 = (lfsr0 >> 8) | (o_lfsr0 << 24);
combined += o_lfsr0 + (unsigned char)~o_lfsr1;
*sec = csstab1[*sec] ^ (combined & 0xff);
sec++;
combined >>= 8;
}
//printf("descramble\n");
}
/* =============================== Entry Points ================================= */
mpeg3_css_t* mpeg3_new_css()
{
mpeg3_css_t *css = calloc(1, sizeof(mpeg3_css_t));
css->varient = -1;
return css;
}
int mpeg3_delete_css(mpeg3_css_t *css)
{
free(css);
return 0;
}
int mpeg3_get_keys(mpeg3_css_t *css, char *path)
{
int result = 0;
strcpy(css->path, path);
/* Get disk key */
result = validate_path(css, 0);
/* Get title key */
if(!result) result = validate_path(css, 1);
/* Descramble the title key */
if(!result) result = decrypt_title_key(css, css->disk_key, css->title_key);
return css->encrypted ? result : 0;
}
/* sector is the full 2048 byte sector */
int mpeg3_decrypt_packet(mpeg3_css_t *css, unsigned char *sector, int offset)
{
//printf("mpeg3_decrypt_packet %d\n", css->encrypted);
if(!css->encrypted) return 0; /* Not encrypted */
descramble(sector, css->title_key, offset);
return 0;
}
#else // HAVE_CSS
#include "mpeg3css_fake.c"
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -