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