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