Add a code word client and descrambling code.
This commit is contained in:
parent
1941c4c319
commit
364f88f3f3
14 changed files with 3051 additions and 37 deletions
11
Makefile
11
Makefile
|
@ -22,16 +22,21 @@ SRCS += htsclient.c rtsp.c rtp.c
|
|||
|
||||
SRCS += v4l.c
|
||||
|
||||
SRCS += cwc.c krypt.c
|
||||
|
||||
VPATH += ffdecsa
|
||||
SRCS += FFdecsa.c
|
||||
|
||||
PROG = tvheadend
|
||||
CFLAGS += -g -Wall -Werror -O2
|
||||
CFLAGS += -g -Wall -Werror -O2 -mmmx
|
||||
CFLAGS += -I$(INCLUDES_INSTALL_BASE) $(HTS_CFLAGS)
|
||||
CFLAGS += -Wno-deprecated-declarations
|
||||
CFLAGS += -D_LARGEFILE64_SOURCE
|
||||
CFLAGS += -DENABLE_INPUT_IPTV -DENABLE_INPUT_DVB -DENABLE_INPUT_V4L
|
||||
LDFLAGS += -L$(LIBS_INSTALL_BASE) -rdynamic
|
||||
LDFLAGS += -L$(LIBS_INSTALL_BASE)
|
||||
|
||||
SLIBS += ${LIBHTS_SLIBS}
|
||||
DLIBS += ${LIBHTS_DLIBS}
|
||||
DLIBS += ${LIBHTS_DLIBS} -lcrypt
|
||||
|
||||
#
|
||||
# ffmpeg
|
||||
|
|
873
cwc.c
Normal file
873
cwc.c
Normal file
|
@ -0,0 +1,873 @@
|
|||
/*
|
||||
* tvheadend, CWC interface
|
||||
* Copyright (C) 2007 Andreas Öman
|
||||
*
|
||||
* This program 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
#include <rpc/des_crypt.h>
|
||||
|
||||
#include "tvhead.h"
|
||||
#include "tcp.h"
|
||||
#include "psi.h"
|
||||
#include "tsdemux.h"
|
||||
#include "ffdecsa/FFdecsa.h"
|
||||
#include "dispatch.h"
|
||||
|
||||
#define CWC_KEEPALIVE_INTERVAL 600
|
||||
|
||||
#define CWS_NETMSGSIZE 240
|
||||
#define CWS_FIRSTCMDNO 0xe0
|
||||
|
||||
typedef enum {
|
||||
MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
|
||||
MSG_CLIENT_2_SERVER_LOGIN_ACK,
|
||||
MSG_CLIENT_2_SERVER_LOGIN_NAK,
|
||||
MSG_CARD_DATA_REQ,
|
||||
MSG_CARD_DATA,
|
||||
MSG_SERVER_2_CLIENT_NAME,
|
||||
MSG_SERVER_2_CLIENT_NAME_ACK,
|
||||
MSG_SERVER_2_CLIENT_NAME_NAK,
|
||||
MSG_SERVER_2_CLIENT_LOGIN,
|
||||
MSG_SERVER_2_CLIENT_LOGIN_ACK,
|
||||
MSG_SERVER_2_CLIENT_LOGIN_NAK,
|
||||
MSG_ADMIN,
|
||||
MSG_ADMIN_ACK,
|
||||
MSG_ADMIN_LOGIN,
|
||||
MSG_ADMIN_LOGIN_ACK,
|
||||
MSG_ADMIN_LOGIN_NAK,
|
||||
MSG_ADMIN_COMMAND,
|
||||
MSG_ADMIN_COMMAND_ACK,
|
||||
MSG_ADMIN_COMMAND_NAK,
|
||||
MSG_KEEPALIVE = CWS_FIRSTCMDNO + 0x1d
|
||||
} net_msg_type_t;
|
||||
|
||||
extern char *cwc_krypt(const char *key, const char *salt);
|
||||
|
||||
static LIST_HEAD(, cwc_transport) cwc_pending_requests;
|
||||
|
||||
typedef struct cwc_transport {
|
||||
th_descrambler_t ct_head;
|
||||
|
||||
th_transport_t *ct_transport;
|
||||
|
||||
struct cwc *ct_cwc;
|
||||
|
||||
LIST_ENTRY(cwc_transport) ct_cwc_link; /* Always linked */
|
||||
|
||||
LIST_ENTRY(cwc_transport) ct_link; /* linked if we are waiting
|
||||
on a reply from server */
|
||||
int ct_pending;
|
||||
|
||||
enum {
|
||||
CT_UNKNOWN,
|
||||
CT_RESOLVED,
|
||||
CT_FORBIDDEN
|
||||
} ct_keystate;
|
||||
|
||||
uint16_t ct_seq;
|
||||
|
||||
uint8_t ct_ecm[256];
|
||||
int ct_ecmsize;
|
||||
|
||||
void *ct_keys;
|
||||
|
||||
#define CT_CLUSTER_SIZE 32
|
||||
|
||||
uint8_t ct_tsbcluster[188 * CT_CLUSTER_SIZE];
|
||||
int ct_fill;
|
||||
|
||||
} cwc_transport_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct cwc {
|
||||
tcp_session_t cwc_tcp_session; /* Must be first */
|
||||
|
||||
LIST_ENTRY(cwc) cwc_link;
|
||||
|
||||
LIST_HEAD(, cwc_transport) cwc_transports;
|
||||
|
||||
enum {
|
||||
CWC_STATE_IDLE,
|
||||
CWC_STATE_WAIT_LOGIN_KEY,
|
||||
CWC_STATE_WAIT_LOGIN_ACK,
|
||||
CWC_STATE_WAIT_CARD_DATA,
|
||||
CWC_STATE_RUNNING,
|
||||
} cwc_state;
|
||||
|
||||
uint16_t cwc_caid;
|
||||
|
||||
uint16_t cwc_seq;
|
||||
|
||||
uint8_t cwc_key[16];
|
||||
|
||||
uint8_t cwc_buf[256];
|
||||
int cwc_bufptr;
|
||||
|
||||
/* From configuration */
|
||||
|
||||
uint8_t cwc_confedkey[14];
|
||||
const char *cwc_username;
|
||||
const char *cwc_password; /* salted version */
|
||||
|
||||
dtimer_t cwc_idle_timer;
|
||||
|
||||
dtimer_t cwc_send_ka_timer;
|
||||
} cwc_t;
|
||||
|
||||
static LIST_HEAD(, cwc) cwcs;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
des_key_parity_adjust(uint8_t *key, uint8_t len)
|
||||
{
|
||||
uint8_t i, j, parity;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
parity = 1;
|
||||
for (j = 1; j < 8; j++) if ((key[i] >> j) & 0x1) parity = ~parity & 0x01;
|
||||
key[i] |= parity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static uint8_t *
|
||||
des_key_spread(uint8_t *normal)
|
||||
{
|
||||
static uint8_t spread[16];
|
||||
|
||||
spread[ 0] = normal[ 0] & 0xfe;
|
||||
spread[ 1] = ((normal[ 0] << 7) | (normal[ 1] >> 1)) & 0xfe;
|
||||
spread[ 2] = ((normal[ 1] << 6) | (normal[ 2] >> 2)) & 0xfe;
|
||||
spread[ 3] = ((normal[ 2] << 5) | (normal[ 3] >> 3)) & 0xfe;
|
||||
spread[ 4] = ((normal[ 3] << 4) | (normal[ 4] >> 4)) & 0xfe;
|
||||
spread[ 5] = ((normal[ 4] << 3) | (normal[ 5] >> 5)) & 0xfe;
|
||||
spread[ 6] = ((normal[ 5] << 2) | (normal[ 6] >> 6)) & 0xfe;
|
||||
spread[ 7] = normal[ 6] << 1;
|
||||
spread[ 8] = normal[ 7] & 0xfe;
|
||||
spread[ 9] = ((normal[ 7] << 7) | (normal[ 8] >> 1)) & 0xfe;
|
||||
spread[10] = ((normal[ 8] << 6) | (normal[ 9] >> 2)) & 0xfe;
|
||||
spread[11] = ((normal[ 9] << 5) | (normal[10] >> 3)) & 0xfe;
|
||||
spread[12] = ((normal[10] << 4) | (normal[11] >> 4)) & 0xfe;
|
||||
spread[13] = ((normal[11] << 3) | (normal[12] >> 5)) & 0xfe;
|
||||
spread[14] = ((normal[12] << 2) | (normal[13] >> 6)) & 0xfe;
|
||||
spread[15] = normal[13] << 1;
|
||||
|
||||
des_key_parity_adjust(spread, 16);
|
||||
return spread;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
des_random_get(uint8_t *buffer, uint8_t len)
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
int randomNo = 0;
|
||||
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (!(idx % 3)) randomNo = rand();
|
||||
buffer[idx] = (randomNo >> ((idx % 3) << 3)) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
des_encrypt(uint8_t *buffer, int len, uint8_t *deskey)
|
||||
{
|
||||
uint8_t checksum = 0;
|
||||
uint8_t noPadBytes;
|
||||
uint8_t padBytes[7];
|
||||
char ivec[8];
|
||||
uint16_t i;
|
||||
|
||||
if (!deskey) return len;
|
||||
noPadBytes = (8 - ((len - 1) % 8)) % 8;
|
||||
if (len + noPadBytes + 1 >= CWS_NETMSGSIZE-8) return -1;
|
||||
des_random_get(padBytes, noPadBytes);
|
||||
for (i = 0; i < noPadBytes; i++) buffer[len++] = padBytes[i];
|
||||
for (i = 2; i < len; i++) checksum ^= buffer[i];
|
||||
buffer[len++] = checksum;
|
||||
des_random_get((uint8_t *)ivec, 8);
|
||||
memcpy(buffer+len, ivec, 8);
|
||||
for (i = 2; i < len; i += 8) {
|
||||
cbc_crypt((char *)deskey , (char *) buffer+i, 8, DES_ENCRYPT, ivec);
|
||||
ecb_crypt((char *)deskey+8, (char *) buffer+i, 8, DES_DECRYPT);
|
||||
ecb_crypt((char *)deskey , (char *) buffer+i, 8, DES_ENCRYPT);
|
||||
memcpy(ivec, buffer+i, 8);
|
||||
}
|
||||
len += 8;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
des_decrypt(uint8_t *buffer, int len, uint8_t *deskey)
|
||||
{
|
||||
char ivec[8];
|
||||
char nextIvec[8];
|
||||
int i;
|
||||
uint8_t checksum = 0;
|
||||
|
||||
if (!deskey) return len;
|
||||
if ((len-2) % 8 || (len-2) < 16) return -1;
|
||||
len -= 8;
|
||||
memcpy(nextIvec, buffer+len, 8);
|
||||
for (i = 2; i < len; i += 8)
|
||||
{
|
||||
memcpy(ivec, nextIvec, 8);
|
||||
memcpy(nextIvec, buffer+i, 8);
|
||||
ecb_crypt((char *)deskey , (char *) buffer+i, 8, DES_DECRYPT);
|
||||
ecb_crypt((char *)deskey+8, (char *) buffer+i, 8, DES_ENCRYPT);
|
||||
cbc_crypt((char *)deskey , (char *) buffer+i, 8, DES_DECRYPT, ivec);
|
||||
}
|
||||
for (i = 2; i < len; i++) checksum ^= buffer[i];
|
||||
if (checksum) return -1;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
des_make_login_key(cwc_t *cwc, uint8_t *k)
|
||||
{
|
||||
uint8_t des14[14];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 14; i++)
|
||||
des14[i] = cwc->cwc_confedkey[i] ^ k[i];
|
||||
memcpy(cwc->cwc_key, des_key_spread(des14), 16);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
des_make_session_key(cwc_t *cwc)
|
||||
{
|
||||
uint8_t des14[14], *k2 = (uint8_t *)cwc->cwc_password;
|
||||
int i, l = strlen(cwc->cwc_password);
|
||||
|
||||
memcpy(des14, cwc->cwc_confedkey, 14);
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
des14[i % 14] ^= k2[i];
|
||||
|
||||
memcpy(cwc->cwc_key, des_key_spread(des14), 16);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
cwc_timeout(void *aux, int64_t now)
|
||||
{
|
||||
cwc_t *cwc = aux;
|
||||
tcp_disconnect(&cwc->cwc_tcp_session, ETIMEDOUT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
cwc_send_msg(cwc_t *cwc, const uint8_t *msg, size_t len, int sid)
|
||||
{
|
||||
tcp_session_t *ses = &cwc->cwc_tcp_session;
|
||||
|
||||
uint8_t *buf = malloc(CWS_NETMSGSIZE);
|
||||
|
||||
memset(buf, 0, 12);
|
||||
memcpy(buf + 12, msg, len);
|
||||
|
||||
len += 12;
|
||||
|
||||
cwc->cwc_seq++;
|
||||
|
||||
buf[2] = cwc->cwc_seq >> 8;
|
||||
buf[3] = cwc->cwc_seq;
|
||||
buf[4] = sid >> 8;
|
||||
buf[5] = sid;
|
||||
|
||||
if((len = des_encrypt(buf, len, cwc->cwc_key)) < 0) {
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[0] = (len - 2) >> 8;
|
||||
buf[1] = len - 2;
|
||||
|
||||
tcp_send_msg(ses, &ses->tcp_q_hi, buf, len);
|
||||
|
||||
/* Expect a response within 4 seconds */
|
||||
dtimer_arm(&cwc->cwc_idle_timer, cwc_timeout, cwc, 4);
|
||||
return cwc->cwc_seq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Card data command
|
||||
*/
|
||||
static void
|
||||
cwc_send_data_req(cwc_t *cwc)
|
||||
{
|
||||
uint8_t buf[CWS_NETMSGSIZE];
|
||||
|
||||
cwc->cwc_state = CWC_STATE_WAIT_CARD_DATA;
|
||||
|
||||
buf[0] = MSG_CARD_DATA_REQ;
|
||||
buf[1] = 0;
|
||||
buf[2] = 0;
|
||||
|
||||
cwc_send_msg(cwc, buf, 3, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send keep alive
|
||||
*/
|
||||
static void
|
||||
cwc_send_ka(void *aux, int64_t now)
|
||||
{
|
||||
cwc_t *cwc = aux;
|
||||
uint8_t buf[CWS_NETMSGSIZE];
|
||||
|
||||
buf[0] = MSG_KEEPALIVE;
|
||||
buf[1] = 0;
|
||||
buf[2] = 0;
|
||||
|
||||
cwc_send_msg(cwc, buf, 3, 0);
|
||||
dtimer_arm(&cwc->cwc_send_ka_timer, cwc_send_ka, cwc,
|
||||
CWC_KEEPALIVE_INTERVAL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle reply to card data request
|
||||
*/
|
||||
static int
|
||||
cwc_dispatch_card_data_reply(cwc_t *cwc, uint8_t msgtype,
|
||||
uint8_t *msg, int len)
|
||||
{
|
||||
int plen;
|
||||
const char *n;
|
||||
|
||||
if(msgtype != MSG_CARD_DATA)
|
||||
return EBADMSG;
|
||||
|
||||
msg += 12;
|
||||
len -= 12;
|
||||
plen = (msg[1] & 0xf) << 8 | msg[2];
|
||||
|
||||
if(plen < 14)
|
||||
return EBADMSG;
|
||||
|
||||
cwc->cwc_caid = (msg[4] << 8) | msg[5];
|
||||
n = psi_caid2name(cwc->cwc_caid) ?: "Unknown";
|
||||
|
||||
syslog(LOG_INFO, "cwc: %s: Connected as user 0x%02x "
|
||||
"to a %s-card [0x%04x : %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x] "
|
||||
"with %d providers",
|
||||
cwc->cwc_tcp_session.tcp_hostname,
|
||||
msg[3], n, cwc->cwc_caid,
|
||||
msg[6], msg[7], msg[8], msg[9], msg[10], msg[11], msg[12], msg[13],
|
||||
msg[14]);
|
||||
|
||||
cwc->cwc_state = CWC_STATE_RUNNING;
|
||||
|
||||
/* Send KA every CWC_KEEPALIVE_INTERVAL seconds */
|
||||
|
||||
dtimer_arm(&cwc->cwc_send_ka_timer, cwc_send_ka, cwc,
|
||||
CWC_KEEPALIVE_INTERVAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Login command
|
||||
*/
|
||||
static void
|
||||
cwc_send_login(cwc_t *cwc)
|
||||
{
|
||||
uint8_t buf[CWS_NETMSGSIZE];
|
||||
int ul = strlen(cwc->cwc_username) + 1;
|
||||
int pl = strlen(cwc->cwc_password) + 1;
|
||||
|
||||
cwc->cwc_state = CWC_STATE_WAIT_LOGIN_ACK;
|
||||
|
||||
buf[0] = MSG_CLIENT_2_SERVER_LOGIN;
|
||||
buf[1] = 0;
|
||||
buf[2] = ul + pl;
|
||||
memcpy(buf + 3, cwc->cwc_username, ul);
|
||||
memcpy(buf + 3 + ul, cwc->cwc_password, pl);
|
||||
|
||||
cwc_send_msg(cwc, buf, ul + pl + 3, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle reply to login
|
||||
*/
|
||||
static int
|
||||
cwc_dispatch_login_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len)
|
||||
{
|
||||
switch(msgtype) {
|
||||
case MSG_CLIENT_2_SERVER_LOGIN_ACK:
|
||||
des_make_session_key(cwc);
|
||||
cwc_send_data_req(cwc);
|
||||
return 0;
|
||||
|
||||
case MSG_CLIENT_2_SERVER_LOGIN_NAK:
|
||||
return EACCES;
|
||||
|
||||
default:
|
||||
return EBADMSG;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle reply to login
|
||||
*/
|
||||
static int
|
||||
cwc_dispatch_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len)
|
||||
{
|
||||
cwc_transport_t *ct;
|
||||
uint16_t seq = (msg[2] << 8) | msg[3];
|
||||
th_transport_t *t;
|
||||
|
||||
len -= 12;
|
||||
msg += 12;
|
||||
|
||||
switch(msgtype) {
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
LIST_FOREACH(ct, &cwc_pending_requests, ct_link) {
|
||||
if(ct->ct_seq == seq)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("got key response, ct = %p, len = %d\n", ct, len);
|
||||
|
||||
if(ct == NULL)
|
||||
return 0;
|
||||
|
||||
t = ct->ct_transport;
|
||||
|
||||
LIST_REMOVE(ct, ct_link);
|
||||
ct->ct_pending = 0;
|
||||
|
||||
if(len < 19) {
|
||||
|
||||
if(ct->ct_keystate != CT_FORBIDDEN)
|
||||
syslog(LOG_ERR,
|
||||
"Cannot descramble \"%s\" for channel \"%s\", access denied",
|
||||
t->tht_uniquename, t->tht_channel->ch_name);
|
||||
|
||||
ct->ct_keystate = CT_FORBIDDEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(ct->ct_keystate != CT_RESOLVED)
|
||||
syslog(LOG_INFO,
|
||||
"Obtained key for \"%s\" for channel \"%s\"",
|
||||
t->tht_uniquename, t->tht_channel->ch_name);
|
||||
|
||||
ct->ct_keystate = CT_RESOLVED;
|
||||
set_control_words(ct->ct_keys, msg + 3, msg + 3 + 8);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
cwc_data_input(cwc_t *cwc)
|
||||
{
|
||||
int msglen, r;
|
||||
tcp_session_t *ses = &cwc->cwc_tcp_session;
|
||||
int fd = ses->tcp_fd;
|
||||
|
||||
if(cwc->cwc_state == CWC_STATE_WAIT_LOGIN_KEY) {
|
||||
|
||||
r = read(fd, cwc->cwc_buf + cwc->cwc_bufptr, 14 - cwc->cwc_bufptr);
|
||||
if(r < 1) {
|
||||
tcp_disconnect(ses, r == 0 ? ECONNRESET : errno);
|
||||
return;
|
||||
}
|
||||
|
||||
cwc->cwc_bufptr += r;
|
||||
if(cwc->cwc_bufptr < 14)
|
||||
return;
|
||||
|
||||
des_make_login_key(cwc, cwc->cwc_buf);
|
||||
cwc_send_login(cwc);
|
||||
cwc->cwc_bufptr = 0;
|
||||
|
||||
} else {
|
||||
|
||||
if(cwc->cwc_bufptr < 2) {
|
||||
msglen = 2;
|
||||
} else {
|
||||
msglen = ((cwc->cwc_buf[0] << 8) | cwc->cwc_buf[1]) + 2;
|
||||
if(msglen >= CWS_NETMSGSIZE) {
|
||||
tcp_disconnect(ses, EMSGSIZE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
r = read(fd, cwc->cwc_buf + cwc->cwc_bufptr, msglen - cwc->cwc_bufptr);
|
||||
if(r < 1) {
|
||||
tcp_disconnect(ses, r == 0 ? ECONNRESET : errno);
|
||||
return;
|
||||
}
|
||||
|
||||
cwc->cwc_bufptr += r;
|
||||
|
||||
if(msglen > 2 && cwc->cwc_bufptr == msglen) {
|
||||
if((msglen = des_decrypt(cwc->cwc_buf, msglen, cwc->cwc_key)) < 15) {
|
||||
tcp_disconnect(ses, EILSEQ);
|
||||
return;
|
||||
}
|
||||
cwc->cwc_bufptr = 0;
|
||||
|
||||
switch(cwc->cwc_state) {
|
||||
case CWC_STATE_WAIT_LOGIN_ACK:
|
||||
r = cwc_dispatch_login_reply(cwc, cwc->cwc_buf[12],
|
||||
cwc->cwc_buf, msglen);
|
||||
break;
|
||||
|
||||
case CWC_STATE_WAIT_CARD_DATA:
|
||||
r = cwc_dispatch_card_data_reply(cwc, cwc->cwc_buf[12],
|
||||
cwc->cwc_buf, msglen);
|
||||
break;
|
||||
|
||||
case CWC_STATE_RUNNING:
|
||||
r = cwc_dispatch_running_reply(cwc, cwc->cwc_buf[12],
|
||||
cwc->cwc_buf, msglen);
|
||||
break;
|
||||
|
||||
default:
|
||||
r = EBADMSG;
|
||||
break;
|
||||
}
|
||||
|
||||
if(r != 0) {
|
||||
tcp_disconnect(ses, r);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
cwc_tcp_callback(tcpevent_t event, void *tcpsession)
|
||||
{
|
||||
cwc_t *cwc = tcpsession;
|
||||
|
||||
dtimer_disarm(&cwc->cwc_idle_timer);
|
||||
|
||||
switch(event) {
|
||||
case TCP_CONNECT:
|
||||
cwc->cwc_seq = 0;
|
||||
cwc->cwc_bufptr = 0;
|
||||
cwc->cwc_state = CWC_STATE_WAIT_LOGIN_KEY;
|
||||
/* We want somthing within 20 seconds */
|
||||
dtimer_arm(&cwc->cwc_idle_timer, cwc_timeout, cwc, 20);
|
||||
break;
|
||||
|
||||
case TCP_DISCONNECT:
|
||||
cwc->cwc_state = CWC_STATE_IDLE;
|
||||
dtimer_disarm(&cwc->cwc_send_ka_timer);
|
||||
break;
|
||||
|
||||
case TCP_INPUT:
|
||||
cwc_data_input(cwc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
cwc_table_input(struct th_descrambler *td, struct th_transport *t,
|
||||
struct th_stream *st, uint8_t *data, int len)
|
||||
{
|
||||
cwc_transport_t *ct = (cwc_transport_t *)td;
|
||||
uint16_t sid = t->tht_dvb_service_id;
|
||||
cwc_t *cwc = ct->ct_cwc;
|
||||
|
||||
if(cwc->cwc_caid != st->st_caid)
|
||||
return;
|
||||
|
||||
if((data[0] & 0xf0) != 0x80)
|
||||
return;
|
||||
|
||||
printf("cwc table %x\n", data[0]);
|
||||
|
||||
switch(data[0]) {
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
/* ECM */
|
||||
|
||||
if(ct->ct_pending)
|
||||
return;
|
||||
|
||||
if(ct->ct_ecmsize == len && !memcmp(ct->ct_ecm, data, len))
|
||||
return; /* key already sent */
|
||||
|
||||
if(cwc->cwc_state != CWC_STATE_RUNNING) {
|
||||
/* New key, but we are not connected (anymore), can not descramble */
|
||||
ct->ct_keystate = CT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(ct->ct_ecm, data, len);
|
||||
ct->ct_ecmsize = len;
|
||||
printf("Key xmitted\n");
|
||||
ct->ct_seq = cwc_send_msg(cwc, data, len, sid);
|
||||
LIST_INSERT_HEAD(&cwc_pending_requests, ct, ct_link);
|
||||
ct->ct_pending = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* EMM */
|
||||
cwc_send_msg(cwc, data, len, sid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
cwc_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st,
|
||||
uint8_t *tsb)
|
||||
{
|
||||
cwc_transport_t *ct = (cwc_transport_t *)td;
|
||||
int r, i;
|
||||
unsigned char *vec[3];
|
||||
uint8_t *t0;
|
||||
|
||||
if(ct->ct_keystate != CT_RESOLVED)
|
||||
return 0;
|
||||
|
||||
memcpy(ct->ct_tsbcluster + ct->ct_fill * 188, tsb, 188);
|
||||
ct->ct_fill++;
|
||||
|
||||
if(ct->ct_fill != CT_CLUSTER_SIZE)
|
||||
return 1;
|
||||
|
||||
ct->ct_fill = 0;
|
||||
|
||||
vec[0] = ct->ct_tsbcluster;
|
||||
vec[1] = ct->ct_tsbcluster + CT_CLUSTER_SIZE * 188;
|
||||
vec[2] = NULL;
|
||||
|
||||
while(1) {
|
||||
t0 = vec[0];
|
||||
r = decrypt_packets(ct->ct_keys, vec);
|
||||
if(r == 0)
|
||||
break;
|
||||
for(i = 0; i < r; i++) {
|
||||
ts_recv_packet(t, (t0[1] & 0x1f) << 8 | t0[2], t0, 0);
|
||||
t0 += 188;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
cwc_transport_stop(th_descrambler_t *td)
|
||||
{
|
||||
cwc_transport_t *ct = (cwc_transport_t *)td;
|
||||
|
||||
if(ct->ct_pending)
|
||||
LIST_REMOVE(ct, ct_link);
|
||||
|
||||
LIST_REMOVE(ct, ct_cwc_link);
|
||||
|
||||
LIST_REMOVE(td, td_transport_link);
|
||||
free_key_struct(ct->ct_keys);
|
||||
free(ct);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if our CAID's matches, and if so, link
|
||||
*/
|
||||
void
|
||||
cwc_transport_start(th_transport_t *t)
|
||||
{
|
||||
cwc_t *cwc;
|
||||
cwc_transport_t *ct;
|
||||
th_descrambler_t *td;
|
||||
|
||||
LIST_FOREACH(cwc, &cwcs, cwc_link) {
|
||||
ct = calloc(1, sizeof(cwc_transport_t));
|
||||
ct->ct_keys = get_key_struct();
|
||||
ct->ct_cwc = cwc;
|
||||
ct->ct_transport = t;
|
||||
LIST_INSERT_HEAD(&cwc->cwc_transports, ct, ct_cwc_link);
|
||||
td = &ct->ct_head;
|
||||
|
||||
td->td_stop = cwc_transport_stop;
|
||||
td->td_table = cwc_table_input;
|
||||
td->td_descramble = cwc_descramble;
|
||||
LIST_INSERT_HEAD(&t->tht_descramblers, td, td_transport_link);
|
||||
printf("descrambler created\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
nibble(char c)
|
||||
{
|
||||
switch(c) {
|
||||
case '0' ... '9':
|
||||
return c - '0';
|
||||
case 'a' ... 'f':
|
||||
return c - 'a' + 10;
|
||||
case 'A' ... 'F':
|
||||
return c - 'A' + 10;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
cwc_init(void)
|
||||
{
|
||||
cwc_t *cwc;
|
||||
void *iterator = NULL, *head;
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *deskey, *k;
|
||||
const char *hostname;
|
||||
int port;
|
||||
uint8_t key[14];
|
||||
int i, u, l;
|
||||
|
||||
while((head = config_iterate_sections(&iterator, "cwc")) != NULL) {
|
||||
|
||||
if((hostname = config_get_str_sub(head, "hostname", NULL)) == NULL) {
|
||||
syslog(LOG_INFO, "cwc: config section missing 'hostname'");
|
||||
}
|
||||
|
||||
if((port = atoi(config_get_str_sub(head, "port", "0"))) == 0) {
|
||||
syslog(LOG_INFO, "cwc: config section missing 'port'");
|
||||
}
|
||||
|
||||
if((username = config_get_str_sub(head, "username", NULL)) == NULL) {
|
||||
syslog(LOG_INFO, "cwc: config section missing 'username'");
|
||||
}
|
||||
|
||||
if((password = config_get_str_sub(head, "password", NULL)) == NULL) {
|
||||
syslog(LOG_INFO, "cwc: config section missing 'password'");
|
||||
}
|
||||
|
||||
if((deskey = config_get_str_sub(head, "deskey", NULL)) == NULL) {
|
||||
syslog(LOG_INFO, "cwc: config section missing 'deskey'");
|
||||
}
|
||||
|
||||
|
||||
k = deskey;
|
||||
for(i = 0; i < 14; i++) {
|
||||
while(*k != 0 && !isxdigit(*k)) k++;
|
||||
if(*k == 0)
|
||||
break;
|
||||
u = nibble(*k++);
|
||||
while(*k != 0 && !isxdigit(*k)) k++;
|
||||
if(*k == 0)
|
||||
break;
|
||||
l = nibble(*k++);
|
||||
key[i] = (u << 4) | l;
|
||||
}
|
||||
|
||||
if(i != 14) {
|
||||
syslog(LOG_INFO, "cwc: 'deskey' is not 14 valid hexadecimal bytes");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(hostname == NULL || username == NULL || password == NULL ||
|
||||
deskey == NULL || port == 0)
|
||||
continue;
|
||||
|
||||
cwc = tcp_create_client(hostname, port, sizeof(cwc_t),
|
||||
"cwc", cwc_tcp_callback);
|
||||
|
||||
cwc->cwc_username = strdup(username);
|
||||
|
||||
if(!strncmp(password, "$1$", 3)) {
|
||||
cwc->cwc_password = strdup(password);
|
||||
} else {
|
||||
cwc->cwc_password = strdup(cwc_krypt(password, "$1$abcdefgh$"));
|
||||
}
|
||||
|
||||
memcpy(cwc->cwc_confedkey, key, 14);
|
||||
LIST_INSERT_HEAD(&cwcs, cwc, cwc_link);
|
||||
|
||||
}
|
||||
}
|
26
cwc.h
Normal file
26
cwc.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* tvheadend, CWC interface
|
||||
* Copyright (C) 2007 Andreas Öman
|
||||
*
|
||||
* This program 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CWC_H_
|
||||
#define CWC_H_
|
||||
|
||||
void cwc_init(void);
|
||||
|
||||
void cwc_transport_start(th_transport_t *t);
|
||||
|
||||
#endif /* CWC_H_ */
|
880
ffdecsa/FFdecsa.c
Normal file
880
ffdecsa/FFdecsa.c
Normal file
|
@ -0,0 +1,880 @@
|
|||
/* FFdecsa -- fast decsa algorithm
|
||||
*
|
||||
* Copyright (C) 2003-2004 fatih89r
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FFdecsa.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DBG(a) a
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
//// parallelization stuff, large speed differences are possible
|
||||
// possible choices
|
||||
#define PARALLEL_32_4CHAR 320
|
||||
#define PARALLEL_32_4CHARA 321
|
||||
#define PARALLEL_32_INT 322
|
||||
#define PARALLEL_64_8CHAR 640
|
||||
#define PARALLEL_64_8CHARA 641
|
||||
#define PARALLEL_64_2INT 642
|
||||
#define PARALLEL_64_LONG 643
|
||||
#define PARALLEL_64_MMX 644
|
||||
#define PARALLEL_128_16CHAR 1280
|
||||
#define PARALLEL_128_16CHARA 1281
|
||||
#define PARALLEL_128_4INT 1282
|
||||
#define PARALLEL_128_2LONG 1283
|
||||
#define PARALLEL_128_2MMX 1284
|
||||
#define PARALLEL_128_SSE 1285
|
||||
#define PARALLEL_128_SSE2 1286
|
||||
|
||||
//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice ////////
|
||||
#ifndef PARALLEL_MODE
|
||||
#define PARALLEL_MODE PARALLEL_64_MMX
|
||||
#endif
|
||||
//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice ////////
|
||||
|
||||
#include "parallel_generic.h"
|
||||
//// conditionals
|
||||
#if PARALLEL_MODE==PARALLEL_32_4CHAR
|
||||
#include "parallel_032_4char.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_32_4CHARA
|
||||
#include "parallel_032_4charA.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_32_INT
|
||||
#include "parallel_032_int.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_64_8CHAR
|
||||
#include "parallel_064_8char.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_64_8CHARA
|
||||
#include "parallel_064_8charA.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_64_2INT
|
||||
#include "parallel_064_2int.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_64_LONG
|
||||
#include "parallel_064_long.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_64_MMX
|
||||
#include "parallel_064_mmx.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_128_16CHAR
|
||||
#include "parallel_128_16char.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_128_16CHARA
|
||||
#include "parallel_128_16charA.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_128_4INT
|
||||
#include "parallel_128_4int.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_128_2LONG
|
||||
#include "parallel_128_2long.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_128_2MMX
|
||||
#include "parallel_128_2mmx.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_128_SSE
|
||||
#include "parallel_128_sse.h"
|
||||
#elif PARALLEL_MODE==PARALLEL_128_SSE2
|
||||
#include "parallel_128_sse2.h"
|
||||
#else
|
||||
#error "unknown/undefined parallel mode"
|
||||
#endif
|
||||
|
||||
// stuff depending on conditionals
|
||||
|
||||
#define BYTES_PER_GROUP (GROUP_PARALLELISM/8)
|
||||
#define BYPG BYTES_PER_GROUP
|
||||
#define BITS_PER_GROUP GROUP_PARALLELISM
|
||||
#define BIPG BITS_PER_GROUP
|
||||
|
||||
#ifndef MALLOC
|
||||
#define MALLOC(X) malloc(X)
|
||||
#endif
|
||||
#ifndef FREE
|
||||
#define FREE(X) free(X)
|
||||
#endif
|
||||
#ifndef MEMALIGN
|
||||
#define MEMALIGN
|
||||
#endif
|
||||
|
||||
//// debug tool
|
||||
|
||||
#if 0
|
||||
static void dump_mem(const char *string, const unsigned char *p, int len, int linelen){
|
||||
int i;
|
||||
for(i=0;i<len;i++){
|
||||
if(i%linelen==0&&i) fprintf(stderr,"\n");
|
||||
if(i%linelen==0) fprintf(stderr,"%s %08x:",string,i);
|
||||
else{
|
||||
if(i%8==0) fprintf(stderr," ");
|
||||
if(i%4==0) fprintf(stderr," ");
|
||||
}
|
||||
fprintf(stderr," %02x",p[i]);
|
||||
}
|
||||
if(i%linelen==0) fprintf(stderr,"\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct csa_key_t{
|
||||
unsigned char ck[8];
|
||||
// used by stream
|
||||
int iA[8]; // iA[0] is for A1, iA[7] is for A8
|
||||
int iB[8]; // iB[0] is for B1, iB[7] is for B8
|
||||
// used by stream (group)
|
||||
MEMALIGN group ck_g[8][8]; // [byte][bit:0=LSB,7=MSB]
|
||||
MEMALIGN group iA_g[8][4]; // [0 for A1][0 for LSB]
|
||||
MEMALIGN group iB_g[8][4]; // [0 for B1][0 for LSB]
|
||||
// used by block
|
||||
unsigned char kk[56];
|
||||
// used by block (group)
|
||||
MEMALIGN batch kkmulti[56]; // many times the same byte in every batch
|
||||
};
|
||||
|
||||
struct csa_keys_t{
|
||||
struct csa_key_t even;
|
||||
struct csa_key_t odd;
|
||||
};
|
||||
|
||||
//-----stream cypher
|
||||
|
||||
//-----key schedule for stream decypher
|
||||
static void key_schedule_stream(
|
||||
unsigned char *ck, // [In] ck[0]-ck[7] 8 bytes | Key.
|
||||
int *iA, // [Out] iA[0]-iA[7] 8 nibbles | Key schedule.
|
||||
int *iB) // [Out] iB[0]-iB[7] 8 nibbles | Key schedule.
|
||||
{
|
||||
iA[0]=(ck[0]>>4)&0xf;
|
||||
iA[1]=(ck[0] )&0xf;
|
||||
iA[2]=(ck[1]>>4)&0xf;
|
||||
iA[3]=(ck[1] )&0xf;
|
||||
iA[4]=(ck[2]>>4)&0xf;
|
||||
iA[5]=(ck[2] )&0xf;
|
||||
iA[6]=(ck[3]>>4)&0xf;
|
||||
iA[7]=(ck[3] )&0xf;
|
||||
iB[0]=(ck[4]>>4)&0xf;
|
||||
iB[1]=(ck[4] )&0xf;
|
||||
iB[2]=(ck[5]>>4)&0xf;
|
||||
iB[3]=(ck[5] )&0xf;
|
||||
iB[4]=(ck[6]>>4)&0xf;
|
||||
iB[5]=(ck[6] )&0xf;
|
||||
iB[6]=(ck[7]>>4)&0xf;
|
||||
iB[7]=(ck[7] )&0xf;
|
||||
}
|
||||
|
||||
//----- stream main function
|
||||
|
||||
#define STREAM_INIT
|
||||
#include "stream.c"
|
||||
#undef STREAM_INIT
|
||||
|
||||
#define STREAM_NORMAL
|
||||
#include "stream.c"
|
||||
#undef STREAM_NORMAL
|
||||
|
||||
|
||||
//-----block decypher
|
||||
|
||||
//-----key schedule for block decypher
|
||||
|
||||
static void key_schedule_block(
|
||||
unsigned char *ck, // [In] ck[0]-ck[7] 8 bytes | Key.
|
||||
unsigned char *kk) // [Out] kk[0]-kk[55] 56 bytes | Key schedule.
|
||||
{
|
||||
static const unsigned char key_perm[0x40] = {
|
||||
0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15, 0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
|
||||
0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01, 0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
|
||||
0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A, 0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
|
||||
0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C, 0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
|
||||
};
|
||||
|
||||
int i,j,k;
|
||||
int bit[64];
|
||||
int newbit[64];
|
||||
int kb[7][8];
|
||||
|
||||
// 56 steps
|
||||
// 56 key bytes kk(55)..kk(0) by key schedule from ck
|
||||
|
||||
// kb(6,0) .. kb(6,7) = ck(0) .. ck(7)
|
||||
kb[6][0] = ck[0];
|
||||
kb[6][1] = ck[1];
|
||||
kb[6][2] = ck[2];
|
||||
kb[6][3] = ck[3];
|
||||
kb[6][4] = ck[4];
|
||||
kb[6][5] = ck[5];
|
||||
kb[6][6] = ck[6];
|
||||
kb[6][7] = ck[7];
|
||||
|
||||
// calculate kb[5] .. kb[0]
|
||||
for(i=5; i>=0; i--){
|
||||
// 64 bit perm on kb
|
||||
for(j=0; j<8; j++){
|
||||
for(k=0; k<8; k++){
|
||||
bit[j*8+k] = (kb[i+1][j] >> (7-k)) & 1;
|
||||
newbit[key_perm[j*8+k]-1] = bit[j*8+k];
|
||||
}
|
||||
}
|
||||
for(j=0; j<8; j++){
|
||||
kb[i][j] = 0;
|
||||
for(k=0; k<8; k++){
|
||||
kb[i][j] |= newbit[j*8+k] << (7-k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// xor to give kk
|
||||
for(i=0; i<7; i++){
|
||||
for(j=0; j<8; j++){
|
||||
kk[i*8+j] = kb[i][j] ^ i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----block utils
|
||||
|
||||
static inline __attribute__((always_inline)) void trasp_N_8 (unsigned char *in,unsigned char* out,int count){
|
||||
int *ri=(int *)in;
|
||||
int *ibi=(int *)out;
|
||||
int j,i,k,g;
|
||||
// copy and first step
|
||||
for(g=0;g<count;g++){
|
||||
ri[g]=ibi[2*g];
|
||||
ri[GROUP_PARALLELISM+g]=ibi[2*g+1];
|
||||
}
|
||||
//dump_mem("NE1 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
|
||||
// now 01230123
|
||||
#define INTS_PER_ROW (GROUP_PARALLELISM/8*2)
|
||||
for(j=0;j<8;j+=4){
|
||||
for(i=0;i<2;i++){
|
||||
for(k=0;k<INTS_PER_ROW;k++){
|
||||
unsigned int t,b;
|
||||
t=ri[INTS_PER_ROW*(j+i)+k];
|
||||
b=ri[INTS_PER_ROW*(j+i+2)+k];
|
||||
ri[INTS_PER_ROW*(j+i)+k]= (t&0x0000ffff) | ((b )<<16);
|
||||
ri[INTS_PER_ROW*(j+i+2)+k]= ((t )>>16) | (b&0xffff0000) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
//dump_mem("NE2 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
|
||||
// now 01010101
|
||||
for(j=0;j<8;j+=2){
|
||||
for(i=0;i<1;i++){
|
||||
for(k=0;k<INTS_PER_ROW;k++){
|
||||
unsigned int t,b;
|
||||
t=ri[INTS_PER_ROW*(j+i)+k];
|
||||
b=ri[INTS_PER_ROW*(j+i+1)+k];
|
||||
ri[INTS_PER_ROW*(j+i)+k]= (t&0x00ff00ff) | ((b&0x00ff00ff)<<8);
|
||||
ri[INTS_PER_ROW*(j+i+1)+k]= ((t&0xff00ff00)>>8) | (b&0xff00ff00);
|
||||
}
|
||||
}
|
||||
}
|
||||
//dump_mem("NE3 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
|
||||
// now 00000000
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) void trasp_8_N (unsigned char *in,unsigned char* out,int count){
|
||||
int *ri=(int *)in;
|
||||
int *bdi=(int *)out;
|
||||
int j,i,k,g;
|
||||
#define INTS_PER_ROW (GROUP_PARALLELISM/8*2)
|
||||
//dump_mem("NE1 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
|
||||
// now 00000000
|
||||
for(j=0;j<8;j+=2){
|
||||
for(i=0;i<1;i++){
|
||||
for(k=0;k<INTS_PER_ROW;k++){
|
||||
unsigned int t,b;
|
||||
t=ri[INTS_PER_ROW*(j+i)+k];
|
||||
b=ri[INTS_PER_ROW*(j+i+1)+k];
|
||||
ri[INTS_PER_ROW*(j+i)+k]= (t&0x00ff00ff) | ((b&0x00ff00ff)<<8);
|
||||
ri[INTS_PER_ROW*(j+i+1)+k]= ((t&0xff00ff00)>>8) | (b&0xff00ff00);
|
||||
}
|
||||
}
|
||||
}
|
||||
//dump_mem("NE2 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
|
||||
// now 01010101
|
||||
for(j=0;j<8;j+=4){
|
||||
for(i=0;i<2;i++){
|
||||
for(k=0;k<INTS_PER_ROW;k++){
|
||||
unsigned int t,b;
|
||||
t=ri[INTS_PER_ROW*(j+i)+k];
|
||||
b=ri[INTS_PER_ROW*(j+i+2)+k];
|
||||
ri[INTS_PER_ROW*(j+i)+k]= (t&0x0000ffff) | ((b )<<16);
|
||||
ri[INTS_PER_ROW*(j+i+2)+k]= ((t )>>16) | (b&0xffff0000) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
//dump_mem("NE3 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
|
||||
// now 01230123
|
||||
for(g=0;g<count;g++){
|
||||
bdi[2*g]=ri[g];
|
||||
bdi[2*g+1]=ri[GROUP_PARALLELISM+g];
|
||||
}
|
||||
}
|
||||
|
||||
//-----block main function
|
||||
|
||||
// block group
|
||||
static void block_decypher_group(
|
||||
batch *kkmulti, // [In] kkmulti[0]-kkmulti[55] 56 batches | Key schedule (each batch has repeated equal bytes).
|
||||
unsigned char *ib, // [In] (ib0,ib1,...ib7)...x32 32*8 bytes | Initialization vector.
|
||||
unsigned char *bd, // [Out] (bd0,bd1,...bd7)...x32 32*8 bytes | Block decipher.
|
||||
int count)
|
||||
{
|
||||
// int is faster than unsigned char. apparently not
|
||||
static const unsigned char block_sbox[0x100] = {
|
||||
0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A, 0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
|
||||
0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70, 0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
|
||||
0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3, 0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
|
||||
0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84, 0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
|
||||
0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C, 0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
|
||||
0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56, 0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
|
||||
0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6, 0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
|
||||
0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E, 0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
|
||||
|
||||
0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B, 0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
|
||||
0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4, 0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
|
||||
0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F, 0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
|
||||
0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6, 0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
|
||||
0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91, 0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
|
||||
0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20, 0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
|
||||
0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4, 0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
|
||||
0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA, 0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
|
||||
};
|
||||
MEMALIGN unsigned char r[GROUP_PARALLELISM*(8+56)]; /* 56 because we will move back in memory while looping */
|
||||
MEMALIGN unsigned char sbox_in[GROUP_PARALLELISM],sbox_out[GROUP_PARALLELISM],perm_out[GROUP_PARALLELISM];
|
||||
int roff;
|
||||
int i,g,count_all=GROUP_PARALLELISM;
|
||||
|
||||
roff=GROUP_PARALLELISM*56;
|
||||
|
||||
#define FASTTRASP1
|
||||
#ifndef FASTTRASP1
|
||||
for(g=0;g<count;g++){
|
||||
// Init registers
|
||||
int j;
|
||||
for(j=0;j<8;j++){
|
||||
r[roff+GROUP_PARALLELISM*j+g]=ib[8*g+j];
|
||||
}
|
||||
}
|
||||
#else
|
||||
trasp_N_8((unsigned char *)&r[roff],(unsigned char *)ib,count);
|
||||
#endif
|
||||
//dump_mem("OLD r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
|
||||
|
||||
// loop over kk[55]..kk[0]
|
||||
for(i=55;i>=0;i--){
|
||||
{
|
||||
MEMALIGN batch tkkmulti=kkmulti[i];
|
||||
batch *si=(batch *)sbox_in;
|
||||
batch *r6_N=(batch *)(r+roff+GROUP_PARALLELISM*6);
|
||||
for(g=0;g<count_all/BYTES_PER_BATCH;g++){
|
||||
si[g]=B_FFXOR(tkkmulti,r6_N[g]); //FIXME: introduce FASTBATCH?
|
||||
}
|
||||
}
|
||||
|
||||
// table lookup, this works on only one byte at a time
|
||||
// most difficult part of all
|
||||
// - can't be parallelized
|
||||
// - can't be synthetized through boolean terms (8 input bits are too many)
|
||||
for(g=0;g<count_all;g++){
|
||||
sbox_out[g]=block_sbox[sbox_in[g]];
|
||||
}
|
||||
|
||||
// bit permutation
|
||||
{
|
||||
unsigned char *po=(unsigned char *)perm_out;
|
||||
unsigned char *so=(unsigned char *)sbox_out;
|
||||
//dump_mem("pre perm ",(unsigned char *)so,GROUP_PARALLELISM,GROUP_PARALLELISM);
|
||||
for(g=0;g<count_all;g+=BYTES_PER_BATCH){
|
||||
MEMALIGN batch in,out;
|
||||
in=*(batch *)&so[g];
|
||||
|
||||
out=B_FFOR(
|
||||
B_FFOR(
|
||||
B_FFOR(
|
||||
B_FFOR(
|
||||
B_FFOR(
|
||||
B_FFSH8L(B_FFAND(in,B_FFN_ALL_29()),1),
|
||||
B_FFSH8L(B_FFAND(in,B_FFN_ALL_02()),6)),
|
||||
B_FFSH8L(B_FFAND(in,B_FFN_ALL_04()),3)),
|
||||
B_FFSH8R(B_FFAND(in,B_FFN_ALL_10()),2)),
|
||||
B_FFSH8R(B_FFAND(in,B_FFN_ALL_40()),6)),
|
||||
B_FFSH8R(B_FFAND(in,B_FFN_ALL_80()),4));
|
||||
|
||||
*(batch *)&po[g]=out;
|
||||
}
|
||||
//dump_mem("post perm",(unsigned char *)po,GROUP_PARALLELISM,GROUP_PARALLELISM);
|
||||
}
|
||||
|
||||
roff-=GROUP_PARALLELISM; /* virtual shift of registers */
|
||||
|
||||
#if 0
|
||||
/* one by one */
|
||||
for(g=0;g<count_all;g++){
|
||||
r[roff+GROUP_PARALLELISM*0+g]=r[roff+GROUP_PARALLELISM*8+g]^sbox_out[g];
|
||||
r[roff+GROUP_PARALLELISM*6+g]^=perm_out[g];
|
||||
r[roff+GROUP_PARALLELISM*4+g]^=r[roff+GROUP_PARALLELISM*0+g];
|
||||
r[roff+GROUP_PARALLELISM*3+g]^=r[roff+GROUP_PARALLELISM*0+g];
|
||||
r[roff+GROUP_PARALLELISM*2+g]^=r[roff+GROUP_PARALLELISM*0+g];
|
||||
}
|
||||
#else
|
||||
for(g=0;g<count_all;g+=BEST_SPAN){
|
||||
XOR_BEST_BY(&r[roff+GROUP_PARALLELISM*0+g],&r[roff+GROUP_PARALLELISM*8+g],&sbox_out[g]);
|
||||
XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*6+g],&perm_out[g]);
|
||||
XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*4+g],&r[roff+GROUP_PARALLELISM*0+g]);
|
||||
XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*3+g],&r[roff+GROUP_PARALLELISM*0+g]);
|
||||
XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*2+g],&r[roff+GROUP_PARALLELISM*0+g]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define FASTTRASP2
|
||||
#ifndef FASTTRASP2
|
||||
for(g=0;g<count;g++){
|
||||
// Copy results
|
||||
int j;
|
||||
for(j=0;j<8;j++){
|
||||
bd[8*g+j]=r[roff+GROUP_PARALLELISM*j+g];
|
||||
}
|
||||
}
|
||||
#else
|
||||
trasp_8_N((unsigned char *)&r[roff],(unsigned char *)bd,count);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------EXTERNAL INTERFACE
|
||||
|
||||
//-----get internal parallelism
|
||||
|
||||
int get_internal_parallelism(void){
|
||||
return GROUP_PARALLELISM;
|
||||
}
|
||||
|
||||
//-----get suggested cluster size
|
||||
|
||||
int get_suggested_cluster_size(void){
|
||||
int r;
|
||||
r=GROUP_PARALLELISM+GROUP_PARALLELISM/10;
|
||||
if(r<GROUP_PARALLELISM+5) r=GROUP_PARALLELISM+5;
|
||||
return r;
|
||||
}
|
||||
|
||||
//-----key structure
|
||||
|
||||
void *get_key_struct(void){
|
||||
struct csa_keys_t *keys=(struct csa_keys_t *)MALLOC(sizeof(struct csa_keys_t));
|
||||
if(keys) {
|
||||
static const unsigned char pk[8] = { 0,0,0,0,0,0,0,0 };
|
||||
set_control_words(keys,pk,pk);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
void free_key_struct(void *keys){
|
||||
return FREE(keys);
|
||||
}
|
||||
|
||||
//-----set control words
|
||||
|
||||
static void schedule_key(struct csa_key_t *key, const unsigned char *pk){
|
||||
// could be made faster, but is not run often
|
||||
int bi,by;
|
||||
int i,j;
|
||||
// key
|
||||
memcpy(key->ck,pk,8);
|
||||
// precalculations for stream
|
||||
key_schedule_stream(key->ck,key->iA,key->iB);
|
||||
for(by=0;by<8;by++){
|
||||
for(bi=0;bi<8;bi++){
|
||||
key->ck_g[by][bi]=(key->ck[by]&(1<<bi))?FF1():FF0();
|
||||
}
|
||||
}
|
||||
for(by=0;by<8;by++){
|
||||
for(bi=0;bi<4;bi++){
|
||||
key->iA_g[by][bi]=(key->iA[by]&(1<<bi))?FF1():FF0();
|
||||
key->iB_g[by][bi]=(key->iB[by]&(1<<bi))?FF1():FF0();
|
||||
}
|
||||
}
|
||||
// precalculations for block
|
||||
key_schedule_block(key->ck,key->kk);
|
||||
for(i=0;i<56;i++){
|
||||
for(j=0;j<BYTES_PER_BATCH;j++){
|
||||
*(((unsigned char *)&key->kkmulti[i])+j)=key->kk[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_control_words(void *keys, const unsigned char *ev, const unsigned char *od){
|
||||
schedule_key(&((struct csa_keys_t *)keys)->even,ev);
|
||||
schedule_key(&((struct csa_keys_t *)keys)->odd,od);
|
||||
}
|
||||
|
||||
void set_even_control_word(void *keys, const unsigned char *pk){
|
||||
schedule_key(&((struct csa_keys_t *)keys)->even,pk);
|
||||
}
|
||||
|
||||
void set_odd_control_word(void *keys, const unsigned char *pk){
|
||||
schedule_key(&((struct csa_keys_t *)keys)->odd,pk);
|
||||
}
|
||||
|
||||
//-----get control words
|
||||
|
||||
void get_control_words(void *keys, unsigned char *even, unsigned char *odd){
|
||||
memcpy(even,&((struct csa_keys_t *)keys)->even.ck,8);
|
||||
memcpy(odd,&((struct csa_keys_t *)keys)->odd.ck,8);
|
||||
}
|
||||
|
||||
//----- decrypt
|
||||
|
||||
int decrypt_packets(void *keys, unsigned char **cluster){
|
||||
// statistics, currently unused
|
||||
int stat_no_scramble=0;
|
||||
int stat_reserved=0;
|
||||
int stat_decrypted[2]={0,0};
|
||||
int stat_decrypted_mini=0;
|
||||
unsigned char **clst;
|
||||
unsigned char **clst2;
|
||||
int grouped;
|
||||
int group_ev_od;
|
||||
int advanced;
|
||||
int can_advance;
|
||||
unsigned char *g_pkt[GROUP_PARALLELISM];
|
||||
int g_len[GROUP_PARALLELISM];
|
||||
int g_offset[GROUP_PARALLELISM];
|
||||
int g_n[GROUP_PARALLELISM];
|
||||
int g_residue[GROUP_PARALLELISM];
|
||||
unsigned char *pkt;
|
||||
int xc0,ev_od,len,offset,n,residue;
|
||||
struct csa_key_t* k;
|
||||
int i,j,iter,g;
|
||||
int t23,tsmall;
|
||||
int alive[24];
|
||||
//icc craziness int pad1=0; //////////align! FIXME
|
||||
unsigned char *encp[GROUP_PARALLELISM];
|
||||
unsigned char stream_in[GROUP_PARALLELISM*8];
|
||||
unsigned char stream_out[GROUP_PARALLELISM*8];
|
||||
MEMALIGN unsigned char ib[GROUP_PARALLELISM*8];
|
||||
MEMALIGN unsigned char block_out[GROUP_PARALLELISM*8];
|
||||
struct stream_regs regs;
|
||||
|
||||
//icc craziness i=(int)&pad1;//////////align!!! FIXME
|
||||
|
||||
// build a list of packets to be processed
|
||||
clst=cluster;
|
||||
grouped=0;
|
||||
advanced=0;
|
||||
can_advance=1;
|
||||
group_ev_od=-1; // silence incorrect compiler warning
|
||||
pkt=*clst;
|
||||
do{ // find a new packet
|
||||
if(grouped==GROUP_PARALLELISM){
|
||||
// full
|
||||
break;
|
||||
}
|
||||
if(pkt==NULL){
|
||||
// no more ranges
|
||||
break;
|
||||
}
|
||||
if(pkt>=*(clst+1)){
|
||||
// out of this range, try next
|
||||
clst++;clst++;
|
||||
pkt=*clst;
|
||||
continue;
|
||||
}
|
||||
|
||||
do{ // handle this packet
|
||||
xc0=pkt[3]&0xc0;
|
||||
DBG(fprintf(stderr," exam pkt=%p, xc0=%02x, can_adv=%i\n",pkt,xc0,can_advance));
|
||||
if(xc0==0x00){
|
||||
DBG(fprintf(stderr,"skip clear pkt %p (can_advance is %i)\n",pkt,can_advance));
|
||||
advanced+=can_advance;
|
||||
stat_no_scramble++;
|
||||
break;
|
||||
}
|
||||
if(xc0==0x40){
|
||||
DBG(fprintf(stderr,"skip reserved pkt %p (can_advance is %i)\n",pkt,can_advance));
|
||||
advanced+=can_advance;
|
||||
stat_reserved++;
|
||||
break;
|
||||
}
|
||||
if(xc0==0x80||xc0==0xc0){ // encrypted
|
||||
ev_od=(xc0&0x40)>>6; // 0 even, 1 odd
|
||||
if(grouped==0) group_ev_od=ev_od; // this group will be all even (or odd)
|
||||
if(group_ev_od==ev_od){ // could be added to group
|
||||
pkt[3]&=0x3f; // consider it decrypted now
|
||||
if(pkt[3]&0x20){ // incomplete packet
|
||||
offset=4+pkt[4]+1;
|
||||
len=188-offset;
|
||||
n=len>>3;
|
||||
residue=len-(n<<3);
|
||||
if(n==0){ // decrypted==encrypted!
|
||||
DBG(fprintf(stderr,"DECRYPTED MINI! (can_advance is %i)\n",can_advance));
|
||||
advanced+=can_advance;
|
||||
stat_decrypted_mini++;
|
||||
break; // this doesn't need more processing
|
||||
}
|
||||
}else{
|
||||
len=184;
|
||||
offset=4;
|
||||
n=23;
|
||||
residue=0;
|
||||
}
|
||||
g_pkt[grouped]=pkt;
|
||||
g_len[grouped]=len;
|
||||
g_offset[grouped]=offset;
|
||||
g_n[grouped]=n;
|
||||
g_residue[grouped]=residue;
|
||||
DBG(fprintf(stderr,"%2i: eo=%i pkt=%p len=%03i n=%2i residue=%i\n",grouped,ev_od,pkt,len,n,residue));
|
||||
grouped++;
|
||||
advanced+=can_advance;
|
||||
stat_decrypted[ev_od]++;
|
||||
}
|
||||
else{
|
||||
can_advance=0;
|
||||
DBG(fprintf(stderr,"skip pkt %p and can_advance set to 0\n",pkt));
|
||||
break; // skip and go on
|
||||
}
|
||||
}
|
||||
} while(0);
|
||||
|
||||
if(can_advance){
|
||||
// move range start forward
|
||||
*clst+=188;
|
||||
}
|
||||
// next packet, if there is one
|
||||
pkt+=188;
|
||||
} while(1);
|
||||
DBG(fprintf(stderr,"-- result: grouped %i pkts, advanced %i pkts\n",grouped,advanced));
|
||||
|
||||
// delete empty ranges and compact list
|
||||
clst2=cluster;
|
||||
for(clst=cluster;*clst!=NULL;clst+=2){
|
||||
// if not empty
|
||||
if(*clst<*(clst+1)){
|
||||
// it will remain
|
||||
*clst2=*clst;
|
||||
*(clst2+1)=*(clst+1);
|
||||
clst2+=2;
|
||||
}
|
||||
}
|
||||
*clst2=NULL;
|
||||
|
||||
if(grouped==0){
|
||||
// no processing needed
|
||||
return advanced;
|
||||
}
|
||||
|
||||
// sort them, longest payload first
|
||||
// we expect many n=23 packets and a few n<23
|
||||
DBG(fprintf(stderr,"PRESORTING\n"));
|
||||
for(i=0;i<grouped;i++){
|
||||
DBG(fprintf(stderr,"%2i of %2i: pkt=%p len=%03i n=%2i residue=%i\n",i,grouped,g_pkt[i],g_len[i],g_n[i],g_residue[i]));
|
||||
}
|
||||
// grouped is always <= GROUP_PARALLELISM
|
||||
|
||||
#define g_swap(a,b) \
|
||||
pkt=g_pkt[a]; \
|
||||
g_pkt[a]=g_pkt[b]; \
|
||||
g_pkt[b]=pkt; \
|
||||
\
|
||||
len=g_len[a]; \
|
||||
g_len[a]=g_len[b]; \
|
||||
g_len[b]=len; \
|
||||
\
|
||||
offset=g_offset[a]; \
|
||||
g_offset[a]=g_offset[b]; \
|
||||
g_offset[b]=offset; \
|
||||
\
|
||||
n=g_n[a]; \
|
||||
g_n[a]=g_n[b]; \
|
||||
g_n[b]=n; \
|
||||
\
|
||||
residue=g_residue[a]; \
|
||||
g_residue[a]=g_residue[b]; \
|
||||
g_residue[b]=residue;
|
||||
|
||||
// step 1: move n=23 packets before small packets
|
||||
t23=0;
|
||||
tsmall=grouped-1;
|
||||
for(;;){
|
||||
for(;t23<grouped;t23++){
|
||||
if(g_n[t23]!=23) break;
|
||||
}
|
||||
DBG(fprintf(stderr,"t23 after for =%i\n",t23));
|
||||
|
||||
for(;tsmall>=0;tsmall--){
|
||||
if(g_n[tsmall]==23) break;
|
||||
}
|
||||
DBG(fprintf(stderr,"tsmall after for =%i\n",tsmall));
|
||||
|
||||
if(tsmall-t23<1) break;
|
||||
|
||||
DBG(fprintf(stderr,"swap t23=%i,tsmall=%i\n",t23,tsmall));
|
||||
|
||||
g_swap(t23,tsmall);
|
||||
|
||||
t23++;
|
||||
tsmall--;
|
||||
DBG(fprintf(stderr,"new t23=%i,tsmall=%i\n\n",t23,tsmall));
|
||||
}
|
||||
DBG(fprintf(stderr,"packets with n=23, t23=%i grouped=%i\n",t23,grouped));
|
||||
DBG(fprintf(stderr,"MIDSORTING\n"));
|
||||
for(i=0;i<grouped;i++){
|
||||
DBG(fprintf(stderr,"%2i of %2i: pkt=%p len=%03i n=%2i residue=%i\n",i,grouped,g_pkt[i],g_len[i],g_n[i],g_residue[i]));
|
||||
}
|
||||
|
||||
// step 2: sort small packets in decreasing order of n (bubble sort is enough)
|
||||
for(i=t23;i<grouped;i++){
|
||||
for(j=i+1;j<grouped;j++){
|
||||
if(g_n[j]>g_n[i]){
|
||||
g_swap(i,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
DBG(fprintf(stderr,"POSTSORTING\n"));
|
||||
for(i=0;i<grouped;i++){
|
||||
DBG(fprintf(stderr,"%2i of %2i: pkt=%p len=%03i n=%2i residue=%i\n",i,grouped,g_pkt[i],g_len[i],g_n[i],g_residue[i]));
|
||||
}
|
||||
|
||||
// we need to know how many packets need 23 iterations, how many 22...
|
||||
for(i=0;i<=23;i++){
|
||||
alive[i]=0;
|
||||
}
|
||||
// count
|
||||
alive[23-1]=t23;
|
||||
for(i=t23;i<grouped;i++){
|
||||
alive[g_n[i]-1]++;
|
||||
}
|
||||
// integrate
|
||||
for(i=22;i>=0;i--){
|
||||
alive[i]+=alive[i+1];
|
||||
}
|
||||
DBG(fprintf(stderr,"ALIVE\n"));
|
||||
for(i=0;i<=23;i++){
|
||||
DBG(fprintf(stderr,"alive%2i=%i\n",i,alive[i]));
|
||||
}
|
||||
|
||||
// choose key
|
||||
if(group_ev_od==0){
|
||||
k=&((struct csa_keys_t *)keys)->even;
|
||||
}
|
||||
else{
|
||||
k=&((struct csa_keys_t *)keys)->odd;
|
||||
}
|
||||
|
||||
//INIT
|
||||
//#define INITIALIZE_UNUSED_INPUT
|
||||
#ifdef INITIALIZE_UNUSED_INPUT
|
||||
// unnecessary zeroing.
|
||||
// without this, we operate on uninitialized memory
|
||||
// when grouped<GROUP_PARALLELISM, but it's not a problem,
|
||||
// as final results will be discarded.
|
||||
// random data makes debugging sessions difficult.
|
||||
for(j=0;j<GROUP_PARALLELISM*8;j++) stream_in[j]=0;
|
||||
DBG(fprintf(stderr,"--- WARNING: you could gain speed by not initializing unused memory ---\n"));
|
||||
#else
|
||||
DBG(fprintf(stderr,"--- WARNING: DEBUGGING IS MORE DIFFICULT WHEN PROCESSING RANDOM DATA CHANGING AT EVERY RUN! ---\n"));
|
||||
#endif
|
||||
|
||||
for(g=0;g<grouped;g++){
|
||||
encp[g]=g_pkt[g];
|
||||
DBG(fprintf(stderr,"header[%i]=%p (%02x)\n",g,encp[g],*(encp[g])));
|
||||
encp[g]+=g_offset[g]; // skip header
|
||||
FFTABLEIN(stream_in,g,encp[g]);
|
||||
}
|
||||
//dump_mem("stream_in",stream_in,GROUP_PARALLELISM*8,BYPG);
|
||||
|
||||
|
||||
// ITER 0
|
||||
DBG(fprintf(stderr,">>>>>ITER 0\n"));
|
||||
iter=0;
|
||||
stream_cypher_group_init(®s,k->iA_g,k->iB_g,stream_in);
|
||||
// fill first ib
|
||||
for(g=0;g<alive[iter];g++){
|
||||
COPY_8_BY(ib+8*g,encp[g]);
|
||||
}
|
||||
DBG(dump_mem("IB ",ib,8*alive[iter],8));
|
||||
// ITER 1..N-1
|
||||
for (iter=1;iter<23&&alive[iter-1]>0;iter++){
|
||||
DBG(fprintf(stderr,">>>>>ITER %i\n",iter));
|
||||
// alive and just dead packets: calc block
|
||||
block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]);
|
||||
DBG(dump_mem("BLO_ib ",block_out,8*alive[iter-1],8));
|
||||
// all packets (dead too): calc stream
|
||||
stream_cypher_group_normal(®s,stream_out);
|
||||
//dump_mem("stream_out",stream_out,GROUP_PARALLELISM*8,BYPG);
|
||||
|
||||
// alive packets: calc ib
|
||||
for(g=0;g<alive[iter];g++){
|
||||
FFTABLEOUT(ib+8*g,stream_out,g);
|
||||
DBG(dump_mem("stream_out_ib ",ib+8*g,8,8));
|
||||
// XOREQ8BY gcc bug? 2x4 ok, 8 ko UPDATE: result ok but speed 1-2% slower (!!!???)
|
||||
#if 1
|
||||
XOREQ_4_BY(ib+8*g,encp[g]+8);
|
||||
XOREQ_4_BY(ib+8*g+4,encp[g]+8+4);
|
||||
#else
|
||||
XOREQ_8_BY(ib+8*g,encp[g]+8);
|
||||
#endif
|
||||
DBG(dump_mem("after_stream_xor_ib ",ib+8*g,8,8));
|
||||
}
|
||||
// alive packets: decrypt data
|
||||
for(g=0;g<alive[iter];g++){
|
||||
DBG(dump_mem("before_ib_decrypt_data ",encp[g],8,8));
|
||||
XOR_8_BY(encp[g],ib+8*g,block_out+8*g);
|
||||
DBG(dump_mem("after_ib_decrypt_data ",encp[g],8,8));
|
||||
}
|
||||
// just dead packets: write decrypted data
|
||||
for(g=alive[iter];g<alive[iter-1];g++){
|
||||
DBG(dump_mem("jd_before_ib_decrypt_data ",encp[g],8,8));
|
||||
COPY_8_BY(encp[g],block_out+8*g);
|
||||
DBG(dump_mem("jd_after_ib_decrypt_data ",encp[g],8,8));
|
||||
}
|
||||
// just dead packets: decrypt residue
|
||||
for(g=alive[iter];g<alive[iter-1];g++){
|
||||
DBG(dump_mem("jd_before_decrypt_residue ",encp[g]+8,g_residue[g],g_residue[g]));
|
||||
FFTABLEOUTXORNBY(g_residue[g],encp[g]+8,stream_out,g);
|
||||
DBG(dump_mem("jd_after_decrypt_residue ",encp[g]+8,g_residue[g],g_residue[g]));
|
||||
}
|
||||
// alive packets: pointers++
|
||||
for(g=0;g<alive[iter];g++) encp[g]+=8;
|
||||
};
|
||||
// ITER N
|
||||
DBG(fprintf(stderr,">>>>>ITER 23\n"));
|
||||
iter=23;
|
||||
// calc block
|
||||
block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]);
|
||||
DBG(dump_mem("23BLO_ib ",block_out,8*alive[iter-1],8));
|
||||
// just dead packets: write decrypted data
|
||||
for(g=alive[iter];g<alive[iter-1];g++){
|
||||
DBG(dump_mem("23jd_before_ib_decrypt_data ",encp[g],8,8));
|
||||
COPY_8_BY(encp[g],block_out+8*g);
|
||||
DBG(dump_mem("23jd_after_ib_decrypt_data ",encp[g],8,8));
|
||||
}
|
||||
// no residue possible
|
||||
// so do nothing
|
||||
|
||||
DBG(fprintf(stderr,"returning advanced=%i\n",advanced));
|
||||
|
||||
M_EMPTY(); // restore CPU multimedia state
|
||||
|
||||
return advanced;
|
||||
}
|
62
ffdecsa/FFdecsa.h
Normal file
62
ffdecsa/FFdecsa.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* FFdecsa -- fast decsa algorithm
|
||||
*
|
||||
* Copyright (C) 2003-2004 fatih89r
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FFDECSA_H
|
||||
#define FFDECSA_H
|
||||
|
||||
//----- public interface
|
||||
|
||||
// -- how many packets can be decrypted at the same time
|
||||
// This is an info about internal decryption parallelism.
|
||||
// You should try to call decrypt_packets with more packets than the number
|
||||
// returned here for performance reasons (use get_suggested_cluster_size to know
|
||||
// how many).
|
||||
int get_internal_parallelism(void);
|
||||
|
||||
// -- how many packets you should have in a cluster when calling decrypt_packets
|
||||
// This is a suggestion to achieve optimal performance; typically a little
|
||||
// higher than what get_internal_parallelism returns.
|
||||
// Passing less packets could slow down the decryption.
|
||||
// Passing more packets is never bad (if you don't spend a lot of time building
|
||||
// the list).
|
||||
int get_suggested_cluster_size(void);
|
||||
|
||||
// -- alloc & free the key structure
|
||||
void *get_key_struct(void);
|
||||
void free_key_struct(void *keys);
|
||||
|
||||
// -- set control words, 8 bytes each
|
||||
void set_control_words(void *keys, const unsigned char *even, const unsigned char *odd);
|
||||
|
||||
// -- set even control word, 8 bytes
|
||||
void set_even_control_word(void *keys, const unsigned char *even);
|
||||
|
||||
// -- set odd control word, 8 bytes
|
||||
void set_odd_control_word(void *keys, const unsigned char *odd);
|
||||
|
||||
// -- get control words, 8 bytes each
|
||||
//void get_control_words(void *keys, unsigned char *even, unsigned char *odd);
|
||||
|
||||
// -- decrypt many TS packets
|
||||
// This interface is a bit complicated because it is designed for maximum speed.
|
||||
// Please read doc/how_to_use.txt.
|
||||
int decrypt_packets(void *keys, unsigned char **cluster);
|
||||
|
||||
#endif
|
56
ffdecsa/fftable.h
Normal file
56
ffdecsa/fftable.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* FFdecsa -- fast decsa algorithm
|
||||
*
|
||||
* Copyright (C) 2007 Dark Avenger
|
||||
* 2003-2004 fatih89r
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef FFTABLE_H
|
||||
#define FFTABLE_H
|
||||
|
||||
void static inline FFTABLEIN(unsigned char *tab, int g, unsigned char *data)
|
||||
{
|
||||
#if 0
|
||||
*(((int *)tab)+2*g)=*((int *)data);
|
||||
*(((int *)tab)+2*g+1)=*(((int *)data)+1);
|
||||
#else
|
||||
*(((long long *)tab)+g)=*((long long *)data);
|
||||
#endif
|
||||
}
|
||||
|
||||
void static inline FFTABLEOUT(unsigned char *data, unsigned char *tab, int g)
|
||||
{
|
||||
#if 1
|
||||
*((int *)data)=*(((int *)tab)+2*g);
|
||||
*(((int *)data)+1)=*(((int *)tab)+2*g+1);
|
||||
#else
|
||||
*((long long *)data)=*(((long long *)tab)+g);
|
||||
#endif
|
||||
}
|
||||
|
||||
void static inline FFTABLEOUTXORNBY(int n, unsigned char *data, unsigned char *tab, int g)
|
||||
{
|
||||
int j;
|
||||
for(j=0;j<n;j++) *(data+j)^=*(tab+8*g+j);
|
||||
}
|
||||
|
||||
#undef XOREQ_BEST_BY
|
||||
static inline void XOREQ_BEST_BY(unsigned char *d, unsigned char *s)
|
||||
{
|
||||
XOR_BEST_BY(d, d, s);
|
||||
}
|
||||
|
||||
#endif //FFTABLE_H
|
83
ffdecsa/parallel_064_mmx.h
Normal file
83
ffdecsa/parallel_064_mmx.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* FFdecsa -- fast decsa algorithm
|
||||
*
|
||||
* Copyright (C) 2007 Dark Avenger
|
||||
* 2003-2004 fatih89r
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <mmintrin.h>
|
||||
|
||||
#define MEMALIGN __attribute__((aligned(16)))
|
||||
|
||||
union __u64 {
|
||||
unsigned int u[2];
|
||||
__m64 v;
|
||||
};
|
||||
|
||||
static const union __u64 ff0 = {{0x00000000U, 0x00000000U}};
|
||||
static const union __u64 ff1 = {{0xffffffffU, 0xffffffffU}};
|
||||
|
||||
typedef __m64 group;
|
||||
#define GROUP_PARALLELISM 64
|
||||
#define FF0() ff0.v
|
||||
#define FF1() ff1.v
|
||||
#define FFAND(a,b) _mm_and_si64((a),(b))
|
||||
#define FFOR(a,b) _mm_or_si64((a),(b))
|
||||
#define FFXOR(a,b) _mm_xor_si64((a),(b))
|
||||
#define FFNOT(a) _mm_xor_si64((a),FF1())
|
||||
|
||||
/* 64 rows of 64 bits */
|
||||
|
||||
static const union __u64 ff29 = {{0x29292929U, 0x29292929U}};
|
||||
static const union __u64 ff02 = {{0x02020202U, 0x02020202U}};
|
||||
static const union __u64 ff04 = {{0x04040404U, 0x04040404U}};
|
||||
static const union __u64 ff10 = {{0x10101010U, 0x10101010U}};
|
||||
static const union __u64 ff40 = {{0x40404040U, 0x40404040U}};
|
||||
static const union __u64 ff80 = {{0x80808080U, 0x80808080U}};
|
||||
|
||||
typedef __m64 batch;
|
||||
#define BYTES_PER_BATCH 8
|
||||
#define B_FFAND(a,b) FFAND((a),(b))
|
||||
#define B_FFOR(a,b) FFOR((a),(b))
|
||||
#define B_FFXOR(a,b) FFXOR((a),(b))
|
||||
#define B_FFN_ALL_29() ff29.v
|
||||
#define B_FFN_ALL_02() ff02.v
|
||||
#define B_FFN_ALL_04() ff04.v
|
||||
#define B_FFN_ALL_10() ff10.v
|
||||
#define B_FFN_ALL_40() ff40.v
|
||||
#define B_FFN_ALL_80() ff80.v
|
||||
#define B_FFSH8L(a,n) _mm_slli_si64((a),(n))
|
||||
#define B_FFSH8R(a,n) _mm_srli_si64((a),(n))
|
||||
|
||||
#define M_EMPTY() _mm_empty()
|
||||
|
||||
|
||||
#undef XOR_8_BY
|
||||
#define XOR_8_BY(d,s1,s2) do { *(__m64*)d = _mm_xor_si64(*(__m64*)(s1), *(__m64*)(s2)); } while(0)
|
||||
|
||||
#undef XOREQ_8_BY
|
||||
#define XOREQ_8_BY(d,s) XOR_8_BY(d, d, s)
|
||||
|
||||
#undef COPY_8_BY
|
||||
#define COPY_8_BY(d,s) do { *(__m64 *)(d) = *(__m64 *)(s); } while(0)
|
||||
|
||||
#undef BEST_SPAN
|
||||
#define BEST_SPAN 8
|
||||
|
||||
#undef XOR_BEST_BY
|
||||
#define XOR_BEST_BY(d,s1,s2) XOR_8_BY(d,s1,s2)
|
||||
|
||||
#include "fftable.h"
|
102
ffdecsa/parallel_generic.h
Normal file
102
ffdecsa/parallel_generic.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/* FFdecsa -- fast decsa algorithm
|
||||
*
|
||||
* Copyright (C) 2003-2004 fatih89r
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
//// generics
|
||||
#define COPY4BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
|
||||
*pd = *ps; }while(0)
|
||||
#define COPY8BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
|
||||
*pd = *ps; }while(0)
|
||||
#define COPY16BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
|
||||
*pd = *ps; \
|
||||
*(pd+1) = *(ps+1); }while(0)
|
||||
#define COPY32BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
|
||||
*pd = *ps; \
|
||||
*(pd+1) = *(ps+1) \
|
||||
*(pd+2) = *(ps+2) \
|
||||
*(pd+3) = *(ps+3); }while(0)
|
||||
#define XOR4BY(d,s1,s2) do{ int *pd=(int *)(d), *ps1=(int *)(s1), *ps2=(int *)(s2); \
|
||||
*pd = *ps1 ^ *ps2; }while(0)
|
||||
#define XOR8BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
|
||||
*pd = *ps1 ^ *ps2; }while(0)
|
||||
#define XOR16BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
|
||||
*pd = *ps1 ^ *ps2; \
|
||||
*(pd+8) = *(ps1+8) ^ *(ps2+8); }while(0)
|
||||
#define XOR32BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
|
||||
*pd = *ps1 ^ *ps2; \
|
||||
*(pd+1) = *(ps1+1) ^ *(ps2+1); \
|
||||
*(pd+2) = *(ps1+2) ^ *(ps2+2); \
|
||||
*(pd+3) = *(ps1+3) ^ *(ps2+3); }while(0)
|
||||
#define XOR32BV(d,s1,s2) do{ int *const pd=(int *const)(d), *ps1=(const int *const)(s1), *ps2=(const int *const)(s2); \
|
||||
int z; \
|
||||
for(z=0;z<8;z++){ \
|
||||
pd[z]=ps1[z]^ps2[z]; \
|
||||
} \
|
||||
}while(0)
|
||||
#define XOREQ4BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
|
||||
*pd ^= *ps; }while(0)
|
||||
#define XOREQ8BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
|
||||
*pd ^= *ps; }while(0)
|
||||
#define XOREQ16BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
|
||||
*pd ^= *ps; \
|
||||
*(pd+1) ^=*(ps+1); }while(0)
|
||||
#define XOREQ32BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
|
||||
*pd ^= *ps; \
|
||||
*(pd+1) ^=*(ps+1); \
|
||||
*(pd+2) ^=*(ps+2); \
|
||||
*(pd+3) ^=*(ps+3); }while(0)
|
||||
#define XOREQ32BY4(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
|
||||
*pd ^= *ps; \
|
||||
*(pd+1) ^=*(ps+1); \
|
||||
*(pd+2) ^=*(ps+2); \
|
||||
*(pd+3) ^=*(ps+3); \
|
||||
*(pd+4) ^=*(ps+4); \
|
||||
*(pd+5) ^=*(ps+5); \
|
||||
*(pd+6) ^=*(ps+6); \
|
||||
*(pd+7) ^=*(ps+7); }while(0)
|
||||
#define XOREQ32BV(d,s) do{ unsigned char *pd=(unsigned char *)(d), *ps=(unsigned char *)(s); \
|
||||
int z; \
|
||||
for(z=0;z<32;z++){ \
|
||||
pd[z]^=ps[z]; \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#else
|
||||
#define XOR_4_BY(d,s1,s2) do{ int *pd=(int *)(d), *ps1=(int *)(s1), *ps2=(int *)(s2); \
|
||||
*pd = *ps1 ^ *ps2; }while(0)
|
||||
#define XOR_8_BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
|
||||
*pd = *ps1 ^ *ps2; }while(0)
|
||||
#define XOREQ_4_BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
|
||||
*pd ^= *ps; }while(0)
|
||||
#define XOREQ_8_BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
|
||||
*pd ^= *ps; }while(0)
|
||||
#define COPY_4_BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
|
||||
*pd = *ps; }while(0)
|
||||
#define COPY_8_BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
|
||||
*pd = *ps; }while(0)
|
||||
|
||||
#define BEST_SPAN 8
|
||||
#define XOR_BEST_BY(d,s1,s2) do{ XOR_8_BY(d,s1,s2); }while(0);
|
||||
#define XOREQ_BEST_BY(d,s) do{ XOREQ_8_BY(d,s); }while(0);
|
||||
#define COPY_BEST_BY(d,s) do{ COPY_8_BY(d,s); }while(0);
|
||||
|
||||
#define END_MM do{ }while(0);
|
||||
#endif
|
906
ffdecsa/stream.c
Normal file
906
ffdecsa/stream.c
Normal file
|
@ -0,0 +1,906 @@
|
|||
/* FFdecsa -- fast decsa algorithm
|
||||
*
|
||||
* Copyright (C) 2003-2004 fatih89r
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// define statics only once, when STREAM_INIT
|
||||
#ifdef STREAM_INIT
|
||||
struct stream_regs {
|
||||
group A[32+10][4]; // 32 because we will move back (virtual shift register)
|
||||
group B[32+10][4]; // 32 because we will move back (virtual shift register)
|
||||
group X[4];
|
||||
group Y[4];
|
||||
group Z[4];
|
||||
group D[4];
|
||||
group E[4];
|
||||
group F[4];
|
||||
group p;
|
||||
group q;
|
||||
group r;
|
||||
};
|
||||
|
||||
static inline void trasp64_32_88ccw(unsigned char *data){
|
||||
/* 64 rows of 32 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
|
||||
#define row ((unsigned int *)data)
|
||||
int i,j;
|
||||
for(j=0;j<64;j+=32){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<16;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+16+i];
|
||||
row[j+i] = (t&0x0000ffff) | ((b )<<16);
|
||||
row[j+16+i]=((t )>>16) | (b&0xffff0000) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=16){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<8;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+8+i];
|
||||
row[j+i] = (t&0x00ff00ff) | ((b&0x00ff00ff)<<8);
|
||||
row[j+8+i] =((t&0xff00ff00)>>8) | (b&0xff00ff00);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=8){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<4;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+4+i];
|
||||
row[j+i] =((t&0x0f0f0f0f)<<4) | (b&0x0f0f0f0f);
|
||||
row[j+4+i] = (t&0xf0f0f0f0) | ((b&0xf0f0f0f0)>>4);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=4){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<2;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+2+i];
|
||||
row[j+i] =((t&0x33333333)<<2) | (b&0x33333333);
|
||||
row[j+2+i] = (t&0xcccccccc) | ((b&0xcccccccc)>>2);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=2){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<1;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+1+i];
|
||||
row[j+i] =((t&0x55555555)<<1) | (b&0x55555555);
|
||||
row[j+1+i] = (t&0xaaaaaaaa) | ((b&0xaaaaaaaa)>>1);
|
||||
}
|
||||
}
|
||||
#undef row
|
||||
}
|
||||
|
||||
static inline void trasp64_32_88cw(unsigned char *data){
|
||||
/* 64 rows of 32 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
|
||||
#define row ((unsigned int *)data)
|
||||
int i,j;
|
||||
for(j=0;j<64;j+=32){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<16;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+16+i];
|
||||
row[j+i] = (t&0x0000ffff) | ((b )<<16);
|
||||
row[j+16+i]=((t )>>16) | (b&0xffff0000) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=16){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<8;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+8+i];
|
||||
row[j+i] = (t&0x00ff00ff) | ((b&0x00ff00ff)<<8);
|
||||
row[j+8+i] =((t&0xff00ff00)>>8) | (b&0xff00ff00);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=8){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<4;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+4+i];
|
||||
row[j+i] =((t&0xf0f0f0f0)>>4) | (b&0xf0f0f0f0);
|
||||
row[j+4+i]= (t&0x0f0f0f0f) | ((b&0x0f0f0f0f)<<4);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=4){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<2;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+2+i];
|
||||
row[j+i] =((t&0xcccccccc)>>2) | (b&0xcccccccc);
|
||||
row[j+2+i]= (t&0x33333333) | ((b&0x33333333)<<2);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=2){
|
||||
unsigned int t,b;
|
||||
for(i=0;i<1;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+1+i];
|
||||
row[j+i] =((t&0xaaaaaaaa)>>1) | (b&0xaaaaaaaa);
|
||||
row[j+1+i]= (t&0x55555555) | ((b&0x55555555)<<1);
|
||||
}
|
||||
}
|
||||
#undef row
|
||||
}
|
||||
|
||||
//64-64----------------------------------------------------------
|
||||
static inline void trasp64_64_88ccw(unsigned char *data){
|
||||
/* 64 rows of 64 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
|
||||
#define row ((unsigned long long int *)data)
|
||||
int i,j;
|
||||
for(j=0;j<64;j+=64){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<32;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+32+i];
|
||||
row[j+i] = (t&0x00000000ffffffffULL) | ((b )<<32);
|
||||
row[j+32+i]=((t )>>32) | (b&0xffffffff00000000ULL) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=32){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<16;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+16+i];
|
||||
row[j+i] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
|
||||
row[j+16+i]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=16){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<8;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+8+i];
|
||||
row[j+i] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
|
||||
row[j+8+i] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=8){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<4;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+4+i];
|
||||
row[j+i] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL);
|
||||
row[j+4+i] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=4){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<2;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+2+i];
|
||||
row[j+i] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL);
|
||||
row[j+2+i] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=2){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<1;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+1+i];
|
||||
row[j+i] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL);
|
||||
row[j+1+i] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
|
||||
}
|
||||
}
|
||||
#undef row
|
||||
}
|
||||
|
||||
static inline void trasp64_64_88cw(unsigned char *data){
|
||||
/* 64 rows of 64 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
|
||||
#define row ((unsigned long long int *)data)
|
||||
int i,j;
|
||||
for(j=0;j<64;j+=64){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<32;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+32+i];
|
||||
row[j+i] = (t&0x00000000ffffffffULL) | ((b )<<32);
|
||||
row[j+32+i]=((t )>>32) | (b&0xffffffff00000000ULL) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=32){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<16;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+16+i];
|
||||
row[j+i] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
|
||||
row[j+16+i]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=16){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<8;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+8+i];
|
||||
row[j+i] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
|
||||
row[j+8+i] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=8){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<4;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+4+i];
|
||||
row[j+i] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL);
|
||||
row[j+4+i] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=4){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<2;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+2+i];
|
||||
row[j+i] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL);
|
||||
row[j+2+i] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=2){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<1;i++){
|
||||
t=row[j+i];
|
||||
b=row[j+1+i];
|
||||
row[j+i] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL);
|
||||
row[j+1+i] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1);
|
||||
}
|
||||
}
|
||||
#undef row
|
||||
}
|
||||
|
||||
//64-128----------------------------------------------------------
|
||||
static inline void trasp64_128_88ccw(unsigned char *data){
|
||||
/* 64 rows of 128 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
|
||||
#define halfrow ((unsigned long long int *)data)
|
||||
int i,j;
|
||||
for(j=0;j<64;j+=64){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<32;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+32+i)];
|
||||
halfrow[2*(j+i)] = (t&0x00000000ffffffffULL) | ((b )<<32);
|
||||
halfrow[2*(j+32+i)]=((t )>>32) | (b&0xffffffff00000000ULL) ;
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+32+i)+1];
|
||||
halfrow[2*(j+i)+1] = (t&0x00000000ffffffffULL) | ((b )<<32);
|
||||
halfrow[2*(j+32+i)+1]=((t )>>32) | (b&0xffffffff00000000ULL) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=32){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<16;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+16+i)];
|
||||
halfrow[2*(j+i)] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
|
||||
halfrow[2*(j+16+i)]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+16+i)+1];
|
||||
halfrow[2*(j+i)+1] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
|
||||
halfrow[2*(j+16+i)+1]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=16){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<8;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+8+i)];
|
||||
halfrow[2*(j+i)] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
|
||||
halfrow[2*(j+8+i)] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+8+i)+1];
|
||||
halfrow[2*(j+i)+1] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
|
||||
halfrow[2*(j+8+i)+1] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=8){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<4;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+4+i)];
|
||||
halfrow[2*(j+i)] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL);
|
||||
halfrow[2*(j+4+i)] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+4+i)+1];
|
||||
halfrow[2*(j+i)+1] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL);
|
||||
halfrow[2*(j+4+i)+1] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=4){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<2;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+2+i)];
|
||||
halfrow[2*(j+i)] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL);
|
||||
halfrow[2*(j+2+i)] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2);
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+2+i)+1];
|
||||
halfrow[2*(j+i)+1] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL);
|
||||
halfrow[2*(j+2+i)+1] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=2){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<1;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+1+i)];
|
||||
halfrow[2*(j+i)] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL);
|
||||
halfrow[2*(j+1+i)] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+1+i)+1];
|
||||
halfrow[2*(j+i)+1] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL);
|
||||
halfrow[2*(j+1+i)+1] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
|
||||
}
|
||||
}
|
||||
#undef halfrow
|
||||
}
|
||||
|
||||
static inline void trasp64_128_88cw(unsigned char *data){
|
||||
/* 64 rows of 128 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
|
||||
#define halfrow ((unsigned long long int *)data)
|
||||
int i,j;
|
||||
for(j=0;j<64;j+=64){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<32;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+32+i)];
|
||||
halfrow[2*(j+i)] = (t&0x00000000ffffffffULL) | ((b )<<32);
|
||||
halfrow[2*(j+32+i)]=((t )>>32) | (b&0xffffffff00000000ULL) ;
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+32+i)+1];
|
||||
halfrow[2*(j+i)+1] = (t&0x00000000ffffffffULL) | ((b )<<32);
|
||||
halfrow[2*(j+32+i)+1]=((t )>>32) | (b&0xffffffff00000000ULL) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=32){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<16;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+16+i)];
|
||||
halfrow[2*(j+i)] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
|
||||
halfrow[2*(j+16+i)]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+16+i)+1];
|
||||
halfrow[2*(j+i)+1] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
|
||||
halfrow[2*(j+16+i)+1]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=16){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<8;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+8+i)];
|
||||
halfrow[2*(j+i)] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
|
||||
halfrow[2*(j+8+i)] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+8+i)+1];
|
||||
halfrow[2*(j+i)+1] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
|
||||
halfrow[2*(j+8+i)+1] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=8){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<4;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+4+i)];
|
||||
halfrow[2*(j+i)] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL);
|
||||
halfrow[2*(j+4+i)] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+4+i)+1];
|
||||
halfrow[2*(j+i)+1] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL);
|
||||
halfrow[2*(j+4+i)+1] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=4){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<2;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+2+i)];
|
||||
halfrow[2*(j+i)] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL);
|
||||
halfrow[2*(j+2+i)] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2);
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+2+i)+1];
|
||||
halfrow[2*(j+i)+1] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL);
|
||||
halfrow[2*(j+2+i)+1] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2);
|
||||
}
|
||||
}
|
||||
for(j=0;j<64;j+=2){
|
||||
unsigned long long int t,b;
|
||||
for(i=0;i<1;i++){
|
||||
t=halfrow[2*(j+i)];
|
||||
b=halfrow[2*(j+1+i)];
|
||||
halfrow[2*(j+i)] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL);
|
||||
halfrow[2*(j+1+i)] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1);
|
||||
t=halfrow[2*(j+i)+1];
|
||||
b=halfrow[2*(j+1+i)+1];
|
||||
halfrow[2*(j+i)+1] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL);
|
||||
halfrow[2*(j+1+i)+1] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1);
|
||||
}
|
||||
}
|
||||
#undef halfrow
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef STREAM_INIT
|
||||
void stream_cypher_group_init(
|
||||
struct stream_regs *regs,
|
||||
group iA[8][4], // [In] iA00,iA01,...iA73 32 groups | Derived from key.
|
||||
group iB[8][4], // [In] iB00,iB01,...iB73 32 groups | Derived from key.
|
||||
unsigned char *sb) // [In] (SB0,SB1,...SB7)...x32 32*8 bytes | Extra input.
|
||||
#endif
|
||||
#ifdef STREAM_NORMAL
|
||||
void stream_cypher_group_normal(
|
||||
struct stream_regs *regs,
|
||||
unsigned char *cb) // [Out] (CB0,CB1,...CB7)...x32 32*8 bytes | Output.
|
||||
#endif
|
||||
{
|
||||
#ifdef STREAM_INIT
|
||||
group in1[4];
|
||||
group in2[4];
|
||||
#endif
|
||||
group extra_B[4];
|
||||
group fa,fb,fc,fd,fe;
|
||||
group s1a,s1b,s2a,s2b,s3a,s3b,s4a,s4b,s5a,s5b,s6a,s6b,s7a,s7b;
|
||||
group next_E[4];
|
||||
group tmp0,tmp1,tmp2,tmp3,tmp4;
|
||||
#ifdef STREAM_INIT
|
||||
group *sb_g=(group *)sb;
|
||||
#endif
|
||||
#ifdef STREAM_NORMAL
|
||||
group *cb_g=(group *)cb;
|
||||
#endif
|
||||
int aboff;
|
||||
int i,j,k,b;
|
||||
int dbg;
|
||||
|
||||
#ifdef STREAM_INIT
|
||||
DBG(fprintf(stderr,":::::::::: BEGIN STREAM INIT\n"));
|
||||
#endif
|
||||
#ifdef STREAM_NORMAL
|
||||
DBG(fprintf(stderr,":::::::::: BEGIN STREAM NORMAL\n"));
|
||||
#endif
|
||||
#ifdef STREAM_INIT
|
||||
for(j=0;j<64;j++){
|
||||
DBG(fprintf(stderr,"precall prerot stream_in[%2i]=",j));
|
||||
DBG(dump_mem("",sb+BYPG*j,BYPG,BYPG));
|
||||
}
|
||||
|
||||
DBG(dump_mem("stream_prerot ",sb,GROUP_PARALLELISM*8,BYPG));
|
||||
#if GROUP_PARALLELISM==32
|
||||
trasp64_32_88ccw(sb);
|
||||
#endif
|
||||
#if GROUP_PARALLELISM==64
|
||||
trasp64_64_88ccw(sb);
|
||||
#endif
|
||||
#if GROUP_PARALLELISM==128
|
||||
trasp64_128_88ccw(sb);
|
||||
#endif
|
||||
DBG(dump_mem("stream_postrot",sb,GROUP_PARALLELISM*8,BYPG));
|
||||
|
||||
for(j=0;j<64;j++){
|
||||
DBG(fprintf(stderr,"precall stream_in[%2i]=",j));
|
||||
DBG(dump_mem("",sb+BYPG*j,BYPG,BYPG));
|
||||
}
|
||||
#endif
|
||||
|
||||
aboff=32;
|
||||
|
||||
#ifdef STREAM_INIT
|
||||
// load first 32 bits of ck into A[aboff+0]..A[aboff+7]
|
||||
// load last 32 bits of ck into B[aboff+0]..B[aboff+7]
|
||||
// all other regs = 0
|
||||
for(i=0;i<8;i++){
|
||||
for(b=0;b<4;b++){
|
||||
DBG(fprintf(stderr,"dbg from iA A[%i][%i]=",i,b));
|
||||
DBG(dump_mem("",(unsigned char *)&iA[i][b],BYPG,BYPG));
|
||||
DBG(fprintf(stderr," dbg from iB B[%i][%i]=",i,b));
|
||||
DBG(dump_mem("",(unsigned char *)&iB[i][b],BYPG,BYPG));
|
||||
regs->A[aboff+i][b]=iA[i][b];
|
||||
regs->B[aboff+i][b]=iB[i][b];
|
||||
}
|
||||
}
|
||||
for(b=0;b<4;b++){
|
||||
regs->A[aboff+8][b]=FF0();
|
||||
regs->A[aboff+9][b]=FF0();
|
||||
regs->B[aboff+8][b]=FF0();
|
||||
regs->B[aboff+9][b]=FF0();
|
||||
}
|
||||
for(b=0;b<4;b++){
|
||||
regs->X[b]=FF0();
|
||||
regs->Y[b]=FF0();
|
||||
regs->Z[b]=FF0();
|
||||
regs->D[b]=FF0();
|
||||
regs->E[b]=FF0();
|
||||
regs->F[b]=FF0();
|
||||
}
|
||||
regs->p=FF0();
|
||||
regs->q=FF0();
|
||||
regs->r=FF0();
|
||||
#endif
|
||||
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"dbg A0[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->A[aboff+0][dbg],BYPG,BYPG));
|
||||
DBG(fprintf(stderr,"dbg B0[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->B[aboff+0][dbg],BYPG,BYPG));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// EXTERNAL LOOP - 8 bytes per operation
|
||||
for(i=0;i<8;i++){
|
||||
|
||||
DBG(fprintf(stderr,"--BEGIN EXTERNAL LOOP %i\n",i));
|
||||
|
||||
#ifdef STREAM_INIT
|
||||
for(b=0;b<4;b++){
|
||||
in1[b]=sb_g[8*i+4+b];
|
||||
in2[b]=sb_g[8*i+b];
|
||||
}
|
||||
#endif
|
||||
|
||||
// INTERNAL LOOP - 2 bits per iteration
|
||||
for(j=0; j<4; j++){
|
||||
|
||||
DBG(fprintf(stderr,"---BEGIN INTERNAL LOOP %i (EXT %i, INT %i)\n",j,i,j));
|
||||
|
||||
// from A0..A9, 35 bits are selected as inputs to 7 s-boxes
|
||||
// 5 bits input per s-box, 2 bits output per s-box
|
||||
|
||||
// we can select bits with zero masking and shifting operations
|
||||
// and synthetize s-boxes with optimized boolean functions.
|
||||
// this is the actual reason we do all the crazy transposition
|
||||
// stuff to switch between normal and bit slice representations.
|
||||
// this code really flies.
|
||||
|
||||
fe=regs->A[aboff+3][0];fa=regs->A[aboff+0][2];fb=regs->A[aboff+5][1];fc=regs->A[aboff+6][3];fd=regs->A[aboff+8][0];
|
||||
/* 1000 1110 1110 0001 : lev 7: */ //tmp0=( fa^( fb^( ( ( ( fa|fb )^fc )|( fc^fd ) )^ALL_ONES ) ) );
|
||||
/* 1110 0010 0011 0011 : lev 6: */ //tmp1=( ( fa|fb )^( ( fc&( fa|( fb^fd ) ) )^ALL_ONES ) );
|
||||
/* 0011 0110 1000 1101 : lev 5: */ //tmp2=( fa^( ( fb&fd )^( ( fa&fd )|fc ) ) );
|
||||
/* 0101 0101 1001 0011 : lev 5: */ //tmp3=( ( fa&fc )^( fa^( ( fa&fb )|fd ) ) );
|
||||
/* 1000 1110 1110 0001 : lev 7: */ tmp0=FFXOR(fa,FFXOR(fb,FFXOR(FFOR(FFXOR(FFOR(fa,fb),fc),FFXOR(fc,fd)),FF1())));
|
||||
/* 1110 0010 0011 0011 : lev 6: */ tmp1=FFXOR(FFOR(fa,fb),FFXOR(FFAND(fc,FFOR(fa,FFXOR(fb,fd))),FF1()));
|
||||
/* 0011 0110 1000 1101 : lev 5: */ tmp2=FFXOR(fa,FFXOR(FFAND(fb,fd),FFOR(FFAND(fa,fd),fc)));
|
||||
/* 0101 0101 1001 0011 : lev 5: */ tmp3=FFXOR(FFAND(fa,fc),FFXOR(fa,FFOR(FFAND(fa,fb),fd)));
|
||||
s1a=FFXOR(tmp0,FFAND(fe,tmp1));
|
||||
s1b=FFXOR(tmp2,FFAND(fe,tmp3));
|
||||
//dump_mem("s1as1b-fe",&fe,BYPG,BYPG);
|
||||
//dump_mem("s1as1b-fa",&fa,BYPG,BYPG);
|
||||
//dump_mem("s1as1b-fb",&fb,BYPG,BYPG);
|
||||
//dump_mem("s1as1b-fc",&fc,BYPG,BYPG);
|
||||
//dump_mem("s1as1b-fd",&fd,BYPG,BYPG);
|
||||
|
||||
fe=regs->A[aboff+1][1];fa=regs->A[aboff+2][2];fb=regs->A[aboff+5][3];fc=regs->A[aboff+6][0];fd=regs->A[aboff+8][1];
|
||||
/* 1001 1110 0110 0001 : lev 6: */ //tmp0=( fa^( ( fb&( fc|fd ) )^( fc^( fd^ALL_ONES ) ) ) );
|
||||
/* 0000 0011 0111 1011 : lev 5: */ //tmp1=( ( fa&( fb^fd ) )|( ( fa|fb )&fc ) );
|
||||
/* 1100 0110 1101 0010 : lev 6: */ //tmp2=( ( fb&fd )^( ( fa&fd )|( fb^( fc^ALL_ONES ) ) ) );
|
||||
/* 0001 1110 1111 0101 : lev 5: */ //tmp3=( ( fa&fd )|( fa^( fb^( fc&fd ) ) ) );
|
||||
/* 1001 1110 0110 0001 : lev 6: */ tmp0=FFXOR(fa,FFXOR(FFAND(fb,FFOR(fc,fd)),FFXOR(fc,FFXOR(fd,FF1()))));
|
||||
/* 0000 0011 0111 1011 : lev 5: */ tmp1=FFOR(FFAND(fa,FFXOR(fb,fd)),FFAND(FFOR(fa,fb),fc));
|
||||
/* 1100 0110 1101 0010 : lev 6: */ tmp2=FFXOR(FFAND(fb,fd),FFOR(FFAND(fa,fd),FFXOR(fb,FFXOR(fc,FF1()))));
|
||||
/* 0001 1110 1111 0101 : lev 5: */ tmp3=FFOR(FFAND(fa,fd),FFXOR(fa,FFXOR(fb,FFAND(fc,fd))));
|
||||
s2a=FFXOR(tmp0,FFAND(fe,tmp1));
|
||||
s2b=FFXOR(tmp2,FFAND(fe,tmp3));
|
||||
|
||||
fe=regs->A[aboff+0][3];fa=regs->A[aboff+1][0];fb=regs->A[aboff+4][1];fc=regs->A[aboff+4][3];fd=regs->A[aboff+5][2];
|
||||
/* 0100 1011 1001 0110 : lev 5: */ //tmp0=( fa^( fb^( ( fc&( fa|fd ) )^fd ) ) );
|
||||
/* 1101 0101 1000 1100 : lev 7: */ //tmp1=( ( fa&fc )^( ( fa^fd )|( ( fb|fc )^( fd^ALL_ONES ) ) ) );
|
||||
/* 0010 0111 1101 1000 : lev 4: */ //tmp2=( fa^( ( ( fb^fc )&fd )^fc ) );
|
||||
/* 1111 1111 1111 1111 : lev 0: */ //tmp3=ALL_ONES;
|
||||
/* 0100 1011 1001 0110 : lev 5: */ tmp0=FFXOR(fa,FFXOR(fb,FFXOR(FFAND(fc,FFOR(fa,fd)),fd)));
|
||||
/* 1101 0101 1000 1100 : lev 7: */ tmp1=FFXOR(FFAND(fa,fc),FFOR(FFXOR(fa,fd),FFXOR(FFOR(fb,fc),FFXOR(fd,FF1()))));
|
||||
/* 0010 0111 1101 1000 : lev 4: */ tmp2=FFXOR(fa,FFXOR(FFAND(FFXOR(fb,fc),fd),fc));
|
||||
/* 1111 1111 1111 1111 : lev 0: */ tmp3=FF1();
|
||||
s3a=FFXOR(tmp0,FFAND(FFNOT(fe),tmp1));
|
||||
s3b=FFXOR(tmp2,FFAND(fe,tmp3));
|
||||
|
||||
fe=regs->A[aboff+2][3];fa=regs->A[aboff+0][1];fb=regs->A[aboff+1][3];fc=regs->A[aboff+3][2];fd=regs->A[aboff+7][0];
|
||||
/* 1011 0101 0100 1001 : lev 7: */ //tmp0=( fa^( ( fc&( fa^fd ) )|( fb^( fc|( fd^ALL_ONES ) ) ) ) );
|
||||
/* 0010 1101 0110 0110 : lev 6: */ //tmp1=( ( fa&fb )^( fb^( ( ( fa|fc )&fd )^fc ) ) );
|
||||
/* 0110 0111 1101 0000 : lev 7: */ //tmp2=( fa^( ( fb&fc )|( ( ( fa&( fb^fd ) )|fc )^fd ) ) );
|
||||
/* 1111 1111 1111 1111 : lev 0: */ //tmp3=ALL_ONES;
|
||||
/* 1011 0101 0100 1001 : lev 7: */ tmp0=FFXOR(fa,FFOR(FFAND(fc,FFXOR(fa,fd)),FFXOR(fb,FFOR(fc,FFXOR(fd,FF1())))));
|
||||
/* 0010 1101 0110 0110 : lev 6: */ tmp1=FFXOR(FFAND(fa,fb),FFXOR(fb,FFXOR(FFAND(FFOR(fa,fc),fd),fc)));
|
||||
/* 0110 0111 1101 0000 : lev 7: */ tmp2=FFXOR(fa,FFOR(FFAND(fb,fc),FFXOR(FFOR(FFAND(fa,FFXOR(fb,fd)),fc),fd)));
|
||||
/* 1111 1111 1111 1111 : lev 0: */ tmp3=FF1();
|
||||
s4a=FFXOR(tmp0,FFAND(fe,FFXOR(tmp1,tmp0)));
|
||||
s4b=FFXOR(FFXOR(s4a,tmp2),FFAND(fe,tmp3));
|
||||
|
||||
fe=regs->A[aboff+4][2];fa=regs->A[aboff+3][3];fb=regs->A[aboff+5][0];fc=regs->A[aboff+7][1];fd=regs->A[aboff+8][2];
|
||||
/* 1000 1111 0011 0010 : lev 7: */ //tmp0=( ( ( fa&( fb|fc ) )^fb )|( ( ( fa^fc )|fd )^ALL_ONES ) );
|
||||
/* 0110 1011 0000 1011 : lev 6: */ //tmp1=( fb^( ( fc^fd )&( fc^( fb|( fa^fd ) ) ) ) );
|
||||
/* 0001 1010 0111 1001 : lev 6: */ //tmp2=( ( fa&fc )^( fb^( ( fb|( fa^fc ) )&fd ) ) );
|
||||
/* 0101 1101 1101 0101 : lev 4: */ //tmp3=( ( ( fa^fb )&( fc^ALL_ONES ) )|fd );
|
||||
/* 1000 1111 0011 0010 : lev 7: */ tmp0=FFOR(FFXOR(FFAND(fa,FFOR(fb,fc)),fb),FFXOR(FFOR(FFXOR(fa,fc),fd),FF1()));
|
||||
/* 0110 1011 0000 1011 : lev 6: */ tmp1=FFXOR(fb,FFAND(FFXOR(fc,fd),FFXOR(fc,FFOR(fb,FFXOR(fa,fd)))));
|
||||
/* 0001 1010 0111 1001 : lev 6: */ tmp2=FFXOR(FFAND(fa,fc),FFXOR(fb,FFAND(FFOR(fb,FFXOR(fa,fc)),fd)));
|
||||
/* 0101 1101 1101 0101 : lev 4: */ tmp3=FFOR(FFAND(FFXOR(fa,fb),FFXOR(fc,FF1())),fd);
|
||||
s5a=FFXOR(tmp0,FFAND(fe,tmp1));
|
||||
s5b=FFXOR(tmp2,FFAND(fe,tmp3));
|
||||
|
||||
fe=regs->A[aboff+2][1];fa=regs->A[aboff+3][1];fb=regs->A[aboff+4][0];fc=regs->A[aboff+6][2];fd=regs->A[aboff+8][3];
|
||||
/* 0011 0110 0010 1101 : lev 6: */ //tmp0=( ( ( fa&fc )&fd )^( ( fb&( fa|fd ) )^fc ) );
|
||||
/* 1110 1110 1011 1011 : lev 3: */ //tmp1=( ( ( fa^fc )&fd )^ALL_ONES );
|
||||
/* 0101 1000 0110 0111 : lev 6: */ //tmp2=( ( fa&( fb|fc ) )^( fb^( ( fb&fc )|fd ) ) );
|
||||
/* 0001 0011 0000 0001 : lev 5: */ //tmp3=( fc&( ( fa&( fb^fd ) )^( fb|fd ) ) );
|
||||
/* 0011 0110 0010 1101 : lev 6: */ tmp0=FFXOR(FFAND(FFAND(fa,fc),fd),FFXOR(FFAND(fb,FFOR(fa,fd)),fc));
|
||||
/* 1110 1110 1011 1011 : lev 3: */ tmp1=FFXOR(FFAND(FFXOR(fa,fc),fd),FF1());
|
||||
/* 0101 1000 0110 0111 : lev 6: */ tmp2=FFXOR(FFAND(fa,FFOR(fb,fc)),FFXOR(fb,FFOR(FFAND(fb,fc),fd)));
|
||||
/* 0001 0011 0000 0001 : lev 5: */ tmp3=FFAND(fc,FFXOR(FFAND(fa,FFXOR(fb,fd)),FFOR(fb,fd)));
|
||||
s6a=FFXOR(tmp0,FFAND(fe,tmp1));
|
||||
s6b=FFXOR(tmp2,FFAND(fe,tmp3));
|
||||
|
||||
fe=regs->A[aboff+1][2];fa=regs->A[aboff+2][0];fb=regs->A[aboff+6][1];fc=regs->A[aboff+7][2];fd=regs->A[aboff+7][3];
|
||||
/* 0111 1000 1001 0110 : lev 5: */ //tmp0=( fb^( ( fc&fd )|( fa^( fc^fd ) ) ) );
|
||||
/* 0100 1001 0101 1011 : lev 6: */ //tmp1=( ( fb|fd )&( ( fa&fc )|( fb^( fc^fd ) ) ) );
|
||||
/* 0100 1001 1011 1001 : lev 5: */ //tmp2=( ( fa|fb )^( ( fc&( fb|fd ) )^fd ) );
|
||||
/* 1111 1111 1101 1101 : lev 3: */ //tmp3=( fd|( ( fa&fc )^ALL_ONES ) );
|
||||
/* 0111 1000 1001 0110 : lev 5: */ tmp0=FFXOR(fb,FFOR(FFAND(fc,fd),FFXOR(fa,FFXOR(fc,fd))));
|
||||
/* 0100 1001 0101 1011 : lev 6: */ tmp1=FFAND(FFOR(fb,fd),FFOR(FFAND(fa,fc),FFXOR(fb,FFXOR(fc,fd))));
|
||||
/* 0100 1001 1011 1001 : lev 5: */ tmp2=FFXOR(FFOR(fa,fb),FFXOR(FFAND(fc,FFOR(fb,fd)),fd));
|
||||
/* 1111 1111 1101 1101 : lev 3: */ tmp3=FFOR(fd,FFXOR(FFAND(fa,fc),FF1()));
|
||||
s7a=FFXOR(tmp0,FFAND(fe,tmp1));
|
||||
s7b=FFXOR(tmp2,FFAND(fe,tmp3));
|
||||
|
||||
|
||||
/*
|
||||
we have just done this:
|
||||
|
||||
int sbox1[0x20] = {2,0,1,1,2,3,3,0, 3,2,2,0,1,1,0,3, 0,3,3,0,2,2,1,1, 2,2,0,3,1,1,3,0};
|
||||
int sbox2[0x20] = {3,1,0,2,2,3,3,0, 1,3,2,1,0,0,1,2, 3,1,0,3,3,2,0,2, 0,0,1,2,2,1,3,1};
|
||||
int sbox3[0x20] = {2,0,1,2,2,3,3,1, 1,1,0,3,3,0,2,0, 1,3,0,1,3,0,2,2, 2,0,1,2,0,3,3,1};
|
||||
int sbox4[0x20] = {3,1,2,3,0,2,1,2, 1,2,0,1,3,0,0,3, 1,0,3,1,2,3,0,3, 0,3,2,0,1,2,2,1};
|
||||
int sbox5[0x20] = {2,0,0,1,3,2,3,2, 0,1,3,3,1,0,2,1, 2,3,2,0,0,3,1,1, 1,0,3,2,3,1,0,2};
|
||||
int sbox6[0x20] = {0,1,2,3,1,2,2,0, 0,1,3,0,2,3,1,3, 2,3,0,2,3,0,1,1, 2,1,1,2,0,3,3,0};
|
||||
int sbox7[0x20] = {0,3,2,2,3,0,0,1, 3,0,1,3,1,2,2,1, 1,0,3,3,0,1,1,2, 2,3,1,0,2,3,0,2};
|
||||
|
||||
s12 = sbox1[ (((A3>>0)&1)<<4) | (((A0>>2)&1)<<3) | (((A5>>1)&1)<<2) | (((A6>>3)&1)<<1) | (((A8>>0)&1)<<0) ]
|
||||
|sbox2[ (((A1>>1)&1)<<4) | (((A2>>2)&1)<<3) | (((A5>>3)&1)<<2) | (((A6>>0)&1)<<1) | (((A8>>1)&1)<<0) ];
|
||||
s34 = sbox3[ (((A0>>3)&1)<<4) | (((A1>>0)&1)<<3) | (((A4>>1)&1)<<2) | (((A4>>3)&1)<<1) | (((A5>>2)&1)<<0) ]
|
||||
|sbox4[ (((A2>>3)&1)<<4) | (((A0>>1)&1)<<3) | (((A1>>3)&1)<<2) | (((A3>>2)&1)<<1) | (((A7>>0)&1)<<0) ];
|
||||
s56 = sbox5[ (((A4>>2)&1)<<4) | (((A3>>3)&1)<<3) | (((A5>>0)&1)<<2) | (((A7>>1)&1)<<1) | (((A8>>2)&1)<<0) ]
|
||||
|sbox6[ (((A2>>1)&1)<<4) | (((A3>>1)&1)<<3) | (((A4>>0)&1)<<2) | (((A6>>2)&1)<<1) | (((A8>>3)&1)<<0) ];
|
||||
s7 = sbox7[ (((A1>>2)&1)<<4) | (((A2>>0)&1)<<3) | (((A6>>1)&1)<<2) | (((A7>>2)&1)<<1) | (((A7>>3)&1)<<0) ];
|
||||
*/
|
||||
|
||||
// use 4x4 xor to produce extra nibble for T3
|
||||
|
||||
extra_B[3]=FFXOR(FFXOR(FFXOR(regs->B[aboff+2][0],regs->B[aboff+5][1]),regs->B[aboff+6][2]),regs->B[aboff+8][3]);
|
||||
extra_B[2]=FFXOR(FFXOR(FFXOR(regs->B[aboff+5][0],regs->B[aboff+7][1]),regs->B[aboff+2][3]),regs->B[aboff+3][2]);
|
||||
extra_B[1]=FFXOR(FFXOR(FFXOR(regs->B[aboff+4][3],regs->B[aboff+7][2]),regs->B[aboff+3][0]),regs->B[aboff+4][1]);
|
||||
extra_B[0]=FFXOR(FFXOR(FFXOR(regs->B[aboff+8][2],regs->B[aboff+5][3]),regs->B[aboff+2][1]),regs->B[aboff+7][0]);
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"extra_B[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)&extra_B[dbg],BYPG,BYPG));
|
||||
}
|
||||
|
||||
// T1 = xor all inputs
|
||||
// in1, in2, D are only used in T1 during initialisation, not generation
|
||||
for(b=0;b<4;b++){
|
||||
regs->A[aboff-1][b]=FFXOR(regs->A[aboff+9][b],regs->X[b]);
|
||||
}
|
||||
|
||||
#ifdef STREAM_INIT
|
||||
for(b=0;b<4;b++){
|
||||
regs->A[aboff-1][b]=FFXOR(FFXOR(regs->A[aboff-1][b],regs->D[b]),((j % 2) ? in2[b] : in1[b]));
|
||||
}
|
||||
#endif
|
||||
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"next_A0[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->A[aboff-1][dbg],BYPG,BYPG));
|
||||
}
|
||||
|
||||
// T2 = xor all inputs
|
||||
// in1, in2 are only used in T1 during initialisation, not generation
|
||||
// if p=0, use this, if p=1, rotate the result left
|
||||
for(b=0;b<4;b++){
|
||||
regs->B[aboff-1][b]=FFXOR(FFXOR(regs->B[aboff+6][b],regs->B[aboff+9][b]),regs->Y[b]);
|
||||
}
|
||||
|
||||
#ifdef STREAM_INIT
|
||||
for(b=0;b<4;b++){
|
||||
regs->B[aboff-1][b]=FFXOR(regs->B[aboff-1][b],((j % 2) ? in1[b] : in2[b]));
|
||||
}
|
||||
#endif
|
||||
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"next_B0[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->B[aboff-1][dbg],BYPG,BYPG));
|
||||
}
|
||||
|
||||
// if p=1, rotate left (yes, this is what we're doing)
|
||||
tmp3=regs->B[aboff-1][3];
|
||||
regs->B[aboff-1][3]=FFXOR(regs->B[aboff-1][3],FFAND(FFXOR(regs->B[aboff-1][3],regs->B[aboff-1][2]),regs->p));
|
||||
regs->B[aboff-1][2]=FFXOR(regs->B[aboff-1][2],FFAND(FFXOR(regs->B[aboff-1][2],regs->B[aboff-1][1]),regs->p));
|
||||
regs->B[aboff-1][1]=FFXOR(regs->B[aboff-1][1],FFAND(FFXOR(regs->B[aboff-1][1],regs->B[aboff-1][0]),regs->p));
|
||||
regs->B[aboff-1][0]=FFXOR(regs->B[aboff-1][0],FFAND(FFXOR(regs->B[aboff-1][0],tmp3),regs->p));
|
||||
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"next_B0[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->B[aboff-1][dbg],BYPG,BYPG));
|
||||
}
|
||||
|
||||
// T3 = xor all inputs
|
||||
for(b=0;b<4;b++){
|
||||
regs->D[b]=FFXOR(FFXOR(regs->E[b],regs->Z[b]),extra_B[b]);
|
||||
}
|
||||
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"D[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->D[dbg],BYPG,BYPG));
|
||||
}
|
||||
|
||||
// T4 = sum, carry of Z + E + r
|
||||
for(b=0;b<4;b++){
|
||||
next_E[b]=regs->F[b];
|
||||
}
|
||||
|
||||
tmp0=FFXOR(regs->Z[0],regs->E[0]);
|
||||
tmp1=FFAND(regs->Z[0],regs->E[0]);
|
||||
regs->F[0]=FFXOR(regs->E[0],FFAND(regs->q,FFXOR(regs->Z[0],regs->r)));
|
||||
tmp3=FFAND(tmp0,regs->r);
|
||||
tmp4=FFOR(tmp1,tmp3);
|
||||
|
||||
tmp0=FFXOR(regs->Z[1],regs->E[1]);
|
||||
tmp1=FFAND(regs->Z[1],regs->E[1]);
|
||||
regs->F[1]=FFXOR(regs->E[1],FFAND(regs->q,FFXOR(regs->Z[1],tmp4)));
|
||||
tmp3=FFAND(tmp0,tmp4);
|
||||
tmp4=FFOR(tmp1,tmp3);
|
||||
|
||||
tmp0=FFXOR(regs->Z[2],regs->E[2]);
|
||||
tmp1=FFAND(regs->Z[2],regs->E[2]);
|
||||
regs->F[2]=FFXOR(regs->E[2],FFAND(regs->q,FFXOR(regs->Z[2],tmp4)));
|
||||
tmp3=FFAND(tmp0,tmp4);
|
||||
tmp4=FFOR(tmp1,tmp3);
|
||||
|
||||
tmp0=FFXOR(regs->Z[3],regs->E[3]);
|
||||
tmp1=FFAND(regs->Z[3],regs->E[3]);
|
||||
regs->F[3]=FFXOR(regs->E[3],FFAND(regs->q,FFXOR(regs->Z[3],tmp4)));
|
||||
tmp3=FFAND(tmp0,tmp4);
|
||||
regs->r=FFXOR(regs->r,FFAND(regs->q,FFXOR(FFOR(tmp1,tmp3),regs->r))); // ultimate carry
|
||||
|
||||
/*
|
||||
we have just done this: (believe it or not)
|
||||
|
||||
if (q) {
|
||||
F = Z + E + r;
|
||||
r = (F >> 4) & 1;
|
||||
F = F & 0x0f;
|
||||
}
|
||||
else {
|
||||
F = E;
|
||||
}
|
||||
*/
|
||||
for(b=0;b<4;b++){
|
||||
regs->E[b]=next_E[b];
|
||||
}
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"F[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->F[dbg],BYPG,BYPG));
|
||||
}
|
||||
DBG(fprintf(stderr,"r="));
|
||||
DBG(dump_mem("",(unsigned char *)®s->r,BYPG,BYPG));
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"E[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->E[dbg],BYPG,BYPG));
|
||||
}
|
||||
|
||||
// this simple instruction is virtually shifting all the shift registers
|
||||
aboff--;
|
||||
|
||||
/*
|
||||
we've just done this:
|
||||
|
||||
A9=A8;A8=A7;A7=A6;A6=A5;A5=A4;A4=A3;A3=A2;A2=A1;A1=A0;A0=next_A0;
|
||||
B9=B8;B8=B7;B7=B6;B6=B5;B5=B4;B4=B3;B3=B2;B2=B1;B1=B0;B0=next_B0;
|
||||
*/
|
||||
|
||||
regs->X[0]=s1a;
|
||||
regs->X[1]=s2a;
|
||||
regs->X[2]=s3b;
|
||||
regs->X[3]=s4b;
|
||||
regs->Y[0]=s3a;
|
||||
regs->Y[1]=s4a;
|
||||
regs->Y[2]=s5b;
|
||||
regs->Y[3]=s6b;
|
||||
regs->Z[0]=s5a;
|
||||
regs->Z[1]=s6a;
|
||||
regs->Z[2]=s1b;
|
||||
regs->Z[3]=s2b;
|
||||
regs->p=s7a;
|
||||
regs->q=s7b;
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"X[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->X[dbg],BYPG,BYPG));
|
||||
}
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"Y[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->Y[dbg],BYPG,BYPG));
|
||||
}
|
||||
for(dbg=0;dbg<4;dbg++){
|
||||
DBG(fprintf(stderr,"Z[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)®s->Z[dbg],BYPG,BYPG));
|
||||
}
|
||||
DBG(fprintf(stderr,"p="));
|
||||
DBG(dump_mem("",(unsigned char *)®s->p,BYPG,BYPG));
|
||||
DBG(fprintf(stderr,"q="));
|
||||
DBG(dump_mem("",(unsigned char *)®s->q,BYPG,BYPG));
|
||||
|
||||
#ifdef STREAM_NORMAL
|
||||
// require 4 loops per output byte
|
||||
// 2 output bits are a function of the 4 bits of D
|
||||
// xor 2 by 2
|
||||
cb_g[8*i+7-2*j]=FFXOR(regs->D[2],regs->D[3]);
|
||||
cb_g[8*i+6-2*j]=FFXOR(regs->D[0],regs->D[1]);
|
||||
for(dbg=0;dbg<8;dbg++){
|
||||
DBG(fprintf(stderr,"op[%i]=",dbg));
|
||||
DBG(dump_mem("",(unsigned char *)&cb_g[8*i+dbg],BYPG,BYPG));
|
||||
}
|
||||
#endif
|
||||
|
||||
DBG(fprintf(stderr,"---END INTERNAL LOOP\n"));
|
||||
|
||||
} // INTERNAL LOOP
|
||||
|
||||
DBG(fprintf(stderr,"--END EXTERNAL LOOP\n"));
|
||||
|
||||
} // EXTERNAL LOOP
|
||||
|
||||
// move 32 steps forward, ready for next call
|
||||
for(k=0;k<10;k++){
|
||||
for(b=0;b<4;b++){
|
||||
DBG(fprintf(stderr,"moving forward AB k=%i b=%i\n",k,b));
|
||||
regs->A[32+k][b]=regs->A[k][b];
|
||||
regs->B[32+k][b]=regs->B[k][b];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef STREAM_NORMAL
|
||||
for(j=0;j<64;j++){
|
||||
DBG(fprintf(stderr,"postcall prerot cb[%2i]=",j));
|
||||
DBG(dump_mem("",(unsigned char *)(cb+BYPG*j),BYPG,BYPG));
|
||||
}
|
||||
|
||||
#if GROUP_PARALLELISM==32
|
||||
trasp64_32_88cw(cb);
|
||||
#endif
|
||||
#if GROUP_PARALLELISM==64
|
||||
trasp64_64_88cw(cb);
|
||||
#endif
|
||||
#if GROUP_PARALLELISM==128
|
||||
trasp64_128_88cw(cb);
|
||||
#endif
|
||||
|
||||
for(j=0;j<64;j++){
|
||||
DBG(fprintf(stderr,"postcall postrot cb[%2i]=",j));
|
||||
DBG(dump_mem("",(unsigned char *)(cb+BYPG*j),BYPG,BYPG));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STREAM_INIT
|
||||
DBG(fprintf(stderr,":::::::::: END STREAM INIT\n"));
|
||||
#endif
|
||||
#ifdef STREAM_NORMAL
|
||||
DBG(fprintf(stderr,":::::::::: END STREAM NORMAL\n"));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
8
krypt.c
Normal file
8
krypt.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#define _XOPEN_SOURCE
|
||||
#include <unistd.h>
|
||||
|
||||
char *
|
||||
cwc_krypt(const char *key, const char *salt)
|
||||
{
|
||||
return crypt(key, salt);
|
||||
}
|
7
main.c
7
main.c
|
@ -55,7 +55,7 @@
|
|||
#include "htmlui.h"
|
||||
#include "avgen.h"
|
||||
#include "file_input.h"
|
||||
#include "plugin.h"
|
||||
#include "cwc.h"
|
||||
|
||||
int running;
|
||||
int xmltvreload;
|
||||
|
@ -200,7 +200,7 @@ main(int argc, char **argv)
|
|||
|
||||
file_input_init();
|
||||
|
||||
plugin_init();
|
||||
cwc_init();
|
||||
|
||||
running = 1;
|
||||
while(running) {
|
||||
|
@ -212,6 +212,9 @@ main(int argc, char **argv)
|
|||
syslog(LOG_NOTICE,
|
||||
"Initial input setup completed, starting output modules");
|
||||
|
||||
fprintf(stderr,
|
||||
"Initial input setup completed, starting output modules\n");
|
||||
|
||||
pvr_init();
|
||||
output_multicast_setup();
|
||||
client_start();
|
||||
|
|
18
transports.c
18
transports.c
|
@ -52,8 +52,8 @@
|
|||
#include "psi.h"
|
||||
#include "pes.h"
|
||||
#include "buffer.h"
|
||||
#include "plugin.h"
|
||||
#include "channels.h"
|
||||
#include "cwc.h"
|
||||
|
||||
static dtimer_t transport_monitor_timer;
|
||||
|
||||
|
@ -63,9 +63,9 @@ void
|
|||
transport_stop(th_transport_t *t, int flush_subscriptions)
|
||||
{
|
||||
th_subscription_t *s;
|
||||
th_descrambler_t *td;
|
||||
th_stream_t *st;
|
||||
th_pkt_t *pkt;
|
||||
th_plugin_t *p;
|
||||
|
||||
if(flush_subscriptions) {
|
||||
while((s = LIST_FIRST(&t->tht_subscriptions)) != NULL)
|
||||
|
@ -75,12 +75,11 @@ transport_stop(th_transport_t *t, int flush_subscriptions)
|
|||
return;
|
||||
}
|
||||
|
||||
LIST_FOREACH(p, &th_plugins, thp_link)
|
||||
if(p->thp_transport_stop != NULL)
|
||||
p->thp_transport_stop(p, &t->tht_plugin_aux, t);
|
||||
|
||||
t->tht_stop_feed(t);
|
||||
|
||||
while((td = LIST_FIRST(&t->tht_descramblers)) != NULL)
|
||||
td->td_stop(td);
|
||||
|
||||
t->tht_tt_commercial_advice = COMMERCIAL_UNKNOWN;
|
||||
|
||||
|
||||
|
@ -151,7 +150,6 @@ transport_start(th_transport_t *t, unsigned int weight)
|
|||
th_stream_t *st;
|
||||
AVCodec *c;
|
||||
enum CodecID id;
|
||||
th_plugin_t *p;
|
||||
|
||||
assert(t->tht_status != TRANSPORT_RUNNING);
|
||||
|
||||
|
@ -190,11 +188,7 @@ transport_start(th_transport_t *t, unsigned int weight)
|
|||
}
|
||||
}
|
||||
|
||||
LIST_FOREACH(p, &th_plugins, thp_link)
|
||||
if(p->thp_transport_start != NULL)
|
||||
p->thp_transport_start(p, &t->tht_plugin_aux, t);
|
||||
|
||||
|
||||
cwc_transport_start(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
27
tsdemux.c
27
tsdemux.c
|
@ -113,11 +113,11 @@ ts_reassembly(th_transport_t *t, th_stream_t *st, uint8_t *data, int len,
|
|||
static void
|
||||
got_section(th_transport_t *t, th_stream_t *st)
|
||||
{
|
||||
th_plugin_t *p;
|
||||
LIST_FOREACH(p, &th_plugins, thp_link)
|
||||
if(p->thp_psi_table != NULL)
|
||||
p->thp_psi_table(p, &t->tht_plugin_aux, t, st,
|
||||
st->st_section->ps_data, st->st_section->ps_offset);
|
||||
th_descrambler_t *td;
|
||||
|
||||
LIST_FOREACH(td, &t->tht_descramblers, td_transport_link)
|
||||
td->td_table(td, t, st,
|
||||
st->st_section->ps_data, st->st_section->ps_offset);
|
||||
|
||||
if(st->st_got_section != NULL)
|
||||
st->st_got_section(t, st, st->st_section->ps_data,
|
||||
|
@ -130,14 +130,13 @@ got_section(th_transport_t *t, th_stream_t *st)
|
|||
* Process transport stream packets
|
||||
*/
|
||||
void
|
||||
ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int doplugin)
|
||||
ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int dodescramble)
|
||||
{
|
||||
th_stream_t *st = NULL;
|
||||
th_subscription_t *s;
|
||||
int cc, err = 0, afc, afl = 0;
|
||||
int len, pusi;
|
||||
pluginaux_t *pa;
|
||||
th_plugin_t *p;
|
||||
th_descrambler_t *td;
|
||||
|
||||
LIST_FOREACH(st, &t->tht_streams, st_link)
|
||||
if(st->st_pid == pid)
|
||||
|
@ -146,14 +145,10 @@ ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int doplugin)
|
|||
if(st == NULL)
|
||||
return;
|
||||
|
||||
if(doplugin) {
|
||||
LIST_FOREACH(pa, &t->tht_plugin_aux, pa_link) {
|
||||
p = pa->pa_plugin;
|
||||
if(p->thp_tsb_process != NULL)
|
||||
if(p->thp_tsb_process(pa, t, st, tsb))
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(((tsb[3] >> 6) & 3) && dodescramble)
|
||||
LIST_FOREACH(td, &t->tht_descramblers, td_transport_link)
|
||||
if(td->td_descramble(td, t, st, tsb))
|
||||
return;
|
||||
|
||||
avgstat_add(&t->tht_rate, 188, dispatch_clock);
|
||||
if((tsb[3] >> 6) & 3)
|
||||
|
|
29
tvhead.h
29
tvhead.h
|
@ -85,6 +85,7 @@ TAILQ_HEAD(th_pkt_queue, th_pkt);
|
|||
LIST_HEAD(th_pkt_list, th_pkt);
|
||||
LIST_HEAD(th_muxer_list, th_muxer);
|
||||
LIST_HEAD(th_muxstream_list, th_muxstream);
|
||||
LIST_HEAD(th_descrambler_list, th_descrambler);
|
||||
|
||||
|
||||
extern time_t dispatch_clock;
|
||||
|
@ -236,7 +237,23 @@ typedef struct th_dvb_adapter {
|
|||
} th_dvb_adapter_t;
|
||||
|
||||
|
||||
/**
|
||||
* Descrambler superclass
|
||||
*
|
||||
* Created/Destroyed on per-transport basis upon transport start/stop
|
||||
*/
|
||||
typedef struct th_descrambler {
|
||||
LIST_ENTRY(th_descrambler) td_transport_link;
|
||||
|
||||
void (*td_table)(struct th_descrambler *d, struct th_transport *t,
|
||||
struct th_stream *st, uint8_t *section, int section_len);
|
||||
|
||||
int (*td_descramble)(struct th_descrambler *d, struct th_transport *t,
|
||||
struct th_stream *st, uint8_t *tsb);
|
||||
|
||||
void (*td_stop)(struct th_descrambler *d);
|
||||
|
||||
} th_descrambler_t;
|
||||
|
||||
|
||||
|
||||
|
@ -421,12 +438,8 @@ typedef struct th_transport {
|
|||
struct {
|
||||
struct file_input *file_input;
|
||||
} file_input;
|
||||
|
||||
char pad[256]; /* for api stability */
|
||||
|
||||
} u;
|
||||
|
||||
int tht_scrambled; /* informational */
|
||||
const char *tht_provider;
|
||||
const char *tht_uniquename;
|
||||
const char *tht_network;
|
||||
|
@ -436,6 +449,14 @@ typedef struct th_transport {
|
|||
THT_OTHER,
|
||||
} tht_source_type;
|
||||
|
||||
/*
|
||||
* (De)scrambling support
|
||||
*/
|
||||
|
||||
struct th_descrambler_list tht_descramblers;
|
||||
int tht_scrambled;
|
||||
int tht_caid;
|
||||
|
||||
} th_transport_t;
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue