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