1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004 VideoLAN
5 * $Id: drms.c,v 1.5 2004/01/16 18:26:57 sam Exp $
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Sam Hocevar <sam@zoy.org>
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.
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.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 #include <stdlib.h> /* malloc(), free() */
45 #ifdef HAVE_SYS_STAT_H
48 #ifdef HAVE_SYS_TYPES_H
49 #include <sys/types.h>
53 #include "drmstables.h"
57 /*****************************************************************************
58 * aes_s: AES keys structure
59 *****************************************************************************
60 * This structure stores a set of keys usable for encryption and decryption
61 * with the AES/Rijndael algorithm.
62 *****************************************************************************/
65 uint32_t pp_enc_keys[ AES_KEY_COUNT + 1 ][ 4 ];
66 uint32_t pp_dec_keys[ AES_KEY_COUNT + 1 ][ 4 ];
69 /*****************************************************************************
70 * md5_s: MD5 message structure
71 *****************************************************************************
72 * This structure stores the static information needed to compute an MD5
73 * hash. It has an extra data buffer to allow non-aligned writes.
74 *****************************************************************************/
77 uint64_t i_bits; /* Total written bits */
78 uint32_t p_digest[4]; /* The MD5 digest */
79 uint32_t p_data[16]; /* Buffer to cache non-aligned writes */
82 /*****************************************************************************
83 * shuffle_s: shuffle structure
84 *****************************************************************************
85 * This structure stores the static information needed to shuffle data using
87 *****************************************************************************/
90 uint32_t p_commands[ 20 ];
91 uint32_t p_bordel[ 16 ];
94 /*****************************************************************************
95 * drms_s: DRMS structure
96 *****************************************************************************
97 * This structure stores the static information needed to decrypt DRMS data.
98 *****************************************************************************/
113 /*****************************************************************************
115 *****************************************************************************/
116 static void InitAES ( struct aes_s *, uint32_t * );
117 static void DecryptAES ( struct aes_s *, uint32_t *, const uint32_t * );
119 static void InitMD5 ( struct md5_s * );
120 static void AddMD5 ( struct md5_s *, const uint8_t *, uint32_t );
121 static void AddNativeMD5 ( struct md5_s *, uint32_t *, uint32_t );
122 static void EndMD5 ( struct md5_s * );
123 static void Digest ( struct md5_s *, const uint32_t * );
125 static void InitShuffle ( struct shuffle_s *, uint32_t * );
126 static void DoShuffle ( struct shuffle_s *, uint8_t *, uint32_t );
127 static void Bordelize ( uint32_t *, uint32_t );
129 static int GetSystemKey ( uint32_t * );
130 static int WriteUserKey ( void *, uint32_t * );
131 static int ReadUserKey ( void *, uint32_t * );
132 static int GetUserKey ( void *, uint32_t * );
134 static int GetSCIData ( uint32_t **, uint32_t * );
135 static int HashSystemInfo ( struct md5_s * );
137 /*****************************************************************************
138 * BlockXOR: XOR two 128 bit blocks
139 *****************************************************************************/
140 static inline void BlockXOR( uint32_t *p_dest, uint32_t *p_s1, uint32_t *p_s2 )
144 for( i = 0; i < 4; i++ )
146 p_dest[ i ] = p_s1[ i ] ^ p_s2[ i ];
150 /*****************************************************************************
151 * drms_alloc: allocate a DRMS structure
152 *****************************************************************************/
153 void *drms_alloc( char *psz_homedir )
155 struct drms_s *p_drms;
157 p_drms = malloc( sizeof(struct drms_s) );
164 memset( p_drms, 0, sizeof(struct drms_s) );
166 p_drms->psz_homedir = malloc( PATH_MAX );
167 if( p_drms->psz_homedir != NULL )
169 strncpy( p_drms->psz_homedir, psz_homedir, PATH_MAX );
170 p_drms->psz_homedir[ PATH_MAX - 1 ] = '\0';
174 free( (void *)p_drms );
178 return (void *)p_drms;
181 /*****************************************************************************
182 * drms_free: free a previously allocated DRMS structure
183 *****************************************************************************/
184 void drms_free( void *_p_drms )
186 struct drms_s *p_drms = (struct drms_s *)_p_drms;
188 if( p_drms->p_name != NULL )
190 free( (void *)p_drms->p_name );
193 if( p_drms->p_iviv != NULL )
195 free( (void *)p_drms->p_iviv );
198 if( p_drms->psz_homedir != NULL )
200 free( (void *)p_drms->psz_homedir );
206 /*****************************************************************************
207 * drms_decrypt: unscramble a chunk of data
208 *****************************************************************************/
209 void drms_decrypt( void *_p_drms, uint32_t *p_buffer, uint32_t i_bytes )
211 struct drms_s *p_drms = (struct drms_s *)_p_drms;
213 uint32_t i_blocks, i;
215 /* AES is a block cypher, round down the byte count */
216 i_blocks = i_bytes / 16;
217 i_bytes = i_blocks * 16;
219 /* Initialise the key */
220 memcpy( p_key, p_drms->p_key, 4 * sizeof(uint32_t) );
223 for( i = i_blocks; i--; )
227 DecryptAES( &p_drms->aes, p_tmp, p_buffer );
228 BlockXOR( p_tmp, p_key, p_tmp );
230 /* Use the previous scrambled data as the key for next block */
231 memcpy( p_key, p_buffer, 4 * sizeof(uint32_t) );
233 /* Copy unscrambled data back to the buffer */
234 memcpy( p_buffer, p_tmp, 4 * sizeof(uint32_t) );
240 /*****************************************************************************
241 * drms_init: initialise a DRMS structure
242 *****************************************************************************/
243 int drms_init( void *_p_drms, uint32_t i_type,
244 uint8_t *p_info, uint32_t i_len )
246 struct drms_s *p_drms = (struct drms_s *)_p_drms;
253 if( i_len < sizeof(p_drms->i_user) )
259 p_drms->i_user = U32_AT( p_info );
265 if( i_len < sizeof(p_drms->i_key) )
271 p_drms->i_key = U32_AT( p_info );
277 if( i_len < sizeof(p_drms->p_key) )
283 p_drms->p_iviv = malloc( sizeof(p_drms->p_key) );
284 if( p_drms->p_iviv == NULL )
290 memcpy( p_drms->p_iviv, p_info, sizeof(p_drms->p_key) );
296 p_drms->i_name_len = strlen( p_info );
298 p_drms->p_name = malloc( p_drms->i_name_len );
299 if( p_drms->p_name == NULL )
305 memcpy( p_drms->p_name, p_info, p_drms->i_name_len );
311 uint32_t p_priv[ 64 ];
321 AddMD5( &md5, p_drms->p_name, p_drms->i_name_len );
322 AddMD5( &md5, p_drms->p_iviv, sizeof(p_drms->p_key) );
325 if( GetUserKey( p_drms, p_drms->p_key ) )
331 InitAES( &p_drms->aes, p_drms->p_key );
333 memcpy( p_priv, p_info, 64 );
334 memcpy( p_drms->p_key, md5.p_digest, sizeof(p_drms->p_key) );
335 drms_decrypt( p_drms, p_priv, sizeof(p_priv) );
337 InitAES( &p_drms->aes, p_priv + 6 );
338 memcpy( p_drms->p_key, p_priv + 12, sizeof(p_drms->p_key) );
340 free( (void *)p_drms->psz_homedir );
341 p_drms->psz_homedir = NULL;
342 free( (void *)p_drms->p_name );
343 p_drms->p_name = NULL;
344 free( (void *)p_drms->p_iviv );
345 p_drms->p_iviv = NULL;
353 /* The following functions are local */
355 /*****************************************************************************
356 * InitAES: initialise AES/Rijndael encryption/decryption tables
357 *****************************************************************************
358 * The Advanced Encryption Standard (AES) is described in RFC 3268
359 *****************************************************************************/
360 static void InitAES( struct aes_s *p_aes, uint32_t *p_key )
362 uint32_t i, t, i_key, i_tmp;
364 memset( p_aes->pp_enc_keys[1], 0, 4 * sizeof(uint32_t) );
365 memcpy( p_aes->pp_enc_keys[0], p_key, 4 * sizeof(uint32_t) );
367 /* Generate the key tables */
368 i_tmp = p_aes->pp_enc_keys[ 0 ][ 3 ];
370 for( i_key = 0; i_key < AES_KEY_COUNT; i_key++ )
374 i_tmp = AES_ROR( i_tmp, 8 );
376 j = p_aes_table[ i_key ];
378 j ^= p_aes_encrypt[ (i_tmp >> 24) & 0xFF ]
379 ^ AES_ROR( p_aes_encrypt[ (i_tmp >> 16) & 0xFF ], 8 )
380 ^ AES_ROR( p_aes_encrypt[ (i_tmp >> 8) & 0xFF ], 16 )
381 ^ AES_ROR( p_aes_encrypt[ i_tmp & 0xFF ], 24 );
383 j ^= p_aes->pp_enc_keys[ i_key ][ 0 ];
384 p_aes->pp_enc_keys[ i_key + 1 ][ 0 ] = j;
385 j ^= p_aes->pp_enc_keys[ i_key ][ 1 ];
386 p_aes->pp_enc_keys[ i_key + 1 ][ 1 ] = j;
387 j ^= p_aes->pp_enc_keys[ i_key ][ 2 ];
388 p_aes->pp_enc_keys[ i_key + 1 ][ 2 ] = j;
389 j ^= p_aes->pp_enc_keys[ i_key ][ 3 ];
390 p_aes->pp_enc_keys[ i_key + 1 ][ 3 ] = j;
395 memcpy( p_aes->pp_dec_keys[ 0 ],
396 p_aes->pp_enc_keys[ 0 ], 4 * sizeof(uint32_t) );
398 for( i = 1; i < AES_KEY_COUNT; i++ )
400 for( t = 0; t < 4; t++ )
402 uint32_t j, k, l, m, n;
404 j = p_aes->pp_enc_keys[ i ][ t ];
406 k = (((j >> 7) & 0x01010101) * 27) ^ ((j & 0xFF7F7F7F) << 1);
407 l = (((k >> 7) & 0x01010101) * 27) ^ ((k & 0xFF7F7F7F) << 1);
408 m = (((l >> 7) & 0x01010101) * 27) ^ ((l & 0xFF7F7F7F) << 1);
412 n = AES_ROR( l ^ j, 16 ) ^ AES_ROR( k ^ j, 8 ) ^ AES_ROR( j, 24 );
414 p_aes->pp_dec_keys[ i ][ t ] = k ^ l ^ m ^ n;
419 /*****************************************************************************
420 * DecryptAES: decrypt an AES/Rijndael 128 bit block
421 *****************************************************************************/
422 static void DecryptAES( struct aes_s *p_aes,
423 uint32_t *p_dest, const uint32_t *p_src )
425 uint32_t p_wtxt[ 4 ]; /* Working cyphertext */
429 for( t = 0; t < 4; t++ )
431 /* FIXME: are there any endianness issues here? */
432 p_wtxt[ t ] = p_src[ t ] ^ p_aes->pp_enc_keys[ AES_KEY_COUNT ][ t ];
436 for( round = 0; round < (AES_KEY_COUNT - 1); round++ )
438 for( t = 0; t < 4; t++ )
440 p_tmp[ t ] = AES_XOR_ROR( p_aes_itable, p_wtxt );
443 for( t = 0; t < 4; t++ )
445 p_wtxt[ t ] = p_tmp[ t ]
446 ^ p_aes->pp_dec_keys[ (AES_KEY_COUNT - 1) - round ][ t ];
450 /* Final round (9) */
451 for( t = 0; t < 4; t++ )
453 p_dest[ t ] = AES_XOR_ROR( p_aes_decrypt, p_wtxt );
454 p_dest[ t ] ^= p_aes->pp_dec_keys[ (AES_KEY_COUNT - 1) - round ][ t ];
458 /*****************************************************************************
459 * InitMD5: initialise an MD5 message
460 *****************************************************************************
461 * The MD5 message-digest algorithm is described in RFC 1321
462 *****************************************************************************/
463 static void InitMD5( struct md5_s *p_md5 )
465 p_md5->p_digest[ 0 ] = 0x67452301;
466 p_md5->p_digest[ 1 ] = 0xEFCDAB89;
467 p_md5->p_digest[ 2 ] = 0x98BADCFE;
468 p_md5->p_digest[ 3 ] = 0x10325476;
470 memset( p_md5->p_data, 0, 16 * sizeof(uint32_t) );
474 /*****************************************************************************
475 * AddMD5: add i_len bytes to an MD5 message
476 *****************************************************************************/
477 static void AddMD5( struct md5_s *p_md5, const uint8_t *p_src, uint32_t i_len )
479 uint32_t i_current; /* Current bytes in the spare buffer */
480 uint32_t i_offset = 0;
482 i_current = (p_md5->i_bits / 8) & 63;
484 p_md5->i_bits += 8 * i_len;
486 /* If we can complete our spare buffer to 64 bytes, do it and add the
487 * resulting buffer to the MD5 message */
488 if( i_len >= (64 - i_current) )
490 memcpy( ((uint8_t *)p_md5->p_data) + i_current, p_src,
492 Digest( p_md5, p_md5->p_data );
494 i_offset += (64 - i_current);
495 i_len -= (64 - i_current);
499 /* Add as many entire 64 bytes blocks as we can to the MD5 message */
502 uint32_t p_tmp[ 16 ];
503 memcpy( p_tmp, p_src + i_offset, 16 * sizeof(uint32_t) );
504 Digest( p_md5, p_tmp );
509 /* Copy our remaining data to the message's spare buffer */
510 memcpy( ((uint8_t *)p_md5->p_data) + i_current, p_src + i_offset, i_len );
513 /*****************************************************************************
514 * AddNativeMD5: add i_len big-endian uin32_t to an MD5 message
515 *****************************************************************************
516 * FIXME: I don't really understand what this is supposed to do, especially
517 * with big values of i_len ...
518 *****************************************************************************/
519 static void AddNativeMD5( struct md5_s *p_md5, uint32_t *p_src, uint32_t i_len )
522 /* XXX: it's 32, not 16! */
523 uint32_t p_tmp[ 32 ];
525 /* Convert big endian p_src to native-endian p_tmp */
526 for( x = i_len; x; x -= y )
528 /* XXX: this looks weird! */
531 for( i = 0; i < y; i++ )
533 p_tmp[ i ] = U32_AT(p_src + i);
537 AddMD5( p_md5, (uint8_t *)p_tmp, i_len * sizeof(uint32_t) );
540 /*****************************************************************************
541 * EndMD5: finish an MD5 message
542 *****************************************************************************
543 * This function adds adequate padding to the end of the message, and appends
544 * the bit count so that we end at a block boundary.
545 *****************************************************************************/
546 static void EndMD5( struct md5_s *p_md5 )
550 i_current = (p_md5->i_bits / 8) & 63;
552 /* Append 0x80 to our buffer. No boundary check because the temporary
553 * buffer cannot be full, otherwise AddMD5 would have emptied it. */
554 ((uint8_t *)p_md5->p_data)[ i_current++ ] = 0x80;
556 /* If less than 8 bytes are available at the end of the block, complete
557 * this 64 bytes block with zeros and add it to the message. We'll add
558 * our length at the end of the next block. */
561 memset( ((uint8_t *)p_md5->p_data) + i_current, 0, (64 - i_current) );
562 Digest( p_md5, p_md5->p_data );
566 /* Fill the unused space in our last block with zeroes and put the
567 * message length at the end. */
568 memset( ((uint8_t *)p_md5->p_data) + i_current, 0, (56 - i_current) );
569 p_md5->p_data[ 14 ] = p_md5->i_bits & 0xffffffff;
570 p_md5->p_data[ 15 ] = (p_md5->i_bits >> 32);
572 Digest( p_md5, p_md5->p_data );
575 #define F1( x, y, z ) ((z) ^ ((x) & ((y) ^ (z))))
576 #define F2( x, y, z ) F1((z), (x), (y))
577 #define F3( x, y, z ) ((x) ^ (y) ^ (z))
578 #define F4( x, y, z ) ((y) ^ ((x) | ~(z)))
580 #define MD5_DO( f, w, x, y, z, data, s ) \
581 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
583 /*****************************************************************************
584 * Digest: update the MD5 digest with 64 bytes of data
585 *****************************************************************************/
586 static void Digest( struct md5_s *p_md5, const uint32_t *p_input )
590 a = p_md5->p_digest[ 0 ];
591 b = p_md5->p_digest[ 1 ];
592 c = p_md5->p_digest[ 2 ];
593 d = p_md5->p_digest[ 3 ];
595 MD5_DO( F1, a, b, c, d, p_input[ 0 ] + 0xd76aa478, 7 );
596 MD5_DO( F1, d, a, b, c, p_input[ 1 ] + 0xe8c7b756, 12 );
597 MD5_DO( F1, c, d, a, b, p_input[ 2 ] + 0x242070db, 17 );
598 MD5_DO( F1, b, c, d, a, p_input[ 3 ] + 0xc1bdceee, 22 );
599 MD5_DO( F1, a, b, c, d, p_input[ 4 ] + 0xf57c0faf, 7 );
600 MD5_DO( F1, d, a, b, c, p_input[ 5 ] + 0x4787c62a, 12 );
601 MD5_DO( F1, c, d, a, b, p_input[ 6 ] + 0xa8304613, 17 );
602 MD5_DO( F1, b, c, d, a, p_input[ 7 ] + 0xfd469501, 22 );
603 MD5_DO( F1, a, b, c, d, p_input[ 8 ] + 0x698098d8, 7 );
604 MD5_DO( F1, d, a, b, c, p_input[ 9 ] + 0x8b44f7af, 12 );
605 MD5_DO( F1, c, d, a, b, p_input[ 10 ] + 0xffff5bb1, 17 );
606 MD5_DO( F1, b, c, d, a, p_input[ 11 ] + 0x895cd7be, 22 );
607 MD5_DO( F1, a, b, c, d, p_input[ 12 ] + 0x6b901122, 7 );
608 MD5_DO( F1, d, a, b, c, p_input[ 13 ] + 0xfd987193, 12 );
609 MD5_DO( F1, c, d, a, b, p_input[ 14 ] + 0xa679438e, 17 );
610 MD5_DO( F1, b, c, d, a, p_input[ 15 ] + 0x49b40821, 22 );
612 MD5_DO( F2, a, b, c, d, p_input[ 1 ] + 0xf61e2562, 5 );
613 MD5_DO( F2, d, a, b, c, p_input[ 6 ] + 0xc040b340, 9 );
614 MD5_DO( F2, c, d, a, b, p_input[ 11 ] + 0x265e5a51, 14 );
615 MD5_DO( F2, b, c, d, a, p_input[ 0 ] + 0xe9b6c7aa, 20 );
616 MD5_DO( F2, a, b, c, d, p_input[ 5 ] + 0xd62f105d, 5 );
617 MD5_DO( F2, d, a, b, c, p_input[ 10 ] + 0x02441453, 9 );
618 MD5_DO( F2, c, d, a, b, p_input[ 15 ] + 0xd8a1e681, 14 );
619 MD5_DO( F2, b, c, d, a, p_input[ 4 ] + 0xe7d3fbc8, 20 );
620 MD5_DO( F2, a, b, c, d, p_input[ 9 ] + 0x21e1cde6, 5 );
621 MD5_DO( F2, d, a, b, c, p_input[ 14 ] + 0xc33707d6, 9 );
622 MD5_DO( F2, c, d, a, b, p_input[ 3 ] + 0xf4d50d87, 14 );
623 MD5_DO( F2, b, c, d, a, p_input[ 8 ] + 0x455a14ed, 20 );
624 MD5_DO( F2, a, b, c, d, p_input[ 13 ] + 0xa9e3e905, 5 );
625 MD5_DO( F2, d, a, b, c, p_input[ 2 ] + 0xfcefa3f8, 9 );
626 MD5_DO( F2, c, d, a, b, p_input[ 7 ] + 0x676f02d9, 14 );
627 MD5_DO( F2, b, c, d, a, p_input[ 12 ] + 0x8d2a4c8a, 20 );
629 MD5_DO( F3, a, b, c, d, p_input[ 5 ] + 0xfffa3942, 4 );
630 MD5_DO( F3, d, a, b, c, p_input[ 8 ] + 0x8771f681, 11 );
631 MD5_DO( F3, c, d, a, b, p_input[ 11 ] + 0x6d9d6122, 16 );
632 MD5_DO( F3, b, c, d, a, p_input[ 14 ] + 0xfde5380c, 23 );
633 MD5_DO( F3, a, b, c, d, p_input[ 1 ] + 0xa4beea44, 4 );
634 MD5_DO( F3, d, a, b, c, p_input[ 4 ] + 0x4bdecfa9, 11 );
635 MD5_DO( F3, c, d, a, b, p_input[ 7 ] + 0xf6bb4b60, 16 );
636 MD5_DO( F3, b, c, d, a, p_input[ 10 ] + 0xbebfbc70, 23 );
637 MD5_DO( F3, a, b, c, d, p_input[ 13 ] + 0x289b7ec6, 4 );
638 MD5_DO( F3, d, a, b, c, p_input[ 0 ] + 0xeaa127fa, 11 );
639 MD5_DO( F3, c, d, a, b, p_input[ 3 ] + 0xd4ef3085, 16 );
640 MD5_DO( F3, b, c, d, a, p_input[ 6 ] + 0x04881d05, 23 );
641 MD5_DO( F3, a, b, c, d, p_input[ 9 ] + 0xd9d4d039, 4 );
642 MD5_DO( F3, d, a, b, c, p_input[ 12 ] + 0xe6db99e5, 11 );
643 MD5_DO( F3, c, d, a, b, p_input[ 15 ] + 0x1fa27cf8, 16 );
644 MD5_DO( F3, b, c, d, a, p_input[ 2 ] + 0xc4ac5665, 23 );
646 MD5_DO( F4, a, b, c, d, p_input[ 0 ] + 0xf4292244, 6 );
647 MD5_DO( F4, d, a, b, c, p_input[ 7 ] + 0x432aff97, 10 );
648 MD5_DO( F4, c, d, a, b, p_input[ 14 ] + 0xab9423a7, 15 );
649 MD5_DO( F4, b, c, d, a, p_input[ 5 ] + 0xfc93a039, 21 );
650 MD5_DO( F4, a, b, c, d, p_input[ 12 ] + 0x655b59c3, 6 );
651 MD5_DO( F4, d, a, b, c, p_input[ 3 ] + 0x8f0ccc92, 10 );
652 MD5_DO( F4, c, d, a, b, p_input[ 10 ] + 0xffeff47d, 15 );
653 MD5_DO( F4, b, c, d, a, p_input[ 1 ] + 0x85845dd1, 21 );
654 MD5_DO( F4, a, b, c, d, p_input[ 8 ] + 0x6fa87e4f, 6 );
655 MD5_DO( F4, d, a, b, c, p_input[ 15 ] + 0xfe2ce6e0, 10 );
656 MD5_DO( F4, c, d, a, b, p_input[ 6 ] + 0xa3014314, 15 );
657 MD5_DO( F4, b, c, d, a, p_input[ 13 ] + 0x4e0811a1, 21 );
658 MD5_DO( F4, a, b, c, d, p_input[ 4 ] + 0xf7537e82, 6 );
659 MD5_DO( F4, d, a, b, c, p_input[ 11 ] + 0xbd3af235, 10 );
660 MD5_DO( F4, c, d, a, b, p_input[ 2 ] + 0x2ad7d2bb, 15 );
661 MD5_DO( F4, b, c, d, a, p_input[ 9 ] + 0xeb86d391, 21 );
663 p_md5->p_digest[ 0 ] += a;
664 p_md5->p_digest[ 1 ] += b;
665 p_md5->p_digest[ 2 ] += c;
666 p_md5->p_digest[ 3 ] += d;
669 /*****************************************************************************
670 * InitShuffle: initialise a shuffle structure
671 *****************************************************************************
672 * This function initialises tables in the p_shuffle structure that will be
673 * used later by DoShuffle. The only external parameter is p_sys_key.
674 *****************************************************************************/
675 static void InitShuffle( struct shuffle_s *p_shuffle, uint32_t *p_sys_key )
677 uint32_t p_native_key[ 4 ];
678 uint32_t i, i_seed = 0x5476212A; /* *!vT */
680 /* Store the system key in native endianness */
681 for( i = 0; i < 4; i++ )
683 p_native_key[ i ] = U32_AT(p_sys_key + i);
686 /* Fill p_commands using the native key and our seed */
687 for( i = 0; i < 20; i++ )
693 AddNativeMD5( &md5, p_native_key, 4 );
694 AddNativeMD5( &md5, &i_seed, 1 );
699 i_hash = ((int32_t)U32_AT(md5.p_digest)) % 1024;
701 p_shuffle->p_commands[ i ] = i_hash < 0 ? i_hash * -1 : i_hash;
704 /* Fill p_bordel with completely meaningless initial values.
705 * FIXME: check endianness issues. */
706 p_shuffle->p_bordel[ 0 ] = p_native_key[ 0 ];
707 p_shuffle->p_bordel[ 1 ] = 0x68723876; /* v8rh */
708 p_shuffle->p_bordel[ 2 ] = 0x41617376; /* vsaA */
709 p_shuffle->p_bordel[ 3 ] = 0x4D4B4F76; /* voKM */
711 p_shuffle->p_bordel[ 4 ] = p_native_key[ 1 ];
712 p_shuffle->p_bordel[ 5 ] = 0x48556646; /* FfUH */
713 p_shuffle->p_bordel[ 6 ] = 0x38393725; /* %798 */
714 p_shuffle->p_bordel[ 7 ] = 0x2E3B5B3D; /* =[;. */
716 p_shuffle->p_bordel[ 8 ] = p_native_key[ 2 ];
717 p_shuffle->p_bordel[ 9 ] = 0x37363866; /* f867 */
718 p_shuffle->p_bordel[ 10 ] = 0x30383637; /* 7680 */
719 p_shuffle->p_bordel[ 11 ] = 0x34333661; /* a634 */
721 p_shuffle->p_bordel[ 12 ] = p_native_key[ 3 ];
722 p_shuffle->p_bordel[ 13 ] = 0x37386162; /* ba87 */
723 p_shuffle->p_bordel[ 14 ] = 0x494F6E66; /* fnOI */
724 p_shuffle->p_bordel[ 15 ] = 0x2A282966; /* f)(* */
727 /*****************************************************************************
728 * DoShuffle: shuffle i_len bytes of a buffer
729 *****************************************************************************
730 * This is so ugly and uses so many MD5 checksums that it is most certainly
731 * one-way, though why it needs to be so complicated is beyond me.
732 *****************************************************************************/
733 static void DoShuffle( struct shuffle_s *p_shuffle,
734 uint8_t *p_buffer, uint32_t i_len )
739 /* Randomize p_bordel and compute its MD5 checksum */
740 for( i = 0; i < 20; i++ )
742 if( p_shuffle->p_commands[ i ] )
744 Bordelize( p_shuffle->p_bordel, p_shuffle->p_commands[ i ] );
749 AddNativeMD5( &md5, p_shuffle->p_bordel, 16 );
752 /* There are only 16 bytes in an MD5 hash */
758 /* XOR our buffer with the computed checksum */
759 for( i = 0; i < i_len; i++ )
761 p_buffer[ i ] ^= ((uint8_t *)&md5.p_digest)[ i ];
765 /*****************************************************************************
766 * Bordelize: helper for DoShuffle
767 *****************************************************************************
768 * Using the MD5 hash of a string is probably not one-way enough. This
769 * function randomises p_bordel depending on the value of i_command to make
770 * things even more messy in p_bordel.
771 *****************************************************************************/
772 static void Bordelize( uint32_t *p_bordel, uint32_t i_command )
776 i = (i_command / 16) & 15;
777 x = (~(i_command & 15)) & 15;
779 if( (i_command & 768) == 768 )
784 p_bordel[ i ] = p_bordel[ ((16 - x) & 15) ] + p_bordel[ (15 - x) ];
786 else if( (i_command & 512) == 512 )
788 p_bordel[ i ] ^= p_shuffle_xor[ 15 - i ][ x ];
790 else if( (i_command & 256) == 256 )
792 p_bordel[ i ] -= p_shuffle_sub[ 15 - i ][ x ];
796 p_bordel[ i ] += p_shuffle_add[ 15 - i ][ x ];
800 /*****************************************************************************
801 * GetSystemKey: get the system key
802 *****************************************************************************
803 * Compute the system key from various system information, see HashSystemInfo.
804 *****************************************************************************/
805 static int GetSystemKey( uint32_t *p_sys_key )
808 uint32_t p_tmp_key[ 4 ];
811 if( HashSystemInfo( &md5 ) )
817 /* Write our digest to p_tmp_key */
818 memcpy( p_tmp_key, md5.p_digest, 4 * sizeof(uint32_t) );
821 AddMD5( &md5, "YuaFlafu", 8 );
822 AddMD5( &md5, (uint8_t *)p_tmp_key, 6 );
823 AddMD5( &md5, (uint8_t *)p_tmp_key, 6 );
824 AddMD5( &md5, (uint8_t *)p_tmp_key, 6 );
825 AddMD5( &md5, "zPif98ga", 8 );
828 memcpy( p_sys_key, md5.p_digest, 4 * sizeof(uint32_t) );
834 # define DRMS_DIRNAME "drms"
836 # define DRMS_DIRNAME ".drms"
839 /*****************************************************************************
840 * WriteUserKey: write the user key to hard disk
841 *****************************************************************************
842 * Write the user key to the hard disk so that it can be reused later or used
843 * on operating systems other than Win32.
844 *****************************************************************************/
845 static int WriteUserKey( void *_p_drms, uint32_t *p_user_key )
847 struct drms_s *p_drms = (struct drms_s *)_p_drms;
850 char psz_path[ PATH_MAX ];
852 snprintf( psz_path, PATH_MAX - 1,
853 "%s/" DRMS_DIRNAME, p_drms->psz_homedir );
855 #if defined( HAVE_ERRNO_H )
856 # if defined( WIN32 )
857 if( !mkdir( psz_path ) || errno == EEXIST )
859 if( !mkdir( psz_path, 0755 ) || errno == EEXIST )
862 if( !mkdir( psz_path ) )
865 snprintf( psz_path, PATH_MAX - 1, "%s/" DRMS_DIRNAME "/%08X.%03d",
866 p_drms->psz_homedir, p_drms->i_user, p_drms->i_key );
868 file = fopen( psz_path, "w" );
871 i_ret = fwrite( p_user_key, sizeof(uint32_t),
872 4, file ) == 4 ? 0 : -1;
880 /*****************************************************************************
881 * ReadUserKey: read the user key from hard disk
882 *****************************************************************************
883 * Retrieve the user key from the hard disk if available.
884 *****************************************************************************/
885 static int ReadUserKey( void *_p_drms, uint32_t *p_user_key )
887 struct drms_s *p_drms = (struct drms_s *)_p_drms;
890 char psz_path[ PATH_MAX ];
892 snprintf( psz_path, PATH_MAX - 1,
893 "%s/" DRMS_DIRNAME "/%08X.%03d", p_drms->psz_homedir,
894 p_drms->i_user, p_drms->i_key );
896 file = fopen( psz_path, "r" );
899 i_ret = fread( p_user_key, sizeof(uint32_t),
900 4, file ) == 4 ? 0 : -1;
907 /*****************************************************************************
908 * GetUserKey: get the user key
909 *****************************************************************************
910 * Retrieve the user key from the hard disk if available, otherwise generate
911 * it from the system key. If the key could be successfully generated, write
912 * it to the hard disk for future use.
913 *****************************************************************************/
914 static int GetUserKey( void *_p_drms, uint32_t *p_user_key )
916 struct drms_s *p_drms = (struct drms_s *)_p_drms;
918 struct shuffle_s shuffle;
922 uint32_t p_sys_key[ 4 ];
924 uint32_t *pp_sci[ 2 ];
927 uint32_t p_sci_key[ 4 ] =
929 0x6e66556d, /* nfUm */
930 0x6e676f70, /* ngop */
931 0x67666461, /* gfda */
932 0x33373866 /* 378f */
935 if( !ReadUserKey( p_drms, p_user_key ) )
940 if( GetSystemKey( p_sys_key ) )
945 if( GetSCIData( pp_sci + 0, &i_sci_size ) )
951 pp_sci[ 1 ] = (uint32_t *)(((uint8_t *)pp_sci[ 0 ]) + i_sci_size);
952 i_sci_size -= sizeof(*pp_sci[ 0 ]);
954 InitAES( &aes, p_sys_key );
956 for( i = 0, p_cur_key = p_sci_key;
957 i < i_sci_size / sizeof(p_drms->p_key); i++ )
959 y = i * sizeof(*pp_sci[ 0 ]);
961 DecryptAES( &aes, pp_sci[ 1 ] + y + 1, pp_sci[ 0 ] + y + 1 );
962 BlockXOR( pp_sci[ 1 ] + y + 1, p_cur_key, pp_sci[ 1 ] + y + 1 );
964 p_cur_key = pp_sci[ 0 ] + y + 1;
967 /* Shuffle pp_sci[ 1 ] using a custom routine */
968 InitShuffle( &shuffle, p_sys_key );
970 for( i = 0; i < i_sci_size / sizeof(p_drms->p_key); i++ )
972 y = i * sizeof(*pp_sci[ 1 ]);
974 DoShuffle( &shuffle, (uint8_t *)(pp_sci[ 1 ] + y + 1),
975 sizeof(p_drms->p_key) );
979 i = U32_AT( &pp_sci[ 1 ][ 5 ] );
980 i_sci_size -= 21 * sizeof(*pp_sci[ 1 ]);
984 while( i_sci_size > 0 && i > 0 )
986 if( pp_sci[ 0 ] == NULL )
988 i_sci_size -= 18 * sizeof(*pp_sci[ 1 ]);
989 if( i_sci_size <= 0 )
994 pp_sci[ 0 ] = pp_sci[ 1 ];
995 y = U32_AT( &pp_sci[ 1 ][ 17 ] );
1006 if( U32_AT( &pp_sci[ 0 ][ 0 ] ) == p_drms->i_user &&
1008 (sizeof(p_drms->p_key) + sizeof(pp_sci[ 1 ][ 0 ]) ) ) &&
1009 ( ( U32_AT( &pp_sci[ 1 ][ 0 ] ) == p_drms->i_key ) ||
1010 ( !p_drms->i_key ) || ( pp_sci[ 1 ] == (pp_sci[ 0 ] + 18) ) ) )
1012 memcpy( p_user_key, &pp_sci[ 1 ][ 1 ], sizeof(p_drms->p_key) );
1013 WriteUserKey( p_drms, p_user_key );
1020 i_sci_size -= 5 * sizeof(*pp_sci[ 1 ]);
1023 free( (void *)p_tmp );
1028 /*****************************************************************************
1029 * GetSCIData: get SCI data from "SC Info.sidb"
1030 *****************************************************************************
1031 * Read SCI data from "\Apple Computer\iTunes\SC Info\SC Info.sidb"
1032 *****************************************************************************/
1033 static int GetSCIData( uint32_t **pp_sci, uint32_t *p_sci_size )
1039 DWORD i_size, i_read;
1040 TCHAR p_path[ PATH_MAX ];
1041 TCHAR *p_filename = _T("\\Apple Computer\\iTunes\\SC Info\\SC Info.sidb");
1043 typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
1046 HINSTANCE shfolder_dll = NULL;
1047 SHGETFOLDERPATH dSHGetFolderPath = NULL;
1049 if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
1052 (SHGETFOLDERPATH)GetProcAddress( shfolder_dll,
1054 _T("SHGetFolderPathW") );
1056 _T("SHGetFolderPathA") );
1060 if( dSHGetFolderPath != NULL &&
1061 SUCCEEDED( dSHGetFolderPath( NULL, CSIDL_COMMON_APPDATA,
1062 NULL, 0, p_path ) ) )
1064 _tcsncat( p_path, p_filename, min( _tcslen( p_filename ),
1065 (PATH_MAX-1) - _tcslen( p_path ) ) );
1067 i_file = CreateFile( p_path, GENERIC_READ, 0, NULL,
1068 OPEN_EXISTING, 0, NULL );
1069 if( i_file != INVALID_HANDLE_VALUE )
1071 i_size = GetFileSize( i_file, NULL );
1072 if( i_size != INVALID_FILE_SIZE &&
1073 i_size > (sizeof(*pp_sci[ 0 ]) * 22) )
1075 *pp_sci = malloc( i_size * 2 );
1076 if( *pp_sci != NULL )
1078 if( ReadFile( i_file, *pp_sci, i_size, &i_read, NULL ) &&
1081 *p_sci_size = i_size;
1086 free( (void *)*pp_sci );
1092 CloseHandle( i_file );
1096 if( shfolder_dll != NULL )
1098 FreeLibrary( shfolder_dll );
1105 /*****************************************************************************
1106 * HashSystemInfo: add system information to an MD5 hash
1107 *****************************************************************************
1108 * This function adds the C: hard drive serial number, BIOS version, CPU type
1109 * and Windows version to an MD5 hash.
1110 *****************************************************************************/
1111 static int HashSystemInfo( struct md5_s *p_md5 )
1122 static LPCTSTR p_reg_keys[ 3 ][ 2 ] =
1125 _T("HARDWARE\\DESCRIPTION\\System"),
1126 _T("SystemBiosVersion")
1130 _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
1131 _T("ProcessorNameString")
1135 _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"),
1140 AddMD5( p_md5, "cache-control", 13 );
1141 AddMD5( p_md5, "Ethernet", 8 );
1143 GetVolumeInformation( _T("C:\\"), NULL, 0, &i_serial,
1144 NULL, NULL, NULL, 0 );
1145 AddMD5( p_md5, (uint8_t *)&i_serial, 4 );
1147 for( i = 0; i < sizeof(p_reg_keys)/sizeof(p_reg_keys[ 0 ]); i++ )
1149 if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, p_reg_keys[ i ][ 0 ],
1150 0, KEY_READ, &i_key ) != ERROR_SUCCESS )
1155 if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ],
1156 NULL, NULL, NULL, &i_size ) != ERROR_SUCCESS )
1158 RegCloseKey( i_key );
1162 p_reg_buf = malloc( i_size );
1164 if( p_reg_buf != NULL )
1166 if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ],
1167 NULL, NULL, p_reg_buf,
1168 &i_size ) == ERROR_SUCCESS )
1170 AddMD5( p_md5, (uint8_t *)p_reg_buf, i_size );
1176 RegCloseKey( i_key );