]> git.sesse.net Git - vlc/blob - modules/demux/mp4/drms.c
mp4: fix a memory leak and an invalid release in MacOS code.
[vlc] / modules / demux / mp4 / drms.c
1 /*****************************************************************************
2  * drms.c: DRMS
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Sam Hocevar <sam@zoy.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <vlc_common.h>
30 #include <vlc_md5.h>
31 #include "libmp4.h"
32 #include <vlc_fs.h>
33
34 #ifdef WIN32
35 #   include <io.h>
36 #else
37 #   include <stdio.h>
38 #endif
39
40 #include <errno.h>
41
42 #ifdef WIN32
43 #   if !defined( UNDER_CE )
44 #       include <direct.h>
45 #   endif
46 #   include <tchar.h>
47 #   include <shlobj.h>
48 #   include <windows.h>
49 #endif
50
51 #ifdef HAVE_SYS_STAT_H
52 #   include <sys/stat.h>
53 #endif
54 #include <sys/types.h>
55
56 /* In Solaris (and perhaps others) PATH_MAX is in limits.h. */
57 #include <limits.h>
58
59 #ifdef __APPLE__
60 #   include <mach/mach.h>
61 #   include <IOKit/IOKitLib.h>
62 #   include <CoreFoundation/CFNumber.h>
63 #endif
64
65 #include "drms.h"
66 #include "drmstables.h"
67
68 #if !defined( UNDER_CE )
69 /*****************************************************************************
70  * aes_s: AES keys structure
71  *****************************************************************************
72  * This structure stores a set of keys usable for encryption and decryption
73  * with the AES/Rijndael algorithm.
74  *****************************************************************************/
75 struct aes_s
76 {
77     uint32_t pp_enc_keys[ AES_KEY_COUNT + 1 ][ 4 ];
78     uint32_t pp_dec_keys[ AES_KEY_COUNT + 1 ][ 4 ];
79 };
80
81 #define Digest DigestMD5
82
83 /*****************************************************************************
84  * shuffle_s: shuffle structure
85  *****************************************************************************
86  * This structure stores the static information needed to shuffle data using
87  * a custom algorithm.
88  *****************************************************************************/
89 struct shuffle_s
90 {
91     uint32_t i_version;
92     uint32_t p_commands[ 20 ];
93     uint32_t p_bordel[ 16 ];
94 };
95
96 #define SWAP( a, b ) { (a) ^= (b); (b) ^= (a); (a) ^= (b); }
97
98 /*****************************************************************************
99  * drms_s: DRMS structure
100  *****************************************************************************
101  * This structure stores the static information needed to decrypt DRMS data.
102  *****************************************************************************/
103 struct drms_s
104 {
105     uint32_t i_user;
106     uint32_t i_key;
107     uint8_t  p_iviv[ 16 ];
108     uint8_t *p_name;
109
110     uint32_t p_key[ 4 ];
111     struct aes_s aes;
112
113     char     psz_homedir[ PATH_MAX ];
114 };
115
116 /*****************************************************************************
117  * Local prototypes
118  *****************************************************************************/
119 static void InitAES       ( struct aes_s *, uint32_t * );
120 static void DecryptAES    ( struct aes_s *, uint32_t *, const uint32_t * );
121
122 static void InitShuffle   ( struct shuffle_s *, uint32_t *, uint32_t );
123 static void DoShuffle     ( struct shuffle_s *, uint32_t *, uint32_t );
124
125 static uint32_t FirstPass ( uint32_t * );
126 static void SecondPass    ( uint32_t *, uint32_t );
127 static void ThirdPass     ( uint32_t * );
128 static void FourthPass    ( uint32_t * );
129 static void TinyShuffle1  ( uint32_t * );
130 static void TinyShuffle2  ( uint32_t * );
131 static void TinyShuffle3  ( uint32_t * );
132 static void TinyShuffle4  ( uint32_t * );
133 static void TinyShuffle5  ( uint32_t * );
134 static void TinyShuffle6  ( uint32_t * );
135 static void TinyShuffle7  ( uint32_t * );
136 static void TinyShuffle8  ( uint32_t * );
137 static void DoExtShuffle  ( uint32_t * );
138
139 static int GetSystemKey   ( uint32_t *, bool );
140 static int WriteUserKey   ( void *, uint32_t * );
141 static int ReadUserKey    ( void *, uint32_t * );
142 static int GetUserKey     ( void *, uint32_t * );
143
144 static int GetSCIData     ( char *, uint32_t **, uint32_t * );
145 static int HashSystemInfo ( uint32_t * );
146 static int GetiPodID      ( int64_t * );
147
148 #ifdef WORDS_BIGENDIAN
149 /*****************************************************************************
150  * Reverse: reverse byte order
151  *****************************************************************************/
152 static inline void Reverse( uint32_t *p_buffer, int n )
153 {
154     int i;
155
156     for( i = 0; i < n; i++ )
157     {
158         p_buffer[ i ] = GetDWLE(&p_buffer[ i ]);
159     }
160 }
161 #    define REVERSE( p, n ) Reverse( p, n )
162 #else
163 #    define REVERSE( p, n )
164 #endif
165
166 /*****************************************************************************
167  * BlockXOR: XOR two 128 bit blocks
168  *****************************************************************************/
169 static inline void BlockXOR( uint32_t *p_dest, uint32_t *p_s1, uint32_t *p_s2 )
170 {
171     int i;
172
173     for( i = 0; i < 4; i++ )
174     {
175         p_dest[ i ] = p_s1[ i ] ^ p_s2[ i ];
176     }
177 }
178
179 /*****************************************************************************
180  * drms_alloc: allocate a DRMS structure
181  *****************************************************************************/
182 void *drms_alloc( const char *psz_homedir )
183 {
184     struct drms_s *p_drms;
185
186     p_drms = calloc( 1, sizeof(struct drms_s) );
187     if( !p_drms )
188         return NULL;
189
190     strncpy( p_drms->psz_homedir, psz_homedir, PATH_MAX );
191     p_drms->psz_homedir[ PATH_MAX - 1 ] = '\0';
192
193     return (void *)p_drms;
194 }
195
196 /*****************************************************************************
197  * drms_free: free a previously allocated DRMS structure
198  *****************************************************************************/
199 void drms_free( void *_p_drms )
200 {
201     struct drms_s *p_drms = (struct drms_s *)_p_drms;
202
203     free( (void *)p_drms->p_name );
204     free( p_drms );
205 }
206
207 /*****************************************************************************
208  * drms_decrypt: unscramble a chunk of data
209  *****************************************************************************/
210 void drms_decrypt( void *_p_drms, uint32_t *p_buffer, uint32_t i_bytes, uint32_t *p_key )
211 {
212     struct drms_s *p_drms = (struct drms_s *)_p_drms;
213     uint32_t p_key_buf[ 4 ];
214     unsigned int i_blocks;
215
216     /* AES is a block cypher, round down the byte count */
217     i_blocks = i_bytes / 16;
218     i_bytes = i_blocks * 16;
219
220     /* Initialise the key */
221     if( !p_key )
222     {
223         p_key = p_key_buf;
224         memcpy( p_key, p_drms->p_key, 16 );
225     }
226
227     /* Unscramble */
228     while( i_blocks-- )
229     {
230         uint32_t p_tmp[ 4 ];
231
232         REVERSE( p_buffer, 4 );
233         DecryptAES( &p_drms->aes, p_tmp, p_buffer );
234         BlockXOR( p_tmp, p_key, p_tmp );
235
236         /* Use the previous scrambled data as the key for next block */
237         memcpy( p_key, p_buffer, 16 );
238
239         /* Copy unscrambled data back to the buffer */
240         memcpy( p_buffer, p_tmp, 16 );
241         REVERSE( p_buffer, 4 );
242
243         p_buffer += 4;
244     }
245 }
246
247 /*****************************************************************************
248  * drms_get_p_key: copy the p_key into user buffer
249  ****************************************************************************/
250 void drms_get_p_key( void *_p_drms, uint32_t *p_key )
251 {
252     struct drms_s *p_drms = (struct drms_s *)_p_drms;
253
254     memcpy( p_key, p_drms->p_key, 16 );
255 }
256
257 /*****************************************************************************
258  * drms_init: initialise a DRMS structure
259  *****************************************************************************
260  * Return values:
261  *  0: success
262  * -1: unimplemented
263  * -2: invalid argument
264  * -3: could not get system key
265  * -4: could not get SCI data
266  * -5: no user key found in SCI data
267  * -6: invalid user key
268  *****************************************************************************/
269 int drms_init( void *_p_drms, uint32_t i_type,
270                uint8_t *p_info, uint32_t i_len )
271 {
272     struct drms_s *p_drms = (struct drms_s *)_p_drms;
273     int i_ret = 0;
274
275     switch( i_type )
276     {
277         case FOURCC_user:
278             if( i_len < sizeof(p_drms->i_user) )
279             {
280                 i_ret = -2;
281                 break;
282             }
283
284             p_drms->i_user = U32_AT( p_info );
285             break;
286
287         case FOURCC_key:
288             if( i_len < sizeof(p_drms->i_key) )
289             {
290                 i_ret = -2;
291                 break;
292             }
293
294             p_drms->i_key = U32_AT( p_info );
295             break;
296
297         case FOURCC_iviv:
298             if( i_len < sizeof(p_drms->p_key) )
299             {
300                 i_ret = -2;
301                 break;
302             }
303
304             memcpy( p_drms->p_iviv, p_info, 16 );
305             break;
306
307         case FOURCC_name:
308             p_drms->p_name = (uint8_t*) strdup( (char *)p_info );
309
310             if( p_drms->p_name == NULL )
311             {
312                 i_ret = -2;
313             }
314             break;
315
316         case FOURCC_priv:
317         {
318             uint32_t p_priv[ 64 ];
319             struct md5_s md5;
320
321             if( i_len < 64 )
322             {
323                 i_ret = -2;
324                 break;
325             }
326
327             InitMD5( &md5 );
328             AddMD5( &md5, p_drms->p_name, strlen( (char *)p_drms->p_name ) );
329             AddMD5( &md5, p_drms->p_iviv, 16 );
330             EndMD5( &md5 );
331
332             if( p_drms->i_user == 0 && p_drms->i_key == 0 )
333             {
334                 static const char p_secret[] = "tr1-th3n.y00_by3";
335                 memcpy( p_drms->p_key, p_secret, 16 );
336                 REVERSE( p_drms->p_key, 4 );
337             }
338             else
339             {
340                 i_ret = GetUserKey( p_drms, p_drms->p_key );
341                 if( i_ret )
342                 {
343                     break;
344                 }
345             }
346
347             InitAES( &p_drms->aes, p_drms->p_key );
348
349             memcpy( p_priv, p_info, 64 );
350             memcpy( p_drms->p_key, md5.p_digest, 16 );
351             drms_decrypt( p_drms, p_priv, 64, NULL );
352             REVERSE( p_priv, 64 );
353
354             if( p_priv[ 0 ] != 0x6e757469 ) /* itun */
355             {
356                 i_ret = -6;
357                 break;
358             }
359
360             InitAES( &p_drms->aes, p_priv + 6 );
361             memcpy( p_drms->p_key, p_priv + 12, 16 );
362
363             free( (void *)p_drms->p_name );
364             p_drms->p_name = NULL;
365         }
366         break;
367     }
368
369     return i_ret;
370 }
371
372 /* The following functions are local */
373
374 /*****************************************************************************
375  * InitAES: initialise AES/Rijndael encryption/decryption tables
376  *****************************************************************************
377  * The Advanced Encryption Standard (AES) is described in RFC 3268
378  *****************************************************************************/
379 static void InitAES( struct aes_s *p_aes, uint32_t *p_key )
380 {
381     unsigned int i, t;
382     uint32_t i_key, i_seed;
383
384     memset( p_aes->pp_enc_keys[1], 0, 16 );
385     memcpy( p_aes->pp_enc_keys[0], p_key, 16 );
386
387     /* Generate the key tables */
388     i_seed = p_aes->pp_enc_keys[ 0 ][ 3 ];
389
390     for( i_key = 0; i_key < AES_KEY_COUNT; i_key++ )
391     {
392         uint32_t j;
393
394         i_seed = AES_ROR( i_seed, 8 );
395
396         j = p_aes_table[ i_key ];
397
398         j ^= p_aes_encrypt[ (i_seed >> 24) & 0xff ]
399               ^ AES_ROR( p_aes_encrypt[ (i_seed >> 16) & 0xff ], 8 )
400               ^ AES_ROR( p_aes_encrypt[ (i_seed >> 8) & 0xff ], 16 )
401               ^ AES_ROR( p_aes_encrypt[ i_seed & 0xff ], 24 );
402
403         j ^= p_aes->pp_enc_keys[ i_key ][ 0 ];
404         p_aes->pp_enc_keys[ i_key + 1 ][ 0 ] = j;
405         j ^= p_aes->pp_enc_keys[ i_key ][ 1 ];
406         p_aes->pp_enc_keys[ i_key + 1 ][ 1 ] = j;
407         j ^= p_aes->pp_enc_keys[ i_key ][ 2 ];
408         p_aes->pp_enc_keys[ i_key + 1 ][ 2 ] = j;
409         j ^= p_aes->pp_enc_keys[ i_key ][ 3 ];
410         p_aes->pp_enc_keys[ i_key + 1 ][ 3 ] = j;
411
412         i_seed = j;
413     }
414
415     memcpy( p_aes->pp_dec_keys[ 0 ],
416             p_aes->pp_enc_keys[ 0 ], 16 );
417
418     for( i = 1; i < AES_KEY_COUNT; i++ )
419     {
420         for( t = 0; t < 4; t++ )
421         {
422             uint32_t j, k, l, m, n;
423
424             j = p_aes->pp_enc_keys[ i ][ t ];
425
426             k = (((j >> 7) & 0x01010101) * 27) ^ ((j & 0xff7f7f7f) << 1);
427             l = (((k >> 7) & 0x01010101) * 27) ^ ((k & 0xff7f7f7f) << 1);
428             m = (((l >> 7) & 0x01010101) * 27) ^ ((l & 0xff7f7f7f) << 1);
429
430             j ^= m;
431
432             n = AES_ROR( l ^ j, 16 ) ^ AES_ROR( k ^ j, 8 ) ^ AES_ROR( j, 24 );
433
434             p_aes->pp_dec_keys[ i ][ t ] = k ^ l ^ m ^ n;
435         }
436     }
437 }
438
439 /*****************************************************************************
440  * DecryptAES: decrypt an AES/Rijndael 128 bit block
441  *****************************************************************************/
442 static void DecryptAES( struct aes_s *p_aes,
443                         uint32_t *p_dest, const uint32_t *p_src )
444 {
445     uint32_t p_wtxt[ 4 ]; /* Working cyphertext */
446     uint32_t p_tmp[ 4 ];
447     unsigned int i_round, t;
448
449     for( t = 0; t < 4; t++ )
450     {
451         /* FIXME: are there any endianness issues here? */
452         p_wtxt[ t ] = p_src[ t ] ^ p_aes->pp_enc_keys[ AES_KEY_COUNT ][ t ];
453     }
454
455     /* Rounds 0 - 8 */
456     for( i_round = 0; i_round < (AES_KEY_COUNT - 1); i_round++ )
457     {
458         for( t = 0; t < 4; t++ )
459         {
460             p_tmp[ t ] = AES_XOR_ROR( p_aes_itable, p_wtxt );
461         }
462
463         for( t = 0; t < 4; t++ )
464         {
465             p_wtxt[ t ] = p_tmp[ t ]
466                     ^ p_aes->pp_dec_keys[ (AES_KEY_COUNT - 1) - i_round ][ t ];
467         }
468     }
469
470     /* Final round (9) */
471     for( t = 0; t < 4; t++ )
472     {
473         p_dest[ t ] = AES_XOR_ROR( p_aes_decrypt, p_wtxt );
474         p_dest[ t ] ^= p_aes->pp_dec_keys[ 0 ][ t ];
475     }
476 }
477
478 /*****************************************************************************
479  * InitShuffle: initialise a shuffle structure
480  *****************************************************************************
481  * This function initialises tables in the p_shuffle structure that will be
482  * used later by DoShuffle. The only external parameter is p_sys_key.
483  *****************************************************************************/
484 static void InitShuffle( struct shuffle_s *p_shuffle, uint32_t *p_sys_key,
485                          uint32_t i_version )
486 {
487     char p_secret1[] = "Tv!*";
488     static const char p_secret2[] = "____v8rhvsaAvOKM____FfUH%798=[;."
489                                     "____f8677680a634____ba87fnOIf)(*";
490     unsigned int i;
491
492     p_shuffle->i_version = i_version;
493
494     /* Fill p_commands using the key and a secret seed */
495     for( i = 0; i < 20; i++ )
496     {
497         struct md5_s md5;
498         int32_t i_hash;
499
500         InitMD5( &md5 );
501         AddMD5( &md5, (const uint8_t *)p_sys_key, 16 );
502         AddMD5( &md5, (const uint8_t *)p_secret1, 4 );
503         EndMD5( &md5 );
504
505         p_secret1[ 3 ]++;
506
507         REVERSE( md5.p_digest, 1 );
508         i_hash = ((int32_t)U32_AT(md5.p_digest)) % 1024;
509
510         p_shuffle->p_commands[ i ] = i_hash < 0 ? i_hash * -1 : i_hash;
511     }
512
513     /* Fill p_bordel with completely meaningless initial values. */
514     memcpy( p_shuffle->p_bordel, p_secret2, 64 );
515     for( i = 0; i < 4; i++ )
516     {
517         p_shuffle->p_bordel[ 4 * i ] = U32_AT(p_sys_key + i);
518         REVERSE( p_shuffle->p_bordel + 4 * i + 1, 3 );
519     }
520 }
521
522 /*****************************************************************************
523  * DoShuffle: shuffle buffer
524  *****************************************************************************
525  * This is so ugly and uses so many MD5 checksums that it is most certainly
526  * one-way, though why it needs to be so complicated is beyond me.
527  *****************************************************************************/
528 static void DoShuffle( struct shuffle_s *p_shuffle,
529                        uint32_t *p_buffer, uint32_t i_size )
530 {
531     struct md5_s md5;
532     uint32_t p_big_bordel[ 16 ];
533     uint32_t *p_bordel = p_shuffle->p_bordel;
534     unsigned int i;
535
536     static const uint32_t p_secret3[] =
537     {
538         0xAAAAAAAA, 0x01757700, 0x00554580, 0x01724500, 0x00424580,
539         0x01427700, 0x00000080, 0xC1D59D01, 0x80144981, 0x815C8901,
540         0x80544981, 0x81D45D01, 0x00000080, 0x81A3BB03, 0x00A2AA82,
541         0x01A3BB03, 0x0022A282, 0x813BA202, 0x00000080, 0x6D575737,
542         0x4A5275A5, 0x6D525725, 0x4A5254A5, 0x6B725437, 0x00000080,
543         0xD5DDB938, 0x5455A092, 0x5D95A013, 0x4415A192, 0xC5DD393A,
544         0x00000080, 0x55555555
545     };
546     static const uint32_t i_secret3 = sizeof(p_secret3)/sizeof(p_secret3[0]);
547
548     static const char p_secret4[] =
549         "pbclevtug (p) Nccyr Pbzchgre, Vap.  Nyy Evtugf Erfreirq.";
550     static const uint32_t i_secret4 = sizeof(p_secret4)/sizeof(p_secret4[0]); /* It include the terminal '\0' */
551
552     /* Using the MD5 hash of a memory block is probably not one-way enough
553      * for the iTunes people. This function randomises p_bordel depending on
554      * the values in p_commands to make things even more messy in p_bordel. */
555     for( i = 0; i < 20; i++ )
556     {
557         uint8_t i_command, i_index;
558
559         if( !p_shuffle->p_commands[ i ] )
560         {
561             continue;
562         }
563
564         i_command = (p_shuffle->p_commands[ i ] & 0x300) >> 8;
565         i_index = p_shuffle->p_commands[ i ] & 0xff;
566
567         switch( i_command )
568         {
569         case 0x3:
570             p_bordel[ i_index & 0xf ] = p_bordel[ i_index >> 4 ]
571                                       + p_bordel[ ((i_index + 0x10) >> 4) & 0xf ];
572             break;
573         case 0x2:
574             p_bordel[ i_index >> 4 ] ^= p_shuffle_xor[ 0xff - i_index ];
575             break;
576         case 0x1:
577             p_bordel[ i_index >> 4 ] -= p_shuffle_sub[ 0xff - i_index ];
578             break;
579         default:
580             p_bordel[ i_index >> 4 ] += p_shuffle_add[ 0xff - i_index ];
581             break;
582         }
583     }
584
585     if( p_shuffle->i_version == 0x01000300 )
586     {
587         DoExtShuffle( p_bordel );
588     }
589
590     /* Convert our newly randomised p_bordel to big endianness and take
591      * its MD5 hash. */
592     InitMD5( &md5 );
593     for( i = 0; i < 16; i++ )
594     {
595         p_big_bordel[ i ] = U32_AT(p_bordel + i);
596     }
597     AddMD5( &md5, (const uint8_t *)p_big_bordel, 64 );
598     if( p_shuffle->i_version == 0x01000300 )
599     {
600         uint32_t p_tmp3[i_secret3];
601         char     p_tmp4[i_secret4];
602
603         memcpy( p_tmp3, p_secret3, sizeof(p_secret3) );
604         REVERSE( p_tmp3, i_secret3 );
605
606 #define ROT13(c) (((c)>='A'&&(c)<='Z')?(((c)-'A'+13)%26)+'A':\
607                       ((c)>='a'&&(c)<='z')?(((c)-'a'+13)%26)+'a':c)
608         for( uint32_t i = 0; i < i_secret4; i++ )
609             p_tmp4[i] = ROT13( p_secret4[i] );
610 #undef ROT13
611
612         AddMD5( &md5, (const uint8_t *)p_tmp3, sizeof(p_secret3) );
613         AddMD5( &md5, (const uint8_t *)p_tmp4, i_secret4 );
614     }
615     EndMD5( &md5 );
616
617     /* XOR our buffer with the computed checksum */
618     for( i = 0; i < i_size; i++ )
619     {
620         p_buffer[ i ] ^= md5.p_digest[ i ];
621     }
622 }
623
624 /*****************************************************************************
625  * DoExtShuffle: extended shuffle
626  *****************************************************************************
627  * This is even uglier.
628  *****************************************************************************/
629 static void DoExtShuffle( uint32_t * p_bordel )
630 {
631     uint32_t i_ret;
632
633     i_ret = FirstPass( p_bordel );
634
635     SecondPass( p_bordel, i_ret );
636
637     ThirdPass( p_bordel );
638
639     FourthPass( p_bordel );
640 }
641
642 static uint32_t FirstPass( uint32_t * p_bordel )
643 {
644     uint32_t i, i_cmd, i_ret = 5;
645
646     TinyShuffle1( p_bordel );
647
648     for( ; ; )
649     {
650         for( ; ; )
651         {
652             p_bordel[ 1 ] += 0x10000000;
653             p_bordel[ 3 ] += 0x12777;
654
655             if( (p_bordel[ 10 ] & 1) && i_ret )
656             {
657                 i_ret--;
658                 p_bordel[ 1 ] -= p_bordel[ 2 ];
659                 p_bordel[ 11 ] += p_bordel[ 12 ];
660                 break;
661             }
662
663             if( (p_bordel[ 1 ] + p_bordel[ 2 ]) >= 0x7D0 )
664             {
665                 switch( ((p_bordel[ 3 ] ^ 0x567F) >> 2) & 7 )
666                 {
667                     case 0:
668                         for( i = 0; i < 3; i++ )
669                         {
670                             if( p_bordel[ i + 10 ] > 0x4E20 )
671                             {
672                                 p_bordel[ i + 1 ] += p_bordel[ i + 2 ];
673                             }
674                         }
675                         break;
676                     case 4:
677                         p_bordel[ 1 ] -= p_bordel[ 2 ];
678                         /* no break */
679                     case 3:
680                         p_bordel[ 11 ] += p_bordel[ 12 ];
681                         break;
682                     case 6:
683                         p_bordel[ 3 ] ^= p_bordel[ 4 ];
684                         /* no break */
685                     case 8:
686                         p_bordel[ 13 ] &= p_bordel[ 14 ];
687                         /* no break */
688                     case 1:
689                         p_bordel[ 0 ] |= p_bordel[ 1 ];
690                         if( i_ret )
691                         {
692                             return i_ret;
693                         }
694                         break;
695                 }
696
697                 break;
698             }
699         }
700
701         for( i = 0, i_cmd = 0; i < 16; i++ )
702         {
703             if( p_bordel[ i ] < p_bordel[ i_cmd ] )
704             {
705                 i_cmd = i;
706             }
707         }
708
709         if( i_ret && i_cmd != 5 )
710         {
711             i_ret--;
712         }
713         else
714         {
715             if( i_cmd == 5 )
716             {
717                 p_bordel[ 8 ] &= p_bordel[ 6 ] >> 1;
718                 p_bordel[ 3 ] <<= 1;
719             }
720
721             for( i = 0; i < 3; i++ )
722             {
723                 p_bordel[ 11 ] += 1;
724                 if( p_bordel[ 11 ] & 5 )
725                 {
726                     p_bordel[ 8 ] += p_bordel[ 9 ];
727                 }
728                 else if( i_ret )
729                 {
730                     i_ret--;
731                     i_cmd = 3;
732                     goto break2;
733                 }
734             }
735
736             i_cmd = (p_bordel[ 15 ] + 0x93) >> 3;
737             if( p_bordel[ 15 ] & 0x100 )
738             {
739                 i_cmd ^= 0xDEAD;
740             }
741         }
742
743         switch( i_cmd & 3 )
744         {
745             case 0:
746                 while( p_bordel[ 11 ] & 1 )
747                 {
748                     p_bordel[ 11 ] >>= 1;
749                     p_bordel[ 12 ] += 1;
750                 }
751                 /* no break */
752             case 2:
753                 p_bordel[ 14 ] -= 0x19FE;
754                 break;
755             case 3:
756                 if( i_ret )
757                 {
758                     i_ret--;
759                     p_bordel[ 5 ] += 5;
760                     continue;
761                 }
762                 break;
763         }
764
765         i_cmd = ((p_bordel[ 3 ] + p_bordel[ 4 ] + 10) >> 1) - p_bordel[ 4 ];
766         break;
767     }
768 break2:
769
770     switch( i_cmd & 3 )
771     {
772         case 0:
773             p_bordel[ 14 ] >>= 1;
774             break;
775         case 1:
776             p_bordel[ 5 ] <<= 2;
777             break;
778         case 2:
779             p_bordel[ 12 ] |= 5;
780             break;
781         case 3:
782             p_bordel[ 15 ] &= 0x55;
783             if( i_ret )
784             {
785                 p_bordel[ 2 ] &= 0xB62FC;
786                 return i_ret;
787             }
788             break;
789     }
790
791     TinyShuffle2( p_bordel );
792
793     return i_ret;
794 }
795
796 static void SecondPass( uint32_t * p_bordel, uint32_t i_tmp )
797 {
798     uint32_t i, i_cmd, i_jc = 5;
799
800     TinyShuffle3( p_bordel );
801
802     for( i = 0, i_cmd = 0; i < 16; i++ )
803     {
804         if( p_bordel[ i ] > p_bordel[ i_cmd ] )
805         {
806             i_cmd = i;
807         }
808     }
809
810     switch( i_cmd )
811     {
812         case 0:
813             if( p_bordel[ 1 ] < p_bordel[ 8 ] )
814             {
815                 p_bordel[ 5 ] += 1;
816             }
817             break;
818         case 4:
819             if( (p_bordel[ 9 ] & 0x7777) == 0x3333 )
820             {
821                 p_bordel[ 5 ] -= 1;
822             }
823             else
824             {
825                 i_jc--;
826                 if( p_bordel[ 1 ] < p_bordel[ 8 ] )
827                 {
828                     p_bordel[ 5 ] += 1;
829                 }
830                 break;
831             }
832             /* no break */
833         case 7:
834             p_bordel[ 2 ] -= 1;
835             p_bordel[ 1 ] -= p_bordel[ 5 ];
836             for( i = 0; i < 3; i++ )
837             {
838                 switch( p_bordel[ 1 ] & 3 )
839                 {
840                     case 0:
841                         p_bordel[ 1 ] += 1;
842                         /* no break */
843                     case 1:
844                         p_bordel[ 3 ] -= 8;
845                         break;
846                     case 2:
847                         p_bordel[ 13 ] &= 0xFEFEFEF7;
848                         break;
849                     case 3:
850                         p_bordel[ 8 ] |= 0x80080011;
851                         break;
852                 }
853             }
854             return;
855         case 10:
856             p_bordel[ 4 ] -= 1;
857             p_bordel[ 5 ] += 1;
858             p_bordel[ 6 ] -= 1;
859             p_bordel[ 7 ] += 1;
860             break;
861         default:
862             p_bordel[ 15 ] ^= 0x18547EFF;
863             break;
864     }
865
866     for( i = 3; i--; )
867     {
868         switch( ( p_bordel[ 12 ] + p_bordel[ 13 ] + p_bordel[ 6 ] ) % 5 )
869         {
870             case 0:
871                 p_bordel[ 12 ] -= 1;
872                 /* no break */
873             case 1:
874                 p_bordel[ 12 ] -= 1;
875                 p_bordel[ 13 ] += 1;
876                 break;
877             case 2:
878                 p_bordel[ 13 ] += 4;
879                 /* no break */
880             case 3:
881                 p_bordel[ 12 ] -= 1;
882                 break;
883             case 4:
884                 i_jc--;
885                 p_bordel[ 5 ] += 1;
886                 p_bordel[ 6 ] -= 1;
887                 p_bordel[ 7 ] += 1;
888                 i = 3; /* Restart the whole loop */
889                 break;
890         }
891     }
892
893     TinyShuffle4( p_bordel );
894
895     for( ; ; )
896     {
897         TinyShuffle5( p_bordel );
898
899         switch( ( p_bordel[ 2 ] * 2 + 15 ) % 5 )
900         {
901             case 0:
902                 if( ( p_bordel[ 3 ] + i_tmp ) <=
903                     ( p_bordel[ 1 ] + p_bordel[ 15 ] ) )
904                 {
905                     p_bordel[ 3 ] += 1;
906                 }
907                 break;
908             case 4:
909                 p_bordel[ 10 ] -= 0x13;
910                 break;
911             case 3:
912                 p_bordel[ 5 ] >>= 2;
913                 break;
914         }
915
916         if( !( p_bordel[ 2 ] & 1 ) || i_jc == 0 )
917         {
918             break;
919         }
920
921         i_jc--;
922         p_bordel[ 2 ] += 0x13;
923         p_bordel[ 12 ] += 1;
924     }
925
926     p_bordel[ 2 ] &= 0x10076000;
927 }
928
929 static void ThirdPass( uint32_t * p_bordel )
930 {
931     uint32_t i_cmd;
932
933     i_cmd = ((p_bordel[ 7 ] + p_bordel[ 14 ] + 10) >> 1) - p_bordel[ 14 ];
934     i_cmd = i_cmd % 10;
935
936     switch( i_cmd )
937     {
938         case 0:
939             p_bordel[ 1 ] <<= 1;
940             p_bordel[ 2 ] <<= 2;
941             p_bordel[ 3 ] <<= 3;
942             break;
943         case 6:
944             p_bordel[ i_cmd + 3 ] &= 0x5EDE36B;
945             p_bordel[ 5 ] += p_bordel[ 8 ];
946             p_bordel[ 4 ] += p_bordel[ 7 ];
947             p_bordel[ 3 ] += p_bordel[ 6 ];
948             p_bordel[ 2 ] += p_bordel[ 5 ];
949             /* no break */
950         case 2:
951             p_bordel[ 1 ] += p_bordel[ 4 ];
952             p_bordel[ 0 ] += p_bordel[ 3 ];
953             TinyShuffle6( p_bordel );
954             return; /* jc = 4 */
955         case 3:
956             if( (p_bordel[ 11 ] & p_bordel[ 2 ]) > 0x211B )
957             {
958                 p_bordel[ 6 ] += 1;
959             }
960             break;
961         case 4:
962             p_bordel[ 7 ] += 1;
963             /* no break */
964         case 5:
965             p_bordel[ 9 ] ^= p_bordel[ 2 ];
966             break;
967         case 7:
968             p_bordel[ 2 ] ^= (p_bordel[ 1 ] & p_bordel[ 13 ]);
969             break;
970         case 8:
971             p_bordel[ 0 ] -= p_bordel[ 11 ] & p_bordel[ 15 ];
972             return; /* jc = 4 */
973         case 9:
974             p_bordel[ 6 ] >>= (p_bordel[ 14 ] & 3);
975             break;
976     }
977
978     SWAP( p_bordel[ 0 ], p_bordel[ 10 ] );
979
980     TinyShuffle6( p_bordel );
981
982     return; /* jc = 5 */
983 }
984
985 static void FourthPass( uint32_t * p_bordel )
986 {
987     uint32_t i, j;
988
989     TinyShuffle7( p_bordel );
990
991     switch( p_bordel[ 5 ] % 5)
992     {
993         case 0:
994             p_bordel[ 0 ] += 1;
995             break;
996         case 2:
997             p_bordel[ 11 ] ^= (p_bordel[ 3 ] + p_bordel[ 6 ] + p_bordel[ 8 ]);
998             break;
999         case 3:
1000             for( i = 4; i < 15 && (p_bordel[ i ] & 5) == 0; i++ )
1001             {
1002                 SWAP( p_bordel[ i ], p_bordel[ 15 - i ] );
1003             }
1004             break;
1005         case 4:
1006             p_bordel[ 12 ] -= 1;
1007             p_bordel[ 13 ] += 1;
1008             p_bordel[ 2 ] -= 0x64;
1009             p_bordel[ 3 ] += 0x64;
1010             TinyShuffle8( p_bordel );
1011             return;
1012     }
1013
1014     for( i = 0, j = 0; i < 16; i++ )
1015     {
1016         if( p_bordel[ i ] > p_bordel[ j ] )
1017         {
1018             j = i;
1019         }
1020     }
1021
1022     switch( p_bordel[ j ] % 100 )
1023     {
1024         case 0:
1025             SWAP( p_bordel[ 0 ], p_bordel[ j ] );
1026             break;
1027         case 8:
1028             p_bordel[ 1 ] >>= 1;
1029             p_bordel[ 2 ] <<= 1;
1030             p_bordel[ 14 ] >>= 3;
1031             p_bordel[ 15 ] <<= 4;
1032             break;
1033         case 57:
1034             p_bordel[ j ] += p_bordel[ 13 ];
1035             break;
1036         case 76:
1037             p_bordel[ 1 ] += 0x20E;
1038             p_bordel[ 5 ] += 0x223D;
1039             p_bordel[ 13 ] -= 0x576;
1040             p_bordel[ 15 ] += 0x576;
1041             return;
1042         case 91:
1043             p_bordel[ 2 ] -= 0x64;
1044             p_bordel[ 3 ] += 0x64;
1045             p_bordel[ 12 ] -= 1;
1046             p_bordel[ 13 ] += 1;
1047             break;
1048         case 99:
1049             p_bordel[ 0 ] += 1;
1050             p_bordel[ j ] += p_bordel[ 13 ];
1051             break;
1052     }
1053
1054     TinyShuffle8( p_bordel );
1055 }
1056
1057 /*****************************************************************************
1058  * TinyShuffle[12345678]: tiny shuffle subroutines
1059  *****************************************************************************
1060  * These standalone functions are little helpers for the shuffling process.
1061  *****************************************************************************/
1062 static void TinyShuffle1( uint32_t * p_bordel )
1063 {
1064     uint32_t i_cmd = (p_bordel[ 5 ] + 10) >> 2;
1065
1066     if( p_bordel[ 5 ] > 0x7D0 )
1067     {
1068         i_cmd -= 0x305;
1069     }
1070
1071     switch( i_cmd & 3 )
1072     {
1073         case 0:
1074             p_bordel[ 5 ] += 5;
1075             break;
1076         case 1:
1077             p_bordel[ 4 ] -= 1;
1078             break;
1079         case 2:
1080             if( p_bordel[ 4 ] & 5 )
1081             {
1082                 p_bordel[ 1 ] ^= 0x4D;
1083             }
1084             /* no break */
1085         case 3:
1086             p_bordel[ 12 ] += 5;
1087             break;
1088     }
1089 }
1090
1091 static void TinyShuffle2( uint32_t * p_bordel )
1092 {
1093     uint32_t i, j;
1094
1095     for( i = 0, j = 0; i < 16; i++ )
1096     {
1097         if( (p_bordel[ i ] & 0x777) > (p_bordel[ j ] & 0x777) )
1098         {
1099             j = i;
1100         }
1101     }
1102
1103     if( j > 5 )
1104     {
1105         for( ; j < 15; j++ )
1106         {
1107             p_bordel[ j ] += p_bordel[ j + 1 ];
1108         }
1109     }
1110     else
1111     {
1112         p_bordel[ 2 ] &= 0xB62FC;
1113     }
1114 }
1115
1116 static void TinyShuffle3( uint32_t * p_bordel )
1117 {
1118     uint32_t i_cmd = p_bordel[ 6 ] + 0x194B;
1119
1120     if( p_bordel[ 6 ] > 0x2710 )
1121     {
1122         i_cmd >>= 1;
1123     }
1124
1125     switch( i_cmd & 3 )
1126     {
1127         case 1:
1128             p_bordel[ 3 ] += 0x19FE;
1129             break;
1130         case 2:
1131             p_bordel[ 7 ] -= p_bordel[ 3 ] >> 2;
1132             /* no break */
1133         case 0:
1134             p_bordel[ 5 ] ^= 0x248A;
1135             break;
1136     }
1137 }
1138
1139 static void TinyShuffle4( uint32_t * p_bordel )
1140 {
1141     uint32_t i, j;
1142
1143     for( i = 0, j = 0; i < 16; i++ )
1144     {
1145         if( p_bordel[ i ] < p_bordel[ j ] )
1146         {
1147             j = i;
1148         }
1149     }
1150
1151     if( (p_bordel[ j ] % (j + 1)) > 10 )
1152     {
1153         p_bordel[ 1 ] -= 1;
1154         p_bordel[ 2 ] += 0x13;
1155         p_bordel[ 12 ] += 1;
1156     }
1157 }
1158
1159 static void TinyShuffle5( uint32_t * p_bordel )
1160 {
1161     uint32_t i;
1162
1163     p_bordel[ 2 ] &= 0x7F3F;
1164
1165     for( i = 0; i < 5; i++ )
1166     {
1167         switch( ( p_bordel[ 2 ] + 10 + i ) % 5 )
1168         {
1169             case 0:
1170                 p_bordel[ 12 ] &= p_bordel[ 2 ];
1171                 /* no break */
1172             case 1:
1173                 p_bordel[ 3 ] ^= p_bordel[ 15 ];
1174                 break;
1175             case 2:
1176                 p_bordel[ 15 ] += 0x576;
1177                 /* no break */
1178             case 3:
1179                 p_bordel[ 7 ] -= 0x2D;
1180                 /* no break */
1181             case 4:
1182                 p_bordel[ 1 ] <<= 1;
1183                 break;
1184         }
1185     }
1186 }
1187
1188 static void TinyShuffle6( uint32_t * p_bordel )
1189 {
1190     uint32_t i, j;
1191
1192     for( i = 0; i < 8; i++ )
1193     {
1194         j = p_bordel[ 3 ] & 0x7514 ? 5 : 7;
1195         SWAP( p_bordel[ i ], p_bordel[ i + j ] );
1196     }
1197 }
1198
1199 static void TinyShuffle7( uint32_t * p_bordel )
1200 {
1201     uint32_t i;
1202
1203     i = (((p_bordel[ 9 ] + p_bordel[ 15 ] + 12) >> 2) - p_bordel[ 4 ]) & 7;
1204
1205     while( i-- )
1206     {
1207         SWAP( p_bordel[ i ], p_bordel[ i + 3 ] );
1208     }
1209
1210     SWAP( p_bordel[ 1 ], p_bordel[ 10 ] );
1211 }
1212
1213 static void TinyShuffle8( uint32_t * p_bordel )
1214 {
1215     uint32_t i;
1216
1217     i = (p_bordel[ 0 ] & p_bordel[ 6 ]) & 0xF;
1218
1219     switch( p_bordel[ i ] % 1000 )
1220     {
1221         case 7:
1222             if( (p_bordel[ i ] & 0x777) > (p_bordel[ 7 ] & 0x5555) )
1223             {
1224                 p_bordel[ i ] ^= p_bordel[ 5 ] & p_bordel[ 3 ];
1225             }
1226             break;
1227         case 19:
1228             p_bordel[ 15 ] &= 0x5555;
1229             break;
1230         case 93:
1231             p_bordel[ i ] ^= p_bordel[ 15 ];
1232             break;
1233         case 100:
1234             SWAP( p_bordel[ 0 ], p_bordel[ 3 ] );
1235             SWAP( p_bordel[ 1 ], p_bordel[ 6 ] );
1236             SWAP( p_bordel[ 3 ], p_bordel[ 6 ] );
1237             SWAP( p_bordel[ 4 ], p_bordel[ 9 ] );
1238             SWAP( p_bordel[ 5 ], p_bordel[ 8 ] );
1239             SWAP( p_bordel[ 6 ], p_bordel[ 7 ] );
1240             SWAP( p_bordel[ 13 ], p_bordel[ 14 ] );
1241             break;
1242         case 329:
1243             p_bordel[ i ] += p_bordel[ 1 ] ^ 0x80080011;
1244             p_bordel[ i ] += p_bordel[ 2 ] ^ 0xBEEFDEAD;
1245             p_bordel[ i ] += p_bordel[ 3 ] ^ 0x8765F444;
1246             p_bordel[ i ] += p_bordel[ 4 ] ^ 0x78145326;
1247             break;
1248         case 567:
1249             p_bordel[ 12 ] -= p_bordel[ i ];
1250             p_bordel[ 13 ] += p_bordel[ i ];
1251             break;
1252         case 612:
1253             p_bordel[ i ] += p_bordel[ 1 ];
1254             p_bordel[ i ] -= p_bordel[ 7 ];
1255             p_bordel[ i ] -= p_bordel[ 8 ];
1256             p_bordel[ i ] += p_bordel[ 9 ];
1257             p_bordel[ i ] += p_bordel[ 13 ];
1258             break;
1259         case 754:
1260             i = __MIN( i, 12 );
1261             p_bordel[ i + 1 ] >>= 1;
1262             p_bordel[ i + 2 ] <<= 4;
1263             p_bordel[ i + 3 ] >>= 3;
1264             break;
1265         case 777:
1266             p_bordel[ 1 ] += 0x20E;
1267             p_bordel[ 5 ] += 0x223D;
1268             p_bordel[ 13 ] -= 0x576;
1269             p_bordel[ 15 ] += 0x576;
1270             break;
1271         case 981:
1272             if( (p_bordel[ i ] ^ 0x8765F441) < 0x2710 )
1273             {
1274                 SWAP( p_bordel[ 0 ], p_bordel[ 1 ] );
1275             }
1276             else
1277             {
1278                 SWAP( p_bordel[ 1 ], p_bordel[ 11 ] );
1279             }
1280             break;
1281     }
1282 }
1283
1284 /*****************************************************************************
1285  * GetSystemKey: get the system key
1286  *****************************************************************************
1287  * Compute the system key from various system information, see HashSystemInfo.
1288  *****************************************************************************/
1289 static int GetSystemKey( uint32_t *p_sys_key, bool b_ipod )
1290 {
1291     static const char p_secret5[ 8 ] = "YuaFlafu";
1292     static const char p_secret6[ 8 ] = "zPif98ga";
1293     struct md5_s md5;
1294     int64_t i_ipod_id;
1295     uint32_t p_system_hash[ 4 ];
1296
1297     /* Compute the MD5 hash of our system info */
1298     if( ( !b_ipod && HashSystemInfo( p_system_hash ) ) ||
1299         (  b_ipod && GetiPodID( &i_ipod_id ) ) )
1300     {
1301         return -1;
1302     }
1303
1304     /* Combine our system info hash with additional secret data. The resulting
1305      * MD5 hash will be our system key. */
1306     InitMD5( &md5 );
1307     AddMD5( &md5, (const uint8_t*)p_secret5, 8 );
1308
1309     if( !b_ipod )
1310     {
1311         AddMD5( &md5, (const uint8_t *)p_system_hash, 6 );
1312         AddMD5( &md5, (const uint8_t *)p_system_hash, 6 );
1313         AddMD5( &md5, (const uint8_t *)p_system_hash, 6 );
1314         AddMD5( &md5, (const uint8_t *)p_secret6, 8 );
1315     }
1316     else
1317     {
1318         i_ipod_id = U64_AT(&i_ipod_id);
1319         AddMD5( &md5, (const uint8_t *)&i_ipod_id, sizeof(i_ipod_id) );
1320         AddMD5( &md5, (const uint8_t *)&i_ipod_id, sizeof(i_ipod_id) );
1321         AddMD5( &md5, (const uint8_t *)&i_ipod_id, sizeof(i_ipod_id) );
1322     }
1323
1324     EndMD5( &md5 );
1325
1326     memcpy( p_sys_key, md5.p_digest, 16 );
1327
1328     return 0;
1329 }
1330
1331 #ifdef WIN32
1332 #   define DRMS_DIRNAME "drms"
1333 #else
1334 #   define DRMS_DIRNAME ".drms"
1335 #endif
1336
1337 /*****************************************************************************
1338  * WriteUserKey: write the user key to hard disk
1339  *****************************************************************************
1340  * Write the user key to the hard disk so that it can be reused later or used
1341  * on operating systems other than Win32.
1342  *****************************************************************************/
1343 static int WriteUserKey( void *_p_drms, uint32_t *p_user_key )
1344 {
1345     struct drms_s *p_drms = (struct drms_s *)_p_drms;
1346     FILE *file;
1347     int i_ret = -1;
1348     char psz_path[ PATH_MAX ];
1349
1350     snprintf( psz_path, PATH_MAX - 1,
1351               "%s/" DRMS_DIRNAME, p_drms->psz_homedir );
1352
1353 #if defined( WIN32 )
1354     if( !mkdir( psz_path ) || errno == EEXIST )
1355 #else
1356     if( !mkdir( psz_path, 0755 ) || errno == EEXIST )
1357 #endif
1358     {
1359         snprintf( psz_path, PATH_MAX - 1, "%s/" DRMS_DIRNAME "/%08X.%03d",
1360                   p_drms->psz_homedir, p_drms->i_user, p_drms->i_key );
1361
1362         file = vlc_fopen( psz_path, "wb" );
1363         if( file != NULL )
1364         {
1365             i_ret = fwrite( p_user_key, sizeof(uint32_t),
1366                             4, file ) == 4 ? 0 : -1;
1367             fclose( file );
1368         }
1369     }
1370
1371     return i_ret;
1372 }
1373
1374 /*****************************************************************************
1375  * ReadUserKey: read the user key from hard disk
1376  *****************************************************************************
1377  * Retrieve the user key from the hard disk if available.
1378  *****************************************************************************/
1379 static int ReadUserKey( void *_p_drms, uint32_t *p_user_key )
1380 {
1381     struct drms_s *p_drms = (struct drms_s *)_p_drms;
1382     FILE *file;
1383     int i_ret = -1;
1384     char psz_path[ PATH_MAX ];
1385
1386     snprintf( psz_path, PATH_MAX - 1,
1387               "%s/" DRMS_DIRNAME "/%08X.%03d", p_drms->psz_homedir,
1388               p_drms->i_user, p_drms->i_key );
1389
1390     file = vlc_fopen( psz_path, "rb" );
1391     if( file != NULL )
1392     {
1393         i_ret = fread( p_user_key, sizeof(uint32_t),
1394                        4, file ) == 4 ? 0 : -1;
1395         fclose( file );
1396     }
1397
1398     return i_ret;
1399 }
1400
1401 /*****************************************************************************
1402  * GetUserKey: get the user key
1403  *****************************************************************************
1404  * Retrieve the user key from the hard disk if available, otherwise generate
1405  * it from the system key. If the key could be successfully generated, write
1406  * it to the hard disk for future use.
1407  *****************************************************************************/
1408 static int GetUserKey( void *_p_drms, uint32_t *p_user_key )
1409 {
1410     static const char p_secret7[] = "mUfnpognadfgf873";
1411     struct drms_s *p_drms = (struct drms_s *)_p_drms;
1412     struct aes_s aes;
1413     struct shuffle_s shuffle;
1414     uint32_t i, y;
1415     uint32_t *p_sci_data = NULL;
1416     uint32_t i_user, i_key;
1417     uint32_t p_sys_key[ 4 ];
1418     uint32_t i_sci_size = 0, i_blocks, i_remaining;
1419     uint32_t *p_sci0, *p_sci1, *p_buffer;
1420     uint32_t p_sci_key[ 4 ];
1421     char *psz_ipod;
1422     int i_ret = -5;
1423
1424     if( ReadUserKey( p_drms, p_user_key ) == 0 )
1425     {
1426         REVERSE( p_user_key, 4 );
1427         return 0;
1428     }
1429
1430     psz_ipod = getenv( "IPOD" );
1431
1432     if( GetSystemKey( p_sys_key, psz_ipod ? true : false ) )
1433     {
1434         return -3;
1435     }
1436
1437     if( GetSCIData( psz_ipod, &p_sci_data, &i_sci_size ) )
1438     {
1439         return -4;
1440     }
1441
1442     /* Phase 1: unscramble the SCI data using the system key and shuffle
1443      *          it using DoShuffle(). */
1444
1445     /* Skip the first 4 bytes (some sort of header). Decrypt the rest. */
1446     i_blocks = (i_sci_size - 4) / 16;
1447     i_remaining = (i_sci_size - 4) - (i_blocks * 16);
1448     p_buffer = p_sci_data + 1;
1449
1450     /* Decrypt and shuffle our data at the same time */
1451     InitAES( &aes, p_sys_key );
1452     REVERSE( p_sys_key, 4 );
1453     REVERSE( p_sci_data, 1 );
1454     InitShuffle( &shuffle, p_sys_key, p_sci_data[ 0 ] );
1455
1456     memcpy( p_sci_key, p_secret7, 16 );
1457     REVERSE( p_sci_key, 4 );
1458
1459     while( i_blocks-- )
1460     {
1461         uint32_t p_tmp[ 4 ];
1462
1463         REVERSE( p_buffer, 4 );
1464         DecryptAES( &aes, p_tmp, p_buffer );
1465         BlockXOR( p_tmp, p_sci_key, p_tmp );
1466
1467         /* Use the previous scrambled data as the key for next block */
1468         memcpy( p_sci_key, p_buffer, 16 );
1469
1470         /* Shuffle the decrypted data using a custom routine */
1471         DoShuffle( &shuffle, p_tmp, 4 );
1472
1473         /* Copy this block back to p_buffer */
1474         memcpy( p_buffer, p_tmp, 16 );
1475
1476         p_buffer += 4;
1477     }
1478
1479     if( i_remaining >= 4 )
1480     {
1481         REVERSE( p_buffer, i_remaining / 4 );
1482         DoShuffle( &shuffle, p_buffer, i_remaining / 4 );
1483     }
1484
1485     /* Phase 2: look for the user key in the generated data. I must admit I
1486      *          do not understand what is going on here, because it almost
1487      *          looks like we are browsing data that makes sense, even though
1488      *          the DoShuffle() part made it completely meaningless. */
1489
1490     y = 0;
1491     REVERSE( p_sci_data + 5, 1 );
1492     i = U32_AT( p_sci_data + 5 );
1493     i_sci_size -= 22 * sizeof(uint32_t);
1494     p_sci1 = p_sci_data + 22;
1495     p_sci0 = NULL;
1496
1497     while( i_sci_size >= 20 && i > 0 )
1498     {
1499         if( p_sci0 == NULL )
1500         {
1501             i_sci_size -= 18 * sizeof(uint32_t);
1502             if( i_sci_size < 20 )
1503             {
1504                 break;
1505             }
1506
1507             p_sci0 = p_sci1;
1508             REVERSE( p_sci1 + 17, 1 );
1509             y = U32_AT( p_sci1 + 17 );
1510             p_sci1 += 18;
1511         }
1512
1513         if( !y )
1514         {
1515             i--;
1516             p_sci0 = NULL;
1517             continue;
1518         }
1519
1520         i_user = U32_AT( p_sci0 );
1521         i_key = U32_AT( p_sci1 );
1522         REVERSE( &i_user, 1 );
1523         REVERSE( &i_key, 1 );
1524         if( i_user == p_drms->i_user && ( ( i_key == p_drms->i_key ) ||
1525             ( !p_drms->i_key && ( p_sci1 == (p_sci0 + 18) ) ) ) )
1526         {
1527             memcpy( p_user_key, p_sci1 + 1, 16 );
1528             REVERSE( p_sci1 + 1, 4 );
1529             WriteUserKey( p_drms, p_sci1 + 1 );
1530             i_ret = 0;
1531             break;
1532         }
1533
1534         y--;
1535         p_sci1 += 5;
1536         i_sci_size -= 5 * sizeof(uint32_t);
1537     }
1538
1539     free( p_sci_data );
1540
1541     return i_ret;
1542 }
1543
1544 /*****************************************************************************
1545  * GetSCIData: get SCI data from "SC Info.sidb"
1546  *****************************************************************************
1547  * Read SCI data from "\Apple Computer\iTunes\SC Info\SC Info.sidb"
1548  *****************************************************************************/
1549 static int GetSCIData( char *psz_ipod, uint32_t **pp_sci,
1550                        uint32_t *pi_sci_size )
1551 {
1552     FILE *file;
1553     char *psz_path = NULL;
1554     char p_tmp[ 4 * PATH_MAX ];
1555     int i_ret = -1;
1556
1557     if( psz_ipod == NULL )
1558     {
1559 #ifdef WIN32
1560         const char *SCIfile =
1561         "\\Apple Computer\\iTunes\\SC Info\\SC Info.sidb";
1562         strncpy(p_tmp, config_GetConfDir(), sizeof(p_tmp -1));
1563         if( strlen( p_tmp ) + strlen( SCIfile ) >= PATH_MAX )
1564             return -1;
1565         strcat(p_tmp, SCIfile);
1566         p_tmp[sizeof( p_tmp ) - 1] = '\0';
1567         psz_path = p_tmp;
1568 #endif
1569     }
1570     else
1571     {
1572 #define ISCINFO "iSCInfo"
1573         if( strstr( psz_ipod, ISCINFO ) == NULL )
1574         {
1575             snprintf( p_tmp, sizeof(p_tmp) - 1,
1576                       "%s/iPod_Control/iTunes/" ISCINFO "2", psz_ipod );
1577             psz_path = p_tmp;
1578         }
1579         else
1580         {
1581             psz_path = psz_ipod;
1582         }
1583     }
1584
1585     if( psz_path == NULL )
1586     {
1587         return -1;
1588     }
1589
1590     file = vlc_fopen( psz_path, "rb" );
1591     if( file != NULL )
1592     {
1593         struct stat st;
1594
1595         if( !fstat( fileno( file ), &st ) && st.st_size >= 4 )
1596         {
1597             *pp_sci = malloc( st.st_size );
1598             if( *pp_sci != NULL )
1599             {
1600                 if( fread( *pp_sci, 1, st.st_size,
1601                            file ) == (size_t)st.st_size )
1602                 {
1603                     *pi_sci_size = st.st_size;
1604                     i_ret = 0;
1605                 }
1606                 else
1607                 {
1608                     free( (void *)*pp_sci );
1609                     *pp_sci = NULL;
1610                 }
1611             }
1612         }
1613
1614         fclose( file );
1615     }
1616
1617     return i_ret;
1618 }
1619
1620 /*****************************************************************************
1621  * HashSystemInfo: hash system information
1622  *****************************************************************************
1623  * This function computes the MD5 hash of the C: hard drive serial number,
1624  * BIOS version, CPU type and Windows version.
1625  *****************************************************************************/
1626 static int HashSystemInfo( uint32_t *p_system_hash )
1627 {
1628     struct md5_s md5;
1629     int i_ret = 0;
1630
1631 #ifdef WIN32
1632     HKEY i_key;
1633     unsigned int i;
1634     DWORD i_size;
1635     DWORD i_serial;
1636     LPBYTE p_reg_buf;
1637
1638     static const LPCTSTR p_reg_keys[ 3 ][ 2 ] =
1639     {
1640         {
1641             _T("HARDWARE\\DESCRIPTION\\System"),
1642             _T("SystemBiosVersion")
1643         },
1644
1645         {
1646             _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
1647             _T("ProcessorNameString")
1648         },
1649
1650         {
1651             _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"),
1652             _T("ProductId")
1653         }
1654     };
1655
1656     InitMD5( &md5 );
1657
1658     AddMD5( &md5, "cache-control", 13 );
1659     AddMD5( &md5, "Ethernet", 8 );
1660
1661     GetVolumeInformation( _T("C:\\"), NULL, 0, &i_serial,
1662                           NULL, NULL, NULL, 0 );
1663     AddMD5( &md5, (const uint8_t *)&i_serial, 4 );
1664
1665     for( i = 0; i < sizeof(p_reg_keys) / sizeof(p_reg_keys[ 0 ]); i++ )
1666     {
1667         if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, p_reg_keys[ i ][ 0 ],
1668                           0, KEY_READ, &i_key ) != ERROR_SUCCESS )
1669         {
1670             continue;
1671         }
1672
1673         if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ],
1674                              NULL, NULL, NULL, &i_size ) != ERROR_SUCCESS )
1675         {
1676             RegCloseKey( i_key );
1677             continue;
1678         }
1679
1680         p_reg_buf = malloc( i_size );
1681
1682         if( p_reg_buf != NULL )
1683         {
1684             if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ],
1685                                  NULL, NULL, p_reg_buf,
1686                                  &i_size ) == ERROR_SUCCESS )
1687             {
1688                 AddMD5( &md5, (const uint8_t *)p_reg_buf, i_size );
1689             }
1690
1691             free( p_reg_buf );
1692         }
1693
1694         RegCloseKey( i_key );
1695     }
1696
1697 #else
1698     InitMD5( &md5 );
1699     i_ret = -1;
1700 #endif
1701
1702     EndMD5( &md5 );
1703     memcpy( p_system_hash, md5.p_digest, 16 );
1704
1705     return i_ret;
1706 }
1707
1708 /*****************************************************************************
1709  * GetiPodID: Get iPod ID
1710  *****************************************************************************
1711  * This function gets the iPod ID.
1712  *****************************************************************************/
1713 static int GetiPodID( int64_t *p_ipod_id )
1714 {
1715     int i_ret = -1;
1716
1717 #define PROD_NAME   "iPod"
1718 #define VENDOR_NAME "Apple Computer, Inc."
1719
1720     char *psz_ipod_id = getenv( "IPODID" );
1721     if( psz_ipod_id != NULL )
1722     {
1723         *p_ipod_id = strtoll( psz_ipod_id, NULL, 16 );
1724         return 0;
1725     }
1726
1727 #ifdef __APPLE__
1728     CFTypeRef value;
1729     mach_port_t port;
1730     io_object_t device;
1731     io_iterator_t iterator;
1732     CFMutableDictionaryRef match_dic;
1733     CFMutableDictionaryRef smatch_dic;
1734
1735     if( IOMasterPort( MACH_PORT_NULL, &port ) == KERN_SUCCESS )
1736     {
1737         smatch_dic = IOServiceMatching( "IOFireWireUnit" );
1738         match_dic = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
1739                                            &kCFTypeDictionaryKeyCallBacks,
1740                                            &kCFTypeDictionaryValueCallBacks );
1741
1742         if( smatch_dic != NULL && match_dic != NULL )
1743         {
1744             CFDictionarySetValue( smatch_dic,
1745                                   CFSTR("FireWire Vendor Name"),
1746                                   CFSTR(VENDOR_NAME) );
1747             CFDictionarySetValue( smatch_dic,
1748                                   CFSTR("FireWire Product Name"),
1749                                   CFSTR(PROD_NAME) );
1750
1751             CFDictionarySetValue( match_dic,
1752                                   CFSTR(kIOPropertyMatchKey),
1753                                   smatch_dic );
1754             CFRelease( smatch_dic );
1755
1756             if( IOServiceGetMatchingServices( port, match_dic,
1757                                               &iterator ) == KERN_SUCCESS )
1758             {
1759                 while( ( device = IOIteratorNext( iterator ) ) != 0 )
1760                 {
1761                     value = IORegistryEntryCreateCFProperty( device,
1762                         CFSTR("GUID"), kCFAllocatorDefault, kNilOptions );
1763
1764                     if( value != NULL )
1765                     {
1766                         if( CFGetTypeID( value ) == CFNumberGetTypeID() )
1767                         {
1768                             int64_t i_ipod_id;
1769                             CFNumberGetValue( (CFNumberRef)value,
1770                                               kCFNumberLongLongType,
1771                                               &i_ipod_id );
1772                             *p_ipod_id = i_ipod_id;
1773                             i_ret = 0;
1774                         }
1775
1776                         CFRelease( value );
1777                     }
1778
1779                     IOObjectRelease( device );
1780
1781                     if( !i_ret ) break;
1782                 }
1783
1784                 IOObjectRelease( iterator );
1785             }
1786         }
1787         else
1788         {
1789             if( match_dic )
1790                 CFRelease( match_dic );
1791             if( smatch_dic )
1792                 CFRelease( smatch_dic );
1793         }
1794
1795
1796         mach_port_deallocate( mach_task_self(), port );
1797     }
1798 #endif
1799
1800     return i_ret;
1801 }
1802
1803 #else /* !defined( UNDER_CE ) */
1804
1805 void *drms_alloc( const char *psz_homedir ){ return NULL; }
1806 void drms_free( void *a ){}
1807 void drms_decrypt( void *a, uint32_t *b, uint32_t c, uint32_t *k  ){}
1808 void drms_get_p_key( void *p_drms, uint32_t *p_key ){}
1809 int drms_init( void *a, uint32_t b, uint8_t *c, uint32_t d ){ return -1; }
1810
1811 #endif /* defined( UNDER_CE ) */