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