Commit 95ef185a authored by Stéphane Borel's avatar Stéphane Borel

* Beginning of support for encrypted DVDs.

* It only tests encryption and authenticates disc.

The decryption does not work now et it is very ugly but I'm working on it.
parent 2378ce90
...@@ -187,6 +187,7 @@ INTERFACE = src/interface/main.o \ ...@@ -187,6 +187,7 @@ INTERFACE = src/interface/main.o \
INPUT = src/input/input_ps.o \ INPUT = src/input/input_ps.o \
src/input/input_ts.o \ src/input/input_ts.o \
src/input/dvd_ifo.o \ src/input/dvd_ifo.o \
src/input/dvd_css.o \
src/input/input_dvd.o \ src/input/input_dvd.o \
src/input/mpeg_system.o \ src/input/mpeg_system.o \
src/input/input_ext-dec.o \ src/input/input_ext-dec.o \
......
/*****************************************************************************
* css_table.h : Various tables needed by css unencryption
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
u8 pi_css_mangle0[256] = {
0x00,0x81,0x03,0x82,0x06,0x87,0x05,0x84,0x0C,0x8D,0x0F,0x8E,0x0A,0x8B,0x09,0x88,
0x18,0x99,0x1B,0x9A,0x1E,0x9F,0x1D,0x9C,0x14,0x95,0x17,0x96,0x12,0x93,0x11,0x90,
0x30,0xB1,0x33,0xB2,0x36,0xB7,0x35,0xB4,0x3C,0xBD,0x3F,0xBE,0x3A,0xBB,0x39,0xB8,
0x28,0xA9,0x2B,0xAA,0x2E,0xAF,0x2D,0xAC,0x24,0xA5,0x27,0xA6,0x22,0xA3,0x21,0xA0,
0x60,0xE1,0x63,0xE2,0x66,0xE7,0x65,0xE4,0x6C,0xED,0x6F,0xEE,0x6A,0xEB,0x69,0xE8,
0x78,0xF9,0x7B,0xFA,0x7E,0xFF,0x7D,0xFC,0x74,0xF5,0x77,0xF6,0x72,0xF3,0x71,0xF0,
0x50,0xD1,0x53,0xD2,0x56,0xD7,0x55,0xD4,0x5C,0xDD,0x5F,0xDE,0x5A,0xDB,0x59,0xD8,
0x48,0xC9,0x4B,0xCA,0x4E,0xCF,0x4D,0xCC,0x44,0xC5,0x47,0xC6,0x42,0xC3,0x41,0xC0,
0xC0,0x41,0xC3,0x42,0xC6,0x47,0xC5,0x44,0xCC,0x4D,0xCF,0x4E,0xCA,0x4B,0xC9,0x48,
0xD8,0x59,0xDB,0x5A,0xDE,0x5F,0xDD,0x5C,0xD4,0x55,0xD7,0x56,0xD2,0x53,0xD1,0x50,
0xF0,0x71,0xF3,0x72,0xF6,0x77,0xF5,0x74,0xFC,0x7D,0xFF,0x7E,0xFA,0x7B,0xF9,0x78,
0xE8,0x69,0xEB,0x6A,0xEE,0x6F,0xED,0x6C,0xE4,0x65,0xE7,0x66,0xE2,0x63,0xE1,0x60,
0xA0,0x21,0xA3,0x22,0xA6,0x27,0xA5,0x24,0xAC,0x2D,0xAF,0x2E,0xAA,0x2B,0xA9,0x28,
0xB8,0x39,0xBB,0x3A,0xBE,0x3F,0xBD,0x3C,0xB4,0x35,0xB7,0x36,0xB2,0x33,0xB1,0x30,
0x90,0x11,0x93,0x12,0x96,0x17,0x95,0x14,0x9C,0x1D,0x9F,0x1E,0x9A,0x1B,0x99,0x18,
0x88,0x09,0x8B,0x0A,0x8E,0x0F,0x8D,0x0C,0x84,0x05,0x87,0x06,0x82,0x03,0x81,0x00
};
u8 pi_css_mangle1[256] = {
0xC4,0xCD,0xCE,0xCB,0xC8,0xC9,0xCA,0xCF,0xCC,0xC5,0xC6,0xC3,0xC0,0xC1,0xC2,0xC7,
0x14,0x1D,0x1E,0x1B,0x18,0x19,0x1A,0x1F,0x1C,0x15,0x16,0x13,0x10,0x11,0x12,0x17,
0x24,0x2D,0x2E,0x2B,0x28,0x29,0x2A,0x2F,0x2C,0x25,0x26,0x23,0x20,0x21,0x22,0x27,
0x34,0x3D,0x3E,0x3B,0x38,0x39,0x3A,0x3F,0x3C,0x35,0x36,0x33,0x30,0x31,0x32,0x37,
0x04,0x0D,0x0E,0x0B,0x08,0x09,0x0A,0x0F,0x0C,0x05,0x06,0x03,0x00,0x01,0x02,0x07,
0xD4,0xDD,0xDE,0xDB,0xD8,0xD9,0xDA,0xDF,0xDC,0xD5,0xD6,0xD3,0xD0,0xD1,0xD2,0xD7,
0xE4,0xED,0xEE,0xEB,0xE8,0xE9,0xEA,0xEF,0xEC,0xE5,0xE6,0xE3,0xE0,0xE1,0xE2,0xE7,
0xF4,0xFD,0xFE,0xFB,0xF8,0xF9,0xFA,0xFF,0xFC,0xF5,0xF6,0xF3,0xF0,0xF1,0xF2,0xF7,
0x44,0x4D,0x4E,0x4B,0x48,0x49,0x4A,0x4F,0x4C,0x45,0x46,0x43,0x40,0x41,0x42,0x47,
0x94,0x9D,0x9E,0x9B,0x98,0x99,0x9A,0x9F,0x9C,0x95,0x96,0x93,0x90,0x91,0x92,0x97,
0xA4,0xAD,0xAE,0xAB,0xA8,0xA9,0xAA,0xAF,0xAC,0xA5,0xA6,0xA3,0xA0,0xA1,0xA2,0xA7,
0xB4,0xBD,0xBE,0xBB,0xB8,0xB9,0xBA,0xBF,0xBC,0xB5,0xB6,0xB3,0xB0,0xB1,0xB2,0xB7,
0x84,0x8D,0x8E,0x8B,0x88,0x89,0x8A,0x8F,0x8C,0x85,0x86,0x83,0x80,0x81,0x82,0x87,
0x54,0x5D,0x5E,0x5B,0x58,0x59,0x5A,0x5F,0x5C,0x55,0x56,0x53,0x50,0x51,0x52,0x57,
0x64,0x6D,0x6E,0x6B,0x68,0x69,0x6A,0x6F,0x6C,0x65,0x66,0x63,0x60,0x61,0x62,0x67,
0x74,0x7D,0x7E,0x7B,0x78,0x79,0x7A,0x7F,0x7C,0x75,0x76,0x73,0x70,0x71,0x72,0x77
};
u8 pi_css_mangle2[256] = {
0xC4,0x24,0x14,0x34,0xCE,0x2E,0x1E,0x3E,0xCD,0x2D,0x1D,0x3D,0xCB,0x2B,0x1B,0x3B,
0x44,0xA4,0x94,0xB4,0x4E,0xAE,0x9E,0xBE,0x4D,0xAD,0x9D,0xBD,0x4B,0xAB,0x9B,0xBB,
0x04,0xE4,0xD4,0xF4,0x0E,0xEE,0xDE,0xFE,0x0D,0xED,0xDD,0xFD,0x0B,0xEB,0xDB,0xFB,
0x84,0x64,0x54,0x74,0x8E,0x6E,0x5E,0x7E,0x8D,0x6D,0x5D,0x7D,0x8B,0x6B,0x5B,0x7B,
0xCC,0x2C,0x1C,0x3C,0xC6,0x26,0x16,0x36,0xC5,0x25,0x15,0x35,0xC3,0x23,0x13,0x33,
0x4C,0xAC,0x9C,0xBC,0x46,0xA6,0x96,0xB6,0x45,0xA5,0x95,0xB5,0x43,0xA3,0x93,0xB3,
0x0C,0xEC,0xDC,0xFC,0x06,0xE6,0xD6,0xF6,0x05,0xE5,0xD5,0xF5,0x03,0xE3,0xD3,0xF3,
0x8C,0x6C,0x5C,0x7C,0x86,0x66,0x56,0x76,0x85,0x65,0x55,0x75,0x83,0x63,0x53,0x73,
0xC8,0x28,0x18,0x38,0xCA,0x2A,0x1A,0x3A,0xC9,0x29,0x19,0x39,0xCF,0x2F,0x1F,0x3F,
0x48,0xA8,0x98,0xB8,0x4A,0xAA,0x9A,0xBA,0x49,0xA9,0x99,0xB9,0x4F,0xAF,0x9F,0xBF,
0x08,0xE8,0xD8,0xF8,0x0A,0xEA,0xDA,0xFA,0x09,0xE9,0xD9,0xF9,0x0F,0xEF,0xDF,0xFF,
0x88,0x68,0x58,0x78,0x8A,0x6A,0x5A,0x7A,0x89,0x69,0x59,0x79,0x8F,0x6F,0x5F,0x7F,
0xC0,0x20,0x10,0x30,0xC2,0x22,0x12,0x32,0xC1,0x21,0x11,0x31,0xC7,0x27,0x17,0x37,
0x40,0xA0,0x90,0xB0,0x42,0xA2,0x92,0xB2,0x41,0xA1,0x91,0xB1,0x47,0xA7,0x97,0xB7,
0x00,0xE0,0xD0,0xF0,0x02,0xE2,0xD2,0xF2,0x01,0xE1,0xD1,0xF1,0x07,0xE7,0xD7,0xF7,
0x80,0x60,0x50,0x70,0x82,0x62,0x52,0x72,0x81,0x61,0x51,0x71,0x87,0x67,0x57,0x77
};
u8 pi_reverse[256] = {
0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
};
/*****************************************************************************
* dvd_css.c: Functions for DVD authentification and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <malloc.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
//#if defined(__NetBSD__) || defined(__OpenBSD__)
//# include <sys/dvdio.h>
//#elif defined(__linux__)
#include <linux/cdrom.h>
//#else
//# error "Need the DVD ioctls"
//#endif
#include "common.h"
#include "intf_msg.h"
#include "dvd_css.h"
#include "css_table.h"
/*****************************************************************************
* CSS tables
*****************************************************************************/
unsigned int pi_css_tab0[11]={5,0,1,2,3,4,0,1,2,3,4};
unsigned char pi_css_tab1[256]=
{ 0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76,
0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b,
0xd3, 0x93, 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96,
0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b,
0x57, 0x17, 0x5f, 0x82, 0xc7, 0x87, 0xcf, 0x12,
0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f,
0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, 0x41, 0x90,
0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91,
0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74,
0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75,
0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94,
0xdc, 0x9c, 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95,
0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10,
0x58, 0x18, 0x50, 0x81, 0xc8, 0x88, 0xc0, 0x11,
0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92,
0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, 0x42, 0x9f,
0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16,
0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b,
0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6,
0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb,
0x37, 0x77, 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72,
0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f,
0xb9, 0xf9, 0xb1, 0xa0, 0xe9, 0xa9, 0xe1, 0xf0,
0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1,
0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, 0xc5, 0x14,
0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15,
0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4,
0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5,
0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70,
0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71,
0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2,
0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff };
unsigned char pi_css_tab2[256]=
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e,
0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c,
0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23,
0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a,
0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31,
0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
0x49, 0x48, 0x4b, 0x4a, 0x4d, 0x4c, 0x4f, 0x4e,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x5b, 0x5a, 0x59, 0x58, 0x5f, 0x5e, 0x5d, 0x5c,
0x52, 0x53, 0x50, 0x51, 0x56, 0x57, 0x54, 0x55,
0x6d, 0x6c, 0x6f, 0x6e, 0x69, 0x68, 0x6b, 0x6a,
0x64, 0x65, 0x66, 0x67, 0x60, 0x61, 0x62, 0x63,
0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
0x76, 0x77, 0x74, 0x75, 0x72, 0x73, 0x70, 0x71,
0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
0x9b, 0x9a, 0x99, 0x98, 0x9f, 0x9e, 0x9d, 0x9c,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x89, 0x88, 0x8b, 0x8a, 0x8d, 0x8c, 0x8f, 0x8e,
0xb6, 0xb7, 0xb4, 0xb5, 0xb2, 0xb3, 0xb0, 0xb1,
0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3,
0xad, 0xac, 0xaf, 0xae, 0xa9, 0xa8, 0xab, 0xaa,
0xdb, 0xda, 0xd9, 0xd8, 0xdf, 0xde, 0xdd, 0xdc,
0xd2, 0xd3, 0xd0, 0xd1, 0xd6, 0xd7, 0xd4, 0xd5,
0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
0xf6, 0xf7, 0xf4, 0xf5, 0xf2, 0xf3, 0xf0, 0xf1,
0xed, 0xec, 0xef, 0xee, 0xe9, 0xe8, 0xeb, 0xea,
0xe4, 0xe5, 0xe6, 0xe7, 0xe0, 0xe1, 0xe2, 0xe3
};
unsigned char pi_css_tab3[512]=
{
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff
};
unsigned char pi_css_tab4[256]=
{
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
};
unsigned char pi_css_tab5[256]=
{
0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07,
0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b, 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b,
0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13, 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03,
0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d, 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d,
0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05,
0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09,
0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01,
0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06,
0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a,
0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12, 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02,
0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c, 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c,
0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14, 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04,
0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08,
0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00
};
/*
* Local functions
*/
/*****************************************************************************
* CSSGetASF : Get Authentification success flag
*****************************************************************************/
int CSSGetASF( int i_fd )
{
#if 0
dvd_authinfo auth;
auth.type = DVD_LU_SEND_ASF;
auth.lsasf.asf = 0;
for( auth.lsasf.agid = 0 ; auth.lsasf.agid < 4 ; auth.lsasf.agid++ )
{
if( ioctl( i_fd, DVD_AUTH, &auth ) )
{
intf_ErrMsg( "DVD ioctl error in CSSGetASF" );
return -1;
}
}
// ("%sAuthenticated\n", (ai.lsasf.asf) ? "" : "not");
return 0;
#else
dvd_authinfo ai;
ai.type = DVD_LU_SEND_ASF;
ai.lsasf.asf = 0;
for (ai.lsasf.agid = 0; ai.lsasf.agid < 4; ai.lsasf.agid++) {
if (!(ioctl(i_fd, DVD_AUTH, &ai))) {
fprintf( stderr, "%sAuthenticated\n", (ai.lsasf.asf) ? "" : "not");
return 0;
}
}
intf_ErrMsg( "CSS Error : GetASF" );
return -1;
#endif
}
/*****************************************************************************
* CSSCryptKey : shuffles bits and unencrypt keys.
* ---
* i_key_type : 0->key1, 1->key2, 2->buskey.
* i_varient : between 0 and 31.
*****************************************************************************/
#if 0
static void CSSCryptKey( int i_key_type, int i_varient,
u8* pi_challenge, u8* pi_key )
{
/* Permutation table for challenge */
u8 ppi_perm_challenge[3][10] =
{ { 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 },
{ 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 },
{ 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 } };
/* Permutation table for varient table */
u8 ppi_perm_varient[2][32] =
{ { 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d,
0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d,
0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05,
0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15 },
{ 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e,
0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c,
0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f,
0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d } };
u8 pi_css_secret[5] = { 0xE2,0xA3,0x45,0x10,0xF4 };
u8 pi_css_varients[32] =
{ 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
0x20, 0x21, 0x24, 0x25, 0x30, 0x31, 0x34, 0x35,
0x80, 0x81, 0x84, 0x85, 0x90, 0x91, 0x94, 0x95,
0xA0, 0xA1, 0xA4, 0xA5, 0xB0, 0xB1, 0xB4, 0xB5 };
u8 pi_bits[30];
u8 pi_scratch[10];
u8 pi_tmp1[5], pi_tmp2[2];
u8 i_lfsr0_o, i_lfsr1_o;
u32 i_lfsr0, i_lfsr1;
u8 i_css_varient;
int i_val = 0;
int i_term = 0;
int i, i_index;
for( i=0 ; i<10 ; i++ )
{
pi_scratch[i] = pi_challenge[ppi_perm_challenge[i_key_type][i]];
}
i_css_varient = i_key_type == 0 ? i_varient
: ppi_perm_varient[i_key_type-1][i_varient];
i_css_varient = pi_css_varients[i_css_varient];
for( i=0 ; i<5 ; i++ )
{
pi_tmp1[i] = pi_scratch[5+i] ^ pi_css_secret[i];
}
/* In order to ensure that the LFSR works we need to ensure that the
* initial values are non-zero. Thus when we initialise them from
* the seed, we ensure that a bit is set.
*/
i_lfsr0 = ( pi_key[0] << 17 ) | ( pi_key[1] << 9 ) |
( ( pi_key[2] & ~7 ) << 1 ) | 8 | (pi_key[2] & 7);
/*
* reverse lfsr0/1 to simplify calculation in loop
*/
i_lfsr0 = ( pi_reverse[i_lfsr0 & 0xff] << 17 ) |
( pi_reverse[( i_lfsr0 >> 8 ) & 0xff] << 9 ) |
( pi_reverse[( i_lfsr0 >> 16 ) & 0xff] << 1) |
( i_lfsr0 >> 24 );
i_lfsr1 = ( pi_reverse[pi_key[4]] << 9 ) | 0x100 |
( pi_reverse[pi_key[3]] );
for( i=0 ; i<30 ; i++ )
{
i_lfsr0_o = ( i_lfsr0 >> 12) ^ ( i_lfsr0 >> 4) ^
( i_lfsr0 >> 3) ^ i_lfsr0;
i_lfsr1_o = ( ( i_lfsr1 >> 14 ) & 7) ^ i_lfsr1;
i_lfsr1_o ^= ( i_lfsr1_o << 3 ) ^ ( i_lfsr1_o << 6 );
i_lfsr1 = ( i_lfsr1 >> 8) ^ ( i_lfsr1_o << 9);
i_lfsr0 = ( i_lfsr0 >> 8 ) ^ ( i_lfsr0_o << 17);
i_lfsr0_o = ~i_lfsr0_o;
i_lfsr1_o = ~i_lfsr1_o;
i_val += i_lfsr0_o + i_lfsr1_o;
pi_bits[i] = i_val & 0xFF;
i_val >>= 8;
}
/*
* Mangling
*/
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_scratch[i] )
{
i_index = pi_bits[25+i] ^ pi_scratch[i];
i_index = pi_css_mangle1[i_index] ^ i_css_varient;
pi_tmp1[i] = pi_css_mangle2[i_index] ^ i_term;
}
pi_tmp1[4] ^= pi_tmp1[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp1[i] )
{
i_index = pi_bits[20+i] ^ pi_tmp1[i];
i_index = pi_css_mangle1[i_index] ^ i_css_varient;
pi_tmp2[i] = pi_css_mangle2[i_index] ^ i_term;
}
pi_tmp2[4] ^= pi_tmp2[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp2[i] )
{
i_index = pi_bits[15+i] ^ pi_tmp2[i];
i_index = pi_css_mangle1[i_index] ^ i_css_varient;
i_index = pi_css_mangle2[i_index] ^ i_term;
pi_tmp1[i] = pi_css_mangle0[i_index];
}
pi_tmp1[4] ^= pi_tmp1[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp1[i] )
{
i_index = pi_bits[10+i] ^ pi_tmp1[i];
i_index = pi_css_mangle1[i_index] ^ i_css_varient;
i_index = pi_css_mangle2[i_index] ^ i_term;
pi_tmp2[i] = pi_css_mangle0[i_index];
}
pi_tmp2[4] ^= pi_tmp2[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp2[i] )
{
i_index = pi_bits[5+i] ^ pi_tmp2[i];
i_index = pi_css_mangle1[i_index] ^ i_css_varient;
pi_tmp1[i] = pi_css_mangle2[i_index] ^ i_term;
}
pi_tmp1[4] ^= pi_tmp1[0];
for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp1[i] )
{
i_index = pi_bits[i] ^ pi_tmp1[i];
i_index = pi_css_mangle1[i_index] ^ i_css_varient;
pi_key[i] = pi_css_mangle2[i_index] ^ i_term;
}
return;
}
#else
typedef struct {
uint8_t Challenge[10];
uint8_t Key1[KEY_SIZE];
uint8_t Key2[KEY_SIZE];
uint8_t KeyCheck[KEY_SIZE];
uint8_t varient;
} DiscKeys;
DiscKeys discKeys;
static void _generate_bits (u8 *output, int len, const u8 *s)
{
u32 lfsr0, lfsr1;
int val;
u8 o_lfsr0, o_lfsr1;
/* In order to ensure that the LFSR works we need to ensure that the
* initial values are non-zero. Thus when we initialise them from
* the seed, we ensure that a bit is set.
*/
lfsr0 = (s[0] << 17) | (s[1] << 9) | ((s[2] & ~7) << 1) | 8 | (s[2] & 7);
/*
reverse lfsr0/1 to simplify calculation in loop
*/
lfsr0 = (pi_reverse[lfsr0&0xff]<<17) | (pi_reverse[(lfsr0>>8)&0xff] << 9)
| (pi_reverse[(lfsr0>>16)&0xff]<<1) |(lfsr0>>24);
lfsr1 = (pi_reverse[s[4]] << 9) | 0x100 | ( pi_reverse[ s[3]] );
output++;
val = 0;
do {
o_lfsr0 = (lfsr0 >> 12) ^ (lfsr0 >> 4) ^ (lfsr0 >> 3) ^ lfsr0;
o_lfsr1 = ((lfsr1 >> 14) & 7) ^ lfsr1;
o_lfsr1 ^= (o_lfsr1 << 3) ^ (o_lfsr1 << 6);
lfsr1 = (lfsr1 >> 8) ^ (o_lfsr1 << 9);
lfsr0 = (lfsr0 >> 8) ^ (o_lfsr0 << 17);
o_lfsr0 = ~o_lfsr0;
o_lfsr1 = ~o_lfsr1;
val += o_lfsr0 + o_lfsr1;
*--output = val & 0xFF;
val >>= 8;
fprintf(stderr, "lfsr0=%08x lfsr1=%08x\n", lfsr0, lfsr1);
} while (--len > 0);
}
/**
* This encryption engine implements one of 32 variations
* one the same theme depending upon the choice in the
* varient parameter (0 - 31).
*
* The algorithm itself manipulates a 40 bit input into
* a 40 bit output.
* The parameter 'input' is 80 bits. It consists of
* the 40 bit input value that is to be encrypted followed
* by a 40 bit seed value for the pseudo random number
* generators.
**/
static inline void mangle1( u8 *bs, u8 cse, const u8 *ip, u8 *op)
{
int i, term, index;
for (i = 5, term = 0; --i >= 0; term = ip[i]) {
index = bs[i] ^ ip[i];
index = pi_css_mangle1[index] ^ cse;
op[i] = pi_css_mangle2[index] ^ term;
}
}
/**
*
**/
static inline void mangle2( u8 *bs, u8 cse, const u8 *ip, u8 *op)
{
int i, term, index;
for (i = 5, term = 0; --i >= 0; term = ip[i]) {
index = bs[i] ^ ip[i];
index = pi_css_mangle1[index] ^ cse;
index = pi_css_mangle2[index] ^ term;
op[i] = pi_css_mangle0[index];
}
}
/**
*
**/
static inline void engine (int varient, u8 const *input, u8 *output)
{
u8 cse;
u8 tmp1[5];
u8 tmp2[5];
u8 bits[30];
u8 pi_css_varients[32] =
{ 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
0x20, 0x21, 0x24, 0x25, 0x30, 0x31, 0x34, 0x35,
0x80, 0x81, 0x84, 0x85, 0x90, 0x91, 0x94, 0x95,
0xA0, 0xA1, 0xA4, 0xA5, 0xB0, 0xB1, 0xB4, 0xB5 };
u8 pi_css_secret[5] = { 0xE2,0xA3,0x45,0x10,0xF4 };
int i;
/* Feed the secret into the input values such that
* we alter the seed to the LFSR's used above, then
* generate the bits to play with.
*/
for (i=5; --i>=0; )
tmp1[i] = input[5+i] ^ pi_css_secret[i];
_generate_bits (&bits[29], sizeof bits, &tmp1[0]);
/* This term is used throughout the following to
* select one of 32 different variations on the
* algorithm.
*/
cse = pi_css_varients[varient];
/* Now the actual blocks doing the encryption. Each
* of these works on 40 bits at a time and are quite
* similar.
*/
mangle1( &bits[25], cse, input, tmp1);
tmp1[4] ^= tmp1[0];
mangle1( &bits[20], cse, tmp1, tmp2);
tmp2[4] ^= tmp2[0];
mangle2( &bits[15], cse, tmp2, tmp1);
tmp1[4] ^= tmp1[0];
mangle2( &bits[10], cse, tmp1, tmp2);
tmp2[4] ^= tmp2[0];
mangle1( &bits[5], cse, tmp2, tmp1);
tmp1[4] ^= tmp1[0];
mangle1( &bits[0], cse, tmp1, output);
}
/**
*
**/
void CryptKey1 (int varient, u8 const *challenge, u8 *key)
{
u8 perm_challenge[] = {1,3,0,7,5, 2,9,6,4,8};
u8 scratch[10];
int i;
for (i=9; i>=0; --i)
scratch[i] = challenge[perm_challenge[i]];
engine (varient, scratch, key);
}
/**
* This shuffles the bits in varient to make perm_varient such that
* 4 -> !3
* 3 -> 4
* varient bits: 2 -> 0 perm_varient bits
* 1 -> 2
* 0 -> !1
**/
void CryptKey2 (int varient, u8 const *challenge, u8 *key)
{
static u8 perm_challenge[] = {
0x06,0x01,0x09,0x03,0x08,0x05,0x07,0x04,
0x00,0x02
};
static u8 perm_varient[] = {
0x0a,0x08,0x0e,0x0c,0x0b,0x09,0x0f,0x0d,
0x1a,0x18,0x1e,0x1c,0x1b,0x19,0x1f,0x1d,
0x02,0x00,0x06,0x04,0x03,0x01,0x07,0x05,
0x12,0x10,0x16,0x14,0x13,0x11,0x17,0x15
};
u8 scratch[10];
int i;
for (i=9; i>=0; --i)
scratch[i] = challenge[perm_challenge[i]];
engine (perm_varient[varient], scratch, key);
}
/**
* This shuffles the bits in varient to make perm_varient such that
* 4 -> 0
* 3 -> !1
* varient bits: 2 -> !4 perm_varient bits
* 1 -> 2
* 0 -> 3
**/
void CryptBusKey (int varient, u8 const *challenge, u8 *key)
{
static u8 perm_challenge[] = {
0x04,0x00,0x03,0x05,0x07,0x02,0x08,0x06,
0x01,0x09
};
static u8 perm_varient[] = {
0x12,0x1a,0x16,0x1e,0x02,0x0a,0x06,0x0e,
0x10,0x18,0x14,0x1c,0x00,0x08,0x04,0x0c,
0x13,0x1b,0x17,0x1f,0x03,0x0b,0x07,0x0f,
0x11,0x19,0x15,0x1d,0x01,0x09,0x05,0x0d
};
u8 scratch[10];
int i;
for (i=9; i>=0; --i)
scratch[i] = challenge[perm_challenge[i]];
engine (perm_varient[varient], scratch, key);
}
static int _CSSAuthDrive (const u8 *key, DiscKeys *disc)
{
int i;
for (i=0; i<KEY_SIZE; i++)
disc->Key1[i] = key[4-i];
for (i=0; i<32; ++i) {
CryptKey1( i, disc->Challenge, disc->KeyCheck);
if (memcmp (disc->KeyCheck, disc->Key1, KEY_SIZE ) == 0) {
intf_ErrMsg( "Drive Authentic - using varient %d", i);
disc->varient = i;
return i;
}
}
intf_ErrMsg( "Drive would not Authenticate" );
return -1;
}
static int _CSSAuthHost (dvd_authinfo *ai, DiscKeys *disc)
{
int i;
switch (ai->type) {
/* Host data receive (host changes state) */
case DVD_LU_SEND_AGID:
// _CSSPrintDebug ("AGID %d\n", ai->lsa.agid);
ai->type = DVD_HOST_SEND_CHALLENGE;
break;
case DVD_LU_SEND_KEY1:
// _CSSPrintDebugBytes ("LU sent key1", ai->lsk.key, LEN_KEY);
if (_CSSAuthDrive (ai->lsk.key, disc)<0) {
ai->type = DVD_AUTH_FAILURE;
return -22;
}
ai->type = DVD_LU_SEND_CHALLENGE;
break;
case DVD_LU_SEND_CHALLENGE:
for (i = 0; i < 10; ++i)
disc->Challenge[i] = ai->hsc.chal[9-i];
// _CSSPrintDebugBytes ("LU sent challenge", ai->hsc.chal, 10);
CryptKey2 (disc->varient, disc->Challenge, disc->Key2);
ai->type = DVD_HOST_SEND_KEY2;
break;
/* Host data send */
case DVD_HOST_SEND_CHALLENGE:
for (i = 0; i < 10; ++i)
ai->hsc.chal[9-i] = disc->Challenge[i];
// _CSSPrintDebugBytes ("Host sending challenge", ai->hsc.chal, 10);
/* Returning data, let LU change state */
break;
case DVD_HOST_SEND_KEY2:
for (i = 0; i < KEY_SIZE; ++i)
ai->hsk.key[4-i] = disc->Key2[i];
// _CSSPrintDebugBytes ("Host sending key 2", &disc->Key2[0], LEN_KEY);
/* Returning data, let LU change state */
break;
default:
intf_ErrMsg( "Got invalid state %d", ai->type );
return -22;
}
return 0;
}
#endif
/*****************************************************************************
* CSSCracker : title key decryption by cracking
*****************************************************************************/
// FIXME : adapt to vlc
#define KEYSTREAMBYTES 10
static unsigned char invtab4[256];
static int CSScracker(int StartVal,unsigned char* pCrypted,unsigned char* pDecrypted,DVD40bitKey *StreamKey,DVD40bitKey *pkey)
{
unsigned char MyBuf[10];
unsigned int t1,t2,t3,t4,t5,t6;
unsigned int nTry;
unsigned int vCandidate;
int i;
unsigned int j;
int i_exit = -1;
for (i=0;i<10;i++)
{
MyBuf[i] = pi_css_tab1[pCrypted[i]] ^ pDecrypted[i];
}
/* Test that CSStab4 is a permutation */
memset( invtab4, 0, 256 );
for( i = 0 ; i < 256 ; i++ )
{
invtab4[ pi_css_tab4[i] ] = 1;
}
for (i = 0 ; i < 256 ; i++)
{
if (invtab4[ i ] != 1)
{
printf( "Permutation error\n" );
exit( -1 );
}
}
/* initialize the inverse of table4 */
for( i = 0 ; i < 256 ; i++ )
{
invtab4[ pi_css_tab4[i] ] = i;
}
for( nTry = StartVal ; nTry < 65536 ; nTry++ )
{
t1 = nTry >> 8 | 0x100;
t2 = nTry & 0xff;
t3 = 0; /* not needed */
t5 = 0;
/* iterate cipher 4 times to reconstruct LFSR2 */
for( i = 0 ; i < 4 ; i++ )
{
/* advance LFSR1 normaly */
t4=pi_css_tab2[t2]^pi_css_tab3[t1];
t2=t1>>1;
t1=((t1&1)<<8)^t4;
t4=pi_css_tab5[t4];
/* deduce t6 & t5 */
t6 = MyBuf[ i ];
if( t5 )
{
t6 = ( t6 + 0xff )&0x0ff;
}
if( t6 < t4 )
{
t6 += 0x100;
}
t6 -= t4;
t5 += t6 + t4;
t6 = invtab4[ t6 ];
/* printf( "%02x/%02x ", t4, t6 ); */
/* feed / advance t3 / t5 */
t3 = (t3 << 8) | t6;
t5 >>= 8;
}
vCandidate = t3;
/* iterate 6 more times to validate candidate key */
for( ; i < KEYSTREAMBYTES ; i++ )
{
t4=pi_css_tab2[t2]^pi_css_tab3[t1];
t2=t1>>1;
t1=((t1&1)<<8)^t4;
t4=pi_css_tab5[t4];
t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
t3=(t3<<8)|t6;
t6=pi_css_tab4[t6];
t5+=t6+t4;
if( (t5 & 0xff) != MyBuf[i] ) break;
t5>>=8;
}
if( i == KEYSTREAMBYTES )
{
/* Do 4 backwards steps of iterating t3 to deduce initial state */
t3 = vCandidate;
for( i = 0 ; i < 4 ; i++ )
{
t1 = t3 & 0xff;
t3 = ( t3 >> 8 );
/* easy to code, and fast enough bruteforce
* search for byte shifted in */
for( j=0 ; j < 256 ; j++ )
{
t3 = (t3 & 0x1ffff) | ( j << 17 );
t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
if( t6 == t1 ) break;
}
}
// printf( "Candidate: t1=%03x t2=%02x t3=%08x\n", 0x100|(nTry>>8),nTry&0x0ff, t3 );
t4 = (t3>>1) - 4;
for(t5=0;t5<8;t5++)
{
if ( ((t4+t5)*2 + 8 - ((t4+t5)&7))==t3 )
{
(*pkey)[0] = nTry>>8;
(*pkey)[1] = nTry & 0xFF;
(*pkey)[2] = ((t4+t5) >> 0) & 0xFF;
(*pkey)[3] = ((t4+t5) >> 8) & 0xFF;
(*pkey)[4] = ((t4+t5) >> 16) & 0xFF;
i_exit = nTry+1;
}
}
}
}
if (i_exit>=0)
{
(*pkey)[0] ^= (*StreamKey)[0];
(*pkey)[1] ^= (*StreamKey)[1];
(*pkey)[2] ^= (*StreamKey)[2];
(*pkey)[3] ^= (*StreamKey)[3];
(*pkey)[4] ^= (*StreamKey)[4];
}
return i_exit;
}
/*
* Authentication and keys
*/
/*****************************************************************************
* CSSInit : CSS Structure initialisation and DVD authentication.
*****************************************************************************/
css_t CSSInit( int i_fd )
{
#if 0
css_t css;
dvd_authinfo auth;
int i;
css.i_fd = i_fd;
css.b_error = 0;
memset( &auth, 0, sizeof(auth) );
fprintf( stderr, "0\n" );
#if 0
if( CSSGetASF( i_fd ) )
{
css.b_error = 1;
return css;
}
#endif
fprintf( stderr, "1\n" );
/* Get AGID From drive */
auth.type = DVD_LU_SEND_AGID;
auth.lsa.agid = 0;
if( ioctl( i_fd, DVD_AUTH, &auth ) < 0 )
{
intf_ErrMsg( "DVD ioctl error in CSSInit (AGID)" );
auth.type = DVD_INVALIDATE_AGID;
auth.lsa.agid = 0;
ioctl( i_fd, DVD_AUTH, &auth );
css.b_error = 1;
return css;
}
css.i_agid = auth.lsa.agid;
fprintf( stderr, "2\n" );
/* Get drive keys */
for( i = 0 ; i < 10 ; ++i )
{
css.keys.pi_challenge[i] = i;
}
fprintf( stderr, "3\n" );
if( ioctl( i_fd, DVD_AUTH, &auth ) < 0 )
{
intf_ErrMsg( "DVD ioctl error in CSSInit (Drive keys)" );
css.b_error = 1;
return css;
}
fprintf( stderr, "4\n" );
if( ioctl( i_fd, DVD_AUTH, &auth ) < 0 )
{
intf_ErrMsg( "DVD ioctl error in CSSInit (Drive keys)" );
css.b_error = 1;
return css;
}
fprintf( stderr, "5\n" );
for( i=0 ; i<KEY_SIZE ; i++ )
{
css.keys.pi_key1[i] = auth.lsk.key[KEY_SIZE -1 -i];
}
fprintf( stderr, "6\n" );
i=0;
do {
CSSCryptKey( 0, i, css.keys.pi_challenge, css.keys.pi_key_check );
i++;
intf_Msg( "Drive Authentic - using varient %d", i-1 );
} while( (i<32) &&
( memcmp( css.keys.pi_key_check, css.keys.pi_key1, KEY_SIZE ) != 0 ) );
fprintf( stderr, "1\n" );
css.keys.i_version = i-1;
auth.type = DVD_LU_SEND_CHALLENGE;
if( ioctl( i_fd, DVD_AUTH, &auth ) < 0 )
{
intf_ErrMsg( "DVD ioctl error in CSSInit (drive Keys)" );
css.b_error = 1;
return css;
}
fprintf( stderr, "7\n" );
for( i = 0; i < 2*KEY_SIZE; ++i )
{
css.keys.pi_challenge[i] = auth.hsc.chal[2*KEY_SIZE -1 -i];
}
CSSCryptKey( 1, css.keys.i_version,
css.keys.pi_challenge, css.keys.pi_key2 );
auth.type = DVD_HOST_SEND_KEY2;
for( i = 0 ; i < KEY_SIZE ; ++i )
{
auth.hsk.key[4-i] = css.keys.pi_key2[i];
}
fprintf( stderr, "8\n" );
if( ioctl( i_fd, DVD_AUTH, &auth ) < 0)
{
intf_ErrMsg( "Send key2 to LU failed (expected)" );
css.b_error = 1;
return css;
}
fprintf( stderr, "9\n" );
memcpy( css.keys.pi_challenge, css.keys.pi_key1, KEY_SIZE );
memcpy( css.keys.pi_challenge+KEY_SIZE, css.keys.pi_key2, KEY_SIZE );
fprintf( stderr, "10\n" );
CSSCryptKey( 2, css.keys.i_version,
css.keys.pi_challenge, css.keys.pi_key_check );
intf_WarnMsg( 3, "DVD agid : %d", css.i_agid );
fprintf( stderr, "11\n" );
#else
DiscKeys *disc = &discKeys;
dvd_authinfo ai;
int i, agid;
dvd_struct s;
int fd=i_fd;
int tries;
int rv=-1;
css_t css;
memset (&ai, 0, sizeof (ai));
if (CSSGetASF (fd))
return css;
/* Init sequence, request AGID */
for (tries = 1; (tries < 4)&&(rv== -1) ; ++tries) {
intf_ErrMsg( "Request AGID [%d]...", tries );
ai.type = DVD_LU_SEND_AGID;
ai.lsa.agid = 0;
rv = ioctl (fd, DVD_AUTH, &ai);
if (rv == -1) {
intf_ErrMsg( "N/A, invalidating" );
ai.type = DVD_INVALIDATE_AGID;
ai.lsa.agid = 0;
ioctl (fd, DVD_AUTH, &ai);
}
}
if (rv != -1) {
intf_ErrMsg("Cannot get AGID\n");
}
for (i = 0; i < 10; ++i)
disc->Challenge[i] = i;
/* Send AGID to host */
if (_CSSAuthHost(&ai, disc) < 0) {
intf_ErrMsg("CSS Error :Send AGID to host failed\n");
return css;
}
/* Get challenge from host */
if (_CSSAuthHost(&ai, disc) < 0) {
intf_ErrMsg("CSS Error :Get challenge from host failed\n");
return css;
}
agid = ai.lsa.agid;
/* Send challenge to LU */
if (ioctl(fd, DVD_AUTH, &ai) < 0) {
intf_ErrMsg("CSS Error :Send challenge to LU failed\n");
return css;
}
/* Get key1 from LU */
if (ioctl(fd, DVD_AUTH, &ai) < 0) {
intf_ErrMsg("CSS Error :Get key1 from LU failed\n");
return css;
}
/* Send key1 to host */
if (_CSSAuthHost(&ai, disc) < 0) {
intf_ErrMsg("CSS Error :Send key1 to host failed\n");
return css;
}
/* Get challenge from LU */
if (ioctl(fd, DVD_AUTH, &ai) < 0) {
intf_ErrMsg("CSS Error :Get challenge from LU failed\n");
return css;
}
/* Send challenge to host */
if (_CSSAuthHost (&ai, disc) < 0) {
intf_ErrMsg("CSS Error :Send challenge to host failed\n");
return css;
}
/* Get key2 from host */
if (_CSSAuthHost (&ai, disc) < 0) {
intf_ErrMsg("CSS Error :Get key2 from host failed\n");
return css;
}
/* Send key2 to LU */
if (ioctl(fd, DVD_AUTH, &ai) < 0) {
intf_ErrMsg("CSS Error :Send key2 to LU failed (expected)\n");
return css;
}
if (ai.type == DVD_AUTH_ESTABLISHED)
intf_ErrMsg("CSS Error :DVD is authenticated\n");
else if (ai.type == DVD_AUTH_FAILURE)
intf_ErrMsg("CSS Error :DVD authentication failed\n");
memcpy (disc->Challenge, disc->Key1, KEY_SIZE);
memcpy (disc->Challenge+KEY_SIZE, disc->Key2, KEY_SIZE);
CryptBusKey (disc->varient, disc->Challenge, disc->KeyCheck);
intf_Msg( "Received Session Key\n" );
for( i=0 ; i<KEY_SIZE ; i++ )
{
intf_Msg( "%02x", &disc->KeyCheck[i] );
}
intf_Msg( "\n" );
if (agid < 0)
return css;
if (CSSGetASF (fd) < 0)
return css;
s.type = DVD_STRUCT_DISCKEY;
s.disckey.agid = agid;
memset (s.disckey.value, 0, 2048);
if (ioctl(fd, DVD_READ_STRUCT, &s)<0) {
intf_ErrMsg( "Error : Could not read Disc Key" );
css.b_error = 1;
return css;
}
for (i=0; i<sizeof s.disckey.value; i++)
s.disckey.value[i] ^= disc->KeyCheck[4 - (i % KEY_SIZE)];
// _CSSPrintDebugBytes ("Received Disc Key", s.disckey.value, 10);
memcpy (disc->KeyCheck, s.disckey.value, 2048);
if (CSSGetASF (fd) < 0)
{
css.b_error = 1;
return css;
}
#endif
return css;
}
/*****************************************************************************
* CSSGetKeys : get the disc key of the media en the dvd device, and then
* the title keys.
* The DVD should have been opened before.
*****************************************************************************/
#define MaxKeys 1000
struct
{
int verbosity ; /* 0-9 */
int repetitions ;
int scanall ;
char *infile ;
} params ;
typedef struct
{
int occ;
DVD40bitKey key;
} KeyOcc;
int CSSGetKeys( css_t * p_css )
{
#if 0
/*
* css_auth/libcss method from Derek Fawcus.
* Get encrypted keys with ioctls and decrypt them
* with cracked player keys
*/
dvd_struct dvd;
dvd_authinfo auth;
int i, j;
if( CSSGetASF( p_css->i_fd ) < 0 )
{
return 1;
}
/* Disk key */
dvd.type = DVD_STRUCT_DISCKEY;
dvd.disckey.agid = p_css->i_agid;
memset( dvd.disckey.value, 0, 2048 );
if( ioctl( p_css->i_fd, DVD_READ_STRUCT, &dvd )<0 )
{
intf_ErrMsg( "DVD ioctl error in CSSGetKeys" );
p_css->b_error = 1;
return 1;
}
for( i=0 ; i<sizeof(dvd.disckey.value) ; i++ )
{
dvd.disckey.value[i] ^=
p_css->keys.pi_key_check[4 - (i % KEY_SIZE )];
}
memcpy( p_css->pi_disc_key, dvd.disckey.value, 2048 );
if( CSSGetASF( p_css->i_fd ) < 0 )
{
return 1;
}
/* Title keys */
auth.type = DVD_LU_SEND_TITLE_KEY;
auth.lstk.agid = p_css->i_agid;
for( j=0 ; j<p_css->i_title_nb ; j++ )
{
auth.lstk.lba = p_css->p_title_key[j].i_lba;
if( ioctl( p_css->i_fd, DVD_AUTH, &auth )<0 )
{
intf_ErrMsg( "DVD ioctl error in CSSGetKeys" );
p_css->b_error = 1;
return 1;
}
for( i=0 ; i<KEY_SIZE ; ++i )
{
auth.lstk.title_key[i] ^=
p_css->keys.pi_key_check[4 - (i % KEY_SIZE)];
memcpy( p_css->p_title_key[j].key, auth.lstk.title_key, KEY_SIZE );
}
}
if( CSSGetASF( p_css->i_fd ) < 0 )
{
return 1;
}
#else
/*
* Cracking method from Ethan Hawke.
* Does not use key tables and ioctls.
*/
FILE* in;
unsigned char buf[0x800] ;
DVD40bitKey MyKey ;
int pos ;
int BytesRead ;
int BestPLen ;
int BestP ;
int i,j,k ;
int encrypted=0 ;
int filsize ;
KeyOcc PosKey[MaxKeys] ;
int RegisteredKeys = 0 ;
int TotalKeysFound = 0 ;
int StopScanning = 0 ;
int highest=0 ;
if( (in = fopen( "/dvd/video_ts/vts_01_1.vob", "rb") ) )
{
fprintf( stderr, "CSS:File opened\n" );
pos = 0;
fseek(in,0,SEEK_END);
filsize = ftell(in);
fseek(in,0,SEEK_SET);
do
{
if (params.verbosity >= 1 && filsize > 1024*1024)
{
fprintf(stderr, "%.2f of file read, %i keys found...\r",
pos*100.0/filsize,
TotalKeysFound);
}
BytesRead = fread(buf,1,0x800,in);
if (buf[0x14] & 0x30) // PES_scrambling_control
{
encrypted = 1;
BestPLen = 0;
BestP = 0;
for(i=2;i<0x30;i++)
{
for(j=i; (j < 0x80) && (buf[0x7F - (j%i)] == buf[0x7F-j]); j++);
if ((j>BestPLen) && (j>i))
{
BestPLen = j;
BestP = i;
}
}
if ((BestPLen > 20) && (BestPLen / BestP >= 2))
{
i = CSScracker(0,&buf[0x80],&buf[0x80-(BestPLen/BestP)*BestP],(DVD40bitKey*)&buf[0x54],&MyKey);
while (i>=0)
{
k = 0;
for(j=0;j<RegisteredKeys;j++)
{
if (memcmp(&(PosKey[j].key),&MyKey,sizeof(DVD40bitKey))==0)
{
PosKey[j].occ++ ;
TotalKeysFound++ ;
k = 1 ;
}
}
if (k==0)
{
memcpy(&(PosKey[RegisteredKeys].key), &MyKey, sizeof(DVD40bitKey)) ;
PosKey[RegisteredKeys++].occ = 1 ;
TotalKeysFound++ ;
}
if (params.verbosity >= 2)
{
fprintf(stderr, "\nOfs:%08X - Key: %02X %02X %02X %02X %02X\n",
pos, MyKey[0] ,MyKey[1], MyKey[2],
MyKey[3], MyKey[4]) ;
}
i = CSScracker(i,&buf[0x80],&buf[0x80-(BestPLen/BestP)*BestP],(DVD40bitKey*)&buf[0x54],&MyKey);
}
if (params.scanall==0 && RegisteredKeys==1 && PosKey[0].occ >= params.repetitions)
{
StopScanning = 1;
}
}
}
pos += BytesRead;
} while (BytesRead==0x800 && !StopScanning);
fclose(in);
if (params.verbosity >= 1 && StopScanning)
{
fprintf(stderr, "Found enough occurancies of the same key. Scan stopped.");
}
if (params.verbosity >= 1)
{
fprintf(stderr, "\n\n") ;
}
}
else
{
fprintf(stderr, "FILE ERROR: File could not be opened. [Check if file is readable]\n");
return(1);
}
if (!encrypted)
{
fprintf(stderr, "This file was _NOT_ encrypted!\n");
return(0);
}
if (encrypted && RegisteredKeys==0)
{
fprintf(stderr, "Sorry... Unable to determine keys from file.\n");
return(1);
}
for(i=0;i<RegisteredKeys-1;i++)
{
for(j=i+1;j<RegisteredKeys;j++)
{
if (PosKey[j].occ>PosKey[i].occ)
{
memcpy(&MyKey,&(PosKey[j].key),sizeof(DVD40bitKey));
k = PosKey[j].occ;
memcpy(&(PosKey[j].key),&(PosKey[i].key),sizeof(DVD40bitKey));
PosKey[j].occ = PosKey[i].occ;
memcpy(&(PosKey[i].key),&MyKey,sizeof(DVD40bitKey));
PosKey[i].occ = k;
}
}
}
if (params.verbosity >= 1)
{
fprintf(stderr, " Key(s) & key probability\n--------------------------\n");
highest=0 ;
for(i=0; i<RegisteredKeys; i++)
{
fprintf(stderr, "%d) %02X %02X %02X %02X %02X - %3.2f%%\n", i,
PosKey[i].key[0],PosKey[i].key[1],PosKey[i].key[2],
PosKey[i].key[3],PosKey[i].key[4],
PosKey[i].occ*100.0/TotalKeysFound) ;
if (PosKey[highest].occ*100.0/TotalKeysFound
<= PosKey[i].occ*100.0/TotalKeysFound)
{
highest=i ;
}
}
fprintf(stderr, "\n");
}
/* The "find the key with the highest probability" code
is untested, as I haven't been able to find a VOB that
produces multiple keys (RT)
*/
printf("%02X %02X %02X %02X %02X\n",
PosKey[highest].key[0],PosKey[highest].key[1],PosKey[highest].key[2],
PosKey[highest].key[3],PosKey[highest].key[4]) ;
for( i=0 ; i<5 ; i++ )
{
// p_css->p_title_key->key[i] = PosKey[highest].key[i];
}
#endif
return 0;
}
/*****************************************************************************
* CSSDescrambleSector
*****************************************************************************/
int CSSDescrambleSector( DVD40bitKey* key, unsigned char * sec )
{
#if 0
FILE *in,*out ;
unsigned char buf[0x800] ;
int pos ;
int BytesRead ;
int BytesWritten ;
int filsize ;
do {
BytesRead = fread(&buf,1,0x800,in);
if (buf[0x14] & 0x30) // PES_scrambling_control
{
unsigned int t1,t2,t3,t4,t5,t6;
unsigned char *end=sec+0x800;
t1=((*key)[0] ^ sec[0x54]) | 0x100;
t2=(*key)[1] ^ sec[0x55];
t3= (((*key)[2]) | ((*key)[3]<<8) |
((*key)[4]<<16)) ^ ((sec[0x56]) |
(sec[0x57]<<8) | (sec[0x58]<<16));
t4=t3&7;
t3=t3*2+8-t4;
sec+=0x80;
t5=0;
while(sec!=end)
{
t4 = pi_css_tab2[t2] ^ pi_css_tab3[t1];
t2=t1>>1;
t1=((t1&1)<<8)^t4;
t4 = pi_css_tab5[t4];
t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
t3=(t3<<8)|t6;
t6 = pi_css_tab4[t6];
t5+=t6+t4;
*sec++= pi_css_tab1[*sec]^(t5&0xff);
t5>>=8;
}
buf[0x14] &= 0x8F;
}
BytesWritten = fwrite(&buf,1,BytesRead,out);
if (BytesWritten!=BytesRead)
{
fprintf(stderr, "Could not write to output file.\n");
return(1);
}
pos += BytesRead;
} while (BytesRead==0x800);
#endif
return(0);
}
/*****************************************************************************
* dvd_css.h: Structures for DVD authentification and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define KEY_SIZE 5
typedef unsigned char DVD40bitKey[KEY_SIZE];
typedef struct drive_key_s
{
u8 pi_challenge[2*KEY_SIZE];
u8 pi_key1[KEY_SIZE];
u8 pi_key2[KEY_SIZE];
u8 pi_key_check[KEY_SIZE];
u8 i_version;
} drive_key_t;
typedef struct title_key_s
{
u32 i_lba;
u8 key[KEY_SIZE];
} title_key_t;
typedef struct css_s
{
int i_fd;
boolean_t b_error;
int i_agid;
drive_key_t keys;
u8 pi_disc_key[2048];
int i_title_nb;
title_key_t* p_title_key;
} css_t;
/*****************************************************************************
* Prototypes in dvd_css.c
*****************************************************************************/
struct css_s CSSInit ( int );
int CSSGetKeys ( struct css_s* );
...@@ -39,10 +39,10 @@ ...@@ -39,10 +39,10 @@
*/ */
/***************************************************************************** /*****************************************************************************
* IfoFindStart : When reading directly on a device, finds the offset to the * IfoFindVMG : When reading directly on a device, finds the offset to the
* beginning of video_ts.ifo. * beginning of video_ts.ifo.
*****************************************************************************/ *****************************************************************************/
static int IfoFindStart( ifo_t* p_ifo ) static int IfoFindVMG( ifo_t* p_ifo )
{ {
char psz_ifo_start[12] = "DVDVIDEO-VMG"; char psz_ifo_start[12] = "DVDVIDEO-VMG";
char psz_test[12]; char psz_test[12];
...@@ -103,7 +103,7 @@ ifo_t IfoInit( int i_fd ) ...@@ -103,7 +103,7 @@ ifo_t IfoInit( int i_fd )
* 512000 bytes is just another value :) */ * 512000 bytes is just another value :) */
ifo.i_pos = lseek64( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET ); ifo.i_pos = lseek64( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET );
/* FIXME : use udf filesystem to find the beginning of the file */ /* FIXME : use udf filesystem to find the beginning of the file */
IfoFindStart( &ifo ); IfoFindVMG( &ifo );
return ifo; return ifo;
} }
...@@ -177,7 +177,7 @@ fprintf(stderr, "Pos : %lld Val : %llx\n", \ ...@@ -177,7 +177,7 @@ fprintf(stderr, "Pos : %lld Val : %llx\n", \
(long long)(p_ifo->i_pos - i_start), \ (long long)(p_ifo->i_pos - i_start), \
(long long)*(p_field) ); \ (long long)*(p_field) ); \
p_ifo->i_pos = \ p_ifo->i_pos = \
lseek64( p_ifo->i_fd, p_ifo->i_pos + (i_len), SEEK_SET ); \ lseek64( p_ifo->i_fd, p_ifo->i_pos + (i_len), SEEK_SET );\
} }
#define GETC( p_field ) \ #define GETC( p_field ) \
...@@ -186,7 +186,7 @@ fprintf(stderr, "Pos : %lld Val : %llx\n", \ ...@@ -186,7 +186,7 @@ fprintf(stderr, "Pos : %lld Val : %llx\n", \
fprintf(stderr, "Pos : %lld Value : %d\n", \ fprintf(stderr, "Pos : %lld Value : %d\n", \
(long long)(p_ifo->i_pos - i_start), \ (long long)(p_ifo->i_pos - i_start), \
*(p_field) ); \ *(p_field) ); \
p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 1 , SEEK_SET ); \ p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 1 , SEEK_SET );\
} }
#define GETS( p_field ) \ #define GETS( p_field ) \
...@@ -196,7 +196,7 @@ fprintf(stderr, "Pos : %lld Value : %d\n", \ ...@@ -196,7 +196,7 @@ fprintf(stderr, "Pos : %lld Value : %d\n", \
fprintf(stderr, "Pos : %lld Value : %d\n", \ fprintf(stderr, "Pos : %lld Value : %d\n", \
(long long)(p_ifo->i_pos - i_start), \ (long long)(p_ifo->i_pos - i_start), \
*(p_field) ); \ *(p_field) ); \
p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 2 , SEEK_SET ); \ p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 2 , SEEK_SET );\
} }
#define GETL( p_field ) \ #define GETL( p_field ) \
...@@ -206,7 +206,7 @@ fprintf(stderr, "Pos : %lld Value : %d\n", \ ...@@ -206,7 +206,7 @@ fprintf(stderr, "Pos : %lld Value : %d\n", \
fprintf(stderr, "Pos : %lld Value : %d\n", \ fprintf(stderr, "Pos : %lld Value : %d\n", \
(long long)(p_ifo->i_pos - i_start), \ (long long)(p_ifo->i_pos - i_start), \
*(p_field) ); \ *(p_field) ); \
p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 4 , SEEK_SET ); \ p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 4 , SEEK_SET );\
} }
#define GETLL( p_field ) \ #define GETLL( p_field ) \
...@@ -216,13 +216,13 @@ fprintf(stderr, "Pos : %lld Value : %d\n", \ ...@@ -216,13 +216,13 @@ fprintf(stderr, "Pos : %lld Value : %d\n", \
fprintf(stderr, "Pos : %lld Value : %lld\n", \ fprintf(stderr, "Pos : %lld Value : %lld\n", \
(long long)(p_ifo->i_pos - i_start), \ (long long)(p_ifo->i_pos - i_start), \
*(p_field) ); \ *(p_field) ); \
p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 8 , SEEK_SET ); \ p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 8 , SEEK_SET );\
} }
#define FLUSH( i_len ) \ #define FLUSH( i_len ) \
{ \ { \
fprintf(stderr, "Pos : %lld\n", (long long)(p_ifo->i_pos - i_start)); \ fprintf(stderr, "Pos : %lld\n", (long long)(p_ifo->i_pos - i_start)); \
p_ifo->i_pos = lseek64( p_ifo->i_fd , \ p_ifo->i_pos = lseek64( p_ifo->i_fd , \
p_ifo->i_pos + (i_len), SEEK_SET ); \ p_ifo->i_pos + (i_len), SEEK_SET ); \
} }
...@@ -1069,10 +1069,10 @@ void IfoRead( ifo_t* p_ifo ) ...@@ -1069,10 +1069,10 @@ void IfoRead( ifo_t* p_ifo )
p_ifo->b_error = 1; p_ifo->b_error = 1;
return; return;
} }
for( i=0 ; i<p_ifo->vmg.mat.i_tts_nb ; i++ ) for( i=0 ; i<1 /*p_ifo->vmg.mat.i_tts_nb*/ ; i++ )
{ {
fprintf( stderr, "######### VTS %d #############\n", i ); fprintf( stderr, "######### VTS %d #############\n", i+1 );
i_off = p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector *DVD_LB_SIZE; i_off = p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector *DVD_LB_SIZE;
p_ifo->i_pos = lseek64( p_ifo->i_fd, i_off, SEEK_SET ); p_ifo->i_pos = lseek64( p_ifo->i_fd, i_off, SEEK_SET );
......
/***************************************************************************** /*****************************************************************************
* ifo.h: Structures for ifo parsing * dvd_ifo.h: Structures for ifo parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* *
...@@ -484,8 +484,3 @@ typedef struct ifo_s ...@@ -484,8 +484,3 @@ typedef struct ifo_s
*****************************************************************************/ *****************************************************************************/
ifo_t IfoInit( int ); ifo_t IfoInit( int );
void IfoRead( ifo_t* ); void IfoRead( ifo_t* );
/*****************************************************************************
* Prototypes in input_dvd.c
*****************************************************************************/
off64_t Seek64( int, off64_t, int);
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* decoders. * decoders.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input.c,v 1.71 2001/01/16 05:04:25 sam Exp $ * $Id: input.c,v 1.72 2001/01/20 20:59:44 stef Exp $
* *
* Authors: * Authors:
* *
...@@ -416,7 +416,7 @@ static void DvdOpen( input_thread_t * p_input ) ...@@ -416,7 +416,7 @@ static void DvdOpen( input_thread_t * p_input )
{ {
intf_Msg( "input: opening DVD %s", p_input->p_config->p_source ); intf_Msg( "input: opening DVD %s", p_input->p_config->p_source );
if( (p_input->i_handle = open( p_input->p_config->p_source, if( (p_input->i_handle = open( p_input->p_config->p_source,
O_RDONLY|O_LARGEFILE )) == (-1) ) O_RDONLY| O_NONBLOCK |O_LARGEFILE )) == (-1) )
{ {
intf_ErrMsg( "input error: cannot open device (%s)", strerror(errno) ); intf_ErrMsg( "input error: cannot open device (%s)", strerror(errno) );
p_input->b_error = 1; p_input->b_error = 1;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_dvd.c: DVD reading * input_dvd.c: DVD reading
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.3 2001/01/16 04:41:20 stef Exp $ * $Id: input_dvd.c,v 1.4 2001/01/20 20:59:44 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -30,10 +30,23 @@ ...@@ -30,10 +30,23 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <sys/ioctl.h>
//#if defined(__NetBSD__) || defined(__OpenBSD__)
//# include <sys/dvdio.h>
//#elif defined(__linux__)
#include <linux/cdrom.h>
//#else
//# error "Need the DVD ioctls"
//#endif
#include "config.h" #include "config.h"
#include "common.h" #include "common.h"
#include "threads.h" #include "threads.h"
...@@ -50,6 +63,7 @@ ...@@ -50,6 +63,7 @@
#include "input.h" #include "input.h"
#include "dvd_ifo.h" #include "dvd_ifo.h"
#include "dvd_css.h"
#include "input_dvd.h" #include "input_dvd.h"
#include "mpeg_system.h" #include "mpeg_system.h"
...@@ -79,9 +93,18 @@ static void DeletePES ( void *, struct pes_packet_s * ); ...@@ -79,9 +93,18 @@ static void DeletePES ( void *, struct pes_packet_s * );
*****************************************************************************/ *****************************************************************************/
static int DVDProbe( input_thread_t * p_input ) static int DVDProbe( input_thread_t * p_input )
{ {
/* verify that the first three bytes are 0x000001, or unscramble and dvd_struct dvd;
* re-do. */
return 1; dvd.type = DVD_STRUCT_COPYRIGHT;
dvd.copyright.layer_num = 0;
if( ioctl( p_input->i_handle, DVD_READ_STRUCT, &dvd ) < 0 )
{
intf_ErrMsg( "DVD ioctl error" );
return -1;
}
return dvd.copyright.cpst;
} }
/***************************************************************************** /*****************************************************************************
...@@ -102,18 +125,44 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -102,18 +125,44 @@ static void DVDInit( input_thread_t * p_input )
p_input->p_plugin_data = (void *)p_method; p_input->p_plugin_data = (void *)p_method;
p_input->p_method_data = NULL; p_input->p_method_data = NULL;
p_method->i_fd = p_input->i_handle;
lseek64( p_input->i_handle, 0, SEEK_SET ); lseek64( p_input->i_handle, 0, SEEK_SET );
/* Ifo initialisation */ /* Ifo initialisation */
p_method->ifo = IfoInit( p_input->i_handle ); p_method->ifo = IfoInit( p_input->i_handle );
IfoRead( &(p_method->ifo) ); IfoRead( &(p_method->ifo) );
/* CSS authentication and keys */
if( ( p_method->b_encrypted = DVDProbe( p_input ) ) )
{
fprintf(stderr, " CSS Init start\n" );
p_method->css = CSSInit( p_input->i_handle );
fprintf(stderr, " CSS Init end\n" );
p_method->css.i_title_nb = 1/*p_method->ifo.vmg.ptt_srpt.i_nb*/;
#if 0
if( (p_title_key =
malloc( p_method->css.i_title_nb *sizeof(title_key_t) )) == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
#endif
fprintf(stderr, " CSS Get start\n" );
CSSGetKeys( &(p_method->css) );
fprintf(stderr, " CSS Get end\n" );
}
i_start = p_method->ifo.p_vts[0].i_pos + i_start = p_method->ifo.p_vts[0].i_pos +
p_method->ifo.p_vts[0].mat.i_tt_vobs_ssector *DVD_LB_SIZE; p_method->ifo.p_vts[0].mat.i_tt_vobs_ssector *DVD_LB_SIZE;
i_start = lseek64( p_input->i_handle, i_start, SEEK_SET ); i_start = lseek64( p_input->i_handle, i_start, SEEK_SET );
fprintf(stderr, "Begin at : %lld\n", (long long)i_start ); fprintf(stderr, "Begin at : %lld\n", (long long)i_start );
#if 1
input_InitStream( p_input, sizeof( stream_ps_data_t ) ); input_InitStream( p_input, sizeof( stream_ps_data_t ) );
input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) ); input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
...@@ -232,6 +281,7 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -232,6 +281,7 @@ static void DVDInit( input_thread_t * p_input )
} }
else else
{ {
#endif
/* The programs will be added when we read them. */ /* The programs will be added when we read them. */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.pp_programs[0]->b_is_ok = 0; p_input->stream.pp_programs[0]->b_is_ok = 0;
...@@ -270,6 +320,12 @@ static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer, ...@@ -270,6 +320,12 @@ static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
default: default:
break; break;
} }
#if 0
if( p_method->b_encrypted )
{
CSSDescrambleSector( p_method->css.p_title_key.key, p_buffer );
}
#endif
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_tell += i_nb; p_input->stream.i_tell += i_nb;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
......
...@@ -25,6 +25,12 @@ ...@@ -25,6 +25,12 @@
*****************************************************************************/ *****************************************************************************/
typedef struct thread_dvd_data_s typedef struct thread_dvd_data_s
{ {
int i_fd;
boolean_t b_encrypted;
/* Scrambling Information */
struct css_s css;
/* Structure that contains all information of the DVD */ /* Structure that contains all information of the DVD */
struct ifo_s ifo; struct ifo_s ifo;
} thread_dvd_data_t; } thread_dvd_data_t;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment