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