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