Compute corrent payload start for APDU in dst_ca

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Attached is a patch that fixes a slight issue in dst_ca. If an APDU length is greater than 127 the length field spans 2 bytes. However in dst_ca this was not being calculated and just assumed that the length field was only one byte long.

I came across this when trying to decrypt some Canal+ channels. The ca pmt length was originally greater than 256. As APDU chaining wasn't implemented I ended modifying vlc to strip out some of the un-encrypted elementary streams, just leaving video and audio, which brought the length below 256 but above 127. With this patch it now happily decrypts the channels.

Where is APDU chaining supposed to be implemented, in the kernel driver or in the application? VDR seems to currently implement APDU chaining but VLC doesn't.

Mike

p.s. The hauppauge NOVS-S CI card works fine (the driver handled it correctly) it was only on a Twinhan S CI card that it failed.
diff -urN v4l-dvb.orig/linux/drivers/media/dvb/bt8xx/dst_ca.c v4l-dvb/linux/drivers/media/dvb/bt8xx/dst_ca.c
--- v4l-dvb.orig/linux/drivers/media/dvb/bt8xx/dst_ca.c	2006-12-12 15:18:53.000000000 +0000
+++ v4l-dvb/linux/drivers/media/dvb/bt8xx/dst_ca.c	2006-12-12 15:17:48.000000000 +0000
@@ -344,6 +344,19 @@
 	return 0;
 }
 
+static u8 ca_payload_start(struct ca_msg *p_ca_message)
+{
+	//first 3 bytes are the tag plus 1 for size indicator and length value
+	u8 payload_start = 4;
+	
+	//if the size indicator is set add the length field size to the payload start
+	if (p_ca_message->msg[3] & 0x80) {
+		payload_start += p_ca_message->msg[3] & 0x7f;
+	}
+
+	return payload_start;
+}
+
 static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
 {
 	if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
@@ -362,11 +375,7 @@
 		hw_buffer->msg[5] = length & 0xff;
 		hw_buffer->msg[6] = 0x00;
 
-		/*
-		 *	Need to compute length for EN50221 section 8.3.2, for the time being
-		 *	assuming 8.3.2 is not applicable
-		 */
-		memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
+		memcpy(&hw_buffer->msg[7], &p_ca_message->msg[ca_payload_start(p_ca_message)], length);
 	}
 
 	return 0;
@@ -522,7 +531,7 @@
 
 	length = asn_1_decode(&p_ca_message->msg[3]);
 	dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length);
-	debug_string(&p_ca_message->msg[4], length, 0); /*	length is excluding tag & length	*/
+	debug_string(&p_ca_message->msg[ca_payload_start(p_ca_message)], length, 0); /*	length is excluding tag & length	*/
 
 	memset(hw_buffer->msg, '\0', length);
 	handle_dst_tag(state, p_ca_message, hw_buffer, length);
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux