[vlc-devel] [RFC] VLC and CSA encryption/decryption

Georgi Chorbadzhiyski gf at unixsol.org
Fri Apr 6 12:08:12 CEST 2012


I was adding support for constant code word decryption in tsdecrypt [1] and tried
to test it using VLC [2] to encrypt an audio stream (video was left not encrypted).
I was very surprised to see that the decryption was not working. When i started
digging it turns out that CSA encrypted stream with VLC, can not be decoded by
libdvbcsa.

I thought it was a problem with key setup in the VLC code (modules/mux/mpeg/csa.c)
and to confirm my suspicion I patched csa.c to use libdvbcsa. With the attached patch
the decryption with tsdecrypt started working.

This poses a problem. Currently CSA encrypted streams with VLC can be decoded with
VLC but not libdvbcsa (i suspect decryption will have the same problem VLC<->VLC - works,
libdvbcsa<->VLC - don't work). But if VLC is patched to use libdvbcsa (or fixed to
setup the CSA key like libdvbcsa), older VLC versions will not be able to decrypt
the streams.

I don't know what the correct solution is.

Anyway the attached patch is just a quick hack (no configure support, current csa
code is just commented out) but it works in the sense that libdvbcsa is able to
decrypt VLC generated CSA encrypted stream.

What I have tested:

Run vlc to encrypt audio stream (reads from 239.1.1.1:4000 outputs to 239.1.1.1:5000):
  vlc \
    -I dummy -v \
    --sout '#standard{access=udp,mux=ts,dst=239.1.1.1:5000}' \
    --no-sout-ts-crypt-video \
    --sout-ts-crypt-audio \
    --sout-ts-csa-ck=1234567890123456 \
    --sout-ts-csa2-ck=abcdefabcdefabcd \
    udp://@239.1.1.1:4000/

Install tsdecrypt:
  git clone git://github.com/gfto/tsdecrypt.git
  cd tsdecrypt
  git submodule init
  git submodule update
  make

and run it (reads from 239.1.1.1:5000 outputs to 239.1.1.1:6000):
  ./tsdecrypt --input 239.1.1.1:5000 --output 239.1.1.1:6000 --const-cw 1234567890123456abcdefabcdefabcd

You should be able to open udp://@239.1.1.1:6000/ and watch and listen to the
audio stream in case the VLC is patched or view only the video in case VLC is
not patched.

[1]: https://github.com/gfto/tsdecrypt
[2]: VLC version 2.1.0-git Rincewind (1.3.0-git-2035-g2f35b87)

-- 
Georgi Chorbadzhiyski
http://georgi.unixsol.org/
-------------- next part --------------
From 8da11b38907062cc4a718f0b72e53629931d6f40 Mon Sep 17 00:00:00 2001
From: Georgi Chorbadzhiyski <gf at unixsol.org>
Date: Fri, 6 Apr 2012 12:42:49 +0300
Subject: [PATCH] Use libdvbcsa for csa encryption and decryption.

---
 modules/mux/Modules.am |    2 +-
 modules/mux/mpeg/csa.c |   29 ++++++++++++++++++++++++++++-
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/modules/mux/Modules.am b/modules/mux/Modules.am
index b166cf3..c75a86f 100644
--- a/modules/mux/Modules.am
+++ b/modules/mux/Modules.am
@@ -21,7 +21,7 @@ libmux_ts_plugin_la_SOURCES = \
 	mpeg/csa.c mpeg/csa.h \
 	mpeg/ts.c mpeg/bits.h
 libmux_ts_plugin_la_CFLAGS = $(AM_CFLAGS) $(DVBPSI_CFLAGS)
-libmux_ts_plugin_la_LIBADD = $(AM_LIBADD) $(DVBPSI_LIBS)
+libmux_ts_plugin_la_LIBADD = $(AM_LIBADD) $(DVBPSI_LIBS) -ldvbcsa
 libmux_ts_plugin_la_DEPENDENCIES =
 if HAVE_DVBPSI
 libvlc_LTLIBRARIES += libmux_ts_plugin.la
