[libdvdcss-devel] [Git][videolan/libdvdcss][master] 6 commits: CPXM: convert to pointer type for persistence
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Sat Dec 20 14:16:56 UTC 2025
Jean-Baptiste Kempf pushed to branch master at VideoLAN / libdvdcss
Commits:
099e6384 by Saifelden Mohamed Ismail at 2025-12-20T14:15:51+02:00
CPXM: convert to pointer type for persistence
- - - - -
b926bfd7 by Saifelden Mohamed Ismail at 2025-12-20T14:15:54+02:00
CPXM: give default value for cpxm_was_cached
- - - - -
be3c8eee by Saifelden Mohamed Ismail at 2025-12-20T14:15:54+02:00
CPXM: Add flag for lazy_init check
- - - - -
bd76db71 by Saifelden Mohamed Ismail at 2025-12-20T14:16:29+02:00
CPXM: Make dvdcpxm_init lazy-initialize once
- - - - -
5337002f by Saifelden Mohamed Ismail at 2025-12-20T14:16:30+02:00
CPXM: merge dvdcss_close and dvdcpxm_close
- - - - -
aec7fd48 by Saifelden Mohamed Ismail at 2025-12-20T14:16:30+02:00
CPXM: alias dvdcpxm_close and dvdcpxm_seek
- - - - -
6 changed files:
- src/cpxm.c
- src/cpxm.h
- src/libdvdcpxm.c
- src/libdvdcpxm.h
- src/libdvdcss.c
- src/libdvdcss.h
Changes:
=====================================
src/cpxm.c
=====================================
@@ -73,7 +73,7 @@ int cppm_set_id_album( dvdcss_t dvdcss )
p_buffer[i] ^= dvdcss->css.p_bus_key[4 - (i % DVD_KEY_SIZE)];
}
- READ64_BE( dvdcss->cpxm.id_album, &p_buffer[80] );
+ READ64_BE( dvdcss->cpxm->id_album, &p_buffer[80] );
return 0;
}
@@ -92,7 +92,7 @@ int cprm_set_id_media( dvdcss_t dvdcss )
if( ioctl_ReadCPRMMediaId( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) )
return -1;
- READ64_BE( dvdcss->cpxm.id_media,
+ READ64_BE( dvdcss->cpxm->id_media,
p_buffer + offsetof(cprm_media_id_t, id_media)
);
=====================================
src/cpxm.h
=====================================
@@ -51,7 +51,10 @@ typedef struct cpxm
uint64_t id_album;
uint64_t id_media;
uint64_t vr_k_te;
-} cpxm;
+} cpxm_s;
+
+/* for persistance */
+typedef cpxm_s* p_cpxm;
/* cpxm uses the same css authentification method when using a usb dvd drive */
int cppm_set_id_album( dvdcss_t dvdcss );
=====================================
src/libdvdcpxm.c
=====================================
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include "cpxm.h"
#include "dvdcss/dvdcpxm.h"
@@ -49,6 +50,14 @@
#define IS_SYNC_CODE(word) \
( (word)[0] == 0x00 && (word)[1] == 0x00 && (word)[2] == 0x01 && (word)[3] == 0xBA )
+typedef struct cpxm_cache {
+ p_cpxm cpxm;
+ dev_t st_dev;
+ struct cpxm_cache * p_next;
+} cpxm_cache;
+
+cpxm_cache *g_cpxm_cache = NULL;
+
/* these values are used by libdvdcpxm to process the Media Key Block */
/* They are present inside DVD-Audio players and are used in conjunction with keys taken from the disc in order to generate the final media_key used by the C2 Cypher */
uint32_t sbox_f[256];
@@ -486,7 +495,7 @@ int process_mkb( uint8_t *p_mkb, device_key_t *p_dev_keys, int nr_dev_keys, uint
return -1;
}
-int vr_get_k_te( cpxm cpxm,char *psz_vr_mangr )
+int vr_get_k_te( p_cpxm cpxm,char *psz_vr_mangr )
{
FILE *f_vr_m;
uint8_t vmgi_mat[512];
@@ -501,11 +510,11 @@ int vr_get_k_te( cpxm cpxm,char *psz_vr_mangr )
{
if ( memcmp( vmgi_mat, "DVD_RTR_VMG0", 12 ) == 0 )
{
- cpxm.vr_k_te = 0;
+ cpxm->vr_k_te = 0;
if ( vmgi_mat[267] & 1 ) /* Check encrypted title key status bit */
{
- memcpy( &cpxm.vr_k_te, &vmgi_mat[268], sizeof( cpxm.vr_k_te ) );
- B2N_64( cpxm.vr_k_te );
+ memcpy( &cpxm->vr_k_te, &vmgi_mat[268], sizeof( cpxm->vr_k_te ) );
+ B2N_64( cpxm->vr_k_te );
}
ret = 0;
}
@@ -521,6 +530,32 @@ LIBDVDCSS_EXPORT int dvdcpxm_init( dvdcss_t dvdcss, uint8_t *p_mkb )
{
/* In the case that p_mkb is received as null, then either you were unable
* to read the mkb or the encryption type is cprm */
+ /* if no file mkb file is passed, check cache */
+ if (!p_mkb)
+ {
+ cpxm_cache *cpxm_iterator = g_cpxm_cache;
+ struct stat file_stat;
+ fstat( dvdcss->i_fd, &file_stat );
+ while ( cpxm_iterator != NULL )
+ {
+ /* look for match in cache */
+ if ( file_stat.st_dev == cpxm_iterator->st_dev )
+ {
+ dvdcss->cpxm = cpxm_iterator->cpxm;
+ dvdcss->cpxm_was_cached = 0;
+ return dvdcss->media_type;
+ }
+ cpxm_iterator = cpxm_iterator->p_next;
+ }
+ return -1;
+ }
+
+ p_cpxm cpxm = malloc(sizeof(cpxm_s));
+ if (!cpxm)
+ return -1;
+
+ dvdcss->cpxm = cpxm;
+
char psz_file[PATH_MAX];
int ret = -1;
@@ -537,7 +572,7 @@ LIBDVDCSS_EXPORT int dvdcpxm_init( dvdcss_t dvdcss, uint8_t *p_mkb )
{
ret = process_mkb( p_mkb, cppm_device_keys,
sizeof(cppm_device_keys) / sizeof(*cppm_device_keys),
- &dvdcss->cpxm.media_key );
+ &dvdcss->cpxm->media_key );
free(p_mkb);
if (ret) break;
}
@@ -551,7 +586,7 @@ LIBDVDCSS_EXPORT int dvdcpxm_init( dvdcss_t dvdcss, uint8_t *p_mkb )
{
ret = process_mkb( p_mkb, cprm_device_keys,
sizeof( cprm_device_keys ) / sizeof( *cprm_device_keys ),
- &dvdcss->cpxm.media_key );
+ &dvdcss->cpxm->media_key );
free( p_mkb );
if (ret) break;
}
@@ -567,6 +602,32 @@ LIBDVDCSS_EXPORT int dvdcpxm_init( dvdcss_t dvdcss, uint8_t *p_mkb )
}
break;
}
+
+ /* store in cache */
+ cpxm_cache* cpxm_cache_addition = malloc(sizeof(cpxm_cache));
+
+ if (!cpxm_cache_addition)
+ return -1;
+
+ struct stat stat;
+ fstat(dvdcss->i_fd, &stat);
+
+ /* create cache node */
+ cpxm_cache_addition->cpxm = dvdcss->cpxm;
+ cpxm_cache_addition->st_dev = stat.st_dev;
+ cpxm_cache_addition->p_next = NULL;
+
+ /* copy over so needs to be set only once */
+ if ( g_cpxm_cache == NULL )
+ g_cpxm_cache = cpxm_cache_addition;
+ else
+ {
+ cpxm_cache *cpxm_iterator = g_cpxm_cache;
+ while ( cpxm_iterator->p_next != NULL )
+ cpxm_iterator = cpxm_iterator->p_next;
+ cpxm_iterator->p_next = cpxm_cache_addition;
+ }
+ dvdcss->cpxm_was_cached = 1;
return dvdcss->media_type;
}
@@ -706,30 +767,66 @@ int cprm_decrypt_block( uint8_t *p_buffer, int flags, uint64_t id_album, uint64_
return encrypted;
}
-int dvdcpxm_decrypt( cpxm cpxm, int media_type,void *p_buffer, int flags )
+int dvdcpxm_decrypt( p_cpxm cpxm, int media_type,void *p_buffer, int flags )
{
switch ( media_type )
{
case COPYRIGHT_PROTECTION_CPPM:
- return cppm_decrypt_block( (uint8_t *) p_buffer, flags, cpxm.id_album, cpxm.media_key );
+ return cppm_decrypt_block( (uint8_t *) p_buffer, flags, cpxm->id_album, cpxm->media_key );
case COPYRIGHT_PROTECTION_CPRM:
- return cprm_decrypt_block( (uint8_t* ) p_buffer, flags, cpxm.id_album ,cpxm.media_key );
+ return cprm_decrypt_block( (uint8_t* ) p_buffer, flags, cpxm->id_album ,cpxm->media_key );
}
return 0;
}
+/* this function is used internally */
+int dvdcpxm_close_internal ( dvdcss_t dvdcss )
+{
+ if( dvdcss->cpxm )
+ free( dvdcss->cpxm );
+
+ if ( !g_cpxm_cache )
+ return 0;
+
+ /* check ID */
+ struct stat stat;
+ if ( fstat( dvdcss->i_fd, &stat ) < 0 )
+ return -1;
+
+ cpxm_cache *prev = NULL;
+ cpxm_cache *cpxm_iterator = g_cpxm_cache;
+
+ /* remove only if cached */
+ while ( cpxm_iterator != NULL && dvdcss->cpxm_was_cached )
+ {
+ cpxm_cache *next = cpxm_iterator->p_next;
+ if ( cpxm_iterator->st_dev == stat.st_dev )
+ {
+ if ( prev == NULL )
+ g_cpxm_cache = next;
+ else
+ prev->p_next = next;
+
+ free( cpxm_iterator->cpxm );
+ free( cpxm_iterator );
+ break;
+ }
+ else
+ prev = cpxm_iterator;
+
+ cpxm_iterator = next;
+ }
+ return 0;
+}
+
/* CPXM exported prototype definitions */
/* these methods should behave similarily but use dvdcpxm_decrypt instead of unscramble, and remove any unnecessary code */
+
+/* aliased dvdcpxm_close to not break ABI */
int dvdcpxm_close ( dvdcss_t dvdcss )
{
- int i_ret;
- i_ret = dvdcss_close_device( dvdcss );
-
- free( dvdcss->psz_device );
- free( dvdcss );
-
- return i_ret;
+ return dvdcss_close( dvdcss );
}
int dvdcpxm_read ( dvdcss_t dvdcss, void *p_buffer,
@@ -758,8 +855,7 @@ int dvdcpxm_read ( dvdcss_t dvdcss, void *p_buffer,
int dvdcpxm_seek ( dvdcss_t dvdcss, int i_blocks, int i_flags )
{
- (void)i_flags;
- return dvdcss->pf_seek( dvdcss, i_blocks );
+ dvdcss_seek( dvdcss, i_blocks, DVDCSS_NOFLAGS );
}
int dvdcpxm_readv ( dvdcss_t dvdcss, void *p_iovec,
=====================================
src/libdvdcpxm.h
=====================================
@@ -83,4 +83,7 @@ typedef struct
uint8_t mkb[CPRM_MKB_SIZE];
} cprm_mkb_t;
+/* used to clear dvdcpxm structures, including cache */
+int dvdcpxm_close_internal ( dvdcss_t );
+
#endif
=====================================
src/libdvdcss.c
=====================================
@@ -96,6 +96,7 @@
* Preamble
*/
#include "config.h"
+#include "libdvdcpxm.h"
#include <limits.h>
#include <stdio.h>
@@ -553,6 +554,9 @@ static dvdcss_t dvdcss_open_common ( const char *psz_target, void *p_stream,
dvdcss->p_stream = p_stream;
dvdcss->p_stream_cb = p_stream_cb;
+ dvdcss->cpxm = NULL;
+ dvdcss->cpxm_was_cached = 0;
+
/* Set library verbosity from DVDCSS_VERBOSE environment variable. */
set_verbosity( dvdcss );
@@ -849,6 +853,10 @@ LIBDVDCSS_EXPORT int dvdcss_close ( dvdcss_t dvdcss )
i_ret = dvdcss_close_device( dvdcss );
free( dvdcss->psz_device );
+
+ /* close cpxm related structures if they were used */
+ dvdcpxm_close_internal( dvdcss );
+
free( dvdcss );
return i_ret;
=====================================
src/libdvdcss.h
=====================================
@@ -76,7 +76,10 @@ struct dvdcss_s
int b_debug;
/* struct to be used only internally in CPXM */
- struct cpxm cpxm;
+ p_cpxm cpxm;
+ /* to check if this was cached, or if it was copied from cache */
+ /* will use to check if disc is being closed or if it's just a file */
+ int cpxm_was_cached;
/* i_copyright read from ioctl_copyright used by cpxm to determine type of encryption */
/* 0 - None, 1 - CPPM, 2 - CPRM */
View it on GitLab: https://code.videolan.org/videolan/libdvdcss/-/compare/4b940751fbbc9ca1d0631b21f0bcad56ca0376d9...aec7fd4847f123138ca024760aa28401384ecd6b
--
View it on GitLab: https://code.videolan.org/videolan/libdvdcss/-/compare/4b940751fbbc9ca1d0631b21f0bcad56ca0376d9...aec7fd4847f123138ca024760aa28401384ecd6b
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the libdvdcss-devel
mailing list