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