From 2e69227b2dba26d14589acdfc9a4667ec01a9383 Mon Sep 17 00:00:00 2001 From: Catalin Toda Date: Fri, 6 Jan 2023 18:47:11 -0800 Subject: [PATCH] Add manipulation of the CW based on ECM indo --- src/dvbcsa/dvbcsa.h | 2 ++ src/dvbcsa_bs_key.c | 36 ++++++++++++++++++++++++++++++++++ src/dvbcsa_key.c | 15 ++++++++++++++ src/dvbcsa_pv.h | 48 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) diff --git a/src/dvbcsa/dvbcsa.h b/src/dvbcsa/dvbcsa.h index c7e9c59..b63fb7d 100644 --- a/src/dvbcsa/dvbcsa.h +++ b/src/dvbcsa/dvbcsa.h @@ -93,6 +93,8 @@ void dvbcsa_bs_key_free(struct dvbcsa_bs_key_s *key); void dvbcsa_bs_key_set(const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key); +void dvbcsa_bs_key_set_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key); + /** get maximum number of packet per batch */ unsigned int dvbcsa_bs_batch_size(void); diff --git a/src/dvbcsa_bs_key.c b/src/dvbcsa_bs_key.c index e2fcf55..d703325 100644 --- a/src/dvbcsa_bs_key.c +++ b/src/dvbcsa_bs_key.c @@ -63,3 +63,39 @@ dvbcsa_bs_key_set (const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key) } } +void +dvbcsa_bs_key_set_ecm (const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key) +{ + dvbcsa_keys_t kk; + int i; + + /* precalculations for stream */ + + uint64_t ck = dvbcsa_load_le64(cw); + + for (i = 0; i < DVBCSA_CWBITS_SIZE; i++) + key->stream[i] = (ck >> (i^4)) & 1 ? BS_VAL8(ff) : BS_VAL8(00); + + /* precalculations for block */ + + dvbcsa_key_schedule_block_ecm(ecm, cw, kk); + + for (i = 0; i < DVBCSA_KEYSBUFF_SIZE; i++) + { +#if BS_BATCH_SIZE == 32 + *(dvbcsa_u32_aliasing_t *)(key->block + i) = kk[i] * 0x01010101; + +#elif BS_BATCH_SIZE == 64 + *(dvbcsa_u64_aliasing_t *)(key->block + i) = kk[i] * 0x0101010101010101ULL; + +#elif BS_BATCH_SIZE > 64 && BS_BATCH_SIZE % 64 == 0 + uint64_t v = kk[i] * 0x0101010101010101ULL; + int j; + + for (j = 0; j < BS_BATCH_BYTES / 8; j++) + *((dvbcsa_u64_aliasing_t *)(key->block + i) + j) = v; +#else +# error +#endif + } +} diff --git a/src/dvbcsa_key.c b/src/dvbcsa_key.c index 1ff17e0..bd2a2c1 100644 --- a/src/dvbcsa_key.c +++ b/src/dvbcsa_key.c @@ -585,3 +585,18 @@ dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk) kk[i*8+j] = (k[i]>>(j*8)) ^ i; } +void +dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk) +{ + uint64_t k[7]; + int i, j; + + k[6] = dvbcsa_load_le64_ecm(ecm, cw); + for (i = 6; i > 0; i--) + k[i - 1] = dvbcsa_key_permute_block(k[i]); + + for (i = 0; i < 7; i++) + for (j = 0; j < 8; j++) + kk[i*8+j] = (k[i]>>(j*8)) ^ i; +} + diff --git a/src/dvbcsa_pv.h b/src/dvbcsa_pv.h index 83753b1..e59a70d 100644 --- a/src/dvbcsa_pv.h +++ b/src/dvbcsa_pv.h @@ -88,6 +88,26 @@ struct dvbcsa_key_s extern const uint8_t dvbcsa_block_sbox[256]; +static const uint8_t csa_block_perm_ecm[256] = + { + 0x00,0x02,0x80,0x82,0x20,0x22,0xa0,0xa2, 0x04,0x06,0x84,0x86,0x24,0x26,0xa4,0xa6, + 0x40,0x42,0xc0,0xc2,0x60,0x62,0xe0,0xe2, 0x44,0x46,0xc4,0xc6,0x64,0x66,0xe4,0xe6, + 0x01,0x03,0x81,0x83,0x21,0x23,0xa1,0xa3, 0x05,0x07,0x85,0x87,0x25,0x27,0xa5,0xa7, + 0x41,0x43,0xc1,0xc3,0x61,0x63,0xe1,0xe3, 0x45,0x47,0xc5,0xc7,0x65,0x67,0xe5,0xe7, + 0x08,0x0a,0x88,0x8a,0x28,0x2a,0xa8,0xaa, 0x0c,0x0e,0x8c,0x8e,0x2c,0x2e,0xac,0xae, + 0x48,0x4a,0xc8,0xca,0x68,0x6a,0xe8,0xea, 0x4c,0x4e,0xcc,0xce,0x6c,0x6e,0xec,0xee, + 0x09,0x0b,0x89,0x8b,0x29,0x2b,0xa9,0xab, 0x0d,0x0f,0x8d,0x8f,0x2d,0x2f,0xad,0xaf, + 0x49,0x4b,0xc9,0xcb,0x69,0x6b,0xe9,0xeb, 0x4d,0x4f,0xcd,0xcf,0x6d,0x6f,0xed,0xef, + 0x10,0x12,0x90,0x92,0x30,0x32,0xb0,0xb2, 0x14,0x16,0x94,0x96,0x34,0x36,0xb4,0xb6, + 0x50,0x52,0xd0,0xd2,0x70,0x72,0xf0,0xf2, 0x54,0x56,0xd4,0xd6,0x74,0x76,0xf4,0xf6, + 0x11,0x13,0x91,0x93,0x31,0x33,0xb1,0xb3, 0x15,0x17,0x95,0x97,0x35,0x37,0xb5,0xb7, + 0x51,0x53,0xd1,0xd3,0x71,0x73,0xf1,0xf3, 0x55,0x57,0xd5,0xd7,0x75,0x77,0xf5,0xf7, + 0x18,0x1a,0x98,0x9a,0x38,0x3a,0xb8,0xba, 0x1c,0x1e,0x9c,0x9e,0x3c,0x3e,0xbc,0xbe, + 0x58,0x5a,0xd8,0xda,0x78,0x7a,0xf8,0xfa, 0x5c,0x5e,0xdc,0xde,0x7c,0x7e,0xfc,0xfe, + 0x19,0x1b,0x99,0x9b,0x39,0x3b,0xb9,0xbb, 0x1d,0x1f,0x9d,0x9f,0x3d,0x3f,0xbd,0xbf, + 0x59,0x5b,0xd9,0xdb,0x79,0x7b,0xf9,0xfb, 0x5d,0x5f,0xdd,0xdf,0x7d,0x7f,0xfd,0xff +}; + void dvbcsa_block_decrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out); void dvbcsa_block_encrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out); @@ -95,6 +115,7 @@ void dvbcsa_stream_xor (const dvbcsa_cw_t cw, const dvbcsa_block_t iv, uint8_t *stream, unsigned int len); void dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk); +void dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk); DVBCSA_INLINE static inline void dvbcsa_xor_64 (uint8_t *b, const uint8_t *a) @@ -141,6 +162,33 @@ dvbcsa_load_le64(const uint8_t *p) #endif } +DVBCSA_INLINE static inline uint64_t +dvbcsa_load_le64_ecm(const unsigned char ecm, const uint8_t *p) +{ + dvbcsa_block_t W; + memcpy(W, p, sizeof(W)); + if (ecm == 4) + { + W[0] = csa_block_perm_ecm[p[0]]; + W[4] = csa_block_perm_ecm[p[4]]; + } +#if defined(DVBCSA_ENDIAN_LITTLE) + uint64_t i; + memcpy(&i, W, 8); + return i; +#else + return (uint64_t)( ((uint64_t)W[7] << 56) | + ((uint64_t)W[6] << 48) | + ((uint64_t)W[5] << 40) | + ((uint64_t)W[4] << 32) | + ((uint64_t)W[3] << 24) | + ((uint64_t)W[2] << 16) | + ((uint64_t)W[1] << 8 ) | + (uint64_t)W[0] + ); +#endif +} + DVBCSA_INLINE static inline void dvbcsa_store_le64(uint8_t *p, const uint64_t w) {