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