1 /*****************************************************************************
2 * dvd_css.c: Functions for DVD authentification and unscrambling
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
6 * Author: Stéphane Borel <stef@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
31 #include <netinet/in.h>
32 #include <sys/ioctl.h>
33 //#if defined(__NetBSD__) || defined(__OpenBSD__)
34 //# include <sys/dvdio.h>
35 //#elif defined(__linux__)
36 #include <linux/cdrom.h>
38 //# error "Need the DVD ioctls"
46 #include "css_table.h"
48 /*****************************************************************************
50 *****************************************************************************/
52 unsigned int pi_css_tab0[11]={5,0,1,2,3,4,0,1,2,3,4};
54 unsigned char pi_css_tab1[256]=
55 { 0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76,
56 0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b,
57 0xd3, 0x93, 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96,
58 0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b,
59 0x57, 0x17, 0x5f, 0x82, 0xc7, 0x87, 0xcf, 0x12,
60 0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f,
61 0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, 0x41, 0x90,
62 0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91,
63 0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74,
64 0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75,
65 0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94,
66 0xdc, 0x9c, 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95,
67 0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10,
68 0x58, 0x18, 0x50, 0x81, 0xc8, 0x88, 0xc0, 0x11,
69 0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92,
70 0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, 0x42, 0x9f,
71 0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16,
72 0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b,
73 0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6,
74 0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb,
75 0x37, 0x77, 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72,
76 0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f,
77 0xb9, 0xf9, 0xb1, 0xa0, 0xe9, 0xa9, 0xe1, 0xf0,
78 0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1,
79 0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, 0xc5, 0x14,
80 0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15,
81 0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4,
82 0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5,
83 0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70,
84 0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71,
85 0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2,
86 0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff };
88 unsigned char pi_css_tab2[256]=
89 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
90 0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e,
91 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
92 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c,
93 0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23,
94 0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a,
95 0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31,
96 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
97 0x49, 0x48, 0x4b, 0x4a, 0x4d, 0x4c, 0x4f, 0x4e,
98 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
99 0x5b, 0x5a, 0x59, 0x58, 0x5f, 0x5e, 0x5d, 0x5c,
100 0x52, 0x53, 0x50, 0x51, 0x56, 0x57, 0x54, 0x55,
101 0x6d, 0x6c, 0x6f, 0x6e, 0x69, 0x68, 0x6b, 0x6a,
102 0x64, 0x65, 0x66, 0x67, 0x60, 0x61, 0x62, 0x63,
103 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
104 0x76, 0x77, 0x74, 0x75, 0x72, 0x73, 0x70, 0x71,
105 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
106 0x9b, 0x9a, 0x99, 0x98, 0x9f, 0x9e, 0x9d, 0x9c,
107 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
108 0x89, 0x88, 0x8b, 0x8a, 0x8d, 0x8c, 0x8f, 0x8e,
109 0xb6, 0xb7, 0xb4, 0xb5, 0xb2, 0xb3, 0xb0, 0xb1,
110 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
111 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3,
112 0xad, 0xac, 0xaf, 0xae, 0xa9, 0xa8, 0xab, 0xaa,
113 0xdb, 0xda, 0xd9, 0xd8, 0xdf, 0xde, 0xdd, 0xdc,
114 0xd2, 0xd3, 0xd0, 0xd1, 0xd6, 0xd7, 0xd4, 0xd5,
115 0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce,
116 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
117 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
118 0xf6, 0xf7, 0xf4, 0xf5, 0xf2, 0xf3, 0xf0, 0xf1,
119 0xed, 0xec, 0xef, 0xee, 0xe9, 0xe8, 0xeb, 0xea,
120 0xe4, 0xe5, 0xe6, 0xe7, 0xe0, 0xe1, 0xe2, 0xe3
123 unsigned char pi_css_tab3[512]=
125 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
126 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
127 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
128 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
129 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
130 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
131 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
132 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
133 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
134 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
135 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
136 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
137 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
138 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
139 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
140 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
141 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
142 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
143 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
144 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
145 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
146 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
147 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
148 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
149 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
150 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
151 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
152 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
153 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
154 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
155 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
156 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff
159 unsigned char pi_css_tab4[256]=
161 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
162 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
163 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
164 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
165 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
166 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
167 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
168 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
169 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
170 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
171 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
172 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
173 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
174 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
175 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
176 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
179 unsigned char pi_css_tab5[256]=
181 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
182 0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07,
183 0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b, 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b,
184 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13, 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03,
185 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d, 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d,
186 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05,
187 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09,
188 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01,
189 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
190 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06,
191 0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a,
192 0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12, 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02,
193 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c, 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c,
194 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14, 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04,
195 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08,
196 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00
204 /*****************************************************************************
205 * CSSGetASF : Get Authentification success flag
206 *****************************************************************************/
207 int CSSGetASF( int i_fd )
212 auth.type = DVD_LU_SEND_ASF;
215 for( auth.lsasf.agid = 0 ; auth.lsasf.agid < 4 ; auth.lsasf.agid++ )
217 if( ioctl( i_fd, DVD_AUTH, &auth ) )
219 intf_ErrMsg( "DVD ioctl error in CSSGetASF" );
224 // ("%sAuthenticated\n", (ai.lsasf.asf) ? "" : "not");
230 ai.type = DVD_LU_SEND_ASF;
233 for (ai.lsasf.agid = 0; ai.lsasf.agid < 4; ai.lsasf.agid++) {
234 if (!(ioctl(i_fd, DVD_AUTH, &ai))) {
235 fprintf( stderr, "%sAuthenticated\n", (ai.lsasf.asf) ? "" : "not");
239 intf_ErrMsg( "CSS Error : GetASF" );
245 /*****************************************************************************
246 * CSSCryptKey : shuffles bits and unencrypt keys.
248 * i_key_type : 0->key1, 1->key2, 2->buskey.
249 * i_varient : between 0 and 31.
250 *****************************************************************************/
252 static void CSSCryptKey( int i_key_type, int i_varient,
253 u8* pi_challenge, u8* pi_key )
255 /* Permutation table for challenge */
256 u8 ppi_perm_challenge[3][10] =
257 { { 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 },
258 { 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 },
259 { 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 } };
260 /* Permutation table for varient table */
261 u8 ppi_perm_varient[2][32] =
262 { { 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d,
263 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d,
264 0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05,
265 0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15 },
266 { 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e,
267 0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c,
268 0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f,
269 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d } };
270 u8 pi_css_secret[5] = { 0xE2,0xA3,0x45,0x10,0xF4 };
271 u8 pi_css_varients[32] =
272 { 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
273 0x20, 0x21, 0x24, 0x25, 0x30, 0x31, 0x34, 0x35,
274 0x80, 0x81, 0x84, 0x85, 0x90, 0x91, 0x94, 0x95,
275 0xA0, 0xA1, 0xA4, 0xA5, 0xB0, 0xB1, 0xB4, 0xB5 };
278 u8 pi_tmp1[5], pi_tmp2[2];
279 u8 i_lfsr0_o, i_lfsr1_o;
280 u32 i_lfsr0, i_lfsr1;
286 for( i=0 ; i<10 ; i++ )
288 pi_scratch[i] = pi_challenge[ppi_perm_challenge[i_key_type][i]];
290 i_css_varient = i_key_type == 0 ? i_varient
291 : ppi_perm_varient[i_key_type-1][i_varient];
292 i_css_varient = pi_css_varients[i_css_varient];
294 for( i=0 ; i<5 ; i++ )
296 pi_tmp1[i] = pi_scratch[5+i] ^ pi_css_secret[i];
299 /* In order to ensure that the LFSR works we need to ensure that the
300 * initial values are non-zero. Thus when we initialise them from
301 * the seed, we ensure that a bit is set.
303 i_lfsr0 = ( pi_key[0] << 17 ) | ( pi_key[1] << 9 ) |
304 ( ( pi_key[2] & ~7 ) << 1 ) | 8 | (pi_key[2] & 7);
307 * reverse lfsr0/1 to simplify calculation in loop
309 i_lfsr0 = ( pi_reverse[i_lfsr0 & 0xff] << 17 ) |
310 ( pi_reverse[( i_lfsr0 >> 8 ) & 0xff] << 9 ) |
311 ( pi_reverse[( i_lfsr0 >> 16 ) & 0xff] << 1) |
314 i_lfsr1 = ( pi_reverse[pi_key[4]] << 9 ) | 0x100 |
315 ( pi_reverse[pi_key[3]] );
317 for( i=0 ; i<30 ; i++ )
319 i_lfsr0_o = ( i_lfsr0 >> 12) ^ ( i_lfsr0 >> 4) ^
320 ( i_lfsr0 >> 3) ^ i_lfsr0;
322 i_lfsr1_o = ( ( i_lfsr1 >> 14 ) & 7) ^ i_lfsr1;
323 i_lfsr1_o ^= ( i_lfsr1_o << 3 ) ^ ( i_lfsr1_o << 6 );
325 i_lfsr1 = ( i_lfsr1 >> 8) ^ ( i_lfsr1_o << 9);
326 i_lfsr0 = ( i_lfsr0 >> 8 ) ^ ( i_lfsr0_o << 17);
328 i_lfsr0_o = ~i_lfsr0_o;
329 i_lfsr1_o = ~i_lfsr1_o;
331 i_val += i_lfsr0_o + i_lfsr1_o;
333 pi_bits[i] = i_val & 0xFF;
340 for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_scratch[i] )
342 i_index = pi_bits[25+i] ^ pi_scratch[i];
343 i_index = pi_css_mangle1[i_index] ^ i_css_varient;
344 pi_tmp1[i] = pi_css_mangle2[i_index] ^ i_term;
346 pi_tmp1[4] ^= pi_tmp1[0];
347 for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp1[i] )
349 i_index = pi_bits[20+i] ^ pi_tmp1[i];
350 i_index = pi_css_mangle1[i_index] ^ i_css_varient;
351 pi_tmp2[i] = pi_css_mangle2[i_index] ^ i_term;
353 pi_tmp2[4] ^= pi_tmp2[0];
354 for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp2[i] )
356 i_index = pi_bits[15+i] ^ pi_tmp2[i];
357 i_index = pi_css_mangle1[i_index] ^ i_css_varient;
358 i_index = pi_css_mangle2[i_index] ^ i_term;
359 pi_tmp1[i] = pi_css_mangle0[i_index];
361 pi_tmp1[4] ^= pi_tmp1[0];
362 for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp1[i] )
364 i_index = pi_bits[10+i] ^ pi_tmp1[i];
365 i_index = pi_css_mangle1[i_index] ^ i_css_varient;
366 i_index = pi_css_mangle2[i_index] ^ i_term;
367 pi_tmp2[i] = pi_css_mangle0[i_index];
369 pi_tmp2[4] ^= pi_tmp2[0];
370 for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp2[i] )
372 i_index = pi_bits[5+i] ^ pi_tmp2[i];
373 i_index = pi_css_mangle1[i_index] ^ i_css_varient;
374 pi_tmp1[i] = pi_css_mangle2[i_index] ^ i_term;
376 pi_tmp1[4] ^= pi_tmp1[0];
377 for( i = 5, i_term = 0 ; --i >= 0 ; i_term = pi_tmp1[i] )
379 i_index = pi_bits[i] ^ pi_tmp1[i];
380 i_index = pi_css_mangle1[i_index] ^ i_css_varient;
381 pi_key[i] = pi_css_mangle2[i_index] ^ i_term;
388 uint8_t Challenge[10];
389 uint8_t Key1[KEY_SIZE];
390 uint8_t Key2[KEY_SIZE];
391 uint8_t KeyCheck[KEY_SIZE];
399 static void _generate_bits (u8 *output, int len, const u8 *s)
405 /* In order to ensure that the LFSR works we need to ensure that the
406 * initial values are non-zero. Thus when we initialise them from
407 * the seed, we ensure that a bit is set.
410 lfsr0 = (s[0] << 17) | (s[1] << 9) | ((s[2] & ~7) << 1) | 8 | (s[2] & 7);
413 reverse lfsr0/1 to simplify calculation in loop
415 lfsr0 = (pi_reverse[lfsr0&0xff]<<17) | (pi_reverse[(lfsr0>>8)&0xff] << 9)
416 | (pi_reverse[(lfsr0>>16)&0xff]<<1) |(lfsr0>>24);
418 lfsr1 = (pi_reverse[s[4]] << 9) | 0x100 | ( pi_reverse[ s[3]] );
424 o_lfsr0 = (lfsr0 >> 12) ^ (lfsr0 >> 4) ^ (lfsr0 >> 3) ^ lfsr0;
426 o_lfsr1 = ((lfsr1 >> 14) & 7) ^ lfsr1;
427 o_lfsr1 ^= (o_lfsr1 << 3) ^ (o_lfsr1 << 6);
429 lfsr1 = (lfsr1 >> 8) ^ (o_lfsr1 << 9);
430 lfsr0 = (lfsr0 >> 8) ^ (o_lfsr0 << 17);
435 val += o_lfsr0 + o_lfsr1;
437 *--output = val & 0xFF;
439 fprintf(stderr, "lfsr0=%08x lfsr1=%08x\n", lfsr0, lfsr1);
446 * This encryption engine implements one of 32 variations
447 * one the same theme depending upon the choice in the
448 * varient parameter (0 - 31).
450 * The algorithm itself manipulates a 40 bit input into
452 * The parameter 'input' is 80 bits. It consists of
453 * the 40 bit input value that is to be encrypted followed
454 * by a 40 bit seed value for the pseudo random number
458 static inline void mangle1( u8 *bs, u8 cse, const u8 *ip, u8 *op)
461 for (i = 5, term = 0; --i >= 0; term = ip[i]) {
462 index = bs[i] ^ ip[i];
463 index = pi_css_mangle1[index] ^ cse;
464 op[i] = pi_css_mangle2[index] ^ term;
473 static inline void mangle2( u8 *bs, u8 cse, const u8 *ip, u8 *op)
476 for (i = 5, term = 0; --i >= 0; term = ip[i]) {
477 index = bs[i] ^ ip[i];
478 index = pi_css_mangle1[index] ^ cse;
479 index = pi_css_mangle2[index] ^ term;
480 op[i] = pi_css_mangle0[index];
489 static inline void engine (int varient, u8 const *input, u8 *output)
495 u8 pi_css_varients[32] =
496 { 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
497 0x20, 0x21, 0x24, 0x25, 0x30, 0x31, 0x34, 0x35,
498 0x80, 0x81, 0x84, 0x85, 0x90, 0x91, 0x94, 0x95,
499 0xA0, 0xA1, 0xA4, 0xA5, 0xB0, 0xB1, 0xB4, 0xB5 };
500 u8 pi_css_secret[5] = { 0xE2,0xA3,0x45,0x10,0xF4 };
505 /* Feed the secret into the input values such that
506 * we alter the seed to the LFSR's used above, then
507 * generate the bits to play with.
510 tmp1[i] = input[5+i] ^ pi_css_secret[i];
512 _generate_bits (&bits[29], sizeof bits, &tmp1[0]);
514 /* This term is used throughout the following to
515 * select one of 32 different variations on the
518 cse = pi_css_varients[varient];
520 /* Now the actual blocks doing the encryption. Each
521 * of these works on 40 bits at a time and are quite
524 mangle1( &bits[25], cse, input, tmp1);
527 mangle1( &bits[20], cse, tmp1, tmp2);
530 mangle2( &bits[15], cse, tmp2, tmp1);
533 mangle2( &bits[10], cse, tmp1, tmp2);
536 mangle1( &bits[5], cse, tmp2, tmp1);
538 mangle1( &bits[0], cse, tmp1, output);
546 void CryptKey1 (int varient, u8 const *challenge, u8 *key)
548 u8 perm_challenge[] = {1,3,0,7,5, 2,9,6,4,8};
554 scratch[i] = challenge[perm_challenge[i]];
556 engine (varient, scratch, key);
561 * This shuffles the bits in varient to make perm_varient such that
564 * varient bits: 2 -> 0 perm_varient bits
569 void CryptKey2 (int varient, u8 const *challenge, u8 *key)
571 static u8 perm_challenge[] = {
572 0x06,0x01,0x09,0x03,0x08,0x05,0x07,0x04,
575 static u8 perm_varient[] = {
576 0x0a,0x08,0x0e,0x0c,0x0b,0x09,0x0f,0x0d,
577 0x1a,0x18,0x1e,0x1c,0x1b,0x19,0x1f,0x1d,
578 0x02,0x00,0x06,0x04,0x03,0x01,0x07,0x05,
579 0x12,0x10,0x16,0x14,0x13,0x11,0x17,0x15
585 scratch[i] = challenge[perm_challenge[i]];
587 engine (perm_varient[varient], scratch, key);
592 * This shuffles the bits in varient to make perm_varient such that
595 * varient bits: 2 -> !4 perm_varient bits
600 void CryptBusKey (int varient, u8 const *challenge, u8 *key)
602 static u8 perm_challenge[] = {
603 0x04,0x00,0x03,0x05,0x07,0x02,0x08,0x06,
606 static u8 perm_varient[] = {
607 0x12,0x1a,0x16,0x1e,0x02,0x0a,0x06,0x0e,
608 0x10,0x18,0x14,0x1c,0x00,0x08,0x04,0x0c,
609 0x13,0x1b,0x17,0x1f,0x03,0x0b,0x07,0x0f,
610 0x11,0x19,0x15,0x1d,0x01,0x09,0x05,0x0d
616 scratch[i] = challenge[perm_challenge[i]];
618 engine (perm_varient[varient], scratch, key);
621 static int _CSSAuthDrive (const u8 *key, DiscKeys *disc)
625 for (i=0; i<KEY_SIZE; i++)
626 disc->Key1[i] = key[4-i];
628 for (i=0; i<32; ++i) {
629 CryptKey1( i, disc->Challenge, disc->KeyCheck);
631 if (memcmp (disc->KeyCheck, disc->Key1, KEY_SIZE ) == 0) {
632 intf_ErrMsg( "Drive Authentic - using varient %d", i);
638 intf_ErrMsg( "Drive would not Authenticate" );
644 static int _CSSAuthHost (dvd_authinfo *ai, DiscKeys *disc)
649 /* Host data receive (host changes state) */
650 case DVD_LU_SEND_AGID:
651 // _CSSPrintDebug ("AGID %d\n", ai->lsa.agid);
653 ai->type = DVD_HOST_SEND_CHALLENGE;
656 case DVD_LU_SEND_KEY1:
657 // _CSSPrintDebugBytes ("LU sent key1", ai->lsk.key, LEN_KEY);
659 if (_CSSAuthDrive (ai->lsk.key, disc)<0) {
660 ai->type = DVD_AUTH_FAILURE;
663 ai->type = DVD_LU_SEND_CHALLENGE;
666 case DVD_LU_SEND_CHALLENGE:
667 for (i = 0; i < 10; ++i)
668 disc->Challenge[i] = ai->hsc.chal[9-i];
670 // _CSSPrintDebugBytes ("LU sent challenge", ai->hsc.chal, 10);
672 CryptKey2 (disc->varient, disc->Challenge, disc->Key2);
673 ai->type = DVD_HOST_SEND_KEY2;
677 case DVD_HOST_SEND_CHALLENGE:
678 for (i = 0; i < 10; ++i)
679 ai->hsc.chal[9-i] = disc->Challenge[i];
681 // _CSSPrintDebugBytes ("Host sending challenge", ai->hsc.chal, 10);
683 /* Returning data, let LU change state */
686 case DVD_HOST_SEND_KEY2:
687 for (i = 0; i < KEY_SIZE; ++i)
688 ai->hsk.key[4-i] = disc->Key2[i];
690 // _CSSPrintDebugBytes ("Host sending key 2", &disc->Key2[0], LEN_KEY);
692 /* Returning data, let LU change state */
696 intf_ErrMsg( "Got invalid state %d", ai->type );
708 /*****************************************************************************
709 * CSSCracker : title key decryption by cracking
710 *****************************************************************************/
712 // FIXME : adapt to vlc
713 #define KEYSTREAMBYTES 10
715 static unsigned char invtab4[256];
717 static int CSScracker(int StartVal,unsigned char* pCrypted,unsigned char* pDecrypted,DVD40bitKey *StreamKey,DVD40bitKey *pkey)
719 unsigned char MyBuf[10];
720 unsigned int t1,t2,t3,t4,t5,t6;
722 unsigned int vCandidate;
730 MyBuf[i] = pi_css_tab1[pCrypted[i]] ^ pDecrypted[i];
733 /* Test that CSStab4 is a permutation */
734 memset( invtab4, 0, 256 );
735 for( i = 0 ; i < 256 ; i++ )
737 invtab4[ pi_css_tab4[i] ] = 1;
740 for (i = 0 ; i < 256 ; i++)
742 if (invtab4[ i ] != 1)
744 printf( "Permutation error\n" );
749 /* initialize the inverse of table4 */
750 for( i = 0 ; i < 256 ; i++ )
752 invtab4[ pi_css_tab4[i] ] = i;
755 for( nTry = StartVal ; nTry < 65536 ; nTry++ )
757 t1 = nTry >> 8 | 0x100;
759 t3 = 0; /* not needed */
762 /* iterate cipher 4 times to reconstruct LFSR2 */
763 for( i = 0 ; i < 4 ; i++ )
765 /* advance LFSR1 normaly */
766 t4=pi_css_tab2[t2]^pi_css_tab3[t1];
774 t6 = ( t6 + 0xff )&0x0ff;
783 /* printf( "%02x/%02x ", t4, t6 ); */
784 /* feed / advance t3 / t5 */
791 /* iterate 6 more times to validate candidate key */
792 for( ; i < KEYSTREAMBYTES ; i++ )
794 t4=pi_css_tab2[t2]^pi_css_tab3[t1];
798 t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
802 if( (t5 & 0xff) != MyBuf[i] ) break;
806 if( i == KEYSTREAMBYTES )
808 /* Do 4 backwards steps of iterating t3 to deduce initial state */
810 for( i = 0 ; i < 4 ; i++ )
814 /* easy to code, and fast enough bruteforce
815 * search for byte shifted in */
816 for( j=0 ; j < 256 ; j++ )
818 t3 = (t3 & 0x1ffff) | ( j << 17 );
819 t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
820 if( t6 == t1 ) break;
823 // printf( "Candidate: t1=%03x t2=%02x t3=%08x\n", 0x100|(nTry>>8),nTry&0x0ff, t3 );
828 if ( ((t4+t5)*2 + 8 - ((t4+t5)&7))==t3 )
830 (*pkey)[0] = nTry>>8;
831 (*pkey)[1] = nTry & 0xFF;
832 (*pkey)[2] = ((t4+t5) >> 0) & 0xFF;
833 (*pkey)[3] = ((t4+t5) >> 8) & 0xFF;
834 (*pkey)[4] = ((t4+t5) >> 16) & 0xFF;
843 (*pkey)[0] ^= (*StreamKey)[0];
844 (*pkey)[1] ^= (*StreamKey)[1];
845 (*pkey)[2] ^= (*StreamKey)[2];
846 (*pkey)[3] ^= (*StreamKey)[3];
847 (*pkey)[4] ^= (*StreamKey)[4];
854 * Authentication and keys
857 /*****************************************************************************
858 * CSSInit : CSS Structure initialisation and DVD authentication.
859 *****************************************************************************/
861 css_t CSSInit( int i_fd )
870 memset( &auth, 0, sizeof(auth) );
871 fprintf( stderr, "0\n" );
873 if( CSSGetASF( i_fd ) )
879 fprintf( stderr, "1\n" );
880 /* Get AGID From drive */
881 auth.type = DVD_LU_SEND_AGID;
884 if( ioctl( i_fd, DVD_AUTH, &auth ) < 0 )
886 intf_ErrMsg( "DVD ioctl error in CSSInit (AGID)" );
887 auth.type = DVD_INVALIDATE_AGID;
889 ioctl( i_fd, DVD_AUTH, &auth );
893 css.i_agid = auth.lsa.agid;
895 fprintf( stderr, "2\n" );
897 for( i = 0 ; i < 10 ; ++i )
899 css.keys.pi_challenge[i] = i;
901 fprintf( stderr, "3\n" );
903 if( ioctl( i_fd, DVD_AUTH, &auth ) < 0 )
905 intf_ErrMsg( "DVD ioctl error in CSSInit (Drive keys)" );
909 fprintf( stderr, "4\n" );
911 if( ioctl( i_fd, DVD_AUTH, &auth ) < 0 )
913 intf_ErrMsg( "DVD ioctl error in CSSInit (Drive keys)" );
917 fprintf( stderr, "5\n" );
919 for( i=0 ; i<KEY_SIZE ; i++ )
921 css.keys.pi_key1[i] = auth.lsk.key[KEY_SIZE -1 -i];
923 fprintf( stderr, "6\n" );
927 CSSCryptKey( 0, i, css.keys.pi_challenge, css.keys.pi_key_check );
930 intf_Msg( "Drive Authentic - using varient %d", i-1 );
933 ( memcmp( css.keys.pi_key_check, css.keys.pi_key1, KEY_SIZE ) != 0 ) );
934 fprintf( stderr, "1\n" );
936 css.keys.i_version = i-1;
938 auth.type = DVD_LU_SEND_CHALLENGE;
939 if( ioctl( i_fd, DVD_AUTH, &auth ) < 0 )
941 intf_ErrMsg( "DVD ioctl error in CSSInit (drive Keys)" );
945 fprintf( stderr, "7\n" );
947 for( i = 0; i < 2*KEY_SIZE; ++i )
949 css.keys.pi_challenge[i] = auth.hsc.chal[2*KEY_SIZE -1 -i];
951 CSSCryptKey( 1, css.keys.i_version,
952 css.keys.pi_challenge, css.keys.pi_key2 );
954 auth.type = DVD_HOST_SEND_KEY2;
955 for( i = 0 ; i < KEY_SIZE ; ++i )
957 auth.hsk.key[4-i] = css.keys.pi_key2[i];
959 fprintf( stderr, "8\n" );
961 if( ioctl( i_fd, DVD_AUTH, &auth ) < 0)
963 intf_ErrMsg( "Send key2 to LU failed (expected)" );
967 fprintf( stderr, "9\n" );
969 memcpy( css.keys.pi_challenge, css.keys.pi_key1, KEY_SIZE );
970 memcpy( css.keys.pi_challenge+KEY_SIZE, css.keys.pi_key2, KEY_SIZE );
971 fprintf( stderr, "10\n" );
972 CSSCryptKey( 2, css.keys.i_version,
973 css.keys.pi_challenge, css.keys.pi_key_check );
975 intf_WarnMsg( 3, "DVD agid : %d", css.i_agid );
976 fprintf( stderr, "11\n" );
979 DiscKeys *disc = &discKeys;
991 memset (&ai, 0, sizeof (ai));
997 /* Init sequence, request AGID */
998 for (tries = 1; (tries < 4)&&(rv== -1) ; ++tries) {
999 intf_ErrMsg( "Request AGID [%d]...", tries );
1000 ai.type = DVD_LU_SEND_AGID;
1002 rv = ioctl (fd, DVD_AUTH, &ai);
1004 intf_ErrMsg( "N/A, invalidating" );
1005 ai.type = DVD_INVALIDATE_AGID;
1007 ioctl (fd, DVD_AUTH, &ai);
1011 intf_ErrMsg("Cannot get AGID\n");
1014 for (i = 0; i < 10; ++i)
1015 disc->Challenge[i] = i;
1017 /* Send AGID to host */
1018 if (_CSSAuthHost(&ai, disc) < 0) {
1019 intf_ErrMsg("CSS Error :Send AGID to host failed\n");
1022 /* Get challenge from host */
1023 if (_CSSAuthHost(&ai, disc) < 0) {
1024 intf_ErrMsg("CSS Error :Get challenge from host failed\n");
1028 /* Send challenge to LU */
1029 if (ioctl(fd, DVD_AUTH, &ai) < 0) {
1030 intf_ErrMsg("CSS Error :Send challenge to LU failed\n");
1033 /* Get key1 from LU */
1034 if (ioctl(fd, DVD_AUTH, &ai) < 0) {
1035 intf_ErrMsg("CSS Error :Get key1 from LU failed\n");
1038 /* Send key1 to host */
1039 if (_CSSAuthHost(&ai, disc) < 0) {
1040 intf_ErrMsg("CSS Error :Send key1 to host failed\n");
1043 /* Get challenge from LU */
1044 if (ioctl(fd, DVD_AUTH, &ai) < 0) {
1045 intf_ErrMsg("CSS Error :Get challenge from LU failed\n");
1048 /* Send challenge to host */
1049 if (_CSSAuthHost (&ai, disc) < 0) {
1050 intf_ErrMsg("CSS Error :Send challenge to host failed\n");
1053 /* Get key2 from host */
1054 if (_CSSAuthHost (&ai, disc) < 0) {
1055 intf_ErrMsg("CSS Error :Get key2 from host failed\n");
1058 /* Send key2 to LU */
1059 if (ioctl(fd, DVD_AUTH, &ai) < 0) {
1060 intf_ErrMsg("CSS Error :Send key2 to LU failed (expected)\n");
1064 if (ai.type == DVD_AUTH_ESTABLISHED)
1065 intf_ErrMsg("CSS Error :DVD is authenticated\n");
1066 else if (ai.type == DVD_AUTH_FAILURE)
1067 intf_ErrMsg("CSS Error :DVD authentication failed\n");
1069 memcpy (disc->Challenge, disc->Key1, KEY_SIZE);
1070 memcpy (disc->Challenge+KEY_SIZE, disc->Key2, KEY_SIZE);
1071 CryptBusKey (disc->varient, disc->Challenge, disc->KeyCheck);
1073 intf_Msg( "Received Session Key\n" );
1074 for( i=0 ; i<KEY_SIZE ; i++ )
1076 intf_Msg( "%02x", &disc->KeyCheck[i] );
1083 if (CSSGetASF (fd) < 0)
1086 s.type = DVD_STRUCT_DISCKEY;
1087 s.disckey.agid = agid;
1088 memset (s.disckey.value, 0, 2048);
1090 if (ioctl(fd, DVD_READ_STRUCT, &s)<0) {
1091 intf_ErrMsg( "Error : Could not read Disc Key" );
1096 for (i=0; i<sizeof s.disckey.value; i++)
1097 s.disckey.value[i] ^= disc->KeyCheck[4 - (i % KEY_SIZE)];
1099 // _CSSPrintDebugBytes ("Received Disc Key", s.disckey.value, 10);
1101 memcpy (disc->KeyCheck, s.disckey.value, 2048);
1104 if (CSSGetASF (fd) < 0)
1117 /*****************************************************************************
1118 * CSSGetKeys : get the disc key of the media en the dvd device, and then
1120 * The DVD should have been opened before.
1121 *****************************************************************************/
1123 #define MaxKeys 1000
1127 int verbosity ; /* 0-9 */
1140 int CSSGetKeys( css_t * p_css )
1145 * css_auth/libcss method from Derek Fawcus.
1146 * Get encrypted keys with ioctls and decrypt them
1147 * with cracked player keys
1152 if( CSSGetASF( p_css->i_fd ) < 0 )
1158 dvd.type = DVD_STRUCT_DISCKEY;
1159 dvd.disckey.agid = p_css->i_agid;
1160 memset( dvd.disckey.value, 0, 2048 );
1162 if( ioctl( p_css->i_fd, DVD_READ_STRUCT, &dvd )<0 )
1164 intf_ErrMsg( "DVD ioctl error in CSSGetKeys" );
1169 for( i=0 ; i<sizeof(dvd.disckey.value) ; i++ )
1171 dvd.disckey.value[i] ^=
1172 p_css->keys.pi_key_check[4 - (i % KEY_SIZE )];
1175 memcpy( p_css->pi_disc_key, dvd.disckey.value, 2048 );
1177 if( CSSGetASF( p_css->i_fd ) < 0 )
1183 auth.type = DVD_LU_SEND_TITLE_KEY;
1184 auth.lstk.agid = p_css->i_agid;
1186 for( j=0 ; j<p_css->i_title_nb ; j++ )
1188 auth.lstk.lba = p_css->p_title_key[j].i_lba;
1190 if( ioctl( p_css->i_fd, DVD_AUTH, &auth )<0 )
1192 intf_ErrMsg( "DVD ioctl error in CSSGetKeys" );
1197 for( i=0 ; i<KEY_SIZE ; ++i )
1199 auth.lstk.title_key[i] ^=
1200 p_css->keys.pi_key_check[4 - (i % KEY_SIZE)];
1201 memcpy( p_css->p_title_key[j].key, auth.lstk.title_key, KEY_SIZE );
1205 if( CSSGetASF( p_css->i_fd ) < 0 )
1213 * Cracking method from Ethan Hawke.
1214 * Does not use key tables and ioctls.
1217 unsigned char buf[0x800] ;
1226 KeyOcc PosKey[MaxKeys] ;
1227 int RegisteredKeys = 0 ;
1228 int TotalKeysFound = 0 ;
1229 int StopScanning = 0 ;
1233 if( (in = fopen( "/dvd/video_ts/vts_01_1.vob", "rb") ) )
1235 fprintf( stderr, "CSS:File opened\n" );
1237 fseek(in,0,SEEK_END);
1238 filsize = ftell(in);
1239 fseek(in,0,SEEK_SET);
1242 if (params.verbosity >= 1 && filsize > 1024*1024)
1244 fprintf(stderr, "%.2f of file read, %i keys found...\r",
1248 BytesRead = fread(buf,1,0x800,in);
1249 if (buf[0x14] & 0x30) // PES_scrambling_control
1256 for(j=i; (j < 0x80) && (buf[0x7F - (j%i)] == buf[0x7F-j]); j++);
1257 if ((j>BestPLen) && (j>i))
1263 if ((BestPLen > 20) && (BestPLen / BestP >= 2))
1265 i = CSScracker(0,&buf[0x80],&buf[0x80-(BestPLen/BestP)*BestP],(DVD40bitKey*)&buf[0x54],&MyKey);
1269 for(j=0;j<RegisteredKeys;j++)
1271 if (memcmp(&(PosKey[j].key),&MyKey,sizeof(DVD40bitKey))==0)
1280 memcpy(&(PosKey[RegisteredKeys].key), &MyKey, sizeof(DVD40bitKey)) ;
1281 PosKey[RegisteredKeys++].occ = 1 ;
1284 if (params.verbosity >= 2)
1286 fprintf(stderr, "\nOfs:%08X - Key: %02X %02X %02X %02X %02X\n",
1287 pos, MyKey[0] ,MyKey[1], MyKey[2],
1288 MyKey[3], MyKey[4]) ;
1290 i = CSScracker(i,&buf[0x80],&buf[0x80-(BestPLen/BestP)*BestP],(DVD40bitKey*)&buf[0x54],&MyKey);
1297 if (params.scanall==0 && RegisteredKeys==1 && PosKey[0].occ >= params.repetitions)
1305 } while (BytesRead==0x800 && !StopScanning);
1307 if (params.verbosity >= 1 && StopScanning)
1309 fprintf(stderr, "Found enough occurancies of the same key. Scan stopped.");
1311 if (params.verbosity >= 1)
1313 fprintf(stderr, "\n\n") ;
1318 fprintf(stderr, "FILE ERROR: File could not be opened. [Check if file is readable]\n");
1323 fprintf(stderr, "This file was _NOT_ encrypted!\n");
1326 if (encrypted && RegisteredKeys==0)
1328 fprintf(stderr, "Sorry... Unable to determine keys from file.\n");
1331 for(i=0;i<RegisteredKeys-1;i++)
1333 for(j=i+1;j<RegisteredKeys;j++)
1335 if (PosKey[j].occ>PosKey[i].occ)
1337 memcpy(&MyKey,&(PosKey[j].key),sizeof(DVD40bitKey));
1339 memcpy(&(PosKey[j].key),&(PosKey[i].key),sizeof(DVD40bitKey));
1340 PosKey[j].occ = PosKey[i].occ;
1341 memcpy(&(PosKey[i].key),&MyKey,sizeof(DVD40bitKey));
1346 if (params.verbosity >= 1)
1348 fprintf(stderr, " Key(s) & key probability\n--------------------------\n");
1350 for(i=0; i<RegisteredKeys; i++)
1352 fprintf(stderr, "%d) %02X %02X %02X %02X %02X - %3.2f%%\n", i,
1353 PosKey[i].key[0],PosKey[i].key[1],PosKey[i].key[2],
1354 PosKey[i].key[3],PosKey[i].key[4],
1355 PosKey[i].occ*100.0/TotalKeysFound) ;
1356 if (PosKey[highest].occ*100.0/TotalKeysFound
1357 <= PosKey[i].occ*100.0/TotalKeysFound)
1362 fprintf(stderr, "\n");
1364 /* The "find the key with the highest probability" code
1365 is untested, as I haven't been able to find a VOB that
1366 produces multiple keys (RT)
1368 printf("%02X %02X %02X %02X %02X\n",
1369 PosKey[highest].key[0],PosKey[highest].key[1],PosKey[highest].key[2],
1370 PosKey[highest].key[3],PosKey[highest].key[4]) ;
1372 for( i=0 ; i<5 ; i++ )
1374 // p_css->p_title_key->key[i] = PosKey[highest].key[i];
1381 /*****************************************************************************
1382 * CSSDescrambleSector
1383 *****************************************************************************/
1384 int CSSDescrambleSector( DVD40bitKey* key, unsigned char * sec )
1388 unsigned char buf[0x800] ;
1395 BytesRead = fread(&buf,1,0x800,in);
1396 if (buf[0x14] & 0x30) // PES_scrambling_control
1398 unsigned int t1,t2,t3,t4,t5,t6;
1399 unsigned char *end=sec+0x800;
1401 t1=((*key)[0] ^ sec[0x54]) | 0x100;
1402 t2=(*key)[1] ^ sec[0x55];
1403 t3= (((*key)[2]) | ((*key)[3]<<8) |
1404 ((*key)[4]<<16)) ^ ((sec[0x56]) |
1405 (sec[0x57]<<8) | (sec[0x58]<<16));
1413 t4 = pi_css_tab2[t2] ^ pi_css_tab3[t1];
1416 t4 = pi_css_tab5[t4];
1417 t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
1419 t6 = pi_css_tab4[t6];
1421 *sec++= pi_css_tab1[*sec]^(t5&0xff);
1428 BytesWritten = fwrite(&buf,1,BytesRead,out);
1429 if (BytesWritten!=BytesRead)
1431 fprintf(stderr, "Could not write to output file.\n");
1435 } while (BytesRead==0x800);