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