[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