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