Commit dc0df7c2 authored by Stéphane Borel's avatar Stéphane Borel

-completely changed title and chapter initialization. Now we have real

title units.

-Fixed size for a majority of DVD.
parent 87dc702b
......@@ -2,7 +2,7 @@
* dvd_css.c: Functions for DVD authentification and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_css.c,v 1.16 2001/03/02 13:47:01 sam Exp $
* $Id: dvd_css.c,v 1.17 2001/03/03 07:07:01 stef Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -35,6 +35,7 @@
#include "defs.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
......@@ -100,9 +101,9 @@ int CSSTest( int i_fd )
* Since we don't need the disc key to find the title key, we just run the
* basic unavoidable commands to authenticate device and disc.
*****************************************************************************/
css_t CSSInit( int i_fd )
css_t * CSSInit( int i_fd )
{
css_t css;
css_t * p_css;
#ifdef HAVE_CSS
/* structures defined in cdrom.h or dvdio.h */
......@@ -112,8 +113,13 @@ css_t CSSInit( int i_fd )
int i_error = -1;
int i;
css.i_fd = i_fd;
css.b_error = 0;
p_css = malloc( sizeof(css_t) );
if( p_css == NULL )
{
return NULL;
}
p_css->i_fd = i_fd;
memset( &auth_info, 0, sizeof(auth_info) );
......@@ -121,9 +127,10 @@ css_t CSSInit( int i_fd )
switch( CSSGetASF( i_fd ) )
{
case -1:
css.b_error = 1;
free( p_css );
return NULL;
case 1:
return css;
return p_css;
case 0:
intf_WarnMsg( 3, "css info: authenticating" );
}
......@@ -151,14 +158,14 @@ css_t CSSInit( int i_fd )
/* Unable to authenticate without AGID */
if( i_error == -1 )
{
css.b_error = 1;
intf_ErrMsg( "css error: could not get AGID" );
return css;
free( p_css );
return NULL;
}
for( i = 0 ; i < 10; ++i )
{
css.disc.pi_challenge[i] = i;
p_css->disc.pi_challenge[i] = i;
}
/* Send AGID to host */
......@@ -167,43 +174,43 @@ css_t CSSInit( int i_fd )
/* Get challenge from host */
for( i = 0 ; i < 10 ; ++i )
{
auth_info.hsc.chal[9-i] = css.disc.pi_challenge[i];
auth_info.hsc.chal[9-i] = p_css->disc.pi_challenge[i];
}
/* Returning data, let LU change state */
css.i_agid = auth_info.lsa.agid;
p_css->i_agid = auth_info.lsa.agid;
/* Send challenge to LU */
if( dvd_ioctl( i_fd, DVD_AUTH, &auth_info )<0 )
{
intf_ErrMsg( "css error: failed sending challenge to LU" );
css.b_error = 1;
return css;
free( p_css );
return NULL;
}
/* Get key1 from LU */
if( dvd_ioctl( i_fd, DVD_AUTH, &auth_info ) < 0)
{
intf_ErrMsg( "css error: failed getting key1 from LU" );
css.b_error = 1;
return css;
free( p_css );
return NULL;
}
/* Send key1 to host */
for( i = 0 ; i < KEY_SIZE ; i++ )
{
css.disc.pi_key1[i] = auth_info.lsk.key[4-i];
p_css->disc.pi_key1[i] = auth_info.lsk.key[4-i];
}
for( i = 0 ; i < 32 ; ++i )
{
CSSCryptKey( 0, i, css.disc.pi_challenge,
css.disc.pi_key_check );
CSSCryptKey( 0, i, p_css->disc.pi_challenge,
p_css->disc.pi_key_check );
if( memcmp( css.disc.pi_key_check,
css.disc.pi_key1, KEY_SIZE ) == 0 )
if( memcmp( p_css->disc.pi_key_check,
p_css->disc.pi_key1, KEY_SIZE ) == 0 )
{
intf_WarnMsg( 3, "css info: drive authentic, using variant %d", i);
css.disc.i_varient = i;
p_css->disc.i_varient = i;
auth_info.type = DVD_LU_SEND_CHALLENGE;
break;
}
......@@ -213,32 +220,32 @@ css_t CSSInit( int i_fd )
{
intf_ErrMsg( "css error: drive would not authenticate" );
auth_info.type = DVD_AUTH_FAILURE;
css.b_error = 1;
return css;
free( p_css );
return NULL;
}
/* Get challenge from LU */
if( dvd_ioctl( i_fd, DVD_AUTH, &auth_info ) < 0 )
{
intf_ErrMsg( "css error: failed getting challenge from LU" );
css.b_error = 1;
return css;
free( p_css );
return NULL;
}
/* Send challenge to host */
for( i = 0 ; i < 10 ; ++i )
{
css.disc.pi_challenge[i] = auth_info.hsc.chal[9-i];
p_css->disc.pi_challenge[i] = auth_info.hsc.chal[9-i];
}
CSSCryptKey( 1, css.disc.i_varient, css.disc.pi_challenge,
css.disc.pi_key2 );
CSSCryptKey( 1, p_css->disc.i_varient, p_css->disc.pi_challenge,
p_css->disc.pi_key2 );
auth_info.type = DVD_HOST_SEND_KEY2;
/* Get key2 from host */
for( i = 0 ; i < KEY_SIZE ; ++i )
{
auth_info.hsk.key[4-i] = css.disc.pi_key2[i];
auth_info.hsk.key[4-i] = p_css->disc.pi_key2[i];
}
/* Returning data, let LU change state */
......@@ -246,7 +253,8 @@ css_t CSSInit( int i_fd )
if( dvd_ioctl( i_fd, DVD_AUTH, &auth_info ) < 0 )
{
intf_ErrMsg( "css error: failed sending key2 to LU (expected)" );
return css;
free( p_css );
return NULL;
}
if( auth_info.type == DVD_AUTH_ESTABLISHED )
......@@ -255,71 +263,83 @@ css_t CSSInit( int i_fd )
}
else if( auth_info.type == DVD_AUTH_FAILURE )
{
css.b_error = 1;
intf_ErrMsg( "css error: DVD authentication failed" );
free( p_css );
return NULL;
}
memcpy( css.disc.pi_challenge, css.disc.pi_key1, KEY_SIZE );
memcpy( css.disc.pi_challenge+KEY_SIZE, css.disc.pi_key2, KEY_SIZE );
CSSCryptKey( 2, css.disc.i_varient,
css.disc.pi_challenge,
css.disc.pi_key_check );
memcpy( p_css->disc.pi_challenge, p_css->disc.pi_key1, KEY_SIZE );
memcpy( p_css->disc.pi_challenge+KEY_SIZE, p_css->disc.pi_key2, KEY_SIZE );
CSSCryptKey( 2, p_css->disc.i_varient,
p_css->disc.pi_challenge,
p_css->disc.pi_key_check );
intf_WarnMsg( 1, "css info: received Session Key" );
if( css.i_agid < 0 )
if( p_css->i_agid < 0 )
{
css.b_error = 1;
return css;
free( p_css );
return NULL;
}
/* Test authentication success */
switch( CSSGetASF( i_fd ) )
{
case -1:
css.b_error = 1;
free( p_css );
return NULL;
case 1:
return css;
return p_css;
case 0:
intf_WarnMsg( 3, "css info: getting disc key" );
}
/* Get encrypted disc key */
dvd.type = DVD_STRUCT_DISCKEY;
dvd.disckey.agid = css.i_agid;
dvd.disckey.agid = p_css->i_agid;
memset( dvd.disckey.value, 0, 2048 );
if( dvd_ioctl( i_fd, DVD_READ_STRUCT, &dvd ) < 0 )
{
intf_ErrMsg( "css error: could not read Disc Key" );
css.b_error = 1;
return css;
free( p_css );
return NULL;
}
#if 1
/* Unencrypt disc key using bus key */
for( i = 0 ; i < sizeof(dvd.disckey.value) ; i++ )
{
dvd.disckey.value[i] ^= css.disc.pi_key_check[4 - (i % KEY_SIZE)];
dvd.disckey.value[i] ^= p_css->disc.pi_key_check[4 - (i % KEY_SIZE)];
}
memcpy( css.disc.pi_key_check, dvd.disckey.value, 2048 );
memcpy( p_css->disc.pi_key_check, dvd.disckey.value, 2048 );
#endif
/* Test authentication success */
switch( CSSGetASF( i_fd ) )
{
case -1:
case 0:
css.b_error = 1;
free( p_css );
return NULL;
case 1:
return css;
return p_css;
}
#else /* HAVE_CSS */
intf_ErrMsg( "css error: CSS decryption is disabled in this module" );
css.i_fd = i_fd;
css.b_error = 1;
p_css = NULL;
#endif /* HAVE_CSS */
return css;
return p_css;
}
/*****************************************************************************
* CSSEnd : frees css structure
*****************************************************************************/
void CSSEnd( css_t * p_css )
{
#ifdef HAVE_CSS
free( p_css );
#endif
}
/*****************************************************************************
......@@ -722,9 +742,6 @@ static void CSSCryptKey( int i_key_type, int i_varient,
i_lfsr1_o = ( ( i_lfsr1 >> 16 ) ^ ( i_lfsr1 >> 2 ) ) & 1;
i_lfsr1 = ( i_lfsr1 << 1 ) | i_lfsr1_o;
#define BIT0(x) ((x) & 1)
#define BIT1(x) (((x) >> 1) & 1)
i_combined = !i_lfsr1_o + i_carry + !i_lfsr0_o;
/* taking bit 1 */
i_carry = ( i_combined >> 1 ) & 1;
......
......@@ -2,7 +2,7 @@
* dvd_css.h: Structures for DVD authentification and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_css.h,v 1.4 2001/02/20 02:53:13 stef Exp $
* $Id: dvd_css.h,v 1.5 2001/03/03 07:07:01 stef Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -48,7 +48,6 @@ typedef struct title_key_s
typedef struct css_s
{
int i_fd;
boolean_t b_error;
int i_agid;
disc_t disc;
u8 pi_disc_key[2048];
......
......@@ -7,7 +7,7 @@
* will only be given back to netlist when refcount is zero.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
* $Id: dvd_netlist.c,v 1.1 2001/03/02 03:32:46 stef Exp $
* $Id: dvd_netlist.c,v 1.2 2001/03/03 07:07:01 stef Exp $
*
* Authors: Henri Fallon <henri@videolan.org>
* Stphane Borel <stef@videolan.org>
......@@ -64,23 +64,21 @@
*
* Warning: i_nb_iovec, i_nb_data, i_nb_pes have to be 2^x
*****************************************************************************/
int DVDNetlistInit( input_thread_t * p_input,
int i_nb_iovec, int i_nb_data, int i_nb_pes,
size_t i_buffer_size, int i_read_once )
dvd_netlist_t * DVDNetlistInit( int i_nb_iovec, int i_nb_data, int i_nb_pes,
size_t i_buffer_size, int i_read_once )
{
unsigned int i_loop;
netlist_t * p_netlist;
unsigned int i_loop;
dvd_netlist_t * p_netlist;
/* First we allocate and initialise our netlist struct */
p_input->p_method_data = malloc(sizeof(netlist_t));
if ( p_input->p_method_data == NULL )
p_netlist = malloc( sizeof(dvd_netlist_t) );
if ( p_netlist == NULL )
{
intf_ErrMsg("Unable to malloc the DVD netlist struct");
return (-1);
free( p_netlist );
return NULL;
}
p_netlist = (netlist_t *) p_input->p_method_data;
/* Nb of packets read once by input */
p_netlist->i_read_once = i_read_once;
......@@ -89,7 +87,9 @@ int DVDNetlistInit( input_thread_t * p_input,
if ( p_netlist->p_buffers == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (1)");
return (-1);
free( p_netlist->p_buffers );
free( p_netlist );
return NULL;
}
/* table of pointers to data packets */
......@@ -97,7 +97,10 @@ int DVDNetlistInit( input_thread_t * p_input,
if ( p_netlist->p_data == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (2)");
return (-1);
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist );
return NULL;
}
/* table of pointer to PES packets */
......@@ -105,7 +108,11 @@ int DVDNetlistInit( input_thread_t * p_input,
if ( p_netlist->p_pes == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (3)");
return (-1);
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist );
return NULL;
}
/* allocate the FIFOs : tables of free pointers */
......@@ -114,12 +121,25 @@ int DVDNetlistInit( input_thread_t * p_input,
if ( p_netlist->pp_free_data == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (4)");
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist->pp_free_data );
free( p_netlist );
return NULL;
}
p_netlist->pp_free_pes =
malloc( i_nb_pes *sizeof(pes_packet_t *) );
if ( p_netlist->pp_free_pes == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (5)");
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist->pp_free_data );
free( p_netlist->pp_free_pes );
free( p_netlist );
return NULL;
}
p_netlist->p_free_iovec =
......@@ -127,6 +147,14 @@ int DVDNetlistInit( input_thread_t * p_input,
if ( p_netlist->p_free_iovec == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (6)");
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist->pp_free_data );
free( p_netlist->pp_free_pes );
free( p_netlist->p_free_iovec );
free( p_netlist );
return NULL;
}
/* table for reference counter of iovecs */
......@@ -134,7 +162,15 @@ int DVDNetlistInit( input_thread_t * p_input,
if ( p_netlist->pi_refcount == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (7)");
return (-1);
free( p_netlist->p_buffers );
free( p_netlist->p_data );
free( p_netlist->p_pes );
free( p_netlist->pp_free_data );
free( p_netlist->pp_free_pes );
free( p_netlist->p_free_iovec );
free( p_netlist->pi_refcount );
free( p_netlist );
return NULL;
}
/* Fill the data FIFO */
......@@ -183,7 +219,7 @@ int DVDNetlistInit( input_thread_t * p_input,
p_netlist->i_nb_pes = i_nb_pes - 1;
p_netlist->i_buffer_size = i_buffer_size;
return (0); /* Everything went all right */
return p_netlist; /* Everything went all right */
}
/*****************************************************************************
......@@ -195,10 +231,10 @@ int DVDNetlistInit( input_thread_t * p_input,
*****************************************************************************/
struct iovec * DVDGetiovec( void * p_method_data )
{
netlist_t * p_netlist;
dvd_netlist_t * p_netlist;
/* cast */
p_netlist = ( netlist_t * ) p_method_data;
p_netlist = (dvd_netlist_t *)p_method_data;
/* check */
if( (
......@@ -236,11 +272,11 @@ struct iovec * DVDGetiovec( void * p_method_data )
void DVDMviovec( void * p_method_data, int i_nb_iovec,
struct data_packet_s ** pp_data )
{
netlist_t * p_netlist;
unsigned int i_loop = 0;
dvd_netlist_t * p_netlist;
unsigned int i_loop = 0;
/* cast */
p_netlist = (netlist_t *)p_method_data;
p_netlist = (dvd_netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock( &p_netlist->lock );
......@@ -275,11 +311,11 @@ void DVDMviovec( void * p_method_data, int i_nb_iovec,
*****************************************************************************/
struct data_packet_s * DVDNewPtr( void * p_method_data )
{
netlist_t * p_netlist;
struct data_packet_s * p_return;
dvd_netlist_t * p_netlist;
struct data_packet_s * p_return;
/* cast */
p_netlist = ( netlist_t * ) p_method_data;
p_netlist = (dvd_netlist_t *)p_method_data;
#ifdef DEBUG
if( i_buffer_size > p_netlist->i_buffer_size )
......@@ -318,11 +354,11 @@ struct data_packet_s * DVDNewPtr( void * p_method_data )
struct data_packet_s * DVDNewPacket( void * p_method_data,
size_t i_buffer_size )
{
netlist_t * p_netlist;
dvd_netlist_t * p_netlist;
struct data_packet_s * p_packet;
/* cast */
p_netlist = (netlist_t *)p_method_data;
p_netlist = (dvd_netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock( &p_netlist->lock );
......@@ -371,11 +407,11 @@ struct data_packet_s * DVDNewPacket( void * p_method_data,
*****************************************************************************/
struct pes_packet_s * DVDNewPES( void * p_method_data )
{
netlist_t * p_netlist;
pes_packet_t * p_return;
dvd_netlist_t * p_netlist;
pes_packet_t * p_return;
/* cast */
p_netlist = (netlist_t *) p_method_data;
p_netlist = (dvd_netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
......@@ -410,10 +446,10 @@ struct pes_packet_s * DVDNewPES( void * p_method_data )
*****************************************************************************/
void DVDDeletePacket( void * p_method_data, data_packet_t * p_data )
{
netlist_t * p_netlist;
dvd_netlist_t * p_netlist;
/* cast */
p_netlist = (netlist_t *) p_method_data;
p_netlist = (dvd_netlist_t *) p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
......@@ -450,11 +486,12 @@ void DVDDeletePacket( void * p_method_data, data_packet_t * p_data )
*****************************************************************************/
void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes )
{
netlist_t * p_netlist;
data_packet_t * p_current_packet,* p_next_packet;
dvd_netlist_t * p_netlist;
data_packet_t * p_current_packet;
data_packet_t * p_next_packet;
/* cast */
p_netlist = (netlist_t *)p_method_data;
p_netlist = (dvd_netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
......@@ -502,24 +539,19 @@ void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes )
/*****************************************************************************
* DVDNetlistEnd: frees all allocated structures
*****************************************************************************/
void DVDNetlistEnd( input_thread_t * p_input)
void DVDNetlistEnd( dvd_netlist_t * p_netlist )
{
netlist_t * p_netlist;
/* cast */
p_netlist = ( netlist_t * ) p_input->p_method_data;
/* destroy the mutex lock */
vlc_mutex_destroy (&p_netlist->lock);
vlc_mutex_destroy( &p_netlist->lock );
/* free the FIFO, the buffer, and the netlist structure */
free (p_netlist->pp_free_data);
free (p_netlist->pp_free_pes);
free (p_netlist->pi_refcount);
free (p_netlist->p_pes);
free (p_netlist->p_data);
free (p_netlist->p_buffers);
free( p_netlist->pp_free_data );
free( p_netlist->pp_free_pes );
free( p_netlist->pi_refcount );
free( p_netlist->p_pes );
free( p_netlist->p_data );
free( p_netlist->p_buffers );
/* free the netlist */
free (p_netlist);
free( p_netlist );
}
......@@ -2,7 +2,7 @@
* dvd_netlist.h: Specific netlist structures for DVD packets
*****************************************************************************
* Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
* $Id: dvd_netlist.h,v 1.1 2001/03/02 03:32:46 stef Exp $
* $Id: dvd_netlist.h,v 1.2 2001/03/03 07:07:01 stef Exp $
*
* Authors: Henri Fallon <henri@videolan.org>
* Stphane Borel <stef@videolan.org>
......@@ -25,7 +25,7 @@
/*****************************************************************************
* netlist_t: structure to manage a netlist
*****************************************************************************/
typedef struct netlist_s
typedef struct dvd_netlist_s
{
vlc_mutex_t lock;
......@@ -57,14 +57,12 @@ typedef struct netlist_s
/* Nb of packets read once */
unsigned int i_read_once;
} netlist_t;
} dvd_netlist_t;
/*****************************************************************************
* Prototypes
*****************************************************************************/
int DVDNetlistInit( struct input_thread_s *,
int , int, int, size_t, int );
struct dvd_netlist_s * DVDNetlistInit( int , int, int, size_t, int );
struct iovec * DVDGetiovec( void * p_method_data );
void DVDMviovec( void * , int, struct data_packet_s **);
struct data_packet_s * DVDNewPtr( void * );
......@@ -72,4 +70,4 @@ struct data_packet_s * DVDNewPacket( void *, size_t );
struct pes_packet_s * DVDNewPES( void * );
void DVDDeletePacket( void *, struct data_packet_s * );
void DVDDeletePES( void *, struct pes_packet_s * );
void DVDNetlistEnd( struct input_thread_s * );
void DVDNetlistEnd( struct dvd_netlist_s * );
......@@ -10,7 +10,7 @@
* -dvd_udf to find files
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.24 2001/03/02 13:49:37 massiot Exp $
* $Id: input_dvd.c,v 1.25 2001/03/03 07:07:01 stef Exp $
*