diff --git a/modules/mux/mpeg/csa.c b/modules/mux/mpeg/csa.c
index b1381a8..29e8399 100644
--- a/modules/mux/mpeg/csa.c
+++ b/modules/mux/mpeg/csa.c
@@ -26,6 +26,8 @@
 # include "config.h"
 #endif
 
+#include <dvbcsa/dvbcsa.h>
+
 #include <vlc_common.h>
 
 #include "csa.h"
@@ -36,6 +38,9 @@ struct csa_t
     uint8_t o_ck[8];
     uint8_t e_ck[8];
 
+    struct dvbcsa_key_s *dcsa_o;
+    struct dvbcsa_key_s *dcsa_e;
+
     uint8_t o_kk[57];
     uint8_t e_kk[57];
 
@@ -61,7 +66,12 @@ static void csa_BlockCypher( uint8_t kk[57], uint8_t bd[8], uint8_t ib[8] );
  *****************************************************************************/
 csa_t *csa_New( void )
 {
-    return calloc( 1, sizeof( csa_t ) );
+    csa_t *csa = calloc( 1, sizeof( csa_t ) );
+    if ( csa ) {
+        csa->dcsa_o = dvbcsa_key_alloc();
+        csa->dcsa_e = dvbcsa_key_alloc();
+    }
+    return csa;
 }
 
 /*****************************************************************************
@@ -69,6 +79,9 @@ csa_t *csa_New( void )
  *****************************************************************************/
 void csa_Delete( csa_t *c )
 {
+    dvbcsa_key_free( c->dcsa_o );
+    dvbcsa_key_free( c->dcsa_e );
+
     free( c );
 }
 
@@ -111,11 +124,13 @@ int csa_SetCW( vlc_object_t *p_caller, csa_t *c, char *psz_ck, bool set_odd )
         {
             memcpy( c->o_ck, ck, 8 );
             csa_ComputeKey( c->o_kk, ck );
+            dvbcsa_key_set( c->o_ck, c->dcsa_o );
         }
         else
         {
             memcpy( c->e_ck , ck, 8 );
             csa_ComputeKey( c->e_kk , ck );
+            dvbcsa_key_set( c->e_ck, c->dcsa_e );
         }
         return VLC_SUCCESS;
     }
@@ -142,6 +157,7 @@ void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
 {
     uint8_t *ck;
     uint8_t *kk;
+    struct dvbcsa_key_s *dcsa;
 
     uint8_t  ib[8], stream[8], block[8];
 
@@ -158,11 +174,13 @@ void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
     {
         ck = c->o_ck;
         kk = c->o_kk;
+        dcsa = c->dcsa_o;
     }
     else
     {
         ck = c->e_ck;
         kk = c->e_kk;
+        dcsa = c->dcsa_e;
     }
 
     /* clear transport scrambling control */
@@ -178,6 +196,9 @@ void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
     if( 188 - i_hdr < 8 )
         return;
 
+    dvbcsa_decrypt(dcsa, &pkt[i_hdr], 188 - i_hdr);
+    return;
+
     /* init csa state */
     csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
 
@@ -231,6 +252,7 @@ void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
 {
     uint8_t *ck;
     uint8_t *kk;
+    struct dvbcsa_key_s *dcsa;
 
     int i, j;
     int i_hdr = 4; /* hdr len */
@@ -245,11 +267,13 @@ void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
         pkt[3] |= 0x40;
         ck = c->o_ck;
         kk = c->o_kk;
+        dcsa = c->dcsa_o;
     }
     else
     {
         ck = c->e_ck;
         kk = c->e_kk;
+        dcsa = c->dcsa_e;
     }
 
     /* hdr len */
@@ -268,6 +292,9 @@ void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
         return;
     }
 
+    dvbcsa_encrypt(dcsa, &pkt[i_hdr], 188 - i_hdr);
+    return;
+
     /* */
     for( i = 0; i < 8; i++ )
     {
-- 
1.7.5.1



More information about the vlc-devel mailing list