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