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