Mercurial > mplayer.hg
comparison libmpdvdkit2/css.c @ 16630:954cdf2171f6
upgrade to libdvdcss 1.2.9
author | diego |
---|---|
date | Sat, 01 Oct 2005 17:19:33 +0000 |
parents | c2ddedd0619e |
children | 0af14c5fee82 |
comparison
equal
deleted
inserted
replaced
16629:045e93202e4a | 16630:954cdf2171f6 |
---|---|
1 /***************************************************************************** | 1 /***************************************************************************** |
2 * css.c: Functions for DVD authentication and descrambling | 2 * css.c: Functions for DVD authentication and descrambling |
3 ***************************************************************************** | 3 ***************************************************************************** |
4 * Copyright (C) 1999-2001 VideoLAN | 4 * Copyright (C) 1999-2003 VideoLAN |
5 * | |
6 * Modified for use with MPlayer, changes contained in libdvdcss_changes.diff. | |
7 * detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/ | |
8 * $Id$ | 5 * $Id$ |
9 * | 6 * |
10 * Author: Stéphane Borel <stef@via.ecp.fr> | 7 * Authors: Stéphane Borel <stef@via.ecp.fr> |
11 * Håkan Hjort <d95hjort@dtek.chalmers.se> | 8 * Håkan Hjort <d95hjort@dtek.chalmers.se> |
12 * | 9 * |
13 * based on: | 10 * based on: |
14 * - css-auth by Derek Fawcus <derek@spider.com> | 11 * - css-auth by Derek Fawcus <derek@spider.com> |
15 * - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv@usa.net> | 12 * - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv@usa.net> |
16 * - The Divide and conquer attack by Frank A. Stevenson <frank@funcom.com> | 13 * - The Divide and conquer attack by Frank A. Stevenson <frank@funcom.com> |
14 * (see http://www-2.cs.cmu.edu/~dst/DeCSS/FrankStevenson/index.html) | |
17 * - DeCSSPlus by Ethan Hawke | 15 * - DeCSSPlus by Ethan Hawke |
18 * - DecVOB | 16 * - DecVOB |
19 * see http://www.lemuria.org/DeCSS/ by Tom Vogt for more information. | 17 * see http://www.lemuria.org/DeCSS/ by Tom Vogt for more information. |
20 * | 18 * |
21 * This program is free software; you can redistribute it and/or modify | 19 * This program is free software; you can redistribute it and/or modify |
41 #include <stdio.h> | 39 #include <stdio.h> |
42 #include <stdlib.h> | 40 #include <stdlib.h> |
43 #include <string.h> | 41 #include <string.h> |
44 #include <sys/types.h> | 42 #include <sys/types.h> |
45 #include <sys/stat.h> | 43 #include <sys/stat.h> |
44 # include <unistd.h> | |
46 #include <fcntl.h> | 45 #include <fcntl.h> |
47 #include <unistd.h> | 46 # include <limits.h> |
48 #include <limits.h> | |
49 | 47 |
50 #include "dvdcss.h" | 48 #include "dvdcss.h" |
51 | 49 |
52 #include "common.h" | 50 #include "common.h" |
53 #include "css.h" | 51 #include "css.h" |
57 #include "device.h" | 55 #include "device.h" |
58 | 56 |
59 /***************************************************************************** | 57 /***************************************************************************** |
60 * Local prototypes | 58 * Local prototypes |
61 *****************************************************************************/ | 59 *****************************************************************************/ |
60 static void PrintKey ( dvdcss_t, char *, uint8_t const * ); | |
61 | |
62 static int GetBusKey ( dvdcss_t ); | 62 static int GetBusKey ( dvdcss_t ); |
63 static int GetASF ( dvdcss_t ); | 63 static int GetASF ( dvdcss_t ); |
64 | 64 |
65 static void CryptKey ( int, int, uint8_t const *, uint8_t * ); | 65 static void CryptKey ( int, int, uint8_t const *, uint8_t * ); |
66 static void DecryptKey ( uint8_t, | 66 static void DecryptKey ( uint8_t, |
67 uint8_t const *, uint8_t const *, uint8_t * ); | 67 uint8_t const *, uint8_t const *, uint8_t * ); |
68 | 68 |
69 static int DecryptDiscKey ( uint8_t const *, dvd_key_t ); | 69 static int DecryptDiscKey ( dvdcss_t, uint8_t const *, dvd_key_t ); |
70 static int CrackDiscKey ( dvdcss_t, uint8_t * ); | 70 static int CrackDiscKey ( dvdcss_t, uint8_t * ); |
71 | 71 |
72 static void DecryptTitleKey ( dvd_key_t, dvd_key_t ); | 72 static void DecryptTitleKey ( dvd_key_t, dvd_key_t ); |
73 static int RecoverTitleKey ( int, uint8_t const *, | 73 static int RecoverTitleKey ( int, uint8_t const *, |
74 uint8_t const *, uint8_t const *, uint8_t * ); | 74 uint8_t const *, uint8_t const *, uint8_t * ); |
89 i_ret = ioctl_ReadCopyright( dvdcss->i_fd, 0 /* i_layer */, &i_copyright ); | 89 i_ret = ioctl_ReadCopyright( dvdcss->i_fd, 0 /* i_layer */, &i_copyright ); |
90 | 90 |
91 #ifdef WIN32 | 91 #ifdef WIN32 |
92 if( i_ret < 0 ) | 92 if( i_ret < 0 ) |
93 { | 93 { |
94 /* Maybe we didn't have enough priviledges to read the copyright | 94 /* Maybe we didn't have enough privileges to read the copyright |
95 * (see ioctl_ReadCopyright comments). | 95 * (see ioctl_ReadCopyright comments). |
96 * Apparently, on unencrypted DVDs _dvdcss_disckey() always fails, so | 96 * Apparently, on unencrypted DVDs _dvdcss_disckey() always fails, so |
97 * we can check this as a work-around. */ | 97 * we can check this as a workaround. */ |
98 i_ret = 0; | 98 i_ret = 0; |
99 i_copyright = 1; | |
99 if( _dvdcss_disckey( dvdcss ) < 0 ) | 100 if( _dvdcss_disckey( dvdcss ) < 0 ) |
101 { | |
100 i_copyright = 0; | 102 i_copyright = 0; |
101 else | 103 } |
102 i_copyright = 1; | |
103 } | 104 } |
104 #endif | 105 #endif |
105 | 106 |
106 if( i_ret < 0 ) | 107 if( i_ret < 0 ) |
107 { | 108 { |
108 /* Since it's the first ioctl we try to issue, we add a notice */ | 109 /* Since it's the first ioctl we try to issue, we add a notice */ |
109 _dvdcss_error( dvdcss, "css error: ioctl_ReadCopyright failed, " | 110 print_error( dvdcss, "css error: ioctl_ReadCopyright failed, " |
110 "make sure there is a DVD in the drive, and that " | 111 "make sure there is a DVD in the drive, and that " |
111 "you have used the correct device node." ); | 112 "you have used the correct device node." ); |
112 | 113 |
113 return i_ret; | 114 return i_ret; |
114 } | 115 } |
115 | 116 |
116 return i_copyright; | 117 return i_copyright; |
117 } | |
118 | |
119 /***************************************************************************** | |
120 * GetBusKey : Go through the CSS Authentication process | |
121 ***************************************************************************** | |
122 * It simulates the mutual authentication between logical unit and host, | |
123 * and stops when a session key (called bus key) has been established. | |
124 * Always do the full auth sequence. Some drives seem to lie and always | |
125 * respond with ASF=1. For instance the old DVD roms on Compaq Armada says | |
126 * that ASF=1 from the start and then later fail with a 'read of scrambled | |
127 * block without authentication' error. | |
128 *****************************************************************************/ | |
129 static int GetBusKey( dvdcss_t dvdcss ) | |
130 { | |
131 uint8_t p_buffer[10]; | |
132 uint8_t p_challenge[2*KEY_SIZE]; | |
133 dvd_key_t p_key1; | |
134 dvd_key_t p_key2; | |
135 dvd_key_t p_key_check; | |
136 uint8_t i_variant = 0; | |
137 char psz_warning[80]; | |
138 int i_ret = -1; | |
139 int i; | |
140 | |
141 _dvdcss_debug( dvdcss, "requesting AGID" ); | |
142 i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
143 | |
144 /* We might have to reset hung authentication processes in the drive | |
145 by invalidating the corresponding AGID'. As long as we haven't got | |
146 an AGID, invalidate one (in sequence) and try again. */ | |
147 for( i = 0; i_ret == -1 && i < 4 ; ++i ) | |
148 { | |
149 sprintf( psz_warning, | |
150 "ioctl ReportAgid failed, invalidating AGID %d", i ); | |
151 _dvdcss_debug( dvdcss, psz_warning ); | |
152 | |
153 /* This is really _not good_, should be handled by the OS. | |
154 Invalidating an AGID could make another process fail some | |
155 where in it's authentication process. */ | |
156 dvdcss->css.i_agid = i; | |
157 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
158 | |
159 _dvdcss_debug( dvdcss, "requesting AGID" ); | |
160 i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
161 } | |
162 | |
163 /* Unable to authenticate without AGID */ | |
164 if( i_ret == -1 ) | |
165 { | |
166 _dvdcss_error( dvdcss, "ioctl ReportAgid failed, fatal" ); | |
167 return -1; | |
168 } | |
169 | |
170 /* Setup a challenge, any values should work */ | |
171 for( i = 0 ; i < 10; ++i ) | |
172 { | |
173 p_challenge[i] = i; | |
174 } | |
175 | |
176 /* Get challenge from host */ | |
177 for( i = 0 ; i < 10 ; ++i ) | |
178 { | |
179 p_buffer[9-i] = p_challenge[i]; | |
180 } | |
181 | |
182 /* Send challenge to LU */ | |
183 if( ioctl_SendChallenge( dvdcss->i_fd, | |
184 &dvdcss->css.i_agid, p_buffer ) < 0 ) | |
185 { | |
186 _dvdcss_error( dvdcss, "ioctl SendChallenge failed" ); | |
187 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
188 return -1; | |
189 } | |
190 | |
191 /* Get key1 from LU */ | |
192 if( ioctl_ReportKey1( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0) | |
193 { | |
194 _dvdcss_error( dvdcss, "ioctl ReportKey1 failed" ); | |
195 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
196 return -1; | |
197 } | |
198 | |
199 /* Send key1 to host */ | |
200 for( i = 0 ; i < KEY_SIZE ; i++ ) | |
201 { | |
202 p_key1[i] = p_buffer[4-i]; | |
203 } | |
204 | |
205 for( i = 0 ; i < 32 ; ++i ) | |
206 { | |
207 CryptKey( 0, i, p_challenge, p_key_check ); | |
208 | |
209 if( memcmp( p_key_check, p_key1, KEY_SIZE ) == 0 ) | |
210 { | |
211 snprintf( psz_warning, sizeof(psz_warning), | |
212 "drive authenticated, using variant %d", i ); | |
213 _dvdcss_debug( dvdcss, psz_warning ); | |
214 i_variant = i; | |
215 break; | |
216 } | |
217 } | |
218 | |
219 if( i == 32 ) | |
220 { | |
221 _dvdcss_error( dvdcss, "drive would not authenticate" ); | |
222 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
223 return -1; | |
224 } | |
225 | |
226 /* Get challenge from LU */ | |
227 if( ioctl_ReportChallenge( dvdcss->i_fd, | |
228 &dvdcss->css.i_agid, p_buffer ) < 0 ) | |
229 { | |
230 _dvdcss_error( dvdcss, "ioctl ReportKeyChallenge failed" ); | |
231 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
232 return -1; | |
233 } | |
234 | |
235 /* Send challenge to host */ | |
236 for( i = 0 ; i < 10 ; ++i ) | |
237 { | |
238 p_challenge[i] = p_buffer[9-i]; | |
239 } | |
240 | |
241 CryptKey( 1, i_variant, p_challenge, p_key2 ); | |
242 | |
243 /* Get key2 from host */ | |
244 for( i = 0 ; i < KEY_SIZE ; ++i ) | |
245 { | |
246 p_buffer[4-i] = p_key2[i]; | |
247 } | |
248 | |
249 /* Send key2 to LU */ | |
250 if( ioctl_SendKey2( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) | |
251 { | |
252 _dvdcss_error( dvdcss, "ioctl SendKey2 failed" ); | |
253 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
254 return -1; | |
255 } | |
256 | |
257 /* The drive has accepted us as authentic. */ | |
258 _dvdcss_debug( dvdcss, "authentication established" ); | |
259 | |
260 memcpy( p_challenge, p_key1, KEY_SIZE ); | |
261 memcpy( p_challenge + KEY_SIZE, p_key2, KEY_SIZE ); | |
262 | |
263 CryptKey( 2, i_variant, p_challenge, dvdcss->css.p_bus_key ); | |
264 | |
265 return 0; | |
266 } | |
267 | |
268 /***************************************************************************** | |
269 * PrintKey : debug function that dumps a key value | |
270 *****************************************************************************/ | |
271 static void PrintKey( dvdcss_t dvdcss, char *prefix, uint8_t const *data ) | |
272 { | |
273 char psz_output[80]; | |
274 | |
275 sprintf( psz_output, "%s%02x:%02x:%02x:%02x:%02x", prefix, | |
276 data[0], data[1], data[2], data[3], data[4] ); | |
277 _dvdcss_debug( dvdcss, psz_output ); | |
278 } | 118 } |
279 | 119 |
280 /***************************************************************************** | 120 /***************************************************************************** |
281 * _dvdcss_title: crack or decrypt the current title key if needed | 121 * _dvdcss_title: crack or decrypt the current title key if needed |
282 ***************************************************************************** | 122 ***************************************************************************** |
320 i_fd = open( dvdcss->psz_cachefile, O_RDONLY ); | 160 i_fd = open( dvdcss->psz_cachefile, O_RDONLY ); |
321 b_cache = 1; | 161 b_cache = 1; |
322 | 162 |
323 if( i_fd >= 0 ) | 163 if( i_fd >= 0 ) |
324 { | 164 { |
325 if( read( i_fd, p_title_key, 5 ) == 5 ) | 165 unsigned char psz_key[KEY_SIZE * 3]; |
326 { | 166 unsigned int k0, k1, k2, k3, k4; |
327 _dvdcss_debug( dvdcss, "key found in cache" ); | 167 |
168 psz_key[KEY_SIZE * 3 - 1] = '\0'; | |
169 | |
170 if( read( i_fd, psz_key, KEY_SIZE * 3 - 1 ) == KEY_SIZE * 3 - 1 | |
171 && sscanf( psz_key, "%x:%x:%x:%x:%x", | |
172 &k0, &k1, &k2, &k3, &k4 ) == 5 ) | |
173 { | |
174 p_title_key[0] = k0; | |
175 p_title_key[1] = k1; | |
176 p_title_key[2] = k2; | |
177 p_title_key[3] = k3; | |
178 p_title_key[4] = k4; | |
179 PrintKey( dvdcss, "title key found in cache ", p_title_key ); | |
180 | |
328 /* Don't try to save it again */ | 181 /* Don't try to save it again */ |
329 b_cache = 0; | 182 b_cache = 0; |
330 i_ret = 1; | 183 i_ret = 1; |
331 } | 184 } |
185 | |
332 close( i_fd ); | 186 close( i_fd ); |
333 } | 187 } |
334 } | 188 } |
335 | 189 |
336 /* Crack or decrypt CSS title key for current VTS */ | 190 /* Crack or decrypt CSS title key for current VTS */ |
338 { | 192 { |
339 i_ret = _dvdcss_titlekey( dvdcss, i_block, p_title_key ); | 193 i_ret = _dvdcss_titlekey( dvdcss, i_block, p_title_key ); |
340 | 194 |
341 if( i_ret < 0 ) | 195 if( i_ret < 0 ) |
342 { | 196 { |
343 _dvdcss_error( dvdcss, "fatal error in vts css key" ); | 197 print_error( dvdcss, "fatal error in vts css key" ); |
344 return i_ret; | 198 return i_ret; |
345 } | 199 } |
346 | 200 |
347 if( i_ret == 0 ) | 201 if( i_ret == 0 ) |
348 { | 202 { |
349 _dvdcss_debug( dvdcss, "unencrypted title" ); | 203 print_debug( dvdcss, "unencrypted title" ); |
350 /* We cache this anyway, so we don't need to check again. */ | 204 /* We cache this anyway, so we don't need to check again. */ |
351 } | 205 } |
352 } | 206 } |
353 | 207 |
354 /* Key is valid, we store it on disk. */ | 208 /* Key is valid, we store it on disk. */ |
355 if( b_cache ) | 209 if( dvdcss->psz_cachefile[0] && b_cache ) |
356 { | 210 { |
357 i_fd = open( dvdcss->psz_cachefile, O_RDWR|O_CREAT|O_EXCL, 0644 ); | 211 i_fd = open( dvdcss->psz_cachefile, O_RDWR|O_CREAT, 0644 ); |
358 if( i_fd >= 0 ) | 212 if( i_fd >= 0 ) |
359 { | 213 { |
360 write( i_fd, p_title_key, 5 ); | 214 unsigned char psz_key[KEY_SIZE * 3 + 2]; |
215 | |
216 sprintf( psz_key, "%02x:%02x:%02x:%02x:%02x\r\n", | |
217 p_title_key[0], p_title_key[1], p_title_key[2], | |
218 p_title_key[3], p_title_key[4] ); | |
219 | |
220 write( i_fd, psz_key, KEY_SIZE * 3 + 1 ); | |
361 close( i_fd ); | 221 close( i_fd ); |
362 } | 222 } |
363 } | 223 } |
364 | 224 |
365 /* Find our spot in the list */ | 225 /* Find our spot in the list */ |
418 } | 278 } |
419 | 279 |
420 /* Get encrypted disc key */ | 280 /* Get encrypted disc key */ |
421 if( ioctl_ReadDiscKey( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) | 281 if( ioctl_ReadDiscKey( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) |
422 { | 282 { |
423 _dvdcss_error( dvdcss, "ioctl ReadDiscKey failed" ); | 283 print_error( dvdcss, "ioctl ReadDiscKey failed" ); |
424 return -1; | 284 return -1; |
425 } | 285 } |
426 | 286 |
427 /* This should have invaidated the AGID and got us ASF=1. */ | 287 /* This should have invaidated the AGID and got us ASF=1. */ |
428 if( GetASF( dvdcss ) != 1 ) | 288 if( GetASF( dvdcss ) != 1 ) |
429 { | 289 { |
430 /* Region mismatch (or region not set) is the most likely source. */ | 290 /* Region mismatch (or region not set) is the most likely source. */ |
431 _dvdcss_error( dvdcss, | 291 print_error( dvdcss, |
432 "ASF not 1 after reading disc key (region mismatch?)" ); | 292 "ASF not 1 after reading disc key (region mismatch?)" ); |
433 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | 293 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); |
434 return -1; | 294 return -1; |
435 } | 295 } |
436 | 296 |
437 /* Decrypt disc key using bus key */ | 297 /* Shuffle disc key using bus key */ |
438 for( i = 0 ; i < DVD_DISCKEY_SIZE ; i++ ) | 298 for( i = 0 ; i < DVD_DISCKEY_SIZE ; i++ ) |
439 { | 299 { |
440 p_buffer[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE) ]; | 300 p_buffer[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE) ]; |
441 } | 301 } |
442 | 302 |
303 /* Decrypt disc key */ | |
443 switch( dvdcss->i_method ) | 304 switch( dvdcss->i_method ) |
444 { | 305 { |
445 case DVDCSS_METHOD_KEY: | 306 case DVDCSS_METHOD_KEY: |
446 | 307 |
447 /* Decrypt disc key with player key. */ | 308 /* Decrypt disc key with player key. */ |
448 _dvdcss_debug( dvdcss, "decrypting disc key with player keys" ); | 309 PrintKey( dvdcss, "decrypting disc key ", p_buffer ); |
449 if( ! DecryptDiscKey( p_buffer, p_disc_key ) ) | 310 if( ! DecryptDiscKey( dvdcss, p_buffer, p_disc_key ) ) |
450 { | 311 { |
451 PrintKey( dvdcss, "decrypted disc key is ", p_disc_key ); | 312 PrintKey( dvdcss, "decrypted disc key is ", p_disc_key ); |
452 break; | 313 break; |
453 } | 314 } |
454 _dvdcss_debug( dvdcss, "failed to decrypt the disc key, " | 315 print_debug( dvdcss, "failed to decrypt the disc key, " |
455 "faulty drive/kernel? " | 316 "faulty drive/kernel? " |
456 "cracking title keys instead" ); | 317 "cracking title keys instead" ); |
457 | 318 |
458 /* Fallback, but not to DISC as the disc key might be faulty */ | 319 /* Fallback, but not to DISC as the disc key might be faulty */ |
459 dvdcss->i_method = DVDCSS_METHOD_TITLE; | 320 dvdcss->i_method = DVDCSS_METHOD_TITLE; |
460 break; | 321 break; |
461 | 322 |
462 case DVDCSS_METHOD_DISC: | 323 case DVDCSS_METHOD_DISC: |
463 | 324 |
464 /* Crack Disc key to be able to use it */ | 325 /* Crack Disc key to be able to use it */ |
465 _dvdcss_debug( dvdcss, "cracking disc key from key hash ..." | |
466 " this will take some time" ); | |
467 memcpy( p_disc_key, p_buffer, KEY_SIZE ); | 326 memcpy( p_disc_key, p_buffer, KEY_SIZE ); |
327 PrintKey( dvdcss, "cracking disc key ", p_disc_key ); | |
468 if( ! CrackDiscKey( dvdcss, p_disc_key ) ) | 328 if( ! CrackDiscKey( dvdcss, p_disc_key ) ) |
469 { | 329 { |
470 PrintKey( dvdcss, "cracked disc key is ", p_disc_key ); | 330 PrintKey( dvdcss, "cracked disc key is ", p_disc_key ); |
471 break; | 331 break; |
472 } | 332 } |
473 _dvdcss_debug( dvdcss, "failed to crack the disc key" ); | 333 print_debug( dvdcss, "failed to crack the disc key" ); |
474 memset( p_disc_key, 0, KEY_SIZE ); | 334 memset( p_disc_key, 0, KEY_SIZE ); |
475 dvdcss->i_method = DVDCSS_METHOD_TITLE; | 335 dvdcss->i_method = DVDCSS_METHOD_TITLE; |
476 break; | 336 break; |
477 | 337 |
478 default: | 338 default: |
479 | 339 |
480 _dvdcss_debug( dvdcss, "disc key needs not be decrypted" ); | 340 print_debug( dvdcss, "disc key needs not be decrypted" ); |
481 memset( p_disc_key, 0, KEY_SIZE ); | 341 memset( p_disc_key, 0, KEY_SIZE ); |
482 break; | 342 break; |
483 } | 343 } |
484 | 344 |
485 memcpy( dvdcss->css.p_disc_key, p_disc_key, KEY_SIZE ); | 345 memcpy( dvdcss->css.p_disc_key, p_disc_key, KEY_SIZE ); |
502 { | 362 { |
503 /* We have a decrypted Disc key and the ioctls are available, | 363 /* We have a decrypted Disc key and the ioctls are available, |
504 * read the title key and decrypt it. | 364 * read the title key and decrypt it. |
505 */ | 365 */ |
506 | 366 |
507 _dvdcss_debug( dvdcss, "getting title key the classic way" ); | 367 print_debug( dvdcss, "getting title key at block %i the classic way", |
368 i_pos ); | |
508 | 369 |
509 /* We need to authenticate again every time to get a new session key */ | 370 /* We need to authenticate again every time to get a new session key */ |
510 if( GetBusKey( dvdcss ) < 0 ) | 371 if( GetBusKey( dvdcss ) < 0 ) |
511 { | 372 { |
512 return -1; | 373 return -1; |
514 | 375 |
515 /* Get encrypted title key */ | 376 /* Get encrypted title key */ |
516 if( ioctl_ReadTitleKey( dvdcss->i_fd, &dvdcss->css.i_agid, | 377 if( ioctl_ReadTitleKey( dvdcss->i_fd, &dvdcss->css.i_agid, |
517 i_pos, p_key ) < 0 ) | 378 i_pos, p_key ) < 0 ) |
518 { | 379 { |
519 _dvdcss_debug( dvdcss, | 380 print_debug( dvdcss, |
520 "ioctl ReadTitleKey failed (region mismatch?)" ); | 381 "ioctl ReadTitleKey failed (region mismatch?)" ); |
521 i_ret = -1; | 382 i_ret = -1; |
522 } | 383 } |
523 | 384 |
524 /* Test ASF, it will be reset to 0 if we got a Region error */ | 385 /* Test ASF, it will be reset to 0 if we got a Region error */ |
525 switch( GetASF( dvdcss ) ) | 386 switch( GetASF( dvdcss ) ) |
526 { | 387 { |
527 case -1: | 388 case -1: |
528 /* An error getting the ASF status, something must be wrong. */ | 389 /* An error getting the ASF status, something must be wrong. */ |
529 _dvdcss_debug( dvdcss, "lost ASF requesting title key" ); | 390 print_debug( dvdcss, "lost ASF requesting title key" ); |
530 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | 391 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); |
531 i_ret = -1; | 392 i_ret = -1; |
532 break; | 393 break; |
533 | 394 |
534 case 0: | 395 case 0: |
535 /* This might either be a title that has no key, | 396 /* This might either be a title that has no key, |
536 * or we encountered a region error. */ | 397 * or we encountered a region error. */ |
537 _dvdcss_debug( dvdcss, "lost ASF requesting title key" ); | 398 print_debug( dvdcss, "lost ASF requesting title key" ); |
538 break; | 399 break; |
539 | 400 |
540 case 1: | 401 case 1: |
541 /* Drive status is ok. */ | 402 /* Drive status is ok. */ |
542 /* If the title key request failed, but we did not loose ASF, | 403 /* If the title key request failed, but we did not loose ASF, |
563 { | 424 { |
564 i_ret = 0; | 425 i_ret = 0; |
565 } | 426 } |
566 else | 427 else |
567 { | 428 { |
429 PrintKey( dvdcss, "initial disc key ", dvdcss->css.p_disc_key ); | |
568 DecryptTitleKey( dvdcss->css.p_disc_key, p_key ); | 430 DecryptTitleKey( dvdcss->css.p_disc_key, p_key ); |
431 PrintKey( dvdcss, "decrypted title key ", p_key ); | |
569 i_ret = 1; | 432 i_ret = 1; |
570 } | 433 } |
571 | 434 |
572 /* All went well either there wasn't a key or we have it now. */ | 435 /* All went well either there wasn't a key or we have it now. */ |
573 memcpy( p_title_key, p_key, KEY_SIZE ); | 436 memcpy( p_title_key, p_key, KEY_SIZE ); |
575 | 438 |
576 return i_ret; | 439 return i_ret; |
577 } | 440 } |
578 | 441 |
579 /* The title key request failed */ | 442 /* The title key request failed */ |
580 _dvdcss_debug( dvdcss, "resetting drive and cracking title key" ); | 443 print_debug( dvdcss, "resetting drive and cracking title key" ); |
581 | 444 |
582 /* Read an unscrambled sector and reset the drive */ | 445 /* Read an unscrambled sector and reset the drive */ |
583 dvdcss->pf_seek( dvdcss, 0 ); | 446 dvdcss->pf_seek( dvdcss, 0 ); |
584 dvdcss->pf_read( dvdcss, p_garbage, 1 ); | 447 dvdcss->pf_read( dvdcss, p_garbage, 1 ); |
585 dvdcss->pf_seek( dvdcss, 0 ); | 448 dvdcss->pf_seek( dvdcss, 0 ); |
610 { | 473 { |
611 unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6; | 474 unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6; |
612 uint8_t *p_end = p_sec + DVDCSS_BLOCK_SIZE; | 475 uint8_t *p_end = p_sec + DVDCSS_BLOCK_SIZE; |
613 | 476 |
614 /* PES_scrambling_control */ | 477 /* PES_scrambling_control */ |
615 if( p_sec[0x14] & 0x30) | 478 if( !(p_sec[0x14] & 0x30) ) |
616 { | 479 { |
617 i_t1 = (p_key[0] ^ p_sec[0x54]) | 0x100; | 480 return 0; |
618 i_t2 = p_key[1] ^ p_sec[0x55]; | 481 } |
619 i_t3 = (p_key[2] | (p_key[3] << 8) | | 482 |
620 (p_key[4] << 16)) ^ (p_sec[0x56] | | 483 i_t1 = (p_key[0] ^ p_sec[0x54]) | 0x100; |
621 (p_sec[0x57] << 8) | (p_sec[0x58] << 16)); | 484 i_t2 = p_key[1] ^ p_sec[0x55]; |
622 i_t4 = i_t3 & 7; | 485 i_t3 = (p_key[2] | (p_key[3] << 8) | |
623 i_t3 = i_t3 * 2 + 8 - i_t4; | 486 (p_key[4] << 16)) ^ (p_sec[0x56] | |
624 p_sec += 0x80; | 487 (p_sec[0x57] << 8) | (p_sec[0x58] << 16)); |
625 i_t5 = 0; | 488 i_t4 = i_t3 & 7; |
626 | 489 i_t3 = i_t3 * 2 + 8 - i_t4; |
627 while( p_sec != p_end ) | 490 p_sec += 0x80; |
628 { | 491 i_t5 = 0; |
629 i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1]; | 492 |
630 i_t2 = i_t1>>1; | 493 while( p_sec != p_end ) |
631 i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4; | 494 { |
632 i_t4 = p_css_tab5[i_t4]; | 495 i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1]; |
633 i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^ | 496 i_t2 = i_t1>>1; |
634 i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff; | 497 i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4; |
635 i_t3 = (i_t3 << 8 ) | i_t6; | 498 i_t4 = p_css_tab5[i_t4]; |
636 i_t6 = p_css_tab4[i_t6]; | 499 i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^ |
637 i_t5 += i_t6 + i_t4; | 500 i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff; |
638 *p_sec = p_css_tab1[*p_sec] ^ ( i_t5 & 0xff ); | 501 i_t3 = (i_t3 << 8 ) | i_t6; |
639 p_sec++; | 502 i_t6 = p_css_tab4[i_t6]; |
640 i_t5 >>= 8; | 503 i_t5 += i_t6 + i_t4; |
641 } | 504 *p_sec = p_css_tab1[*p_sec] ^ ( i_t5 & 0xff ); |
505 p_sec++; | |
506 i_t5 >>= 8; | |
642 } | 507 } |
643 | 508 |
644 return 0; | 509 return 0; |
645 } | 510 } |
646 | 511 |
647 /* Following functions are local */ | 512 /* Following functions are local */ |
513 | |
514 /***************************************************************************** | |
515 * GetBusKey : Go through the CSS Authentication process | |
516 ***************************************************************************** | |
517 * It simulates the mutual authentication between logical unit and host, | |
518 * and stops when a session key (called bus key) has been established. | |
519 * Always do the full auth sequence. Some drives seem to lie and always | |
520 * respond with ASF=1. For instance the old DVD roms on Compaq Armada says | |
521 * that ASF=1 from the start and then later fail with a 'read of scrambled | |
522 * block without authentication' error. | |
523 *****************************************************************************/ | |
524 static int GetBusKey( dvdcss_t dvdcss ) | |
525 { | |
526 uint8_t p_buffer[10]; | |
527 uint8_t p_challenge[2*KEY_SIZE]; | |
528 dvd_key_t p_key1; | |
529 dvd_key_t p_key2; | |
530 dvd_key_t p_key_check; | |
531 uint8_t i_variant = 0; | |
532 int i_ret = -1; | |
533 int i; | |
534 | |
535 print_debug( dvdcss, "requesting AGID" ); | |
536 i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
537 | |
538 /* We might have to reset hung authentication processes in the drive | |
539 * by invalidating the corresponding AGID'. As long as we haven't got | |
540 * an AGID, invalidate one (in sequence) and try again. */ | |
541 for( i = 0; i_ret == -1 && i < 4 ; ++i ) | |
542 { | |
543 print_debug( dvdcss, "ioctl ReportAgid failed, " | |
544 "invalidating AGID %d", i ); | |
545 | |
546 /* This is really _not good_, should be handled by the OS. | |
547 * Invalidating an AGID could make another process fail somewhere | |
548 * in its authentication process. */ | |
549 dvdcss->css.i_agid = i; | |
550 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
551 | |
552 print_debug( dvdcss, "requesting AGID" ); | |
553 i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
554 } | |
555 | |
556 /* Unable to authenticate without AGID */ | |
557 if( i_ret == -1 ) | |
558 { | |
559 print_error( dvdcss, "ioctl ReportAgid failed, fatal" ); | |
560 return -1; | |
561 } | |
562 | |
563 /* Setup a challenge, any values should work */ | |
564 for( i = 0 ; i < 10; ++i ) | |
565 { | |
566 p_challenge[i] = i; | |
567 } | |
568 | |
569 /* Get challenge from host */ | |
570 for( i = 0 ; i < 10 ; ++i ) | |
571 { | |
572 p_buffer[9-i] = p_challenge[i]; | |
573 } | |
574 | |
575 /* Send challenge to LU */ | |
576 if( ioctl_SendChallenge( dvdcss->i_fd, | |
577 &dvdcss->css.i_agid, p_buffer ) < 0 ) | |
578 { | |
579 print_error( dvdcss, "ioctl SendChallenge failed" ); | |
580 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
581 return -1; | |
582 } | |
583 | |
584 /* Get key1 from LU */ | |
585 if( ioctl_ReportKey1( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0) | |
586 { | |
587 print_error( dvdcss, "ioctl ReportKey1 failed" ); | |
588 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
589 return -1; | |
590 } | |
591 | |
592 /* Send key1 to host */ | |
593 for( i = 0 ; i < KEY_SIZE ; i++ ) | |
594 { | |
595 p_key1[i] = p_buffer[4-i]; | |
596 } | |
597 | |
598 for( i = 0 ; i < 32 ; ++i ) | |
599 { | |
600 CryptKey( 0, i, p_challenge, p_key_check ); | |
601 | |
602 if( memcmp( p_key_check, p_key1, KEY_SIZE ) == 0 ) | |
603 { | |
604 print_debug( dvdcss, "drive authenticated, using variant %d", i ); | |
605 i_variant = i; | |
606 break; | |
607 } | |
608 } | |
609 | |
610 if( i == 32 ) | |
611 { | |
612 print_error( dvdcss, "drive would not authenticate" ); | |
613 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
614 return -1; | |
615 } | |
616 | |
617 /* Get challenge from LU */ | |
618 if( ioctl_ReportChallenge( dvdcss->i_fd, | |
619 &dvdcss->css.i_agid, p_buffer ) < 0 ) | |
620 { | |
621 print_error( dvdcss, "ioctl ReportKeyChallenge failed" ); | |
622 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
623 return -1; | |
624 } | |
625 | |
626 /* Send challenge to host */ | |
627 for( i = 0 ; i < 10 ; ++i ) | |
628 { | |
629 p_challenge[i] = p_buffer[9-i]; | |
630 } | |
631 | |
632 CryptKey( 1, i_variant, p_challenge, p_key2 ); | |
633 | |
634 /* Get key2 from host */ | |
635 for( i = 0 ; i < KEY_SIZE ; ++i ) | |
636 { | |
637 p_buffer[4-i] = p_key2[i]; | |
638 } | |
639 | |
640 /* Send key2 to LU */ | |
641 if( ioctl_SendKey2( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) | |
642 { | |
643 print_error( dvdcss, "ioctl SendKey2 failed" ); | |
644 ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); | |
645 return -1; | |
646 } | |
647 | |
648 /* The drive has accepted us as authentic. */ | |
649 print_debug( dvdcss, "authentication established" ); | |
650 | |
651 memcpy( p_challenge, p_key1, KEY_SIZE ); | |
652 memcpy( p_challenge + KEY_SIZE, p_key2, KEY_SIZE ); | |
653 | |
654 CryptKey( 2, i_variant, p_challenge, dvdcss->css.p_bus_key ); | |
655 | |
656 return 0; | |
657 } | |
658 | |
659 /***************************************************************************** | |
660 * PrintKey : debug function that dumps a key value | |
661 *****************************************************************************/ | |
662 static void PrintKey( dvdcss_t dvdcss, char *prefix, uint8_t const *data ) | |
663 { | |
664 print_debug( dvdcss, "%s%02x:%02x:%02x:%02x:%02x", prefix, | |
665 data[0], data[1], data[2], data[3], data[4] ); | |
666 } | |
648 | 667 |
649 /***************************************************************************** | 668 /***************************************************************************** |
650 * GetASF : Get Authentication success flag | 669 * GetASF : Get Authentication success flag |
651 ***************************************************************************** | 670 ***************************************************************************** |
652 * Returns : | 671 * Returns : |
659 int i_asf = 0; | 678 int i_asf = 0; |
660 | 679 |
661 if( ioctl_ReportASF( dvdcss->i_fd, NULL, &i_asf ) != 0 ) | 680 if( ioctl_ReportASF( dvdcss->i_fd, NULL, &i_asf ) != 0 ) |
662 { | 681 { |
663 /* The ioctl process has failed */ | 682 /* The ioctl process has failed */ |
664 _dvdcss_error( dvdcss, "GetASF fatal error" ); | 683 print_error( dvdcss, "GetASF fatal error" ); |
665 return -1; | 684 return -1; |
666 } | 685 } |
667 | 686 |
668 if( i_asf ) | 687 if( i_asf ) |
669 { | 688 { |
670 _dvdcss_debug( dvdcss, "GetASF authenticated, ASF=1" ); | 689 print_debug( dvdcss, "GetASF authenticated, ASF=1" ); |
671 } | 690 } |
672 else | 691 else |
673 { | 692 { |
674 _dvdcss_debug( dvdcss, "GetASF not authenticated, ASF=0" ); | 693 print_debug( dvdcss, "GetASF not authenticated, ASF=0" ); |
675 } | 694 } |
676 | 695 |
677 return i_asf; | 696 return i_asf; |
678 } | 697 } |
679 | 698 |
943 | 962 |
944 return; | 963 return; |
945 } | 964 } |
946 | 965 |
947 /***************************************************************************** | 966 /***************************************************************************** |
967 * player_keys: alternate DVD player keys | |
968 ***************************************************************************** | |
969 * These player keys were generated using Frank A. Stevenson's PlayerKey | |
970 * cracker. A copy of his article can be found here: | |
971 * http://www-2.cs.cmu.edu/~dst/DeCSS/FrankStevenson/mail2.txt | |
972 *****************************************************************************/ | |
973 static const dvd_key_t player_keys[] = | |
974 { | |
975 { 0x01, 0xaf, 0xe3, 0x12, 0x80 }, | |
976 { 0x12, 0x11, 0xca, 0x04, 0x3b }, | |
977 { 0x14, 0x0c, 0x9e, 0xd0, 0x09 }, | |
978 { 0x14, 0x71, 0x35, 0xba, 0xe2 }, | |
979 { 0x1a, 0xa4, 0x33, 0x21, 0xa6 }, | |
980 { 0x26, 0xec, 0xc4, 0xa7, 0x4e }, | |
981 { 0x2c, 0xb2, 0xc1, 0x09, 0xee }, | |
982 { 0x2f, 0x25, 0x9e, 0x96, 0xdd }, | |
983 { 0x33, 0x2f, 0x49, 0x6c, 0xe0 }, | |
984 { 0x35, 0x5b, 0xc1, 0x31, 0x0f }, | |
985 { 0x36, 0x67, 0xb2, 0xe3, 0x85 }, | |
986 { 0x39, 0x3d, 0xf1, 0xf1, 0xbd }, | |
987 { 0x3b, 0x31, 0x34, 0x0d, 0x91 }, | |
988 { 0x45, 0xed, 0x28, 0xeb, 0xd3 }, | |
989 { 0x48, 0xb7, 0x6c, 0xce, 0x69 }, | |
990 { 0x4b, 0x65, 0x0d, 0xc1, 0xee }, | |
991 { 0x4c, 0xbb, 0xf5, 0x5b, 0x23 }, | |
992 { 0x51, 0x67, 0x67, 0xc5, 0xe0 }, | |
993 { 0x53, 0x94, 0xe1, 0x75, 0xbf }, | |
994 { 0x57, 0x2c, 0x8b, 0x31, 0xae }, | |
995 { 0x63, 0xdb, 0x4c, 0x5b, 0x4a }, | |
996 { 0x7b, 0x1e, 0x5e, 0x2b, 0x57 }, | |
997 { 0x85, 0xf3, 0x85, 0xa0, 0xe0 }, | |
998 { 0xab, 0x1e, 0xe7, 0x7b, 0x72 }, | |
999 { 0xab, 0x36, 0xe3, 0xeb, 0x76 }, | |
1000 { 0xb1, 0xb8, 0xf9, 0x38, 0x03 }, | |
1001 { 0xb8, 0x5d, 0xd8, 0x53, 0xbd }, | |
1002 { 0xbf, 0x92, 0xc3, 0xb0, 0xe2 }, | |
1003 { 0xcf, 0x1a, 0xb2, 0xf8, 0x0a }, | |
1004 { 0xec, 0xa0, 0xcf, 0xb3, 0xff }, | |
1005 { 0xfc, 0x95, 0xa9, 0x87, 0x35 } | |
1006 }; | |
1007 | |
1008 /***************************************************************************** | |
948 * DecryptDiscKey | 1009 * DecryptDiscKey |
949 ***************************************************************************** | 1010 ***************************************************************************** |
950 * Decryption of the disc key with player keys if they are available. | 1011 * Decryption of the disc key with player keys: try to decrypt the disc key |
951 * Try to decrypt the disc key from every position with every player key. | 1012 * from every position with every player key. |
952 * p_struct_disckey: the 2048 byte DVD_STRUCT_DISCKEY data | 1013 * p_struct_disckey: the 2048 byte DVD_STRUCT_DISCKEY data |
953 * p_disc_key: result, the 5 byte disc key | 1014 * p_disc_key: result, the 5 byte disc key |
954 *****************************************************************************/ | 1015 *****************************************************************************/ |
955 static int DecryptDiscKey( uint8_t const *p_struct_disckey, | 1016 static int DecryptDiscKey( dvdcss_t dvdcss, uint8_t const *p_struct_disckey, |
956 dvd_key_t p_disc_key ) | 1017 dvd_key_t p_disc_key ) |
957 { | 1018 { |
958 uint8_t p_verify[KEY_SIZE]; | 1019 uint8_t p_verify[KEY_SIZE]; |
959 unsigned int i, n = 0; | 1020 unsigned int i, n = 0; |
960 | 1021 |
961 static const dvd_key_t player_keys[] = | |
962 { | |
963 { 0x01, 0xaf, 0xe3, 0x12, 0x80 }, | |
964 { 0x12, 0x11, 0xca, 0x04, 0x3b }, | |
965 { 0x14, 0x0c, 0x9e, 0xd0, 0x09 }, | |
966 { 0x14, 0x71, 0x35, 0xba, 0xe2 }, | |
967 { 0x1a, 0xa4, 0x33, 0x21, 0xa6 }, | |
968 { 0x26, 0xec, 0xc4, 0xa7, 0x4e }, | |
969 { 0x2c, 0xb2, 0xc1, 0x09, 0xee }, | |
970 { 0x2f, 0x25, 0x9e, 0x96, 0xdd }, | |
971 { 0x33, 0x2f, 0x49, 0x6c, 0xe0 }, | |
972 { 0x35, 0x5b, 0xc1, 0x31, 0x0f }, | |
973 { 0x36, 0x67, 0xb2, 0xe3, 0x85 }, | |
974 { 0x39, 0x3d, 0xf1, 0xf1, 0xbd }, | |
975 { 0x3b, 0x31, 0x34, 0x0d, 0x91 }, | |
976 { 0x45, 0xed, 0x28, 0xeb, 0xd3 }, | |
977 { 0x48, 0xb7, 0x6c, 0xce, 0x69 }, | |
978 { 0x4b, 0x65, 0x0d, 0xc1, 0xee }, | |
979 { 0x4c, 0xbb, 0xf5, 0x5b, 0x23 }, | |
980 { 0x51, 0x67, 0x67, 0xc5, 0xe0 }, | |
981 { 0x53, 0x94, 0xe1, 0x75, 0xbf }, | |
982 { 0x57, 0x2c, 0x8b, 0x31, 0xae }, | |
983 { 0x63, 0xdb, 0x4c, 0x5b, 0x4a }, | |
984 { 0x7b, 0x1e, 0x5e, 0x2b, 0x57 }, | |
985 { 0x85, 0xf3, 0x85, 0xa0, 0xe0 }, | |
986 { 0xab, 0x1e, 0xe7, 0x7b, 0x72 }, | |
987 { 0xab, 0x36, 0xe3, 0xeb, 0x76 }, | |
988 { 0xb1, 0xb8, 0xf9, 0x38, 0x03 }, | |
989 { 0xb8, 0x5d, 0xd8, 0x53, 0xbd }, | |
990 { 0xbf, 0x92, 0xc3, 0xb0, 0xe2 }, | |
991 { 0xcf, 0x1a, 0xb2, 0xf8, 0x0a }, | |
992 { 0xec, 0xa0, 0xcf, 0xb3, 0xff }, | |
993 { 0xfc, 0x95, 0xa9, 0x87, 0x35 } | |
994 }; | |
995 | |
996 /* Decrypt disc key with the above player keys */ | 1022 /* Decrypt disc key with the above player keys */ |
997 while( n < sizeof(player_keys) / sizeof(dvd_key_t) ) | 1023 for( n = 0; n < sizeof(player_keys) / sizeof(dvd_key_t); n++ ) |
998 { | 1024 { |
1025 PrintKey( dvdcss, "trying player key ", player_keys[n] ); | |
1026 | |
999 for( i = 1; i < 409; i++ ) | 1027 for( i = 1; i < 409; i++ ) |
1000 { | 1028 { |
1001 /* Check if player key n is the right key for position i. */ | 1029 /* Check if player key n is the right key for position i. */ |
1002 DecryptKey( 0, player_keys[n], p_struct_disckey + 5 * i, | 1030 DecryptKey( 0, player_keys[n], p_struct_disckey + 5 * i, |
1003 p_disc_key ); | 1031 p_disc_key ); |
1011 if( memcmp( p_disc_key, p_verify, KEY_SIZE ) == 0 ) | 1039 if( memcmp( p_disc_key, p_verify, KEY_SIZE ) == 0 ) |
1012 { | 1040 { |
1013 return 0; | 1041 return 0; |
1014 } | 1042 } |
1015 } | 1043 } |
1016 n++; | |
1017 } | 1044 } |
1018 | 1045 |
1019 /* Have tried all combinations of positions and keys, | 1046 /* Have tried all combinations of positions and keys, |
1020 * and we still didn't succeed. */ | 1047 * and we still didn't succeed. */ |
1021 memset( p_disc_key, 0, KEY_SIZE ); | 1048 memset( p_disc_key, 0, KEY_SIZE ); |
1074 unsigned int nPossibleK1; /* #of possible K[1] values */ | 1101 unsigned int nPossibleK1; /* #of possible K[1] values */ |
1075 unsigned char* K1table; /* Lookup table for possible K[1] */ | 1102 unsigned char* K1table; /* Lookup table for possible K[1] */ |
1076 unsigned int* BigTable; /* LFSR2 startstate indexed by | 1103 unsigned int* BigTable; /* LFSR2 startstate indexed by |
1077 * 1,2,5 output byte */ | 1104 * 1,2,5 output byte */ |
1078 | 1105 |
1079 _dvdcss_debug( dvdcss, "cracking disc key" ); | |
1080 | |
1081 /* | 1106 /* |
1082 * Prepare tables for hash reversal | 1107 * Prepare tables for hash reversal |
1083 */ | 1108 */ |
1084 | |
1085 | 1109 |
1086 /* initialize lookup tables for k[1] */ | 1110 /* initialize lookup tables for k[1] */ |
1087 K1table = malloc( 65536 * K1TABLEWIDTH ); | 1111 K1table = malloc( 65536 * K1TABLEWIDTH ); |
1088 memset( K1table, 0 , 65536 * K1TABLEWIDTH ); | 1112 memset( K1table, 0 , 65536 * K1TABLEWIDTH ); |
1089 if( K1table == NULL ) | 1113 if( K1table == NULL ) |
1102 tmp4 = K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) ]; /* count of entries here */ | 1126 tmp4 = K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) ]; /* count of entries here */ |
1103 tmp4++; | 1127 tmp4++; |
1104 /* | 1128 /* |
1105 if( tmp4 == K1TABLEWIDTH ) | 1129 if( tmp4 == K1TABLEWIDTH ) |
1106 { | 1130 { |
1107 _dvdcss_debug( dvdcss, "Table disaster %d", tmp4 ); | 1131 print_debug( dvdcss, "Table disaster %d", tmp4 ); |
1108 } | 1132 } |
1109 */ | 1133 */ |
1110 if( tmp4 < K1TABLEWIDTH ) | 1134 if( tmp4 < K1TABLEWIDTH ) |
1111 { | 1135 { |
1112 K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) + tmp4 ] = i; | 1136 K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) + tmp4 ] = i; |
1123 return -1; | 1147 return -1; |
1124 } | 1148 } |
1125 | 1149 |
1126 tmp3 = 0; | 1150 tmp3 = 0; |
1127 | 1151 |
1128 _dvdcss_debug( dvdcss, "initializing the big table" ); | 1152 print_debug( dvdcss, "initializing the big table" ); |
1129 | 1153 |
1130 for( i = 0 ; i < 16777216 ; i++ ) | 1154 for( i = 0 ; i < 16777216 ; i++ ) |
1131 { | 1155 { |
1132 tmp = (( i + i ) & 0x1fffff0 ) | 0x8 | ( i & 0x7 ); | 1156 tmp = (( i + i ) & 0x1fffff0 ) | 0x8 | ( i & 0x7 ); |
1133 | 1157 |
1374 return i_exit; | 1398 return i_exit; |
1375 } | 1399 } |
1376 | 1400 |
1377 | 1401 |
1378 /****************************************************************************** | 1402 /****************************************************************************** |
1379 * Various pices for the title crack engine. | 1403 * Various pieces for the title crack engine. |
1380 ****************************************************************************** | 1404 ****************************************************************************** |
1381 * The length of the PES packet is located at 0x12-0x13. | 1405 * The length of the PES packet is located at 0x12-0x13. |
1382 * The the copyrigth protection bits are located at 0x14 (bits 0x20 and 0x10). | 1406 * The the copyrigth protection bits are located at 0x14 (bits 0x20 and 0x10). |
1383 * The data of the PES packet begins at 0x15 (if there isn't any PTS/DTS) | 1407 * The data of the PES packet begins at 0x15 (if there isn't any PTS/DTS) |
1384 * or at 0x?? if there are both PTS and DTS's. | 1408 * or at 0x?? if there are both PTS and DTS's. |
1406 int i_encrypted = 0; | 1430 int i_encrypted = 0; |
1407 int b_stop_scanning = 0; | 1431 int b_stop_scanning = 0; |
1408 int b_read_error = 0; | 1432 int b_read_error = 0; |
1409 int i_ret; | 1433 int i_ret; |
1410 | 1434 |
1411 _dvdcss_debug( dvdcss, "cracking title key" ); | 1435 print_debug( dvdcss, "cracking title key at block %i", i_pos ); |
1412 | 1436 |
1413 i_tries = 0; | 1437 i_tries = 0; |
1414 i_success = 0; | 1438 i_success = 0; |
1415 | 1439 |
1416 do | 1440 do |
1417 { | 1441 { |
1418 i_ret = dvdcss->pf_seek( dvdcss, i_pos ); | 1442 i_ret = dvdcss->pf_seek( dvdcss, i_pos ); |
1419 | 1443 |
1420 if( i_ret != i_pos ) | 1444 if( i_ret != i_pos ) |
1421 { | 1445 { |
1422 _dvdcss_error( dvdcss, "seek failed" ); | 1446 print_error( dvdcss, "seek failed" ); |
1423 } | 1447 } |
1424 | 1448 |
1425 i_ret = dvdcss_read( dvdcss, p_buf, 1, DVDCSS_NOFLAGS ); | 1449 i_ret = dvdcss_read( dvdcss, p_buf, 1, DVDCSS_NOFLAGS ); |
1426 | 1450 |
1427 /* Either we are at the end of the physical device or the auth | 1451 /* Either we are at the end of the physical device or the auth |
1428 * have failed / were not done and we got a read error. */ | 1452 * have failed / were not done and we got a read error. */ |
1429 if( i_ret <= 0 ) | 1453 if( i_ret <= 0 ) |
1430 { | 1454 { |
1431 if( i_ret == 0 ) | 1455 if( i_ret == 0 ) |
1432 { | 1456 { |
1433 _dvdcss_debug( dvdcss, "read returned 0 (end of device?)" ); | 1457 print_debug( dvdcss, "read returned 0 (end of device?)" ); |
1434 } | 1458 } |
1435 else if( !b_read_error ) | 1459 else if( !b_read_error ) |
1436 { | 1460 { |
1437 _dvdcss_debug( dvdcss, "read error, resorting to secret " | 1461 print_debug( dvdcss, "read error at block %i, resorting to " |
1438 "arcanes to recover" ); | 1462 "secret arcanes to recover", i_pos ); |
1439 | 1463 |
1440 /* Reset the drive before trying to continue */ | 1464 /* Reset the drive before trying to continue */ |
1441 _dvdcss_close( dvdcss ); | 1465 _dvdcss_close( dvdcss ); |
1442 _dvdcss_open( dvdcss ); | 1466 _dvdcss_open( dvdcss ); |
1443 | 1467 |
1450 /* Stop when we find a non MPEG stream block. | 1474 /* Stop when we find a non MPEG stream block. |
1451 * (We must have reached the end of the stream). | 1475 * (We must have reached the end of the stream). |
1452 * For now, allow all blocks that begin with a start code. */ | 1476 * For now, allow all blocks that begin with a start code. */ |
1453 if( memcmp( p_buf, p_packstart, 3 ) ) | 1477 if( memcmp( p_buf, p_packstart, 3 ) ) |
1454 { | 1478 { |
1455 _dvdcss_debug( dvdcss, "non MPEG block found (end of title)" ); | 1479 print_debug( dvdcss, "non MPEG block found at block %i " |
1480 "(end of title)", i_pos ); | |
1456 break; | 1481 break; |
1457 } | 1482 } |
1458 | 1483 |
1459 if( p_buf[0x0d] & 0x07 ) | 1484 if( p_buf[0x0d] & 0x07 ) |
1460 _dvdcss_debug( dvdcss, "stuffing in pack header" ); | 1485 print_debug( dvdcss, "stuffing in pack header" ); |
1461 | 1486 |
1462 /* PES_scrambling_control does not exist in a system_header, | 1487 /* PES_scrambling_control does not exist in a system_header, |
1463 * a padding_stream or a private_stream2 (and others?). */ | 1488 * a padding_stream or a private_stream2 (and others?). */ |
1464 if( p_buf[0x14] & 0x30 && ! ( p_buf[0x11] == 0xbb | 1489 if( p_buf[0x14] & 0x30 && ! ( p_buf[0x11] == 0xbb |
1465 || p_buf[0x11] == 0xbe | 1490 || p_buf[0x11] == 0xbe |
1484 i_reads++; | 1509 i_reads++; |
1485 | 1510 |
1486 /* Emit a progress indication now and then. */ | 1511 /* Emit a progress indication now and then. */ |
1487 if( !( i_reads & 0xfff ) ) | 1512 if( !( i_reads & 0xfff ) ) |
1488 { | 1513 { |
1489 _dvdcss_debug( dvdcss, "still cracking..." ); | 1514 print_debug( dvdcss, "at block %i, still cracking...", i_pos ); |
1490 } | 1515 } |
1491 | 1516 |
1492 /* Stop after 2000 blocks if we haven't seen any encrypted blocks. */ | 1517 /* Stop after 2000 blocks if we haven't seen any encrypted blocks. */ |
1493 if( i_reads >= 2000 && i_encrypted == 0 ) break; | 1518 if( i_reads >= 2000 && i_encrypted == 0 ) break; |
1494 | 1519 |
1495 } while( !b_stop_scanning && i_len > 0); | 1520 } while( !b_stop_scanning && i_len > 0); |
1496 | 1521 |
1497 if( !b_stop_scanning ) | 1522 if( !b_stop_scanning ) |
1498 { | 1523 { |
1499 _dvdcss_debug( dvdcss, "end of title reached" ); | 1524 print_debug( dvdcss, "end of title reached" ); |
1500 } | 1525 } |
1501 | 1526 |
1502 { /* Print some statistics. */ | 1527 /* Print some statistics. */ |
1503 char psz_info[128]; | 1528 print_debug( dvdcss, "successful attempts %d/%d, scrambled blocks %d/%d", |
1504 snprintf( psz_info, sizeof(psz_info), | 1529 i_success, i_tries, i_encrypted, i_reads ); |
1505 "%d of %d attempts successful, %d of %d blocks scrambled", | |
1506 i_success, i_tries, i_encrypted, i_reads ); | |
1507 _dvdcss_debug( dvdcss, psz_info ); | |
1508 } | |
1509 | 1530 |
1510 if( i_success > 0 /* b_stop_scanning */ ) | 1531 if( i_success > 0 /* b_stop_scanning */ ) |
1511 { | 1532 { |
1512 _dvdcss_debug( dvdcss, "vts key initialized" ); | 1533 print_debug( dvdcss, "vts key initialized" ); |
1513 return 1; | 1534 return 1; |
1514 } | 1535 } |
1515 | 1536 |
1516 if( i_encrypted == 0 && i_reads > 0 ) | 1537 if( i_encrypted == 0 && i_reads > 0 ) |
1517 { | 1538 { |
1518 memset( p_titlekey, 0, KEY_SIZE ); | 1539 memset( p_titlekey, 0, KEY_SIZE ); |
1519 _dvdcss_debug( dvdcss, "file was unscrambled" ); | 1540 print_debug( dvdcss, "no scrambled sectors found" ); |
1520 return 0; | 1541 return 0; |
1521 } | 1542 } |
1522 | 1543 |
1523 memset( p_titlekey, 0, KEY_SIZE ); | 1544 memset( p_titlekey, 0, KEY_SIZE ); |
1524 return -1; | 1545 return -1; |