⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drms.c

📁 betaplayer_0.096源码 tcpmp老版本
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * drms.c: DRMS ***************************************************************************** * Copyright (C) 2004 VideoLAN * $Id: drms.c,v 1.6 2004/04/12 18:17:41 menno Exp $ * * Authors: Jon Lech Johansen <jon-vl@nanocrew.net> *          Sam Hocevar <sam@zoy.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************/#include <stdlib.h>                                      /* malloc(), free() */#ifndef _WIN32#include "config.h"#endif#include "mp4ffint.h"#ifdef ITUNES_DRM#ifdef _WIN32#   include <io.h>#   include <stdio.h>#   include <sys/stat.h>#   define PATH_MAX MAX_PATH#else#   include <stdio.h>#endif#ifdef HAVE_ERRNO_H#   include <errno.h>#endif#ifdef _WIN32#   include <tchar.h>#   include <shlobj.h>#   include <windows.h>#endif#ifdef HAVE_SYS_STAT_H#   include <sys/stat.h>#endif#ifdef HAVE_SYS_TYPES_H#   include <sys/types.h>#endif/* In Solaris (and perhaps others) PATH_MAX is in limits.h. */#ifdef HAVE_LIMITS_H#   include <limits.h>#endif#ifdef HAVE_IOKIT_IOKITLIB_H#   include <mach/mach.h>#   include <IOKit/IOKitLib.h>#   include <CoreFoundation/CFNumber.h>#endif#ifdef HAVE_SYSFS_LIBSYSFS_H#   include <sysfs/libsysfs.h>#endif#include "drms.h"#include "drmstables.h"/***************************************************************************** * aes_s: AES keys structure ***************************************************************************** * This structure stores a set of keys usable for encryption and decryption * with the AES/Rijndael algorithm. *****************************************************************************/struct aes_s{    uint32_t pp_enc_keys[ AES_KEY_COUNT + 1 ][ 4 ];    uint32_t pp_dec_keys[ AES_KEY_COUNT + 1 ][ 4 ];};/***************************************************************************** * md5_s: MD5 message structure ***************************************************************************** * This structure stores the static information needed to compute an MD5 * hash. It has an extra data buffer to allow non-aligned writes. *****************************************************************************/struct md5_s{    uint64_t i_bits;      /* Total written bits */    uint32_t p_digest[4]; /* The MD5 digest */    uint32_t p_data[16];  /* Buffer to cache non-aligned writes */};/***************************************************************************** * shuffle_s: shuffle structure ***************************************************************************** * This structure stores the static information needed to shuffle data using * a custom algorithm. *****************************************************************************/struct shuffle_s{    uint32_t p_commands[ 20 ];    uint32_t p_bordel[ 16 ];};/***************************************************************************** * drms_s: DRMS structure ***************************************************************************** * This structure stores the static information needed to decrypt DRMS data. *****************************************************************************/struct drms_s{    uint32_t i_user;    uint32_t i_key;    uint8_t  p_iviv[ 16 ];    uint8_t *p_name;    uint32_t p_key[ 4 ];    struct aes_s aes;    char     psz_homedir[ PATH_MAX ];};/***************************************************************************** * Local prototypes *****************************************************************************/static void InitAES       ( struct aes_s *, uint32_t * );static void DecryptAES    ( struct aes_s *, uint32_t *, const uint32_t * );static void InitMD5       ( struct md5_s * );static void AddMD5        ( struct md5_s *, const uint8_t *, uint32_t );static void EndMD5        ( struct md5_s * );static void Digest        ( struct md5_s *, uint32_t * );static void InitShuffle   ( struct shuffle_s *, uint32_t * );static void DoShuffle     ( struct shuffle_s *, uint32_t *, uint32_t );static int GetSystemKey   ( uint32_t *, uint32_t );static int WriteUserKey   ( void *, uint32_t * );static int ReadUserKey    ( void *, uint32_t * );static int GetUserKey     ( void *, uint32_t * );static int GetSCIData     ( char *, uint32_t **, uint32_t * );static int HashSystemInfo ( uint32_t * );static int GetiPodID      ( int64_t * );#ifdef WORDS_BIGENDIAN/***************************************************************************** * Reverse: reverse byte order *****************************************************************************/static __inline void Reverse( uint32_t *p_buffer, int n ){    int i;    for( i = 0; i < n; i++ )    {        p_buffer[ i ] = GetDWLE(&p_buffer[ i ]);    }}#    define REVERSE( p, n ) Reverse( p, n )#else#    define REVERSE( p, n )#endif/***************************************************************************** * BlockXOR: XOR two 128 bit blocks *****************************************************************************/static __inline void BlockXOR( uint32_t *p_dest, uint32_t *p_s1, uint32_t *p_s2 ){    int i;    for( i = 0; i < 4; i++ )    {        p_dest[ i ] = p_s1[ i ] ^ p_s2[ i ];    }}/***************************************************************************** * drms_alloc: allocate a DRMS structure *****************************************************************************/void *drms_alloc( char *psz_homedir ){    struct drms_s *p_drms;    p_drms = malloc( sizeof(struct drms_s) );    if( p_drms == NULL )    {        return NULL;    }    memset( p_drms, 0, sizeof(struct drms_s) );    strncpy( p_drms->psz_homedir, psz_homedir, PATH_MAX );    p_drms->psz_homedir[ PATH_MAX - 1 ] = '\0';    return (void *)p_drms;}/***************************************************************************** * drms_free: free a previously allocated DRMS structure *****************************************************************************/void drms_free( void *_p_drms ){    struct drms_s *p_drms = (struct drms_s *)_p_drms;    if( p_drms->p_name != NULL )    {        free( (void *)p_drms->p_name );    }    free( p_drms );}/***************************************************************************** * drms_decrypt: unscramble a chunk of data *****************************************************************************/void drms_decrypt( void *_p_drms, uint32_t *p_buffer, uint32_t i_bytes ){    struct drms_s *p_drms = (struct drms_s *)_p_drms;    uint32_t p_key[ 4 ];    unsigned int i_blocks;    /* AES is a block cypher, round down the byte count */    i_blocks = i_bytes / 16;    i_bytes = i_blocks * 16;    /* Initialise the key */    memcpy( p_key, p_drms->p_key, 16 );    /* Unscramble */    while( i_blocks-- )    {        uint32_t p_tmp[ 4 ];        REVERSE( p_buffer, 4 );        DecryptAES( &p_drms->aes, p_tmp, p_buffer );        BlockXOR( p_tmp, p_key, p_tmp );        /* Use the previous scrambled data as the key for next block */        memcpy( p_key, p_buffer, 16 );        /* Copy unscrambled data back to the buffer */        memcpy( p_buffer, p_tmp, 16 );        REVERSE( p_buffer, 4 );        p_buffer += 4;    }}/***************************************************************************** * drms_init: initialise a DRMS structure *****************************************************************************/int drms_init( void *_p_drms, uint32_t i_type,               uint8_t *p_info, uint32_t i_len ){    struct drms_s *p_drms = (struct drms_s *)_p_drms;    int i_ret = 0;    switch( i_type )    {        case FOURCC_user:            if( i_len < sizeof(p_drms->i_user) )            {                i_ret = -1;                break;            }            p_drms->i_user = U32_AT( p_info );            break;        case FOURCC_key:            if( i_len < sizeof(p_drms->i_key) )            {                i_ret = -1;                break;            }            p_drms->i_key = U32_AT( p_info );            break;        case FOURCC_iviv:            if( i_len < sizeof(p_drms->p_key) )            {                i_ret = -1;                break;            }            memcpy( p_drms->p_iviv, p_info, 16 );            break;        case FOURCC_name:            p_drms->p_name = strdup( p_info );            if( p_drms->p_name == NULL )            {                i_ret = -1;            }            break;        case FOURCC_priv:        {            uint32_t p_priv[ 64 ];            struct md5_s md5;            if( i_len < 64 )            {                i_ret = -1;                break;            }            InitMD5( &md5 );            AddMD5( &md5, p_drms->p_name, strlen( p_drms->p_name ) );            AddMD5( &md5, p_drms->p_iviv, 16 );            EndMD5( &md5 );            if( GetUserKey( p_drms, p_drms->p_key ) )            {                i_ret = -1;                break;            }            InitAES( &p_drms->aes, p_drms->p_key );            memcpy( p_priv, p_info, 64 );            memcpy( p_drms->p_key, md5.p_digest, 16 );            drms_decrypt( p_drms, p_priv, 64 );            REVERSE( p_priv, 64 );            if( p_priv[ 0 ] != 0x6e757469 ) /* itun */            {                i_ret = -1;                break;            }            InitAES( &p_drms->aes, p_priv + 6 );            memcpy( p_drms->p_key, p_priv + 12, 16 );            free( (void *)p_drms->p_name );            p_drms->p_name = NULL;        }        break;    }    return i_ret;}/* The following functions are local *//***************************************************************************** * InitAES: initialise AES/Rijndael encryption/decryption tables ***************************************************************************** * The Advanced Encryption Standard (AES) is described in RFC 3268 *****************************************************************************/static void InitAES( struct aes_s *p_aes, uint32_t *p_key ){    unsigned int i, t;    uint32_t i_key, i_seed;    memset( p_aes->pp_enc_keys[1], 0, 16 );    memcpy( p_aes->pp_enc_keys[0], p_key, 16 );    /* Generate the key tables */    i_seed = p_aes->pp_enc_keys[ 0 ][ 3 ];    for( i_key = 0; i_key < AES_KEY_COUNT; i_key++ )    {        uint32_t j;        i_seed = AES_ROR( i_seed, 8 );        j = p_aes_table[ i_key ];        j ^= p_aes_encrypt[ (i_seed >> 24) & 0xff ]              ^ AES_ROR( p_aes_encrypt[ (i_seed >> 16) & 0xff ], 8 )              ^ AES_ROR( p_aes_encrypt[ (i_seed >> 8) & 0xff ], 16 )              ^ AES_ROR( p_aes_encrypt[ i_seed & 0xff ], 24 );        j ^= p_aes->pp_enc_keys[ i_key ][ 0 ];        p_aes->pp_enc_keys[ i_key + 1 ][ 0 ] = j;        j ^= p_aes->pp_enc_keys[ i_key ][ 1 ];        p_aes->pp_enc_keys[ i_key + 1 ][ 1 ] = j;        j ^= p_aes->pp_enc_keys[ i_key ][ 2 ];        p_aes->pp_enc_keys[ i_key + 1 ][ 2 ] = j;        j ^= p_aes->pp_enc_keys[ i_key ][ 3 ];        p_aes->pp_enc_keys[ i_key + 1 ][ 3 ] = j;        i_seed = j;    }    memcpy( p_aes->pp_dec_keys[ 0 ],            p_aes->pp_enc_keys[ 0 ], 16 );    for( i = 1; i < AES_KEY_COUNT; i++ )    {        for( t = 0; t < 4; t++ )        {            uint32_t j, k, l, m, n;            j = p_aes->pp_enc_keys[ i ][ t ];            k = (((j >> 7) & 0x01010101) * 27) ^ ((j & 0xff7f7f7f) << 1);            l = (((k >> 7) & 0x01010101) * 27) ^ ((k & 0xff7f7f7f) << 1);            m = (((l >> 7) & 0x01010101) * 27) ^ ((l & 0xff7f7f7f) << 1);            j ^= m;            n = AES_ROR( l ^ j, 16 ) ^ AES_ROR( k ^ j, 8 ) ^ AES_ROR( j, 24 );            p_aes->pp_dec_keys[ i ][ t ] = k ^ l ^ m ^ n;        }    }}/***************************************************************************** * DecryptAES: decrypt an AES/Rijndael 128 bit block *****************************************************************************/static void DecryptAES( struct aes_s *p_aes,                        uint32_t *p_dest, const uint32_t *p_src ){    uint32_t p_wtxt[ 4 ]; /* Working cyphertext */    uint32_t p_tmp[ 4 ];    unsigned int i_round, t;    for( t = 0; t < 4; t++ )    {        /* FIXME: are there any endianness issues here? */        p_wtxt[ t ] = p_src[ t ] ^ p_aes->pp_enc_keys[ AES_KEY_COUNT ][ t ];    }    /* Rounds 0 - 8 */    for( i_round = 0; i_round < (AES_KEY_COUNT - 1); i_round++ )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -