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