/* This file is part of libdvbcsa. libdvbcsa is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. libdvbcsa is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with libdvbcsa; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (c) 2006-2008 Alexandre Becoulet */ #include "dvbcsa/dvbcsa.h" #include "dvbcsa_pv.h" /* ** Get nibble from A and B 40 bits registers */ #define NBGET(r, n) (r >> (n * 4)) /* ** CSA algorithm is using X, Y, Z, D, E, F 4 bits registers ** and P, Q, C 1 bits registers. these registers are stored ** in `pqzyx' and `cfed' variables to improve speed. */ #define GETX(x) (x) #define GETY(x) ((x) >> 4) #define GETZ(x) ((x) >> 8) #define TSTP(x) ((x) & 0x1000) #define TSTQ(x) ((x) & 0x2000) #define GETD(x) (x) #define GETE(x) ((x) >> 4) #define GETF(x) ((x) >> 8) #define GETC(x) ((x) >> 12) /* ** swap nibbles in byte */ DVBCSA_INLINE static inline uint8_t swap_nbl (register uint8_t byte) { return ((byte >> 4) | (byte << 4)); } /* ** conditional rotation used in stream round */ DVBCSA_INLINE static inline uint8_t csa_stream_rotate (register uint32_t pqzyx, register uint32_t x) { return TSTP(pqzyx) ? ((x << 1) | ((x >> 3) & 1)) & 0xf : x; } /* ** process bit selection, permutation and sboxes */ DVBCSA_INLINE static inline uint32_t csa_stream_sboxes(register uint64_t A) { /* modified sboxes tables */ static const uint16_t sbox[7][32] = { { 0x0001, 0x0000, 0x0400, 0x0400, 0x0001, 0x0401, 0x0401, 0x0000, 0x0401, 0x0001, 0x0001, 0x0000, 0x0400, 0x0400, 0x0000, 0x0401, 0x0000, 0x0401, 0x0401, 0x0000, 0x0001, 0x0001, 0x0400, 0x0400, 0x0001, 0x0001, 0x0000, 0x0401, 0x0400, 0x0400, 0x0401, 0x0000, }, { 0x0802, 0x0800, 0x0002, 0x0800, 0x0802, 0x0002, 0x0002, 0x0800, 0x0800, 0x0802, 0x0000, 0x0002, 0x0000, 0x0000, 0x0000, 0x0802, 0x0802, 0x0800, 0x0800, 0x0002, 0x0002, 0x0802, 0x0800, 0x0802, 0x0000, 0x0000, 0x0000, 0x0802, 0x0800, 0x0002, 0x0002, 0x0000, }, { 0x0010, 0x0000, 0x0010, 0x0010, 0x0010, 0x0014, 0x0000, 0x0004, 0x0004, 0x0014, 0x0014, 0x0014, 0x0014, 0x0000, 0x0004, 0x0000, 0x0014, 0x0000, 0x0004, 0x0010, 0x0004, 0x0014, 0x0014, 0x0004, 0x0000, 0x0004, 0x0000, 0x0004, 0x0010, 0x0000, 0x0010, 0x0010, }, { 0x0028, 0x0008, 0x0020, 0x0028, 0x0020, 0x0000, 0x0020, 0x0008, 0x0008, 0x0020, 0x0000, 0x0008, 0x0000, 0x0028, 0x0028, 0x0000, 0x0008, 0x0000, 0x0028, 0x0008, 0x0028, 0x0020, 0x0028, 0x0000, 0x0000, 0x0028, 0x0020, 0x0000, 0x0020, 0x0008, 0x0008, 0x0020, }, { 0x0100, 0x0000, 0x0000, 0x0040, 0x0140, 0x0100, 0x0140, 0x0100, 0x0140, 0x0140, 0x0000, 0x0040, 0x0100, 0x0040, 0x0040, 0x0000, 0x0140, 0x0100, 0x0000, 0x0100, 0x0140, 0x0000, 0x0040, 0x0040, 0x0100, 0x0140, 0x0000, 0x0040, 0x0100, 0x0000, 0x0040, 0x0140, }, { 0x0000, 0x0080, 0x0200, 0x0280, 0x0080, 0x0200, 0x0200, 0x0000, 0x0000, 0x0080, 0x0280, 0x0000, 0x0200, 0x0280, 0x0080, 0x0280, 0x0200, 0x0280, 0x0000, 0x0200, 0x0280, 0x0000, 0x0080, 0x0080, 0x0200, 0x0080, 0x0080, 0x0200, 0x0000, 0x0280, 0x0280, 0x0000, }, { 0x0000, 0x0000, 0x1000, 0x2000, 0x3000, 0x3000, 0x0000, 0x1000, 0x3000, 0x1000, 0x2000, 0x2000, 0x2000, 0x0000, 0x1000, 0x3000, 0x3000, 0x1000, 0x2000, 0x2000, 0x2000, 0x3000, 0x0000, 0x0000, 0x2000, 0x1000, 0x1000, 0x3000, 0x0000, 0x0000, 0x1000, 0x3000, }, }; uint32_t res; uint64_t t; t = A & 0x2018004200LL; res = sbox[1][ ((t >> 37) ^ (t >> 27) ^ (t >> 25) ^ (t >> 11) ^ (t >> 5)) & 0x1f ]; t = A & 0x4201480000LL; res |= sbox[4][ ((t >> 38) ^ (t >> 32) ^ (t >> 22) ^ (t >> 16) ^ (t >> 18)) & 0x1f ]; t = A & 0x8040122000LL; res |= sbox[5][ ((t >> 39) ^ (t >> 29) ^ (t >> 18) ^ (t >> 14) ^ (t >> 9)) & 0x1f ]; t = A & 0x1082010040LL; res |= sbox[0][ ((t >> 36) ^ (t >> 30) ^ (t >> 23) ^ (t >> 3) ^ (t >> 12)) & 0x1f ]; t = A & 0x0004a00180LL; res |= sbox[2][ ((t >> 26) ^ (t >> 22) ^ (t >> 19) ^ (t >> 5) ^ (t >> 3)) & 0x1f ]; t = A & 0x0100048820LL; res |= sbox[3][ ((t >> 32) ^ (t >> 17) ^ (t >> 9) ^ (t >> 2) ^ (t >> 11)) & 0x1f ]; t = A & 0x0c20001400LL; res |= sbox[6][ ((t >> 35) ^ (t >> 33) ^ (t >> 27) ^ (t >> 9) ^ (t >> 6)) & 0x1f ]; return res; } /* ** bit selection and XOR from B */ DVBCSA_INLINE static inline uint32_t csa_stream_B_sel (register uint64_t B) { uint32_t t = B >> 9; /* 10000000 01000010000000000001000000000000 */ /* 00000010 00000001000001001000000000000000 */ /* 00000100 00000000101000010000000000000000 */ /* 01000001 00001000000000000010000000000000 */ return (((t ) ^ (t >> 27)) & 0x8) ^ (((t >> 18) ) & 0x9) ^ (( (t >> 22) ^ (t >> 7)) & 0x4) ^ (((t >> 4 ) ) & 0x5) ^ (( (t >> 24) ^ (t >> 6) ^ (t >> 11)) & 0x2) ^ (((t >> 29) ^ (t >> 23)) & 0x1) ^ (((t >> 13) ) & 0xe); } /* ** cfed precomputed operations */ DVBCSA_INLINE static inline uint32_t csa_stream_cfed (uint32_t pqzyx, uint32_t cfed) { static const uint16_t csa_stream_cdef[0x400] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, 0x0001, 0x0100, 0x0203, 0x0302, 0x0405, 0x0504, 0x0607, 0x0706, 0x0809, 0x0908, 0x0a0b, 0x0b0a, 0x0c0d, 0x0d0c, 0x0e0f, 0x0f0e, 0x0002, 0x0103, 0x0200, 0x0301, 0x0406, 0x0507, 0x0604, 0x0705, 0x080a, 0x090b, 0x0a08, 0x0b09, 0x0c0e, 0x0d0f, 0x0e0c, 0x0f0d, 0x0003, 0x0102, 0x0201, 0x0300, 0x0407, 0x0506, 0x0605, 0x0704, 0x080b, 0x090a, 0x0a09, 0x0b08, 0x0c0f, 0x0d0e, 0x0e0d, 0x0f0c, 0x0004, 0x0105, 0x0206, 0x0307, 0x0400, 0x0501, 0x0602, 0x0703, 0x080c, 0x090d, 0x0a0e, 0x0b0f, 0x0c08, 0x0d09, 0x0e0a, 0x0f0b, 0x0005, 0x0104, 0x0207, 0x0306, 0x0401, 0x0500, 0x0603, 0x0702, 0x080d, 0x090c, 0x0a0f, 0x0b0e, 0x0c09, 0x0d08, 0x0e0b, 0x0f0a, 0x0006, 0x0107, 0x0204, 0x0305, 0x0402, 0x0503, 0x0600, 0x0701, 0x080e, 0x090f, 0x0a0c, 0x0b0d, 0x0c0a, 0x0d0b, 0x0e08, 0x0f09, 0x0007, 0x0106, 0x0205, 0x0304, 0x0403, 0x0502, 0x0601, 0x0700, 0x080f, 0x090e, 0x0a0d, 0x0b0c, 0x0c0b, 0x0d0a, 0x0e09, 0x0f08, 0x0008, 0x0109, 0x020a, 0x030b, 0x040c, 0x050d, 0x060e, 0x070f, 0x0800, 0x0901, 0x0a02, 0x0b03, 0x0c04, 0x0d05, 0x0e06, 0x0f07, 0x0009, 0x0108, 0x020b, 0x030a, 0x040d, 0x050c, 0x060f, 0x070e, 0x0801, 0x0900, 0x0a03, 0x0b02, 0x0c05, 0x0d04, 0x0e07, 0x0f06, 0x000a, 0x010b, 0x0208, 0x0309, 0x040e, 0x050f, 0x060c, 0x070d, 0x0802, 0x0903, 0x0a00, 0x0b01, 0x0c06, 0x0d07, 0x0e04, 0x0f05, 0x000b, 0x010a, 0x0209, 0x0308, 0x040f, 0x050e, 0x060d, 0x070c, 0x0803, 0x0902, 0x0a01, 0x0b00, 0x0c07, 0x0d06, 0x0e05, 0x0f04, 0x000c, 0x010d, 0x020e, 0x030f, 0x0408, 0x0509, 0x060a, 0x070b, 0x0804, 0x0905, 0x0a06, 0x0b07, 0x0c00, 0x0d01, 0x0e02, 0x0f03, 0x000d, 0x010c, 0x020f, 0x030e, 0x0409, 0x0508, 0x060b, 0x070a, 0x0805, 0x0904, 0x0a07, 0x0b06, 0x0c01, 0x0d00, 0x0e03, 0x0f02, 0x000e, 0x010f, 0x020c, 0x030d, 0x040a, 0x050b, 0x0608, 0x0709, 0x0806, 0x0907, 0x0a04, 0x0b05, 0x0c02, 0x0d03, 0x0e00, 0x0f01, 0x000f, 0x010e, 0x020d, 0x030c, 0x040b, 0x050a, 0x0609, 0x0708, 0x0807, 0x0906, 0x0a05, 0x0b04, 0x0c03, 0x0d02, 0x0e01, 0x0f00, 0x1000, 0x1101, 0x1202, 0x1303, 0x1404, 0x1505, 0x1606, 0x1707, 0x1808, 0x1909, 0x1a0a, 0x1b0b, 0x1c0c, 0x1d0d, 0x1e0e, 0x1f0f, 0x1001, 0x1100, 0x1203, 0x1302, 0x1405, 0x1504, 0x1607, 0x1706, 0x1809, 0x1908, 0x1a0b, 0x1b0a, 0x1c0d, 0x1d0c, 0x1e0f, 0x1f0e, 0x1002, 0x1103, 0x1200, 0x1301, 0x1406, 0x1507, 0x1604, 0x1705, 0x180a, 0x190b, 0x1a08, 0x1b09, 0x1c0e, 0x1d0f, 0x1e0c, 0x1f0d, 0x1003, 0x1102, 0x1201, 0x1300, 0x1407, 0x1506, 0x1605, 0x1704, 0x180b, 0x190a, 0x1a09, 0x1b08, 0x1c0f, 0x1d0e, 0x1e0d, 0x1f0c, 0x1004, 0x1105, 0x1206, 0x1307, 0x1400, 0x1501, 0x1602, 0x1703, 0x180c, 0x190d, 0x1a0e, 0x1b0f, 0x1c08, 0x1d09, 0x1e0a, 0x1f0b, 0x1005, 0x1104, 0x1207, 0x1306, 0x1401, 0x1500, 0x1603, 0x1702, 0x180d, 0x190c, 0x1a0f, 0x1b0e, 0x1c09, 0x1d08, 0x1e0b, 0x1f0a, 0x1006, 0x1107, 0x1204, 0x1305, 0x1402, 0x1503, 0x1600, 0x1701, 0x180e, 0x190f, 0x1a0c, 0x1b0d, 0x1c0a, 0x1d0b, 0x1e08, 0x1f09, 0x1007, 0x1106, 0x1205, 0x1304, 0x1403, 0x1502, 0x1601, 0x1700, 0x180f, 0x190e, 0x1a0d, 0x1b0c, 0x1c0b, 0x1d0a, 0x1e09, 0x1f08, 0x1008, 0x1109, 0x120a, 0x130b, 0x140c, 0x150d, 0x160e, 0x170f, 0x1800, 0x1901, 0x1a02, 0x1b03, 0x1c04, 0x1d05, 0x1e06, 0x1f07, 0x1009, 0x1108, 0x120b, 0x130a, 0x140d, 0x150c, 0x160f, 0x170e, 0x1801, 0x1900, 0x1a03, 0x1b02, 0x1c05, 0x1d04, 0x1e07, 0x1f06, 0x100a, 0x110b, 0x1208, 0x1309, 0x140e, 0x150f, 0x160c, 0x170d, 0x1802, 0x1903, 0x1a00, 0x1b01, 0x1c06, 0x1d07, 0x1e04, 0x1f05, 0x100b, 0x110a, 0x1209, 0x1308, 0x140f, 0x150e, 0x160d, 0x170c, 0x1803, 0x1902, 0x1a01, 0x1b00, 0x1c07, 0x1d06, 0x1e05, 0x1f04, 0x100c, 0x110d, 0x120e, 0x130f, 0x1408, 0x1509, 0x160a, 0x170b, 0x1804, 0x1905, 0x1a06, 0x1b07, 0x1c00, 0x1d01, 0x1e02, 0x1f03, 0x100d, 0x110c, 0x120f, 0x130e, 0x1409, 0x1508, 0x160b, 0x170a, 0x1805, 0x1904, 0x1a07, 0x1b06, 0x1c01, 0x1d00, 0x1e03, 0x1f02, 0x100e, 0x110f, 0x120c, 0x130d, 0x140a, 0x150b, 0x1608, 0x1709, 0x1806, 0x1907, 0x1a04, 0x1b05, 0x1c02, 0x1d03, 0x1e00, 0x1f01, 0x100f, 0x110e, 0x120d, 0x130c, 0x140b, 0x150a, 0x1609, 0x1708, 0x1807, 0x1906, 0x1a05, 0x1b04, 0x1c03, 0x1d02, 0x1e01, 0x1f00, 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, 0x0101, 0x0200, 0x0303, 0x0402, 0x0505, 0x0604, 0x0707, 0x0806, 0x0909, 0x0a08, 0x0b0b, 0x0c0a, 0x0d0d, 0x0e0c, 0x0f0f, 0x100e, 0x0202, 0x0303, 0x0400, 0x0501, 0x0606, 0x0707, 0x0804, 0x0905, 0x0a0a, 0x0b0b, 0x0c08, 0x0d09, 0x0e0e, 0x0f0f, 0x100c, 0x110d, 0x0303, 0x0402, 0x0501, 0x0600, 0x0707, 0x0806, 0x0905, 0x0a04, 0x0b0b, 0x0c0a, 0x0d09, 0x0e08, 0x0f0f, 0x100e, 0x110d, 0x120c, 0x0404, 0x0505, 0x0606, 0x0707, 0x0800, 0x0901, 0x0a02, 0x0b03, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, 0x1008, 0x1109, 0x120a, 0x130b, 0x0505, 0x0604, 0x0707, 0x0806, 0x0901, 0x0a00, 0x0b03, 0x0c02, 0x0d0d, 0x0e0c, 0x0f0f, 0x100e, 0x1109, 0x1208, 0x130b, 0x140a, 0x0606, 0x0707, 0x0804, 0x0905, 0x0a02, 0x0b03, 0x0c00, 0x0d01, 0x0e0e, 0x0f0f, 0x100c, 0x110d, 0x120a, 0x130b, 0x1408, 0x1509, 0x0707, 0x0806, 0x0905, 0x0a04, 0x0b03, 0x0c02, 0x0d01, 0x0e00, 0x0f0f, 0x100e, 0x110d, 0x120c, 0x130b, 0x140a, 0x1509, 0x1608, 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, 0x1000, 0x1101, 0x1202, 0x1303, 0x1404, 0x1505, 0x1606, 0x1707, 0x0909, 0x0a08, 0x0b0b, 0x0c0a, 0x0d0d, 0x0e0c, 0x0f0f, 0x100e, 0x1101, 0x1200, 0x1303, 0x1402, 0x1505, 0x1604, 0x1707, 0x1806, 0x0a0a, 0x0b0b, 0x0c08, 0x0d09, 0x0e0e, 0x0f0f, 0x100c, 0x110d, 0x1202, 0x1303, 0x1400, 0x1501, 0x1606, 0x1707, 0x1804, 0x1905, 0x0b0b, 0x0c0a, 0x0d09, 0x0e08, 0x0f0f, 0x100e, 0x110d, 0x120c, 0x1303, 0x1402, 0x1501, 0x1600, 0x1707, 0x1806, 0x1905, 0x1a04, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, 0x1008, 0x1109, 0x120a, 0x130b, 0x1404, 0x1505, 0x1606, 0x1707, 0x1800, 0x1901, 0x1a02, 0x1b03, 0x0d0d, 0x0e0c, 0x0f0f, 0x100e, 0x1109, 0x1208, 0x130b, 0x140a, 0x1505, 0x1604, 0x1707, 0x1806, 0x1901, 0x1a00, 0x1b03, 0x1c02, 0x0e0e, 0x0f0f, 0x100c, 0x110d, 0x120a, 0x130b, 0x1408, 0x1509, 0x1606, 0x1707, 0x1804, 0x1905, 0x1a02, 0x1b03, 0x1c00, 0x1d01, 0x0f0f, 0x100e, 0x110d, 0x120c, 0x130b, 0x140a, 0x1509, 0x1608, 0x1707, 0x1806, 0x1905, 0x1a04, 0x1b03, 0x1c02, 0x1d01, 0x1e00, 0x0100, 0x0201, 0x0302, 0x0403, 0x0504, 0x0605, 0x0706, 0x0807, 0x0908, 0x0a09, 0x0b0a, 0x0c0b, 0x0d0c, 0x0e0d, 0x0f0e, 0x100f, 0x0201, 0x0300, 0x0403, 0x0502, 0x0605, 0x0704, 0x0807, 0x0906, 0x0a09, 0x0b08, 0x0c0b, 0x0d0a, 0x0e0d, 0x0f0c, 0x100f, 0x110e, 0x0302, 0x0403, 0x0500, 0x0601, 0x0706, 0x0807, 0x0904, 0x0a05, 0x0b0a, 0x0c0b, 0x0d08, 0x0e09, 0x0f0e, 0x100f, 0x110c, 0x120d, 0x0403, 0x0502, 0x0601, 0x0700, 0x0807, 0x0906, 0x0a05, 0x0b04, 0x0c0b, 0x0d0a, 0x0e09, 0x0f08, 0x100f, 0x110e, 0x120d, 0x130c, 0x0504, 0x0605, 0x0706, 0x0807, 0x0900, 0x0a01, 0x0b02, 0x0c03, 0x0d0c, 0x0e0d, 0x0f0e, 0x100f, 0x1108, 0x1209, 0x130a, 0x140b, 0x0605, 0x0704, 0x0807, 0x0906, 0x0a01, 0x0b00, 0x0c03, 0x0d02, 0x0e0d, 0x0f0c, 0x100f, 0x110e, 0x1209, 0x1308, 0x140b, 0x150a, 0x0706, 0x0807, 0x0904, 0x0a05, 0x0b02, 0x0c03, 0x0d00, 0x0e01, 0x0f0e, 0x100f, 0x110c, 0x120d, 0x130a, 0x140b, 0x1508, 0x1609, 0x0807, 0x0906, 0x0a05, 0x0b04, 0x0c03, 0x0d02, 0x0e01, 0x0f00, 0x100f, 0x110e, 0x120d, 0x130c, 0x140b, 0x150a, 0x1609, 0x1708, 0x0908, 0x0a09, 0x0b0a, 0x0c0b, 0x0d0c, 0x0e0d, 0x0f0e, 0x100f, 0x1100, 0x1201, 0x1302, 0x1403, 0x1504, 0x1605, 0x1706, 0x1807, 0x0a09, 0x0b08, 0x0c0b, 0x0d0a, 0x0e0d, 0x0f0c, 0x100f, 0x110e, 0x1201, 0x1300, 0x1403, 0x1502, 0x1605, 0x1704, 0x1807, 0x1906, 0x0b0a, 0x0c0b, 0x0d08, 0x0e09, 0x0f0e, 0x100f, 0x110c, 0x120d, 0x1302, 0x1403, 0x1500, 0x1601, 0x1706, 0x1807, 0x1904, 0x1a05, 0x0c0b, 0x0d0a, 0x0e09, 0x0f08, 0x100f, 0x110e, 0x120d, 0x130c, 0x1403, 0x1502, 0x1601, 0x1700, 0x1807, 0x1906, 0x1a05, 0x1b04, 0x0d0c, 0x0e0d, 0x0f0e, 0x100f, 0x1108, 0x1209, 0x130a, 0x140b, 0x1504, 0x1605, 0x1706, 0x1807, 0x1900, 0x1a01, 0x1b02, 0x1c03, 0x0e0d, 0x0f0c, 0x100f, 0x110e, 0x1209, 0x1308, 0x140b, 0x150a, 0x1605, 0x1704, 0x1807, 0x1906, 0x1a01, 0x1b00, 0x1c03, 0x1d02, 0x0f0e, 0x100f, 0x110c, 0x120d, 0x130a, 0x140b, 0x1508, 0x1609, 0x1706, 0x1807, 0x1904, 0x1a05, 0x1b02, 0x1c03, 0x1d00, 0x1e01, 0x100f, 0x110e, 0x120d, 0x130c, 0x140b, 0x150a, 0x1609, 0x1708, 0x1807, 0x1906, 0x1a05, 0x1b04, 0x1c03, 0x1d02, 0x1e01, 0x1f00, }; return ((cfed & 0x0f00) >> 4) | csa_stream_cdef[((cfed & 0x10ff) | (pqzyx & 0x2f00)) >> 4]; } /* ** stream cipher initialization rounds */ static inline void csa_stream_init_round(uint32_t iv, uint64_t *A, uint64_t *B, uint32_t *pqzyx, uint32_t *cfed) { uint32_t tmp; *A <<= 4; *A |= (NBGET(*A, 10) ^ GETX(*pqzyx) ^ GETD(*cfed) ^ (iv >> 4)) & 0x0f; tmp = (NBGET(*B, 6) ^ NBGET(*B, 9) ^ GETY(*pqzyx) ^ (iv)) & 0x0f; tmp = csa_stream_rotate(*pqzyx, tmp); *B <<= 4; *B |= tmp; *cfed = csa_stream_cfed(*pqzyx, *cfed) ^ csa_stream_B_sel(*B); *pqzyx = csa_stream_sboxes(*A); } /* ** stream cipher stream generation rounds */ DVBCSA_INLINE static inline void csa_stream_round(uint64_t *A, uint64_t *B, uint32_t *pqzyx, uint32_t *cfed) { uint32_t tmp; *A <<= 4; *A |= (NBGET(*A, 10) ^ GETX(*pqzyx)) & 0xf; tmp = (NBGET(*B, 6) ^ NBGET(*B, 9) ^ GETY(*pqzyx)) & 0xf; *B <<= 4; *B |= csa_stream_rotate(*pqzyx, tmp); *cfed = csa_stream_cfed(*pqzyx, *cfed) ^ csa_stream_B_sel(*B); *pqzyx = csa_stream_sboxes(*A); } /* ** xor data buffer with generated stream */ void dvbcsa_stream_xor (const dvbcsa_cw_t cw, const dvbcsa_block_t iv, uint8_t *data, unsigned int len) { unsigned int i; uint64_t A, B; uint32_t pqzyx = 0; uint32_t cfed = 0; A = dvbcsa_load_le32(cw); B = dvbcsa_load_le32(cw + 4); for(i = 0; i < 8; i++) { csa_stream_init_round(iv[i] , &A, &B, &pqzyx, &cfed); csa_stream_init_round(swap_nbl(iv[i]) , &A, &B, &pqzyx, &cfed); csa_stream_init_round(iv[i] , &A, &B, &pqzyx, &cfed); csa_stream_init_round(swap_nbl(iv[i]) , &A, &B, &pqzyx, &cfed); } for(i = 0; i < len; i++) /* 4 round = 1 stream byte */ { static const uint8_t csa_stream_out[16] = { 0x00, 0x55, 0x55, 0x00, 0xaa, 0xff, 0xff, 0xaa, 0xaa, 0xff, 0xff, 0xaa, 0x00, 0x55, 0x55, 0x00, }; csa_stream_round(&A, &B, &pqzyx, &cfed); data[i] ^= csa_stream_out[GETD(cfed) & 0xf] & 0xc0; csa_stream_round(&A, &B, &pqzyx, &cfed); data[i] ^= csa_stream_out[GETD(cfed) & 0xf] & 0x30; csa_stream_round(&A, &B, &pqzyx, &cfed); data[i] ^= csa_stream_out[GETD(cfed) & 0xf] & 0x0c; csa_stream_round(&A, &B, &pqzyx, &cfed); data[i] ^= csa_stream_out[GETD(cfed) & 0xf] & 0x03; } }