ref: deb00934e5084f5e171bc2a831e5af779f13d8c2
parent: cae41322be6cba155c5344922f671d8784e5fb21
author: menno <menno>
date: Sun Jan 11 08:59:33 EST 2004
Updated mp4ff library
--- a/common/mp4ff/drms.c
+++ b/common/mp4ff/drms.c
@@ -2,7 +2,7 @@
* drms.c : DRMS
*****************************************************************************
* Copyright (C) 2004 VideoLAN
- * $Id: drms.c,v 1.1 2004/01/10 18:55:24 menno Exp $
+ * $Id: drms.c,v 1.2 2004/01/11 13:59:33 menno Exp $
*
* Author: Jon Lech Johansen <jon-vl@nanocrew.net>
*
@@ -23,12 +23,21 @@
#include <stdlib.h> /* malloc(), free() */
-/* #include <vlc/vlc.h> */
+#ifdef WIN32
+#include <io.h>
+#include <stdio.h>
+#else
+#include <stdio.h>
+#endif
+
+//#include <vlc/vlc.h>
#include "mp4ffint.h"
-#ifdef ITUNES_DRM
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
-#ifdef _WIN32
+#ifdef WIN32
#include <tchar.h>
#include <shlobj.h>
#include <windows.h>
@@ -37,6 +46,8 @@
#include "drms.h"
#include "drmstables.h"
+//#include "libmp4.h"
+
static __inline uint32_t U32_AT( void * _p )
{
uint8_t * p = (uint8_t *)_p;
@@ -526,7 +537,7 @@
{
int i_ret = 0;
-#ifdef _WIN32
+#ifdef WIN32
HKEY i_key;
uint32_t i;
DWORD i_size;
@@ -594,45 +605,62 @@
return( i_ret );
}
-static int get_sci_data( uint32_t p_sci[ 11 ][ 4 ] )
+static int get_sci_data( uint32_t **pp_sci, uint32_t *p_sci_size )
{
int i_ret = -1;
-#ifdef _WIN32
+#ifdef WIN32
HANDLE i_file;
DWORD i_size, i_read;
TCHAR p_path[ MAX_PATH ];
TCHAR *p_filename = _T("\\Apple Computer\\iTunes\\SC Info\\SC Info.sidb");
-#if 1
- if( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA,
- NULL, 0, p_path ) ) )
+ typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
+ LPTSTR );
+
+ HINSTANCE shfolder_dll = NULL;
+ SHGETFOLDERPATH dSHGetFolderPath = NULL;
+
+ if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
+ {
+ dSHGetFolderPath =
+ (SHGETFOLDERPATH)GetProcAddress( shfolder_dll,
+#ifdef _UNICODE
+ _T("SHGetFolderPathW") );
#else
- lstrcpy(p_path,
- _T("C:\\Documents and Settings\\All Users\\Application Data\\Apple Computer\\iTunes\\SC Info\\SC Info.sidb"));
+ _T("SHGetFolderPathA") );
#endif
+ }
+
+ if( dSHGetFolderPath != NULL &&
+ SUCCEEDED( dSHGetFolderPath( NULL, /*CSIDL_COMMON_APPDATA*/ 0x0023,
+ NULL, 0, p_path ) ) )
{
-#if 1
_tcsncat( p_path, p_filename, min( _tcslen( p_filename ),
(MAX_PATH-1) - _tcslen( p_path ) ) );
-#endif
i_file = CreateFile( p_path, GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL );
if( i_file != INVALID_HANDLE_VALUE )
{
- i_read = sizeof(p_sci[ 0 ]) * 11;
i_size = GetFileSize( i_file, NULL );
- if( i_size != INVALID_FILE_SIZE && i_size >= i_read )
+ if( i_size != INVALID_FILE_SIZE &&
+ i_size > (sizeof(*pp_sci[ 0 ]) * 22) )
{
- i_size = SetFilePointer( i_file, 4, NULL, FILE_BEGIN );
- if( i_size != /*INVALID_SET_FILE_POINTER*/ ((DWORD)-1))
+ *pp_sci = malloc( i_size * 2 );
+ if( *pp_sci != NULL )
{
- if( ReadFile( i_file, p_sci, i_read, &i_size, NULL ) &&
- i_size == i_read )
+ if( ReadFile( i_file, *pp_sci, i_size, &i_read, NULL ) &&
+ i_read == i_size )
{
+ *p_sci_size = i_size;
i_ret = 0;
}
+ else
+ {
+ free( (void *)*pp_sci );
+ *pp_sci = NULL;
+ }
}
}
@@ -639,6 +667,11 @@
CloseHandle( i_file );
}
}
+
+ if( shfolder_dll != NULL )
+ {
+ FreeLibrary( shfolder_dll );
+ }
#endif
return( i_ret );
@@ -766,7 +799,7 @@
}
}
-int drms_get_sys_key( uint32_t *p_sys_key )
+static int get_sys_key( uint32_t *p_sys_key )
{
uint32_t p_tmp[ 128 ];
uint32_t p_tmp_key[ 4 ];
@@ -791,14 +824,97 @@
return( 0 );
}
-int drms_get_user_key( uint32_t *p_sys_key, uint32_t *p_user_key )
+struct drms_s
{
- uint32_t i;
- uint32_t p_tmp[ 4 ];
+ uint32_t i_user;
+ uint32_t i_key;
+ uint8_t *p_iviv;
+ uint8_t *p_name;
+ uint32_t i_name_len;
+
+ uint32_t *p_tmp;
+ uint32_t i_tmp_len;
+
+ uint32_t p_key[ 4 ];
+ uint32_t p_ctx[ 128 ];
+
+ char *psz_homedir;
+};
+
+#define P_DRMS ((struct drms_s *)p_drms)
+
+#if 0
+static int rw_user_key( void *p_drms, uint32_t i_rw, uint32_t *p_user_key )
+{
+ FILE *file;
+ int i_ret = -1;
+ char sz_path[ MAX_PATH ];
+
+#define DRMS_PI_DIRNAME "drms"
+#ifdef WIN32
+#define DRMS_DIRNAME DRMS_PI_DIRNAME
+#else
+#define DRMS_DIRNAME "." DRMS_PI_DIRNAME
+#endif
+
+ if( i_rw )
+ {
+ sprintf( sz_path, /* (sizeof(sz_path)/sizeof(sz_path[ 0 ])) - 1, */
+ "%s/" DRMS_DIRNAME "/%08X.%03d", P_DRMS->psz_homedir,
+ P_DRMS->i_user, P_DRMS->i_key );
+
+ file = fopen( sz_path, "r" );
+ if( file != NULL )
+ {
+ i_ret = fread( p_user_key, sizeof(*p_user_key),
+ 4, file ) == 4 ? 0 : -1;
+ fclose( file );
+ }
+ }
+ else
+ {
+ sprintf( sz_path, /*(sizeof(sz_path)/sizeof(sz_path[ 0 ])) - 1,*/
+ "%s/" DRMS_DIRNAME, P_DRMS->psz_homedir );
+
+#if defined( HAVE_ERRNO_H )
+# if defined( WIN32 )
+ if( !mkdir( sz_path ) || errno == EEXIST )
+# else
+ if( !mkdir( sz_path, 0755 ) || errno == EEXIST )
+# endif
+#else
+ if( !mkdir( sz_path ) )
+#endif
+ {
+ sprintf( sz_path, /* (sizeof(sz_path)/sizeof(sz_path[ 0 ])) - 1,*/
+ "%s/" DRMS_DIRNAME "/%08X.%03d", P_DRMS->psz_homedir,
+ P_DRMS->i_user, P_DRMS->i_key );
+
+ file = fopen( sz_path, "w" );
+ if( file != NULL )
+ {
+ i_ret = fwrite( p_user_key, sizeof(*p_user_key),
+ 4, file ) == 4 ? 0 : -1;
+ fclose( file );
+ }
+ }
+ }
+
+ return( i_ret );
+}
+#endif
+
+static int get_user_key( void *p_drms, uint32_t *p_user_key )
+{
+ uint32_t i, y;
+ uint32_t *p_tmp;
uint32_t *p_cur_key;
uint32_t p_acei[ 41 ];
uint32_t p_ctx[ 128 ];
- uint32_t p_sci[ 2 ][ 11 ][ 4 ];
+ uint32_t p_sys_key[ 4 ];
+ uint32_t i_sci_size;
+ uint32_t *p_sci[ 2 ];
+ int i_ret = -1;
uint32_t p_sci_key[ 4 ] =
{
@@ -805,63 +921,104 @@
0x6E66556D, 0x6E676F70, 0x67666461, 0x33373866
};
- if( p_sys_key == NULL )
+#if 0
+ if( !rw_user_key( p_drms, 1, p_user_key ) )
{
- if( drms_get_sys_key( p_tmp ) )
- {
- return( -1 );
- }
+ return( 0 );
+ }
+#endif
- p_sys_key = p_tmp;
+ if( get_sys_key( p_sys_key ) )
+ {
+ return( -1 );
}
- if( get_sci_data( p_sci[ 0 ] ) )
+
+ if( get_sci_data( &p_sci[ 0 ], &i_sci_size ) )
{
return( -1 );
}
+ p_tmp = p_sci[ 0 ];
+ p_sci[ 1 ] = (uint32_t *)(((uint8_t *)p_sci[ 0 ]) + i_sci_size);
+ i_sci_size -= sizeof(*p_sci[ 0 ]);
+
init_ctx( p_ctx, p_sys_key );
for( i = 0, p_cur_key = p_sci_key;
- i < sizeof(p_sci[ 0 ])/sizeof(p_sci[ 0 ][ 0 ]); i++ )
+ i < i_sci_size / sizeof(P_DRMS->p_key); i++ )
{
- ctx_xor( p_ctx, &p_sci[ 0 ][ i ][ 0 ], &p_sci[ 1 ][ i ][ 0 ],
+ y = i * sizeof(*p_sci[ 0 ]);
+
+ ctx_xor( p_ctx, p_sci[ 0 ] + y + 1, p_sci[ 1 ] + y + 1,
p_drms_tab3, p_drms_tab4 );
- block_xor( &p_sci[ 1 ][ i ][ 0 ], p_cur_key, &p_sci[ 1 ][ i ][ 0 ] );
+ block_xor( p_sci[ 1 ] + y + 1, p_cur_key, p_sci[ 1 ] + y + 1 );
- p_cur_key = &p_sci[ 0 ][ i ][ 0 ];
+ p_cur_key = p_sci[ 0 ] + y + 1;
}
acei_init( p_acei, p_sys_key );
- for( i = 0; i < sizeof(p_sci[ 1 ])/sizeof(p_sci[ 1 ][ 0 ]); i++ )
+ for( i = 0; i < i_sci_size / sizeof(P_DRMS->p_key); i++ )
{
- acei( p_acei, (uint8_t *)&p_sci[ 1 ][ i ][ 0 ],
- sizeof(p_sci[ 1 ][ i ]) );
+ y = i * sizeof(*p_sci[ 1 ]);
+
+ acei( p_acei, (uint8_t *)(p_sci[ 1 ] + y + 1),
+ sizeof(P_DRMS->p_key) );
}
- memcpy( p_user_key, &p_sci[ 1 ][ 10 ][ 0 ], sizeof(p_sci[ 1 ][ i ]) );
+ y = 0;
+ i = U32_AT( &p_sci[ 1 ][ 5 ] );
+ i_sci_size -= 21 * sizeof(*p_sci[ 1 ]);
+ p_sci[ 1 ] += 22;
+ p_sci[ 0 ] = NULL;
- return( 0 );
-}
+ while( i_sci_size > 0 && i > 0 )
+ {
+ if( p_sci[ 0 ] == NULL )
+ {
+ i_sci_size -= 18 * sizeof(*p_sci[ 1 ]);
+ if( i_sci_size <= 0 )
+ {
+ break;
+ }
-struct drms_s
-{
- uint8_t *p_iviv;
- uint32_t i_iviv_len;
- uint8_t *p_name;
- uint32_t i_name_len;
+ p_sci[ 0 ] = p_sci[ 1 ];
+ y = U32_AT( &p_sci[ 1 ][ 17 ] );
+ p_sci[ 1 ] += 18;
+ }
- uint32_t *p_tmp;
- uint32_t i_tmp_len;
+ if( !y )
+ {
+ i--;
+ p_sci[ 0 ] = NULL;
+ continue;
+ }
- uint32_t p_key[ 4 ];
- uint32_t p_ctx[ 128 ];
-};
+ if( U32_AT( &p_sci[ 0 ][ 0 ] ) == P_DRMS->i_user &&
+ ( i_sci_size >=
+ (sizeof(P_DRMS->p_key) + sizeof(p_sci[ 1 ][ 0 ]) ) ) &&
+ ( ( U32_AT( &p_sci[ 1 ][ 0 ] ) == P_DRMS->i_key ) ||
+ ( !P_DRMS->i_key ) || ( p_sci[ 1 ] == (p_sci[ 0 ] + 18) ) ) )
+ {
+ memcpy( p_user_key, &p_sci[ 1 ][ 1 ], sizeof(P_DRMS->p_key) );
+// rw_user_key( p_drms, 0, p_user_key );
+ i_ret = 0;
+ break;
+ }
-#define P_DRMS ((struct drms_s *)p_drms)
+ y--;
+ p_sci[ 1 ] += 5;
+ i_sci_size -= 5 * sizeof(*p_sci[ 1 ]);
+ }
-void *drms_alloc()
+ free( (void *)p_tmp );
+
+ return( i_ret );
+}
+
+
+void *drms_alloc( char *psz_homedir )
{
struct drms_s *p_drms;
@@ -878,6 +1035,19 @@
free( (void *)p_drms );
p_drms = NULL;
}
+
+ p_drms->psz_homedir = malloc( MAX_PATH );
+ if( p_drms->psz_homedir != NULL )
+ {
+ strncpy( p_drms->psz_homedir, psz_homedir, MAX_PATH );
+ p_drms->psz_homedir[ MAX_PATH - 1 ] = '\0';
+ }
+ else
+ {
+ free( (void *)p_drms->p_tmp );
+ free( (void *)p_drms );
+ p_drms = NULL;
+ }
}
return( (void *)p_drms );
@@ -895,6 +1065,11 @@
free( (void *)P_DRMS->p_iviv );
}
+ if( P_DRMS->psz_homedir != NULL )
+ {
+ free( (void *)P_DRMS->psz_homedir );
+ }
+
if( P_DRMS->p_tmp != NULL )
{
free( (void *)P_DRMS->p_tmp );
@@ -942,27 +1117,39 @@
switch( i_type )
{
- case DRMS_INIT_UKEY:
+ case DRMS_INIT_USER:
{
- if( i_len != sizeof(P_DRMS->p_key) )
+ if( i_len < sizeof(P_DRMS->i_user) )
{
i_ret = -1;
break;
}
- init_ctx( P_DRMS->p_ctx, (uint32_t *)p_info );
+ P_DRMS->i_user = U32_AT( p_info );
}
break;
+ case DRMS_INIT_KEY:
+ {
+ if( i_len < sizeof(P_DRMS->i_key) )
+ {
+ i_ret = -1;
+ break;
+ }
+
+ P_DRMS->i_key = U32_AT( p_info );
+ }
+ break;
+
case DRMS_INIT_IVIV:
{
- if( i_len != sizeof(P_DRMS->p_key) )
+ if( i_len < sizeof(P_DRMS->p_key) )
{
i_ret = -1;
break;
}
- P_DRMS->p_iviv = malloc( i_len );
+ P_DRMS->p_iviv = malloc( sizeof(P_DRMS->p_key) );
if( P_DRMS->p_iviv == NULL )
{
i_ret = -1;
@@ -969,14 +1156,15 @@
break;
}
- memcpy( P_DRMS->p_iviv, p_info, i_len );
- P_DRMS->i_iviv_len = i_len;
+ memcpy( P_DRMS->p_iviv, p_info, sizeof(P_DRMS->p_key) );
}
break;
case DRMS_INIT_NAME:
{
- P_DRMS->p_name = malloc( i_len );
+ P_DRMS->i_name_len = strlen( p_info );
+
+ P_DRMS->p_name = malloc( P_DRMS->i_name_len );
if( P_DRMS->p_name == NULL )
{
i_ret = -1;
@@ -983,8 +1171,7 @@
break;
}
- memcpy( P_DRMS->p_name, p_info, i_len );
- P_DRMS->i_name_len = i_len;
+ memcpy( P_DRMS->p_name, p_info, P_DRMS->i_name_len );
}
break;
@@ -1002,7 +1189,7 @@
TAOS_INIT( p_tmp, 0 );
taos_add3( p_tmp, P_DRMS->p_name, P_DRMS->i_name_len );
- taos_add3( p_tmp, P_DRMS->p_iviv, P_DRMS->i_iviv_len );
+ taos_add3( p_tmp, P_DRMS->p_iviv, sizeof(P_DRMS->p_key) );
memcpy( p_priv, &p_tmp[ 4 ], sizeof(p_priv[ 0 ]) * 2 );
i = (p_tmp[ 4 ] / 8) & 63;
i = i >= 56 ? 120 - i : 56 - i;
@@ -1009,6 +1196,14 @@
taos_add3( p_tmp, p_drms_tab_tend, i );
taos_add3( p_tmp, (uint8_t *)p_priv, sizeof(p_priv[ 0 ]) * 2 );
+ if( get_user_key( p_drms, P_DRMS->p_key ) )
+ {
+ i_ret = -1;
+ break;
+ }
+
+ init_ctx( P_DRMS->p_ctx, P_DRMS->p_key );
+
memcpy( p_priv, p_info, 64 );
memcpy( P_DRMS->p_key, p_tmp, sizeof(P_DRMS->p_key) );
drms_decrypt( p_drms, p_priv, sizeof(p_priv) );
@@ -1016,6 +1211,8 @@
init_ctx( P_DRMS->p_ctx, &p_priv[ 6 ] );
memcpy( P_DRMS->p_key, &p_priv[ 12 ], sizeof(P_DRMS->p_key) );
+ free( (void *)P_DRMS->psz_homedir );
+ P_DRMS->psz_homedir = NULL;
free( (void *)P_DRMS->p_name );
P_DRMS->p_name = NULL;
free( (void *)P_DRMS->p_iviv );
@@ -1028,6 +1225,4 @@
}
#undef P_DRMS
-
-#endif
--- a/common/mp4ff/drms.h
+++ b/common/mp4ff/drms.h
@@ -2,7 +2,7 @@
* drms.h : DRMS
*****************************************************************************
* Copyright (C) 2004 VideoLAN
- * $Id: drms.h,v 1.1 2004/01/10 18:55:24 menno Exp $
+ * $Id: drms.h,v 1.2 2004/01/11 13:59:33 menno Exp $
*
* Author: Jon Lech Johansen <jon-vl@nanocrew.net>
*
@@ -21,10 +21,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
-#define DRMS_INIT_UKEY 0
+#define DRMS_INIT_KEY 0
#define DRMS_INIT_IVIV 1
#define DRMS_INIT_NAME 2
#define DRMS_INIT_PRIV 3
+#define DRMS_INIT_USER 4
extern int drms_get_sys_key( uint32_t *p_sys_key );
extern int drms_get_user_key( uint32_t *p_sys_key,
--- a/common/mp4ff/mp4atom.c
+++ b/common/mp4ff/mp4atom.c
@@ -22,7 +22,7 @@
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
-** $Id: mp4atom.c,v 1.15 2004/01/10 18:55:24 menno Exp $
+** $Id: mp4atom.c,v 1.16 2004/01/11 13:59:33 menno Exp $
**/
#include <stdlib.h>
@@ -173,6 +173,10 @@
return ATOM_PRIV;
else if (mp4ff_atom_compare(a,b,c,d, 'i','v','i','v'))
return ATOM_IVIV;
+ else if (mp4ff_atom_compare(a,b,c,d, 'u','s','e','r'))
+ return ATOM_USER;
+ else if (mp4ff_atom_compare(a,b,c,d, 'k','e','y',' '))
+ return ATOM_KEY;
else
return ATOM_UNKNOWN;
}
@@ -331,17 +335,9 @@
int32_t i;
uint8_t atom_type = 0;
uint8_t header_size = 0;
- uint32_t drms_user_key[4];
- if (drms_get_user_key(NULL, drms_user_key) == 0)
- {
- f->track[f->total_tracks - 1]->p_drms = drms_alloc();
+ f->track[f->total_tracks - 1]->p_drms = drms_alloc();
- drms_init( f->track[f->total_tracks - 1]->p_drms,
- DRMS_INIT_UKEY, (uint8_t *)drms_user_key,
- sizeof(drms_user_key) );
- }
-
for (i = 0; i < 6; i++)
{
mp4ff_read_char(f); /* reserved */
@@ -450,6 +446,40 @@
return 0;
}
+
+static int32_t mp4ff_read_user(mp4ff_t *f, uint64_t size)
+{
+ uint8_t *data = malloc(size);
+ mp4ff_read_data(f, data, size);
+
+ if (f->track[f->total_tracks - 1]->p_drms != 0)
+ {
+ drms_init(f->track[f->total_tracks - 1]->p_drms,
+ DRMS_INIT_USER, data, sizeof(uint32_t) * 4 );
+ }
+
+ if (data)
+ free(data);
+
+ return 0;
+}
+
+static int32_t mp4ff_read_key(mp4ff_t *f, uint64_t size)
+{
+ uint8_t *data = malloc(size);
+ mp4ff_read_data(f, data, size);
+
+ if (f->track[f->total_tracks - 1]->p_drms != 0)
+ {
+ drms_init(f->track[f->total_tracks - 1]->p_drms,
+ DRMS_INIT_KEY, data, sizeof(uint32_t) * 4 );
+ }
+
+ if (data)
+ free(data);
+
+ return 0;
+}
#endif
static int32_t mp4ff_read_stsd(mp4ff_t *f)
@@ -766,6 +796,10 @@
mp4ff_read_name(f, size-8);
} else if (atom_type == ATOM_PRIV) {
mp4ff_read_priv(f, size-8);
+ } else if (atom_type == ATOM_USER) {
+ mp4ff_read_user(f, size-8);
+ } else if (atom_type == ATOM_KEY) {
+ mp4ff_read_key(f, size-8);
#endif
#ifdef USE_TAGGING
} else if (atom_type == ATOM_META) {
--- a/common/mp4ff/mp4ffint.h
+++ b/common/mp4ff/mp4ffint.h
@@ -22,7 +22,7 @@
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
-** $Id: mp4ffint.h,v 1.12 2004/01/10 18:55:24 menno Exp $
+** $Id: mp4ffint.h,v 1.13 2004/01/11 13:59:33 menno Exp $
**/
#ifndef MP4FF_INTERNAL_H
@@ -35,7 +35,7 @@
#include "mp4ff_int_types.h"
-//#define ITUNES_DRM
+#define ITUNES_DRM
#define MAX_TRACKS 1024
@@ -74,6 +74,8 @@
#define ATOM_FRMA 152
#define ATOM_IVIV 153
#define ATOM_PRIV 154
+#define ATOM_USER 155
+#define ATOM_KEY 156
#define ATOM_UNKNOWN 255
#define ATOM_FREE ATOM_UNKNOWN