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