]> git.sesse.net Git - vlc/blob - modules/demux/mp4/drms.c
* ./modules/demux/mp4: DRMS support.
[vlc] / modules / demux / mp4 / drms.c
1 /*****************************************************************************
2  * drms.c : DRMS
3  *****************************************************************************
4  * Copyright (C) 2004 VideoLAN
5  * $Id: drms.c,v 1.1 2004/01/05 12:37:52 jlj Exp $
6  *
7  * Author: Jon Lech Johansen <jon-vl@nanocrew.net>
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 #include <stdlib.h>                                      /* malloc(), free() */
25
26 #include <vlc/vlc.h>
27
28 #ifdef WIN32
29 #include <tchar.h>
30 #include <shlobj.h>
31 #include <windows.h>
32 #endif
33
34 #include "drms.h"
35 #include "drmstables.h"
36
37 #define TAOS_INIT( tmp, i ) \
38     memset( tmp, 0, sizeof(tmp) ); \
39     tmp[ i + 0 ] = 0x67452301; \
40     tmp[ i + 1 ] = 0xEFCDAB89; \
41     tmp[ i + 2 ] = 0x98BADCFE; \
42     tmp[ i + 3 ] = 0x10325476;
43
44 #define ROR( x, n ) (((x) << (32-(n))) | ((x) >> (n)))
45
46 static void init_ctx( uint32_t *p_ctx, uint32_t *p_input )
47 {
48     uint32_t i;
49     uint32_t p_tmp[ 6 ];
50
51     p_ctx[ 0 ] = sizeof(*p_input);
52
53     memset( &p_ctx[ 1 + 4 ], 0, sizeof(*p_input) * 4 );
54     memcpy( &p_ctx[ 1 + 0 ], p_input, sizeof(*p_input) * 4 );
55
56     p_tmp[ 0 ] = p_ctx[ 1 + 3 ];
57
58     for( i = 0; i < sizeof(p_drms_tab1)/sizeof(p_drms_tab1[ 0 ]); i++ )
59     {
60         p_tmp[ 0 ] = ROR( p_tmp[ 0 ], 8 );
61
62         p_tmp[ 5 ] = p_drms_tab2[ (p_tmp[ 0 ] >> 24) & 0xFF ]
63                    ^ ROR( p_drms_tab2[ (p_tmp[ 0 ] >> 16) & 0xFF ], 8 )
64                    ^ ROR( p_drms_tab2[ (p_tmp[ 0 ] >> 8) & 0xFF ], 16 )
65                    ^ ROR( p_drms_tab2[ p_tmp[ 0 ] & 0xFF ], 24 )
66                    ^ p_drms_tab1[ i ]
67                    ^ p_ctx[ 1 + ((i + 1) * 4) - 4 ];
68
69         p_ctx[ 1 + ((i + 1) * 4) + 0 ] = p_tmp[ 5 ];
70         p_tmp[ 5 ] ^= p_ctx[ 1 + ((i + 1) * 4) - 3 ];
71         p_ctx[ 1 + ((i + 1) * 4) + 1 ] = p_tmp[ 5 ];
72         p_tmp[ 5 ] ^= p_ctx[ 1 + ((i + 1) * 4) - 2 ];
73         p_ctx[ 1 + ((i + 1) * 4) + 2 ] = p_tmp[ 5 ];
74         p_tmp[ 5 ] ^= p_ctx[ 1 + ((i + 1) * 4) - 1 ];
75         p_ctx[ 1 + ((i + 1) * 4) + 3 ] = p_tmp[ 5 ];
76
77         p_tmp[ 0 ] = p_tmp[ 5 ];
78     }
79
80     memcpy( &p_ctx[ 1 + 64 ], &p_ctx[ 1 ], sizeof(*p_ctx) * 4 );
81
82     for( i = 4; i < sizeof(p_drms_tab1); i++ )
83     {
84         p_tmp[ 2 ] = p_ctx[ 1 + 4 + (i - 4) ];
85
86         p_tmp[ 0 ] = (((p_tmp[ 2 ] >> 7) & 0x01010101) * 27)
87                    ^ ((p_tmp[ 2 ] & 0xFF7F7F7F) << 1);
88         p_tmp[ 1 ] = (((p_tmp[ 0 ] >> 7) & 0x01010101) * 27)
89                    ^ ((p_tmp[ 0 ] & 0xFF7F7F7F) << 1);
90         p_tmp[ 4 ] = (((p_tmp[ 1 ] >> 7) & 0x01010101) * 27)
91                    ^ ((p_tmp[ 1 ] & 0xFF7F7F7F) << 1);
92
93         p_tmp[ 2 ] ^= p_tmp[ 4 ];
94
95         p_tmp[ 3 ] = ROR( p_tmp[ 1 ] ^ p_tmp[ 2 ], 16 )
96                    ^ ROR( p_tmp[ 0 ] ^ p_tmp[ 2 ], 8 )
97                    ^ ROR( p_tmp[ 2 ], 24 );
98
99         p_ctx[ 1 + 4 + 64 + (i - 4) ] = p_tmp[ 3 ] ^ p_tmp[ 4 ]
100                                       ^ p_tmp[ 1 ] ^ p_tmp[ 0 ];
101     }
102 }
103
104 static void ctx_xor( uint32_t *p_ctx, uint32_t *p_in, uint32_t *p_out,
105                      uint32_t p_table1[ 256 ], uint32_t p_table2[ 256 ] )
106 {
107     uint32_t i, x, y;
108     uint32_t p_tmp1[ 4 ];
109     uint32_t p_tmp2[ 4 ];
110
111     i = p_ctx[ 0 ] * 4;
112
113     p_tmp1[ 0 ] = p_ctx[ 1 + i + 24 ] ^ p_in[ 0 ];
114     p_tmp1[ 1 ] = p_ctx[ 1 + i + 25 ] ^ p_in[ 1 ];
115     p_tmp1[ 2 ] = p_ctx[ 1 + i + 26 ] ^ p_in[ 2 ];
116     p_tmp1[ 3 ] = p_ctx[ 1 + i + 27 ] ^ p_in[ 3 ];
117
118     i += 84;
119
120 #define XOR_ROR( p_table, p_tmp, i_ctx ) \
121     p_table[ (p_tmp[ y > 2 ? y - 3 : y + 1 ] >> 24) & 0xFF ] \
122     ^ ROR( p_table[ (p_tmp[ y > 1 ? y - 2 : y + 2 ] >> 16) & 0xFF ], 8 ) \
123     ^ ROR( p_table[ (p_tmp[ y > 0 ? y - 1 : y + 3 ] >> 8) & 0xFF ], 16 ) \
124     ^ ROR( p_table[ p_tmp[ y ] & 0xFF ], 24 ) \
125     ^ p_ctx[ i_ctx ]
126
127     for( x = 0; x < 1; x++ )
128     {
129         memcpy( p_tmp2, p_tmp1, sizeof(p_tmp1) );
130
131         for( y = 0; y < 4; y++ )
132         {
133             p_tmp1[ y ] = XOR_ROR( p_table1, p_tmp2, 1 + i - x + y );
134         }
135     }
136
137     for( ; x < 9; x++ )
138     {
139         memcpy( p_tmp2, p_tmp1, sizeof(p_tmp1) );
140
141         for( y = 0; y < 4; y++ )
142         {
143             p_tmp1[ y ] = XOR_ROR( p_table1, p_tmp2,
144                                    1 + i - x - ((x * 3) - y) );
145         }
146     }
147
148     for( y = 0; y < 4; y++ )
149     {
150         p_out[ y ] = XOR_ROR( p_table2, p_tmp1,
151                               1 + i - x - ((x * 3) - y) );
152     }
153
154 #undef XOR_ROR
155 }
156
157 static void taos( uint32_t *p_buffer, uint32_t *p_input )
158 {
159     uint32_t i;
160     uint32_t x = 0;
161     uint32_t p_tmp1[ 4 ];
162     uint32_t p_tmp2[ 4 ];
163
164     memcpy( p_tmp1, p_buffer, sizeof(p_tmp1) );
165
166     p_tmp2[ 0 ] = ((~p_tmp1[ 1 ] & p_tmp1[ 3 ])
167                 |   (p_tmp1[ 2 ] & p_tmp1[ 1 ])) + p_input[ x ];
168     p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp1[ 0 ] + p_drms_tab_taos[ x++ ];
169
170     for( i = 0; i < 4; i++ )
171     {
172         p_tmp2[ 0 ] = ((p_tmp1[ 0 ] >> 0x19)
173                     |  (p_tmp1[ 0 ] << 0x7)) + p_tmp1[ 1 ];
174         p_tmp2[ 1 ] = ((~p_tmp2[ 0 ] & p_tmp1[ 2 ])
175                     |   (p_tmp1[ 1 ] & p_tmp2[ 0 ])) + p_input[ x ];
176         p_tmp2[ 1 ] += p_tmp1[ 3 ] + p_drms_tab_taos[ x++ ];
177
178         p_tmp1[ 3 ] = ((p_tmp2[ 1 ] >> 0x14)
179                     |  (p_tmp2[ 1 ] << 0xC)) + p_tmp2[ 0 ];
180         p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] & p_tmp1[ 1 ])
181                     |   (p_tmp1[ 3 ] & p_tmp2[ 0 ])) + p_input[ x ];
182         p_tmp2[ 1 ] += p_tmp1[ 2 ] + p_drms_tab_taos[ x++ ];
183
184         p_tmp1[ 2 ] = ((p_tmp2[ 1 ] >> 0xF)
185                     |  (p_tmp2[ 1 ] << 0x11)) + p_tmp1[ 3 ];
186         p_tmp2[ 1 ] = ((~p_tmp1[ 2 ] & p_tmp2[ 0 ])
187                     |   (p_tmp1[ 3 ] & p_tmp1[ 2 ])) + p_input[ x ];
188         p_tmp2[ 2 ] = p_tmp2[ 1 ] + p_tmp1[ 1 ] + p_drms_tab_taos[ x++ ];
189
190         p_tmp1[ 1 ] = ((p_tmp2[ 2 ] << 0x16)
191                     |  (p_tmp2[ 2 ] >> 0xA)) + p_tmp1[ 2 ];
192         if( i == 3 )
193         {
194             p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] & p_tmp1[ 2 ])
195                         |   (p_tmp1[ 3 ] & p_tmp1[ 1 ])) + p_input[ 1 ];
196         }
197         else
198         {
199             p_tmp2[ 1 ] = ((~p_tmp1[ 1 ] & p_tmp1[ 3 ])
200                         |   (p_tmp1[ 2 ] & p_tmp1[ 1 ])) + p_input[ x ];
201         }
202         p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp2[ 1 ] + p_drms_tab_taos[ x++ ];
203     }
204
205     for( i = 0; i < 4; i++ )
206     {
207         uint8_t p_table[ 4 ][ 4 ] =
208         {
209             {  6, 11,  0,  5 },
210             { 10, 15,  4,  9 },
211             { 14,  3,  8, 13 },
212             {  2,  7, 12,  5 }
213         };
214
215         p_tmp2[ 0 ] = ((p_tmp1[ 0 ] >> 0x1B)
216                     |  (p_tmp1[ 0 ] << 0x5)) + p_tmp1[ 1 ];
217         p_tmp2[ 1 ] = ((~p_tmp1[ 2 ] & p_tmp1[ 1 ])
218                     |   (p_tmp1[ 2 ] & p_tmp2[ 0 ]))
219                     +   p_input[ p_table[ i ][ 0 ] ];
220         p_tmp2[ 1 ] += p_tmp1[ 3 ] + p_drms_tab_taos[ x++ ];
221
222         p_tmp1[ 3 ] = ((p_tmp2[ 1 ] >> 0x17)
223                     |  (p_tmp2[ 1 ] << 0x9)) + p_tmp2[ 0 ];
224         p_tmp2[ 1 ] = ((~p_tmp1[ 1 ] & p_tmp2[ 0 ])
225                     |   (p_tmp1[ 3 ] & p_tmp1[ 1 ]))
226                     +   p_input[ p_table[ i ][ 1 ] ];
227         p_tmp2[ 1 ] += p_tmp1[ 2 ] + p_drms_tab_taos[ x++ ];
228
229         p_tmp1[ 2 ] = ((p_tmp2[ 1 ] >> 0x12)
230                     |  (p_tmp2[ 1 ] << 0xE)) + p_tmp1[ 3 ];
231         p_tmp2[ 1 ] = ((~p_tmp2[ 0 ] & p_tmp1[ 3 ])
232                     |   (p_tmp1[ 2 ] & p_tmp2[ 0 ]))
233                     +   p_input[ p_table[ i ][ 2 ] ];
234         p_tmp2[ 1 ] += p_tmp1[ 1 ] + p_drms_tab_taos[ x++ ];
235
236         p_tmp1[ 1 ] = ((p_tmp2[ 1 ] << 0x14)
237                     |  (p_tmp2[ 1 ] >> 0xC)) + p_tmp1[ 2 ];
238         if( i == 3 )
239         {
240             p_tmp2[ 1 ] = (p_tmp1[ 3 ] ^ p_tmp1[ 2 ] ^ p_tmp1[ 1 ])
241                         + p_input[ p_table[ i ][ 3 ] ];
242         }
243         else
244         {
245             p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] & p_tmp1[ 2 ])
246                         |   (p_tmp1[ 3 ] & p_tmp1[ 1 ]))
247                         +   p_input[ p_table[ i ][ 3 ] ];
248         }
249         p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp2[ 1 ] + p_drms_tab_taos[ x++ ];
250     }
251
252     for( i = 0; i < 4; i++ )
253     {
254         uint8_t p_table[ 4 ][ 4 ] =
255         {
256             {  8, 11, 14,  1 },
257             {  4,  7, 10, 13 },
258             {  0,  3,  6,  9 },
259             { 12, 15,  2,  0 }
260         };
261
262         p_tmp2[ 0 ] = ((p_tmp1[ 0 ] >> 0x1C)
263                     |  (p_tmp1[ 0 ] << 0x4)) + p_tmp1[ 1 ];
264         p_tmp2[ 1 ] = (p_tmp1[ 2 ] ^ p_tmp1[ 1 ] ^ p_tmp2[ 0 ])
265                     + p_input[ p_table[ i ][ 0 ] ];
266         p_tmp2[ 1 ] += p_tmp1[ 3 ] + p_drms_tab_taos[ x++ ];
267
268         p_tmp1[ 3 ] = ((p_tmp2[ 1 ] >> 0x15)
269                     |  (p_tmp2[ 1 ] << 0xB)) + p_tmp2[ 0 ];
270         p_tmp2[ 1 ] = (p_tmp1[ 3 ] ^ p_tmp1[ 1 ] ^ p_tmp2[ 0 ])
271                     + p_input[ p_table[ i ][ 1 ] ];
272         p_tmp2[ 1 ] += p_tmp1[ 2 ] + p_drms_tab_taos[ x++ ];
273
274         p_tmp1[ 2 ] = ((p_tmp2[ 1 ] >> 0x10)
275                     |  (p_tmp2[ 1 ] << 0x10)) + p_tmp1[ 3 ];
276         p_tmp2[ 1 ] = (p_tmp1[ 3 ] ^ p_tmp1[ 2 ] ^ p_tmp2[ 0 ])
277                     + p_input[ p_table[ i ][ 2 ] ];
278         p_tmp2[ 1 ] += p_tmp1[ 1 ] + p_drms_tab_taos[ x++ ];
279
280         p_tmp1[ 1 ] = ((p_tmp2[ 1 ] << 0x17)
281                     |  (p_tmp2[ 1 ] >> 0x9)) + p_tmp1[ 2 ];
282         if( i == 3 )
283         {
284             p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] | p_tmp1[ 1 ]) ^ p_tmp1[ 2 ])
285                         +   p_input[ p_table[ i ][ 3 ] ];
286         }
287         else
288         {
289             p_tmp2[ 1 ] = (p_tmp1[ 3 ] ^ p_tmp1[ 2 ] ^ p_tmp1[ 1 ])
290                         + p_input[ p_table[ i ][ 3 ] ];
291         }
292         p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp2[ 1 ] + p_drms_tab_taos[ x++ ];
293     }
294
295     for( i = 0; i < 4; i++ )
296     {
297         uint8_t p_table[ 4 ][ 4 ] =
298         {
299             {  7, 14,  5, 12 },
300             {  3, 10,  1,  8 },
301             { 15,  6, 13,  4 },
302             { 11,  2,  9,  0 }
303         };
304
305         p_tmp2[ 0 ] = ((p_tmp1[ 0 ] >> 0x1A)
306                     |  (p_tmp1[ 0 ] << 0x6)) + p_tmp1[ 1 ];
307         p_tmp2[ 1 ] = ((~p_tmp1[ 2 ] | p_tmp2[ 0 ]) ^ p_tmp1[ 1 ])
308                     +   p_input[ p_table[ i ][ 0 ] ];
309         p_tmp2[ 1 ] += p_tmp1[ 3 ] + p_drms_tab_taos[ x++ ];
310
311         p_tmp1[ 3 ] = ((p_tmp2[ 1 ] >> 0x16)
312                     |  (p_tmp2[ 1 ] << 0xA)) + p_tmp2[ 0 ];
313         p_tmp2[ 1 ] = ((~p_tmp1[ 1 ] | p_tmp1[ 3 ]) ^ p_tmp2[ 0 ])
314                     +   p_input[ p_table[ i ][ 1 ] ];
315         p_tmp2[ 1 ] += p_tmp1[ 2 ] + p_drms_tab_taos[ x++ ];
316
317         p_tmp1[ 2 ] = ((p_tmp2[ 1 ] >> 0x11)
318                     |  (p_tmp2[ 1 ] << 0xF)) + p_tmp1[ 3 ];
319         p_tmp2[ 1 ] = ((~p_tmp2[ 0 ] | p_tmp1[ 2 ]) ^ p_tmp1[ 3 ])
320                     +   p_input[ p_table[ i ][ 2 ] ];
321         p_tmp2[ 1 ] += p_tmp1[ 1 ] + p_drms_tab_taos[ x++ ];
322
323         p_tmp1[ 1 ] = ((p_tmp2[ 1 ] << 0x15)
324                     |  (p_tmp2[ 1 ] >> 0xB)) + p_tmp1[ 2 ];
325
326         if( i < 3 )
327         {
328             p_tmp2[ 1 ] = ((~p_tmp1[ 3 ] | p_tmp1[ 1 ]) ^ p_tmp1[ 2 ])
329                         +   p_input[ p_table[ i ][ 3 ] ];
330             p_tmp1[ 0 ] = p_tmp2[ 0 ] + p_tmp2[ 1 ] + p_drms_tab_taos[ x++ ];
331         }
332     }
333
334     p_buffer[ 0 ] += p_tmp2[ 0 ];
335     p_buffer[ 1 ] += p_tmp1[ 1 ];
336     p_buffer[ 2 ] += p_tmp1[ 2 ];
337     p_buffer[ 3 ] += p_tmp1[ 3 ];
338 }
339
340 static void taos_add1( uint32_t *p_buffer,
341                        uint8_t *p_in, uint32_t i_len )
342 {
343     uint32_t i;
344     uint32_t x, y;
345     uint32_t p_tmp[ 16 ];
346     uint32_t i_offset = 0;
347
348     x = p_buffer[ 6 ] & 63;
349     y = 64 - x;
350
351     p_buffer[ 6 ] += i_len;
352
353     if( i_len < y )
354     {
355         memcpy( &((uint8_t *)p_buffer)[ 48 + x ], p_in, i_len );
356     }
357     else
358     {
359         if( x )
360         {
361             memcpy( &((uint8_t *)p_buffer)[ 48 + x ], p_in, y );
362             taos( &p_buffer[ 8 ], &p_buffer[ 12 ] );
363             i_offset = y;
364             i_len -= y;
365         }
366
367         if( i_len >= 64 )
368         {
369             for( i = 0; i < i_len / 64; i++ )
370             {
371                 memcpy( p_tmp, &p_in[ i_offset ], sizeof(p_tmp) );
372                 taos( &p_buffer[ 8 ], p_tmp );
373                 i_offset += 64;
374                 i_len -= 64;
375             }
376         }
377
378         if( i_len )
379         {
380             memcpy( &p_buffer[ 12 ], &p_in[ i_offset ], i_len );
381         }
382     }
383 }
384
385 static void taos_end1( uint32_t *p_buffer, uint32_t *p_out )
386 {
387     uint32_t x, y;
388
389     x = p_buffer[ 6 ] & 63;
390     y = 63 - x;
391
392     ((uint8_t *)p_buffer)[ 48 + x++ ] = 128;
393
394     if( y < 8 )
395     {
396         memset( &((uint8_t *)p_buffer)[ 48 + x ], 0, y );
397         taos( &p_buffer[ 8 ], &p_buffer[ 12 ] );
398         y = 64;
399         x = 0;
400     }
401
402     memset( &((uint8_t *)p_buffer)[ 48 + x ], 0, y );
403
404     p_buffer[ 26 ] = p_buffer[ 6 ] * 8;
405     p_buffer[ 27 ] = p_buffer[ 6 ] >> 29;
406     taos( &p_buffer[ 8 ], &p_buffer[ 12 ] );
407
408     memcpy( p_out, &p_buffer[ 8 ], sizeof(*p_out) * 4 );
409 }
410
411 static void taos_add2( uint32_t *p_buffer, uint8_t *p_in, uint32_t i_len )
412 {
413     uint32_t i, x;
414     uint32_t p_tmp[ 16 ];
415
416     x = (p_buffer[ 0 ] / 8) & 63;
417     i = p_buffer[ 0 ] + i_len * 8;
418
419     if( i < p_buffer[ 0 ] )
420     {
421         p_buffer[ 1 ] += 1;
422     }
423
424     p_buffer[ 0 ] = i;
425     p_buffer[ 1 ] += i_len >> 29;
426
427     for( i = 0; i < i_len; i++ )
428     {
429         ((uint8_t *)p_buffer)[ 24 + x++ ] = p_in[ i ];
430
431         if( x != 64 )
432             continue;
433
434         memcpy( p_tmp, &p_buffer[ 6 ], sizeof(p_tmp) );
435         taos( &p_buffer[ 2 ], p_tmp );
436     }
437 }
438
439 static void taos_add2e( uint32_t *p_buffer, uint32_t *p_in, uint32_t i_len )
440 {
441     uint32_t i, x, y;
442     uint32_t p_tmp[ 32 ];
443
444     if( i_len )
445     {
446         for( x = i_len; x; x -= y )
447         {
448             y = x > 32 ? 32 : x;
449
450             for( i = 0; i < y; i++ )
451             {
452                 p_tmp[ i ] = U32_AT(&p_in[ i ]);
453             }
454         }
455     }
456
457     taos_add2( p_buffer, (uint8_t *)p_tmp, i_len * sizeof(p_tmp[ 0 ]) );
458 }
459
460 static void taos_end2( uint32_t *p_buffer )
461 {
462     uint32_t x;
463     uint32_t p_tmp[ 16 ];
464
465     p_tmp[ 14 ] = p_buffer[ 0 ];
466     p_tmp[ 15 ] = p_buffer[ 1 ];
467
468     x = (p_buffer[ 0 ] / 8) & 63;
469
470     taos_add2( p_buffer, p_drms_tab_tend, 56 - x );
471     memcpy( p_tmp, &p_buffer[ 6 ], 56 );
472     taos( &p_buffer[ 2 ], p_tmp );
473     memcpy( &p_buffer[ 22 ], &p_buffer[ 2 ], sizeof(*p_buffer) * 4 );
474 }
475
476 static void taos_add3( uint32_t *p_buffer, uint8_t *p_key, uint32_t i_len )
477 {
478     uint32_t x, y;
479     uint32_t i = 0;
480
481     x = (p_buffer[ 4 ] / 8) & 63;
482     p_buffer[ 4 ] += i_len * 8;
483
484     if( p_buffer[ 4 ] < i_len * 8 )
485         p_buffer[ 5 ] += 1;
486
487     p_buffer[ 5 ] += i_len >> 29;
488
489     y = 64 - x;
490
491     if( i_len >= y )
492     {
493         memcpy( &((uint8_t *)p_buffer)[ 24 + x ], p_key, y );
494         taos( p_buffer, &p_buffer[ 6 ] );
495
496         i = y;
497         y += 63;
498
499         if( y < i_len )
500         {
501             for( ; y < i_len; y += 64, i += 64 )
502             {
503                 taos( p_buffer, (uint32_t *)&p_key[y - 63] );
504             }
505         }
506         else
507         {
508             x = 0;
509         }
510     }
511
512     memcpy( &((uint8_t *)p_buffer)[ 24 + x ], &p_key[ i ], i_len - i );
513 }
514
515 static int taos_osi( uint32_t *p_buffer )
516 {
517     int i_ret = 0;
518
519 #ifdef WIN32
520     HKEY i_key;
521     uint32_t i;
522     DWORD i_size;
523     DWORD i_serial;
524     LPBYTE p_reg_buf;
525
526     static LPCTSTR p_reg_keys[ 3 ][ 2 ] =
527     {
528         {
529             _T("HARDWARE\\DESCRIPTION\\System"),
530             _T("SystemBiosVersion")
531         },
532
533         {
534             _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
535             _T("ProcessorNameString")
536         },
537
538         {
539             _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"),
540             _T("ProductId")
541         }
542     };
543
544     taos_add1( p_buffer, "cache-control", 13 );
545     taos_add1( p_buffer, "Ethernet", 8 );
546
547     GetVolumeInformation( _T("C:\\"), NULL, 0, &i_serial,
548                           NULL, NULL, NULL, 0 );
549     taos_add1( p_buffer, (uint8_t *)&i_serial, 4 );
550
551     for( i = 0; i < sizeof(p_reg_keys)/sizeof(p_reg_keys[ 0 ]); i++ )
552     {
553         if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, p_reg_keys[ i ][ 0 ],
554                           0, KEY_READ, &i_key ) == ERROR_SUCCESS )
555         {
556             if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ],
557                                  NULL, NULL, NULL,
558                                  &i_size ) == ERROR_SUCCESS )
559             {
560                 p_reg_buf = malloc( i_size );
561
562                 if( p_reg_buf != NULL )
563                 {
564                     if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ],
565                                          NULL, NULL, p_reg_buf,
566                                          &i_size ) == ERROR_SUCCESS )
567                     {
568                         taos_add1( p_buffer, (uint8_t *)p_reg_buf,
569                                    i_size );
570                     }
571
572                     free( p_reg_buf );
573                 }
574             }
575
576             RegCloseKey( i_key );
577         }
578     }
579
580 #else
581     i_ret = -1;
582 #endif
583
584     return( i_ret );
585 }
586
587 static int get_sci_data( uint32_t p_sci[ 11 ][ 4 ] )
588 {
589     int i_ret = -1;
590
591 #ifdef WIN32
592     HANDLE i_file;
593     DWORD i_size, i_read;
594     TCHAR p_path[ MAX_PATH ];
595     TCHAR *p_filename = _T("\\Apple Computer\\iTunes\\SC Info\\SC Info.sidb");
596
597     if( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA,
598                                     NULL, 0, p_path ) ) )
599     {
600         _tcsncat( p_path, p_filename, min( _tcslen( p_filename ),
601                   (MAX_PATH-1) - _tcslen( p_path ) ) );
602
603         i_file = CreateFile( p_path, GENERIC_READ, 0, NULL,
604                              OPEN_EXISTING, 0, NULL );
605         if( i_file != INVALID_HANDLE_VALUE )
606         {
607             i_read = sizeof(p_sci[ 0 ]) * 11;
608             i_size = GetFileSize( i_file, NULL );
609             if( i_size != INVALID_FILE_SIZE && i_size >= i_read )
610             {
611                 i_size = SetFilePointer( i_file, 4, NULL, FILE_BEGIN );
612                 if( i_size != INVALID_SET_FILE_POINTER )
613                 {
614                     if( ReadFile( i_file, p_sci, i_read, &i_size, NULL ) &&
615                         i_size == i_read )
616                     {
617                         i_ret = 0;
618                     }
619                 }
620             }
621
622             CloseHandle( i_file );
623         }
624     }
625 #endif
626
627     return( i_ret );
628 }
629
630 static void acei_taxs( uint32_t *p_acei, uint32_t i_val )
631 {
632     uint32_t i, x;
633
634     i = (i_val / 16) & 15;
635     x = (~(i_val & 15)) & 15;
636
637     if( (i_val & 768) == 768 )
638     {
639         x = (~i) & 15;
640         i = i_val & 15;
641
642         p_acei[ 25 + i ] = p_acei[ 25 + ((16 - x) & 15) ]
643                          + p_acei[ 25 + (15 - x) ];
644     }
645     else if( (i_val & 512) == 512 )
646     {
647         p_acei[ 25 + i ] ^= p_drms_tab_xor[ 15 - i ][ x ];
648     }
649     else if( (i_val & 256) == 256 )
650     {
651         p_acei[ 25 + i ] -= p_drms_tab_sub[ 15 - i ][ x ];
652     }
653     else
654     {
655         p_acei[ 25 + i ] += p_drms_tab_add[ 15 - i ][ x ];
656     }
657 }
658
659 static void acei( uint32_t *p_acei, uint8_t *p_buffer, uint32_t i_len )
660 {
661     uint32_t i, x;
662     uint32_t p_tmp[ 26 ];
663
664     for( i = 5; i < 25; i++ )
665     {
666         if( p_acei[ i ] )
667         {
668             acei_taxs( p_acei, p_acei[ i ] );
669         }
670     }
671
672     TAOS_INIT( p_tmp, 2 );
673     taos_add2e( p_tmp, &p_acei[ 25 ], sizeof(*p_acei) * 4 );
674     taos_end2( p_tmp );
675
676     x = i_len < 16 ? i_len : 16;
677
678     if( x > 0 )
679     {
680         for( i = 0; i < x; i++ )
681         {
682             p_buffer[ i ] ^= ((uint8_t *)&p_tmp)[ 88 + i ];
683         }
684     }
685 }
686
687 static uint32_t ttov_calc( uint32_t *p_acei )
688 {
689     int32_t i_val;
690     uint32_t p_tmp[ 26 ];
691
692     TAOS_INIT( p_tmp, 2 );
693     taos_add2e( p_tmp, &p_acei[ 0 ], 4 );
694     taos_add2e( p_tmp, &p_acei[ 4 ], 1 );
695     taos_end2( p_tmp );
696
697     p_acei[ 4 ]++;
698
699     i_val = ((int32_t)U32_AT(&p_tmp[ 22 ])) % 1024;
700
701     return( i_val < 0 ? i_val * -1 : i_val );
702 }
703
704 static void acei_init( uint32_t *p_acei, uint32_t *p_sys_key )
705 {
706     uint32_t i;
707
708     for( i = 0; i < 4; i++ )
709     {
710         p_acei[ i ] = U32_AT(&p_sys_key[ i ]);
711     }
712
713     p_acei[ 4 ] = 0x5476212A;
714
715     for( i = 5; i < 25; i++ )
716     {
717         p_acei[ i ] = ttov_calc( p_acei );
718     }
719
720     p_acei[ 25 + 0 ] = p_acei[ 0 ];
721     p_acei[ 25 + 1 ] = 0x68723876;
722     p_acei[ 25 + 2 ] = 0x41617376;
723     p_acei[ 25 + 3 ] = 0x4D4B4F76;
724
725     p_acei[ 25 + 4 ] = p_acei[ 1 ];
726     p_acei[ 25 + 5 ] = 0x48556646;
727     p_acei[ 25 + 6 ] = 0x38393725;
728     p_acei[ 25 + 7 ] = 0x2E3B5B3D;
729
730     p_acei[ 25 + 8 ] = p_acei[ 2 ];
731     p_acei[ 25 + 9 ] = 0x37363866;
732     p_acei[ 25 + 10 ] = 0x30383637;
733     p_acei[ 25 + 11 ] = 0x34333661;
734
735     p_acei[ 25 + 12 ] = p_acei[ 3 ];
736     p_acei[ 25 + 13 ] = 0x37386162;
737     p_acei[ 25 + 14 ] = 0x494F6E66;
738     p_acei[ 25 + 15 ] = 0x2A282966;
739 }
740
741 static inline void block_xor( uint32_t *p_in, uint32_t *p_key,
742                               uint32_t *p_out )
743 {
744     uint32_t i;
745
746     for( i = 0; i < 4; i++ )
747     {
748         p_out[ i ] = p_key[ i ] ^ p_in[ i ];
749     }
750 }
751
752 int drms_get_sys_key( uint32_t *p_sys_key )
753 {
754     uint32_t p_tmp[ 128 ];
755     uint32_t p_tmp_key[ 4 ];
756
757     TAOS_INIT( p_tmp, 8 );
758     if( taos_osi( p_tmp ) )
759     {
760         return( -1 );
761     }
762     taos_end1( p_tmp, p_tmp_key );
763
764     TAOS_INIT( p_tmp, 2 );
765     taos_add2( p_tmp, "YuaFlafu", 8 );
766     taos_add2( p_tmp, (uint8_t *)p_tmp_key, 6 );
767     taos_add2( p_tmp, (uint8_t *)p_tmp_key, 6 );
768     taos_add2( p_tmp, (uint8_t *)p_tmp_key, 6 );
769     taos_add2( p_tmp, "zPif98ga", 8 );
770     taos_end2( p_tmp );
771
772     memcpy( p_sys_key, &p_tmp[ 2 ], sizeof(*p_sys_key) * 4 );
773
774     return( 0 );
775 }
776
777 int drms_get_user_key( uint32_t *p_sys_key, uint32_t *p_user_key )
778 {
779     uint32_t i;
780     uint32_t p_tmp[ 4 ];
781     uint32_t *p_cur_key;
782     uint32_t p_acei[ 41 ];
783     uint32_t p_ctx[ 128 ];
784     uint32_t p_sci[ 2 ][ 11 ][ 4 ];
785
786     uint32_t p_sci_key[ 4 ] =
787     {
788         0x6E66556D, 0x6E676F70, 0x67666461, 0x33373866
789     };
790
791     if( p_sys_key == NULL )
792     {
793         if( drms_get_sys_key( p_tmp ) )
794         {
795             return( -1 );
796         }
797
798         p_sys_key = p_tmp;
799     }
800
801     if( get_sci_data( p_sci[ 0 ] ) )
802     {
803         return( -1 );
804     }
805
806     init_ctx( p_ctx, p_sys_key );
807
808     for( i = 0, p_cur_key = p_sci_key;
809          i < sizeof(p_sci[ 0 ])/sizeof(p_sci[ 0 ][ 0 ]); i++ )
810     {
811         ctx_xor( p_ctx, &p_sci[ 0 ][ i ][ 0 ], &p_sci[ 1 ][ i ][ 0 ],
812                  p_drms_tab3, p_drms_tab4 );
813         block_xor( &p_sci[ 1 ][ i ][ 0 ], p_cur_key, &p_sci[ 1 ][ i ][ 0 ] );
814
815         p_cur_key = &p_sci[ 0 ][ i ][ 0 ];
816     }
817
818     acei_init( p_acei, p_sys_key );
819
820     for( i = 0; i < sizeof(p_sci[ 1 ])/sizeof(p_sci[ 1 ][ 0 ]); i++ )
821     {
822         acei( p_acei, (uint8_t *)&p_sci[ 1 ][ i ][ 0 ],
823               sizeof(p_sci[ 1 ][ i ]) );
824     }
825
826     memcpy( p_user_key, &p_sci[ 1 ][ 10 ][ 0 ], sizeof(p_sci[ 1 ][ i ]) );
827
828     return( 0 );
829 }
830
831 struct drms_s
832 {
833     uint8_t *p_iviv;
834     uint32_t i_iviv_len;
835     uint8_t *p_name;
836     uint32_t i_name_len;
837
838     uint32_t *p_tmp;
839     uint32_t i_tmp_len;
840
841     uint32_t p_key[ 4 ];
842     uint32_t p_ctx[ 128 ];
843 };
844
845 #define P_DRMS ((struct drms_s *)p_drms)
846
847 void *drms_alloc()
848 {
849     struct drms_s *p_drms;
850
851     p_drms = malloc( sizeof(struct drms_s) );
852
853     if( p_drms != NULL )
854     {
855         memset( p_drms, 0, sizeof(struct drms_s) );
856
857         p_drms->i_tmp_len = 1024;
858         p_drms->p_tmp = malloc( p_drms->i_tmp_len );
859         if( p_drms->p_tmp == NULL )
860         {
861             free( (void *)p_drms );
862             p_drms = NULL;
863         }
864     }
865
866     return( (void *)p_drms );
867 }
868
869 void drms_free( void *p_drms )
870 {
871     if( P_DRMS->p_name != NULL )
872     {
873         free( (void *)P_DRMS->p_name );
874     }
875
876     if( P_DRMS->p_iviv != NULL )
877     {
878         free( (void *)P_DRMS->p_iviv );
879     }
880
881     if( P_DRMS->p_tmp != NULL )
882     {
883         free( (void *)P_DRMS->p_tmp );
884     }
885
886     free( p_drms );
887 }
888
889 void drms_decrypt( void *p_drms, uint32_t *p_buffer, uint32_t i_len )
890 {
891     uint32_t i, x, y;
892     uint32_t *p_cur_key = P_DRMS->p_key;
893
894     x = (i_len / sizeof(P_DRMS->p_key)) * sizeof(P_DRMS->p_key);
895
896     if( P_DRMS->i_tmp_len < x )
897     {
898         free( (void *)P_DRMS->p_tmp );
899
900         P_DRMS->i_tmp_len = x;
901         P_DRMS->p_tmp = malloc( P_DRMS->i_tmp_len );
902     }
903
904     if( P_DRMS->p_tmp != NULL )
905     {
906         memcpy( P_DRMS->p_tmp, p_buffer, x );
907
908         for( i = 0, x /= sizeof(P_DRMS->p_key); i < x; i++ )
909         {
910             y = i * sizeof(*p_buffer);
911
912             ctx_xor( P_DRMS->p_ctx, P_DRMS->p_tmp + y, p_buffer + y,
913                      p_drms_tab3, p_drms_tab4 );
914             block_xor( p_buffer + y, p_cur_key, p_buffer + y );
915
916             p_cur_key = P_DRMS->p_tmp + y;
917         }
918     }
919 }
920
921 int drms_init( void *p_drms, uint32_t i_type,
922                uint8_t *p_info, uint32_t i_len )
923 {
924     int i_ret = 0;
925
926     switch( i_type )
927     {
928         case DRMS_INIT_UKEY:
929         {
930             if( i_len != sizeof(P_DRMS->p_key) )
931             {
932                 i_ret = -1;
933                 break;
934             }
935
936             init_ctx( P_DRMS->p_ctx, (uint32_t *)p_info );
937         }
938         break;
939
940         case DRMS_INIT_IVIV:
941         {
942             if( i_len != sizeof(P_DRMS->p_key) )
943             {
944                 i_ret = -1;
945                 break;
946             }
947
948             P_DRMS->p_iviv = malloc( i_len );
949             if( P_DRMS->p_iviv == NULL )
950             {
951                 i_ret = -1;
952                 break;
953             }
954
955             memcpy( P_DRMS->p_iviv, p_info, i_len );
956             P_DRMS->i_iviv_len = i_len;
957         }
958         break;
959
960         case DRMS_INIT_NAME:
961         {
962             P_DRMS->p_name = malloc( i_len );
963             if( P_DRMS->p_name == NULL )
964             {
965                 i_ret = -1;
966                 break;
967             }
968
969             memcpy( P_DRMS->p_name, p_info, i_len );
970             P_DRMS->i_name_len = i_len;
971         }
972         break;
973
974         case DRMS_INIT_PRIV:
975         {
976             uint32_t i;
977             uint32_t p_priv[ 64 ];
978             uint32_t p_tmp[ 128 ];
979
980             if( i_len < 64 )
981             {
982                 i_ret = -1;
983                 break;
984             }
985
986             TAOS_INIT( p_tmp, 0 );
987             taos_add3( p_tmp, P_DRMS->p_name, P_DRMS->i_name_len );
988             taos_add3( p_tmp, P_DRMS->p_iviv, P_DRMS->i_iviv_len );
989             memcpy( p_priv, &p_tmp[ 4 ], sizeof(p_priv[ 0 ]) * 2 );
990             i = (p_tmp[ 4 ] / 8) & 63;
991             i = i >= 56 ? 120 - i : 56 - i;
992             taos_add3( p_tmp, p_drms_tab_tend, i );
993             taos_add3( p_tmp, (uint8_t *)p_priv, sizeof(p_priv[ 0 ]) * 2 );
994
995             memcpy( p_priv, p_info, 64 );
996             memcpy( P_DRMS->p_key, p_tmp, sizeof(P_DRMS->p_key) );
997             drms_decrypt( p_drms, p_priv, sizeof(p_priv) );
998
999             init_ctx( P_DRMS->p_ctx, &p_priv[ 6 ] );
1000             memcpy( P_DRMS->p_key, &p_priv[ 12 ], sizeof(P_DRMS->p_key) );
1001
1002             free( (void *)P_DRMS->p_name );
1003             P_DRMS->p_name = NULL;
1004             free( (void *)P_DRMS->p_iviv );
1005             P_DRMS->p_iviv = NULL;
1006         }
1007         break;
1008     }
1009
1010     return( i_ret );
1011 }
1012
1013 #undef P_DRMS
1014