]> git.sesse.net Git - vlc/blob - plugins/dvd/dvd_css.c
This commit is a bit early, but it'll save Stef, Henri and me much
[vlc] / plugins / dvd / dvd_css.c
1 /*****************************************************************************
2  * dvd_css.c: Functions for DVD authentification and unscrambling
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: dvd_css.c,v 1.1 2001/02/08 04:43:27 sam Exp $
6  *
7  * Author: Stéphane Borel <stef@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
30
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <malloc.h>
36 #include <netinet/in.h>
37 #include <sys/ioctl.h>
38 #ifdef HAVE_SYS_DVDIO_H
39 # include <sys/dvdio.h>
40 #endif
41 #ifdef LINUX_DVD
42 # include <linux/cdrom.h>
43 #endif
44
45
46 #include "common.h"
47
48 #include "intf_msg.h"
49 #include "dvd_css.h"
50 #include "dvd_ifo.h"
51 #include "input_dvd.h"
52 #include "css_table.h"
53
54 /*****************************************************************************
55  * CSS tables
56  *****************************************************************************/
57
58 unsigned int pi_css_tab0[11]={ 5, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 };
59
60 unsigned char pi_css_tab1[256]=
61 {   0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76,
62     0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b,
63     0xd3, 0x93, 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96,
64     0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b,
65     0x57, 0x17, 0x5f, 0x82, 0xc7, 0x87, 0xcf, 0x12,
66     0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f,
67     0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, 0x41, 0x90,
68     0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91,
69     0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74,
70     0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75,
71     0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94,
72     0xdc, 0x9c, 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95,
73     0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10,
74     0x58, 0x18, 0x50, 0x81, 0xc8, 0x88, 0xc0, 0x11,
75     0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92,
76     0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, 0x42, 0x9f,
77     0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16,
78     0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b,
79     0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6,
80     0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb,
81     0x37, 0x77, 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72,
82     0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f,
83     0xb9, 0xf9, 0xb1, 0xa0, 0xe9, 0xa9, 0xe1, 0xf0,
84     0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1,
85     0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, 0xc5, 0x14,
86     0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15,
87     0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4,
88     0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5,
89     0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70,
90     0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71,
91     0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2,
92     0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff };
93
94 unsigned char pi_css_tab2[256]=
95 {   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
96     0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e,
97     0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
98     0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c,
99     0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23,
100     0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a,
101     0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31,
102     0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
103     0x49, 0x48, 0x4b, 0x4a, 0x4d, 0x4c, 0x4f, 0x4e,
104     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
105     0x5b, 0x5a, 0x59, 0x58, 0x5f, 0x5e, 0x5d, 0x5c,
106     0x52, 0x53, 0x50, 0x51, 0x56, 0x57, 0x54, 0x55,
107     0x6d, 0x6c, 0x6f, 0x6e, 0x69, 0x68, 0x6b, 0x6a,
108     0x64, 0x65, 0x66, 0x67, 0x60, 0x61, 0x62, 0x63,
109     0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
110     0x76, 0x77, 0x74, 0x75, 0x72, 0x73, 0x70, 0x71,
111     0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
112     0x9b, 0x9a, 0x99, 0x98, 0x9f, 0x9e, 0x9d, 0x9c,
113     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
114     0x89, 0x88, 0x8b, 0x8a, 0x8d, 0x8c, 0x8f, 0x8e,
115     0xb6, 0xb7, 0xb4, 0xb5, 0xb2, 0xb3, 0xb0, 0xb1,
116     0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
117     0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3,
118     0xad, 0xac, 0xaf, 0xae, 0xa9, 0xa8, 0xab, 0xaa,
119     0xdb, 0xda, 0xd9, 0xd8, 0xdf, 0xde, 0xdd, 0xdc,
120     0xd2, 0xd3, 0xd0, 0xd1, 0xd6, 0xd7, 0xd4, 0xd5,
121     0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce,
122     0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
123     0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
124     0xf6, 0xf7, 0xf4, 0xf5, 0xf2, 0xf3, 0xf0, 0xf1,
125     0xed, 0xec, 0xef, 0xee, 0xe9, 0xe8, 0xeb, 0xea,
126     0xe4, 0xe5, 0xe6, 0xe7, 0xe0, 0xe1, 0xe2, 0xe3
127 };
128
129 unsigned char pi_css_tab3[512]=
130 {   0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
131     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
132     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
133     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
134     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
135     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 
136     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
137     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
138     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
139     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
140     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
141     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
142     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
143     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
144     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
145     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
146     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
147     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
148     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
149     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
150     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
151     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
152     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
153     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
154     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
155     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
156     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
157     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
158     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
159     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
160     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
161     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
162     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
163     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
164     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
165     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
166     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
167     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
168     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
169     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
170     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
171     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
172     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
173     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
174     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
175     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 
176     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
177     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
178     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
179     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
180     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
181     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
182     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
183     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
184     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
185     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 
186     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
187     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
188     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
189     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 
190     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
191     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
192     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
193     0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff };
194
195 unsigned char pi_css_tab4[256]=
196 {   0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
197     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
198     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
199     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
200     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
201     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
202     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
203     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
204     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
205     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
206     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
207     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
208     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
209     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
210     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
211     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
212     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
213     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
214     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
215     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
216     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
217     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
218     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
219     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
220     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
221     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
222     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
223     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
224     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
225     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
226     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
227     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff };
228
229 unsigned char pi_css_tab5[256]=
230 {   0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f,
231     0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
232     0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17,
233     0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07,
234     0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b,
235     0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b,
236     0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13,
237     0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03,
238     0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d,
239     0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d,
240     0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15,
241     0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05,
242     0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19,
243     0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09,
244     0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11,
245     0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01,
246     0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e,
247     0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
248     0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16,
249     0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06,
250     0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a,
251     0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a,
252     0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12,
253     0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02,
254     0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c,
255     0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c,
256     0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14,
257     0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04,
258     0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18,
259     0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08,
260     0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10,
261     0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00 };
262
263 /*
264  * Local functions
265  */
266
267 /*****************************************************************************
268  * CSSGetASF : Get Authentification success flag
269  *****************************************************************************/
270 int CSSGetASF( int i_fd )
271 {
272     dvd_authinfo ai;
273
274     ai.type = DVD_LU_SEND_ASF;
275     ai.lsasf.asf = 0;
276
277     for( ai.lsasf.agid = 0 ; ai.lsasf.agid < 4 ; ai.lsasf.agid++ )
278     {
279         if( !( ioctl( i_fd, DVD_AUTH, &ai ) ) )
280         {
281             intf_Msg("CSS: %sAuthenticated\n", (ai.lsasf.asf) ? "" : "not");
282             return 0;
283         }
284     }
285     intf_ErrMsg( "CSS Error: GetASF" );
286     return -1;
287 }
288
289 /*****************************************************************************
290  * CSSCryptKey : shuffles bits and unencrypt keys.
291  * ---
292  * i_key_type : 0->key1, 1->key2, 2->buskey.
293  * i_varient : between 0 and 31.
294  *****************************************************************************/
295 static void CSSCryptKey( int i_key_type, int i_varient,
296                          u8 const * pi_challenge, u8* pi_key )
297 {
298     /* Permutation table for challenge */
299     u8      ppi_perm_challenge[3][10] = 
300             { { 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 },
301               { 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 },
302               { 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 } };
303     /* Permutation table for varient table */
304     u8      ppi_perm_varient[2][32] =
305             { { 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d,
306                 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d,
307                 0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05,
308                 0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15 },
309               { 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e,
310                 0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c,
311                 0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f,
312                 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d } };
313     u8      pi_css_secret[5] = { 0xE2, 0xA3, 0x45, 0x10, 0xF4 };
314     u8      pi_css_varients[32] =
315               { 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
316                 0x20, 0x21, 0x24, 0x25, 0x30, 0x31, 0x34, 0x35,
317                 0x80, 0x81, 0x84, 0x85, 0x90, 0x91, 0x94, 0x95,
318                 0xA0, 0xA1, 0xA4, 0xA5, 0xB0, 0xB1, 0xB4, 0xB5 };
319     u8      pi_bits[30];
320     u8      pi_scratch[10];
321     u8      pi_tmp1[5];
322     u8      pi_tmp2[5];
323     u8      i_lfsr0_o;
324     u8      i_lfsr1_o;
325     u32     i_lfsr0;
326     u32     i_lfsr1;
327     u8      i_css_varient;
328     int     i_val = 0;
329     int     i_term = 0;
330     int     i, i_index;
331
332     for( i=0 ; i<10 ; i++ )
333     {
334         pi_scratch[i] = pi_challenge[ppi_perm_challenge[i_key_type][i]];
335     }
336     i_css_varient = i_key_type == 0 ? i_varient
337                     : ppi_perm_varient[i_key_type-1][i_varient];
338
339     for( i=0 ; i<5 ; i++ )
340     {
341         pi_tmp1[i] = pi_scratch[5+i] ^ pi_css_secret[i];
342     }
343
344     /* In order to ensure that the LFSR works we need to ensure that the
345      * initial values are non-zero.  Thus when we initialise them from
346      * the seed,  we ensure that a bit is set.
347      */
348     i_lfsr0 = ( pi_tmp1[0] << 17 ) | ( pi_tmp1[1] << 9 ) |
349               ( ( pi_tmp1[2] & ~7 ) << 1 ) | 8 | (pi_tmp1[2] & 7);
350
351     /*
352      * reverse lfsr0/1 to simplify calculation in loop
353      */
354     i_lfsr0 = ( pi_reverse[i_lfsr0 & 0xff] << 17 ) |
355               ( pi_reverse[( i_lfsr0 >> 8 ) & 0xff] << 9 ) |
356               ( pi_reverse[( i_lfsr0 >> 16 ) & 0xff] << 1) |
357               ( i_lfsr0 >> 24 );
358
359     i_lfsr1 = ( pi_reverse[pi_tmp1[4]] << 9 ) | 0x100 |
360               ( pi_reverse[pi_tmp1[3]] );
361
362     i_index = sizeof( pi_bits );
363     do
364     {
365         i_lfsr0_o = ( i_lfsr0 >> 12) ^ ( i_lfsr0 >> 4) ^
366                     ( i_lfsr0 >> 3) ^ i_lfsr0;
367
368         i_lfsr1_o = ( ( i_lfsr1 >> 14 ) & 7) ^ i_lfsr1;
369         i_lfsr1_o ^= ( i_lfsr1_o << 3 ) ^ ( i_lfsr1_o << 6 );
370
371         i_lfsr1 = ( i_lfsr1 >> 8) ^ ( i_lfsr1_o << 9);
372         i_lfsr0 = ( i_lfsr0 >> 8 ) ^ ( i_lfsr0_o << 17);
373
374         i_lfsr0_o = ~i_lfsr0_o;
375         i_lfsr1_o = ~i_lfsr1_o;
376
377         i_val += i_lfsr0_o + i_lfsr1_o;
378     
379         pi_bits[--i_index] = i_val & 0xFF;
380         i_val >>= 8;
381
382     } while( i_index > 0 );
383
384     i_css_varient = pi_css_varients[i_css_varient];
385
386     intf_WarnMsg( 3, "CSS varient: %d\n", i_css_varient );
387
388     /* 
389      * Mangling
390      */
391     for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_scratch[i] )
392     {
393         i_index = pi_bits[25+i] ^ pi_scratch[i];
394         i_index = pi_css_mangle1[i_index] ^ i_css_varient;
395         pi_tmp1[i] = pi_css_mangle2[i_index] ^ i_term;
396     }
397     pi_tmp1[4] ^= pi_tmp1[0];
398     for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp1[i] )
399     {
400         i_index = pi_bits[20+i] ^ pi_tmp1[i];
401         i_index = pi_css_mangle1[i_index] ^ i_css_varient;
402         pi_tmp2[i] = pi_css_mangle2[i_index] ^ i_term;
403     }
404     pi_tmp2[4] ^= pi_tmp2[0];
405     for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp2[i] )
406     {
407         i_index = pi_bits[15+i] ^ pi_tmp2[i];
408         i_index = pi_css_mangle1[i_index] ^ i_css_varient;
409         i_index = pi_css_mangle2[i_index] ^ i_term;
410         pi_tmp1[i] = pi_css_mangle0[i_index];
411     }
412     pi_tmp1[4] ^= pi_tmp1[0];
413     for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp1[i] )
414     {
415         i_index = pi_bits[10+i] ^ pi_tmp1[i];
416         i_index = pi_css_mangle1[i_index] ^ i_css_varient;
417         i_index = pi_css_mangle2[i_index] ^ i_term;
418         pi_tmp2[i] = pi_css_mangle0[i_index];
419     }
420     pi_tmp2[4] ^= pi_tmp2[0];
421     for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp2[i] )
422     {
423         i_index = pi_bits[5+i] ^ pi_tmp2[i];
424         i_index = pi_css_mangle1[i_index] ^ i_css_varient;
425         pi_tmp1[i] = pi_css_mangle2[i_index] ^ i_term;
426     }
427     pi_tmp1[4] ^= pi_tmp1[0];
428
429     for( i=5, i_term=0 ; --i>=0 ; i_term=pi_tmp1[i] )
430     {
431         i_index = pi_bits[i] ^ pi_tmp1[i];
432         i_index = pi_css_mangle1[i_index] ^ i_css_varient;
433         pi_key[i] = pi_css_mangle2[i_index] ^ i_term;
434     }
435
436     return;
437 }
438
439 static int CSSAuthHost( dvd_authinfo *ai, disc_t *disc )
440 {
441     int i;
442
443     switch( ai->type )
444     {
445         /* Host data receive (host changes state) */
446         case DVD_LU_SEND_AGID:
447
448             ai->type = DVD_HOST_SEND_CHALLENGE;
449                 break;
450
451         case DVD_LU_SEND_KEY1:
452
453             for( i=0; i<KEY_SIZE; i++ )
454             {
455                 disc->pi_key1[i] = ai->lsk.key[4-i];
456             }
457
458             for( i=0; i<32; ++i )
459             {
460                 CSSCryptKey( 0, i, disc->pi_challenge,
461                                    disc->pi_key_check );
462
463                     if( memcmp( disc->pi_key_check,
464                             disc->pi_key1, KEY_SIZE ) == 0 )
465                 {
466                     intf_WarnMsg( 3, "CSS: Drive Authentic - using varient %d\n", i);
467                     disc->i_varient = i;
468                     ai->type = DVD_LU_SEND_CHALLENGE;
469                     break;
470                 }
471             }
472 //        intf_ErrMsg( "Drive would not Authenticate" );
473 //        ai->type = DVD_AUTH_FAILURE;
474 //        return -22;
475             break;
476     
477         case DVD_LU_SEND_CHALLENGE:
478                 for( i=0; i<10; ++i )
479             {
480                 disc->pi_challenge[i] = ai->hsc.chal[9-i];
481             }
482             CSSCryptKey( 1, disc->i_varient, disc->pi_challenge,
483                                              disc->pi_key2 );
484                 ai->type = DVD_HOST_SEND_KEY2;
485                 break;
486
487         /* Host data send */
488         case DVD_HOST_SEND_CHALLENGE:
489             for( i=0; i<10; ++i )
490             {
491                     ai->hsc.chal[9-i] = disc->pi_challenge[i];
492             }
493             /* Returning data, let LU change state */
494             break;
495
496         case DVD_HOST_SEND_KEY2:
497             for( i=0; i<KEY_SIZE; ++i )
498             {
499                     ai->hsk.key[4-i] = disc->pi_key2[i];
500             }
501             /* Returning data, let LU change state */
502             break;
503
504         default:
505             intf_ErrMsg( "CSS: Got invalid state %d", ai->type );
506             return -22;
507     }
508
509     return 0;
510 }
511
512 /*****************************************************************************
513  * CSSCracker : title key decryption by cracking
514  *****************************************************************************/
515
516 // FIXME : adapt to vlc
517 #define KEYSTREAMBYTES 10
518
519 static unsigned char invtab4[256];
520
521 static int CSScracker( int StartVal,
522                        unsigned char* pCrypted,
523                        unsigned char* pDecrypted,
524                        DVD_key_t *StreamKey,
525                        DVD_key_t *pkey )
526 {
527     unsigned char MyBuf[10];
528     unsigned int t1,t2,t3,t4,t5,t6;
529     unsigned int nTry;
530     unsigned int vCandidate;
531     int i;
532     unsigned int j;
533     int i_exit = -1;
534
535
536     for (i=0;i<10;i++)
537     {
538         MyBuf[i] = pi_css_tab1[pCrypted[i]] ^ pDecrypted[i]; 
539     }
540
541     /* Test that CSStab4 is a permutation */
542     memset( invtab4, 0, 256 );
543     for( i = 0 ; i < 256 ; i++ )
544     {
545         invtab4[ pi_css_tab4[i] ] = 1; 
546     }
547
548     for (i = 0 ; i < 256 ; i++)
549     {
550         if (invtab4[ i ] != 1)
551         {
552             intf_ErrMsg( "CSS: Permutation error" );
553             exit( -1 );
554         }
555     }
556
557     /* initialize the inverse of table4 */
558     for( i = 0 ; i < 256 ; i++ )
559     {
560         invtab4[ pi_css_tab4[i] ] = i;
561     }
562
563     for( nTry = StartVal ; nTry < 65536 ; nTry++ )
564     {
565         t1 = nTry >> 8 | 0x100;
566         t2 = nTry & 0xff;
567         t3 = 0;   /* not needed */
568         t5 = 0;
569
570         /* iterate cipher 4 times to reconstruct LFSR2 */
571         for( i = 0 ; i < 4 ; i++ )
572         {
573             /* advance LFSR1 normaly */
574             t4=pi_css_tab2[t2]^pi_css_tab3[t1];
575             t2=t1>>1;
576             t1=((t1&1)<<8)^t4;
577             t4=pi_css_tab5[t4];
578             /* deduce t6 & t5 */
579             t6 = MyBuf[ i ];    
580             if( t5 )
581             {
582                 t6 = ( t6 + 0xff )&0x0ff;
583             }
584             if( t6 < t4 )
585             {
586                 t6 += 0x100;
587             }
588             t6 -= t4;
589             t5 += t6 + t4;
590             t6 = invtab4[ t6 ];
591             /* feed / advance t3 / t5 */
592             t3 = (t3 << 8) | t6;
593             t5 >>= 8;
594         }
595
596         vCandidate = t3;
597
598         /* iterate 6 more times to validate candidate key */
599         for( ; i < KEYSTREAMBYTES ; i++ )
600         {
601             t4=pi_css_tab2[t2]^pi_css_tab3[t1];
602             t2=t1>>1;
603             t1=((t1&1)<<8)^t4;
604             t4=pi_css_tab5[t4];
605             t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
606             t3=(t3<<8)|t6;
607             t6=pi_css_tab4[t6];
608             t5+=t6+t4;
609             if( (t5 & 0xff) != MyBuf[i] ) break;
610             t5>>=8;
611         }
612
613         if( i == KEYSTREAMBYTES )
614         {
615             /* Do 4 backwards steps of iterating t3 to deduce initial state */
616             t3 = vCandidate;
617             for( i = 0 ; i < 4 ; i++ )
618             {
619                 t1 = t3 & 0xff;
620                 t3 = ( t3 >> 8 );
621                 /* easy to code, and fast enough bruteforce
622                  * search for byte shifted in */
623                 for( j=0 ; j < 256 ; j++ )
624                 {
625                     t3 = (t3 & 0x1ffff) | ( j << 17 );
626                     t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
627                     if( t6 == t1 ) break;  
628                 }
629             }
630 //          printf( "Candidate: t1=%03x t2=%02x t3=%08x\n", 0x100|(nTry>>8),nTry&0x0ff, t3 );
631
632             t4 = (t3>>1) - 4;
633             for(t5=0;t5<8;t5++)
634             {
635                 if ( ((t4+t5)*2 + 8 - ((t4+t5)&7))==t3 )
636                 {
637                     (*pkey)[0] = nTry>>8;
638                     (*pkey)[1] = nTry & 0xFF;
639                     (*pkey)[2] = ((t4+t5) >> 0) & 0xFF;
640                     (*pkey)[3] = ((t4+t5) >> 8) & 0xFF;
641                     (*pkey)[4] = ((t4+t5) >> 16) & 0xFF;
642                     i_exit = nTry+1;
643                 }
644             }
645         }
646     }
647
648     if (i_exit>=0)
649     {
650         (*pkey)[0] ^= (*StreamKey)[0];
651         (*pkey)[1] ^= (*StreamKey)[1];
652         (*pkey)[2] ^= (*StreamKey)[2];
653         (*pkey)[3] ^= (*StreamKey)[3];
654         (*pkey)[4] ^= (*StreamKey)[4];
655     }
656
657     return i_exit;
658 }
659
660 /*
661  * Authentication and keys
662  */
663
664 /*****************************************************************************
665  * CSSTest : check if the disc is encrypted or not
666  *****************************************************************************/
667 int CSSTest( int i_fd )
668 {
669     dvd_struct dvd;
670
671     dvd.type = DVD_STRUCT_COPYRIGHT;
672     dvd.copyright.layer_num = 0;
673
674     if( ioctl( i_fd, DVD_READ_STRUCT, &dvd ) < 0 )
675     {
676         intf_ErrMsg( "DVD ioctl error" );
677         return -1;
678     }
679
680     return dvd.copyright.cpst;
681 }
682
683 /*****************************************************************************
684  * CSSInit : CSS Structure initialisation and DVD authentication.
685  *****************************************************************************/
686
687 css_t CSSInit( int i_fd )
688 {
689     dvd_authinfo    ai;
690     dvd_struct      dvd;
691     css_t           css;
692     int             rv = -1;
693     int             i;
694
695     css.i_fd = i_fd;
696
697     memset( &ai, 0, sizeof(ai) );
698
699 //    if (CSSGetASF (i_fd))
700 //        return css;
701
702
703     /* Init sequence, request AGID */
704     for( i=1; (i<4)&&(rv== -1) ; ++i )
705     {
706         intf_WarnMsg( 3, "CSS: Request AGID [%d]...", i );
707         ai.type = DVD_LU_SEND_AGID;
708         ai.lsa.agid = 0;
709         rv =  ioctl (i_fd, DVD_AUTH, &ai);
710         if (rv == -1)
711         {
712             intf_ErrMsg( "CSS: N/A, invalidating" );
713             ai.type = DVD_INVALIDATE_AGID;
714             ai.lsa.agid = 0;
715             ioctl( i_fd, DVD_AUTH, &ai );
716         }
717     }
718     if( rv==-1 )
719     {
720         intf_ErrMsg( "CSS: Cannot get AGID\n" );
721     }
722
723     for( i=0 ; i<10; ++i )
724     {
725         css.disc.pi_challenge[i] = i;
726     }
727
728     /* Send AGID to host */
729     if( CSSAuthHost(&ai, &(css.disc) )<0 )
730     {
731         intf_ErrMsg( "CSS Error: Send AGID to host failed" );
732         return css;
733     }
734
735     /* Get challenge from host */
736     if( CSSAuthHost( &ai, &(css.disc) )<0)
737     {
738         intf_ErrMsg( "CSS Error: Get challenge from host failed" );
739         return css;
740     }
741     css.i_agid = ai.lsa.agid;
742
743     /* Send challenge to LU */
744     if( ioctl( i_fd, DVD_AUTH, &ai )<0 )
745     {
746         intf_ErrMsg( "CSS Error: Send challenge to LU failed ");
747         return css;
748     }
749
750     /* Get key1 from LU */
751     if( ioctl( i_fd, DVD_AUTH, &ai )<0)
752     {
753         intf_ErrMsg( "CSS Error: Get key1 from LU failed ");
754         return css;
755     }
756
757     /* Send key1 to host */
758 //    if (_CSSAuthHost(&ai, disc) < 0) {
759     if( CSSAuthHost( &ai, &(css.disc) )<0)
760     {
761         intf_ErrMsg( "CSS Error: Send key1 to host failed" );
762         return css;
763     }
764
765     /* Get challenge from LU */
766     if( ioctl( i_fd, DVD_AUTH, &ai)<0 )
767     {
768         intf_ErrMsg( "CSS Error: Get challenge from LU failed ");
769         return css;
770     }
771
772     /* Send challenge to host */
773     if( CSSAuthHost( &ai, &(css.disc) )<0 )
774     {
775         intf_ErrMsg( "CSS Error: Send challenge to host failed");
776         return css;
777     }
778
779     /* Get key2 from host */
780     if( CSSAuthHost( &ai, &(css.disc) )<0 )
781     {
782         intf_ErrMsg( "CSS Error: Get key2 from host failed" );
783         return css;
784     }
785
786     /* Send key2 to LU */
787     if( ioctl( i_fd, DVD_AUTH, &ai )<0 )
788     {
789         intf_ErrMsg( "CSS Error: Send key2 to LU failed (expected)" );
790         return css;
791     }
792
793     if( ai.type == DVD_AUTH_ESTABLISHED )
794     {
795         intf_WarnMsg( 3, "DVD is authenticated");
796     }
797     else if( ai.type == DVD_AUTH_FAILURE )
798     {
799         intf_ErrMsg("CSS Error: DVD authentication failed");
800     }
801
802     memcpy( css.disc.pi_challenge, css.disc.pi_key1, KEY_SIZE );
803     memcpy( css.disc.pi_challenge+KEY_SIZE, css.disc.pi_key2, KEY_SIZE );
804     CSSCryptKey( 2, css.disc.i_varient,
805                     css.disc.pi_challenge,
806                     css.disc.pi_key_check );
807
808         intf_WarnMsg( 3, "CSS: Received Session Key\n" );
809
810     if( css.i_agid < 0 )
811     {
812         return css;
813     }
814
815 //    if (CSSGetASF (i_fd) < 0)
816 //        return css;
817
818     dvd.type = DVD_STRUCT_DISCKEY;
819     dvd.disckey.agid = css.i_agid;
820     memset( dvd.disckey.value, 0, 2048 );
821
822     if( ioctl( i_fd, DVD_READ_STRUCT, &dvd )<0 )
823     {
824         intf_ErrMsg( "CSS Error: Could not read Disc Key" );
825         css.b_error = 1;
826         return css;
827     }
828
829     for (i=0; i<sizeof dvd.disckey.value; i++)
830     {
831         dvd.disckey.value[i] ^= css.disc.pi_key_check[4 - (i % KEY_SIZE)];
832     }
833     memcpy( css.disc.pi_key_check, dvd.disckey.value, 2048 );
834 //    
835 //    if (CSSGetASF (i_fd) < 0)
836 //    {
837 //        css.b_error = 1;
838 //        return css;
839 //    }
840
841     return css;
842 }
843
844 /*****************************************************************************
845  * CSSGetKeys : get the disc key of the media en the dvd device, and then
846  * the title keys.
847  * The DVD should have been opened before.
848  *****************************************************************************/
849 #define MaxKeys 1000
850 #define REPEAT  2
851
852 int CSSGetKeys( css_t * p_css )
853 {
854 #if 0
855
856     /* 
857      * css_auth/libcss method from Derek Fawcus.
858      * Get encrypted keys with ioctls and decrypt them
859      * with cracked player keys
860      */
861     dvd_struct      dvd;
862     dvd_authinfo    auth;
863     int             i, j;
864     if( CSSGetASF( p_css->i_fd ) < 0 )
865     {
866         return 1;
867     }
868
869     /* Disk key */
870     dvd.type = DVD_STRUCT_DISCKEY;
871     dvd.disckey.agid = p_css->i_agid;
872     memset( dvd.disckey.value, 0, 2048 );
873     
874     if( ioctl( p_css->i_fd, DVD_READ_STRUCT, &dvd )<0 )
875     {
876         intf_ErrMsg( "DVD ioctl error in CSSGetKeys" );
877         p_css->b_error = 1;
878         return 1;
879     }
880
881     for( i=0 ; i<sizeof(dvd.disckey.value) ; i++ )
882     {
883         dvd.disckey.value[i] ^=
884                     p_css->keys.pi_key_check[4 - (i % KEY_SIZE )];
885     }
886
887     memcpy( p_css->pi_disc_key, dvd.disckey.value, 2048 );
888
889     if( CSSGetASF( p_css->i_fd ) < 0 )
890     {
891         return 1;
892     }
893
894     /* Title keys */
895     auth.type = DVD_LU_SEND_TITLE_KEY;
896     auth.lstk.agid = p_css->i_agid;
897
898     for( j=0 ; j<p_css->i_title_nb ; j++ )
899     {
900         auth.lstk.lba = p_css->p_title_key[j].i_lba;
901
902         if( ioctl( p_css->i_fd, DVD_AUTH, &auth )<0 )
903         {
904             intf_ErrMsg( "DVD ioctl error in CSSGetKeys" );
905             p_css->b_error = 1;
906             return 1;
907         }
908     
909         for( i=0 ; i<KEY_SIZE ; ++i )
910         {
911             auth.lstk.title_key[i] ^=
912                     p_css->keys.pi_key_check[4 - (i % KEY_SIZE)];
913             memcpy( p_css->p_title_key[j].key, auth.lstk.title_key, KEY_SIZE );
914         }
915     }
916
917     if( CSSGetASF( p_css->i_fd ) < 0 )
918     {
919         return 1;
920     }
921
922 #endif
923 #if 1
924
925     /* 
926      * Cracking method from Ethan Hawke.
927      * Does not use key tables and ioctls.
928      */ 
929     u8          pi_buf[0x800] ;
930     DVD_key_t   my_key;
931     title_key_t title_key[MaxKeys] ;
932     int         i_title;
933     off64_t             i_pos = 0;
934     int         i_bytes_read;
935     int         i_best_plen;
936     int         i_best_p;
937     int         i,j,k;
938     int         i_registered_keys = 0 ;
939     int         i_total_keys_found = 0 ;
940     int                 i_highest=0 ;
941     boolean_t   b_encrypted = 0;
942     boolean_t   b_stop_scanning = 0 ;
943
944     int         i_fd = p_css->i_fd;
945
946     for( i_title=0 ; i_title<1/*p_css->i_title_nb*/ ; i_title++ )
947     {
948         i_pos = p_css->p_title_key[i_title].i;
949         do
950         {
951             i_pos = lseek64( i_fd, i_pos, SEEK_SET );
952             i_bytes_read = read( i_fd, pi_buf, 0x800 );
953             if( pi_buf[0x14] & 0x30 ) // PES_scrambling_control
954             {
955                 b_encrypted = 1;
956                 i_best_plen = 0;
957                 i_best_p = 0;
958                 for( i=2 ; i<0x30 ; i++ )
959                 {
960                     for( j=i ; (j<0x80) && 
961                            (pi_buf[0x7F - (j%i)] == pi_buf[0x7F-j]) ; j++ );
962                     if( (j>i_best_plen) && (j>i) )
963                     {
964                         i_best_plen = j;
965                         i_best_p = i;
966                     }
967                 }
968                 if( (i_best_plen>20) && (i_best_plen / i_best_p >= 2) )
969                 {
970                     i = CSScracker( 0,  &pi_buf[0x80],
971                             &pi_buf[0x80 - ( i_best_plen / i_best_p) *i_best_p],
972                             (DVD_key_t*)&pi_buf[0x54],
973                             &my_key );
974                     while( i>=0 )
975                     {
976                         k = 0;
977                         for( j=0 ; j<i_registered_keys ; j++ )
978                         {
979                             if( memcmp( &(title_key[j].key),
980                                         &my_key, sizeof(DVD_key_t) ) == 0 )
981                             {
982                                 title_key[j].i++;
983                                 i_total_keys_found++;
984                                 k = 1;
985                             }
986                         }
987                         if( k == 0 )
988                         {
989                             memcpy( &( title_key[i_registered_keys].key),
990                                             &my_key,
991                                             sizeof(DVD_key_t) );
992                             title_key[i_registered_keys++].i = 1;
993                             i_total_keys_found++;
994                         }
995                         i = CSScracker( i, &pi_buf[0x80],
996                             &pi_buf[0x80 -( i_best_plen / i_best_p) *i_best_p],
997                             (DVD_key_t*)&pi_buf[0x54], &my_key);
998                     }
999                     if( i_registered_keys == 1 && title_key[0].i >= REPEAT )
1000                     {
1001                         b_stop_scanning = 1;
1002                     }
1003                 }
1004             }
1005             i_pos += i_bytes_read;
1006         } while( i_bytes_read == 0x800 && !b_stop_scanning);
1007     
1008         if( b_stop_scanning)
1009         {
1010             intf_WarnMsg( 3,
1011                 "CSS: Found enough occurancies of the same key." );
1012         }
1013         if( !b_encrypted )
1014         {
1015             intf_WarnMsg( 3, "CSS: This file was _NOT_ encrypted!");
1016             return(0);
1017         }
1018         if( b_encrypted && i_registered_keys == 0 )
1019         {
1020             intf_WarnMsg( 3 , "CSS: Unable to determine keys from file.");
1021             return(1);
1022         }
1023         for( i=0 ; i<i_registered_keys-1 ; i++ )
1024         {
1025             for( j=i+1 ; j<i_registered_keys ; j++ )
1026             {
1027                 if( title_key[j].i > title_key[i].i )
1028                 {
1029                     memcpy( &my_key, &(title_key[j].key), sizeof(DVD_key_t) );
1030                     k = title_key[j].i;
1031                     memcpy( &(title_key[j].key),
1032                             &(title_key[i].key), sizeof(DVD_key_t) );
1033                     title_key[j].i = title_key[i].i;
1034                     memcpy( &(title_key[i].key),&my_key, sizeof(DVD_key_t) );
1035                     title_key[i].i = k;
1036                 }
1037             }
1038         }
1039         i_highest = 0;
1040 #if 0
1041         fprintf(stderr, " Key(s) & key probability\n---------------------\n");
1042         for( i=0 ; i<i_registered_keys ; i++ )
1043         {
1044             fprintf(stderr, "%d) %02X %02X %02X %02X %02X - %3.2f%%\n", i,
1045                         title_key[i].key[0], title_key[i].key[1],
1046                         title_key[i].key[2], title_key[i].key[3],
1047                         title_key[i].key[4],
1048                         title_key[i].i * 100.0 / i_total_keys_found );
1049             if( title_key[i_highest].i * 100.0 / i_total_keys_found
1050                                 <= title_key[i].i*100.0 / i_total_keys_found )
1051             {
1052                 i_highest = i;
1053             }
1054         }
1055         fprintf(stderr, "\n");
1056 #endif
1057     
1058         /* The "find the key with the highest probability" code
1059          * is untested, as I haven't been able to find a VOB that
1060          * produces multiple keys (RT)
1061          */
1062         intf_WarnMsg( 3, "CSS: Title %d key: %02X %02X %02X %02X %02X\n",
1063                     i_title+1,
1064                     title_key[i_highest].key[0],
1065                     title_key[i_highest].key[1],
1066                     title_key[i_highest].key[2],
1067                     title_key[i_highest].key[3],
1068                     title_key[i_highest].key[4] );
1069     
1070         memcpy( p_css->p_title_key[i_title].key,
1071                 title_key[i_highest].key, KEY_SIZE );
1072     }
1073 #endif
1074     return 0;
1075 }
1076
1077 /*****************************************************************************
1078  * CSSDescrambleSector
1079  * ---
1080  * sec : sector to descramble
1081  * key : title key for this sector
1082  *****************************************************************************/
1083 int CSSDescrambleSector( DVD_key_t key, u8* pi_sec )
1084 {
1085     unsigned int    i_t1, i_t2, i_t3, i_t4, i_t5, i_t6;
1086     u8*             pi_end = pi_sec + 0x800;
1087
1088     if( pi_sec[0x14] & 0x30) // PES_scrambling_control
1089     {
1090         i_t1 = ((key)[0] ^ pi_sec[0x54]) | 0x100;
1091         i_t2 = (key)[1] ^ pi_sec[0x55];
1092         i_t3 = (((key)[2]) | ((key)[3] << 8) |
1093                ((key)[4] << 16)) ^ ((pi_sec[0x56]) |
1094                (pi_sec[0x57] << 8) | (pi_sec[0x58] << 16));
1095         i_t4 = i_t3 & 7;
1096         i_t3 = i_t3 * 2 + 8 - i_t4;
1097         pi_sec += 0x80;
1098         i_t5 = 0;
1099
1100         while( pi_sec != pi_end )
1101         {
1102             i_t4 = pi_css_tab2[i_t2] ^ pi_css_tab3[i_t1];
1103             i_t2 = i_t1>>1;
1104             i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4;
1105             i_t4 = pi_css_tab5[i_t4];
1106             i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^
1107                                          i_t3 ) >> 8 ) ^ i_t3 ) >> 5) & 0xff;
1108             i_t3 = (i_t3 << 8 ) | i_t6;
1109             i_t6 = pi_css_tab4[i_t6];
1110             i_t5 += i_t6 + i_t4;
1111             *pi_sec++ = pi_css_tab1[*pi_sec] ^( i_t5 & 0xff );
1112             i_t5 >>= 8;
1113         }
1114
1115         pi_sec[0x14] &= 0x8F;
1116     }
1117
1118     return(0);
1119 }
1120 #endif