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