Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/dvbcsa/dvbcsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
36 changes: 36 additions & 0 deletions src/dvbcsa_bs_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
15 changes: 15 additions & 0 deletions src/dvbcsa_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

48 changes: 48 additions & 0 deletions src/dvbcsa_pv.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,34 @@ 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);

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)
Expand Down Expand Up @@ -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)
{
Expand Down