# crypto algorithms
SRCS-${CONFIG_SSL} += src/descrambler/algo/libaesdec.c
+SRCS-${CONFIG_SSL} += src/descrambler/algo/libaes128dec.c
SRCS-${CONFIG_SSL} += src/descrambler/algo/libdesdec.c
# DBUS
struct mpegts_mux;
struct th_descrambler_data;
-#define DESCRAMBLER_NONE 0
-#define DESCRAMBLER_CSA_CBC 1
-#define DESCRAMBLER_DES_NCB 2 /* no block cipher mode! */
-#define DESCRAMBLER_AES_ECB 3
+#define DESCRAMBLER_NONE 0
+/* 64-bit keys */
+#define DESCRAMBLER_CSA_CBC 1
+#define DESCRAMBLER_DES_NCB 2 /* no block cipher mode! */
+#define DESCRAMBLER_AES_ECB 3
+/* 128-bit keys */
+#define DESCRAMBLER_AES128_ECB 16
+
+#define DESCRAMBLER_KEY_SIZE(type) ((type >= DESCRAMBLER_AES128_ECB) ? 16 : 8)
/**
* Descrambler superclass
--- /dev/null
+/*
+ * libaesdec.c
+ *
+ * Created on: Jun 22, 2014
+ * Author: spdfrk1
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "openssl/aes.h"
+
+#include "libaes128dec.h"
+
+/* key structure */
+typedef struct aes128_priv {
+ AES_KEY keys[2]; /* 0 = even, 1 = odd */
+} aes128_priv_t;
+
+/* even cw represents one full 128-bit AES key */
+void aes128_set_even_control_word(void *keys, const uint8_t *pk)
+{
+ AES_set_decrypt_key(pk, 128, &((aes128_priv_t *) keys)->keys[0]);
+}
+
+/* odd cw represents one full 128-bit AES key */
+void aes128_set_odd_control_word(void *keys, const uint8_t *pk)
+{
+ AES_set_decrypt_key(pk, 128, &((aes128_priv_t *) keys)->keys[1]);
+}
+
+/* set control words */
+void aes128_set_control_words(void *keys,
+ const uint8_t *ev,
+ const uint8_t *od)
+{
+ AES_set_decrypt_key(ev, 128, &((aes128_priv_t *) keys)->keys[0]);
+ AES_set_decrypt_key(od, 128, &((aes128_priv_t *) keys)->keys[1]);
+}
+
+/* allocate key structure */
+void * aes128_get_priv_struct(void)
+{
+ aes128_priv_t *keys;
+
+ keys = (aes128_priv_t *) malloc(sizeof(aes128_priv_t));
+ if (keys) {
+ static const uint8_t pk[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ aes128_set_control_words(keys, pk, pk);
+ }
+ return keys;
+}
+
+/* free key structure */
+void aes128_free_priv_struct(void *keys)
+{
+ free(keys);
+}
+
+/* decrypt */
+void aes128_decrypt_packet(void *keys, const uint8_t *pkt)
+{
+ uint_fast8_t ev_od = 0;
+ uint_fast8_t xc0, offset;
+ AES_KEY *k;
+
+ // skip reserved and not encrypted pkt
+ if (((xc0 = pkt[3]) & 0x80) == 0)
+ return;
+
+ ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd
+ ((uint8_t *)pkt)[3] = xc0 & 0x3f; // consider it decrypted now
+ if (xc0 & 0x20) { // incomplete packet
+ offset = 4 + pkt[4] + 1;
+ if (offset + 16 > 188) { // decrypted==encrypted!
+ return; // this doesn't need more processing
+ }
+ } else {
+ offset = 4;
+ }
+
+ k = &((aes128_priv_t *) keys)->keys[ev_od];
+ for (; offset <= (188 - 16); offset += 16) {
+ AES_ecb_encrypt(pkt + offset, (uint8_t *)(pkt + offset), k, AES_DECRYPT);
+ }
+}
--- /dev/null
+/*
+ * libaes128dec.h
+ *
+ * Created on: Jun 22, 2014
+ * Author: spdfrk1
+ */
+
+#ifndef LIBAES128DEC_H_
+#define LIBAES128DEC_H_
+
+#include <stdint.h>
+#include "build.h"
+
+#if ENABLE_SSL
+
+void *aes128_get_priv_struct(void);
+void aes128_free_priv_struct(void *keys);
+void aes128_set_control_words(void *keys, const uint8_t *even, const uint8_t *odd);
+void aes128_set_even_control_word(void *keys, const uint8_t *even);
+void aes128_set_odd_control_word(void *keys, const uint8_t *odd);
+void aes128_decrypt_packet(void *keys, const uint8_t *pkt);
+
+#else
+
+// empty functions
+static inline void *aes128_get_priv_struct(void) { return NULL; };
+static inline void aes128_free_priv_struct(void *keys) { return; };
+static inline void aes128_set_control_words(void *keys, const uint8_t *even, const uint8_t *odd) { return; };
+static inline void aes128_set_even_control_word(void *keys, const uint8_t *even) { return; };
+static inline void aes128_set_odd_control_word(void *keys, const uint8_t *odd) { return; };
+static inline void aes128_decrypt_packet(void *keys, const uint8_t *pkt) { return; };
+
+#endif
+
+#endif /* LIBAES128DEC_H_ */
/*
* libaesdec.c
*
- * Created on: Jun 22, 2014
- * Author: spdfrk1
+ * Based on code from spdfrk1
*/
#include <sys/types.h>
AES_KEY keys[2]; /* 0 = even, 1 = odd */
} aes_priv_t;
-/* even cw represents one full 128-bit AES key */
+/* even cw represents one full 64-bit AES key */
void aes_set_even_control_word(void *keys, const uint8_t *pk)
{
- AES_set_decrypt_key(pk, 128, &((aes_priv_t *) keys)->keys[0]);
+ AES_set_decrypt_key(pk, 64, &((aes_priv_t *) keys)->keys[0]);
}
-/* odd cw represents one full 128-bit AES key */
+/* odd cw represents one full 64-bit AES key */
void aes_set_odd_control_word(void *keys, const uint8_t *pk)
{
- AES_set_decrypt_key(pk, 128, &((aes_priv_t *) keys)->keys[1]);
+ AES_set_decrypt_key(pk, 64, &((aes_priv_t *) keys)->keys[1]);
}
/* set control words */
const uint8_t *ev,
const uint8_t *od)
{
- AES_set_decrypt_key(ev, 128, &((aes_priv_t *) keys)->keys[0]);
- AES_set_decrypt_key(od, 128, &((aes_priv_t *) keys)->keys[1]);
+ AES_set_decrypt_key(ev, 64, &((aes_priv_t *) keys)->keys[0]);
+ AES_set_decrypt_key(od, 64, &((aes_priv_t *) keys)->keys[1]);
}
/* allocate key structure */
}
k = &((aes_priv_t *) keys)->keys[ev_od];
- for (; offset <= (188 - 16); offset += 16) {
+ for (; offset <= (188 - 8); offset += 8) {
AES_ecb_encrypt(pkt + offset, (uint8_t *)(pkt + offset), k, AES_DECRYPT);
}
}
&caclient_ccw_csa_cbc_class,
&caclient_ccw_des_ncb_class,
&caclient_ccw_aes_ecb_class,
+ &caclient_ccw_aes128_ecb_class,
#endif
NULL
};
extern const idclass_t caclient_ccw_csa_cbc_class;
extern const idclass_t caclient_ccw_des_ncb_class;
extern const idclass_t caclient_ccw_aes_ecb_class;
+extern const idclass_t caclient_ccw_aes128_ecb_class;
TAILQ_HEAD(caclient_entry_queue, caclient);
return DESCRAMBLER_DES_NCB;
if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_aes_ecb_class))
return DESCRAMBLER_AES_ECB;
+ if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_aes128_ecb_class))
+ return DESCRAMBLER_AES128_ECB;
return DESCRAMBLER_CSA_CBC;
}
{
constcw_t *ccw = (constcw_t *)cac;
- if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_csa_cbc_class))
- return 8;
- if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_des_ncb_class))
- return 8;
- return 16;
+ if (idnode_is_instance(&ccw->cac_id, &caclient_ccw_aes128_ecb_class))
+ return 16;
+ return 8;
}
/*
.ic_super = &caclient_class,
.ic_class = "caclient_ccw_aes_ecb",
.ic_caption = N_("AES ECB Constant Code Word"),
+ .ic_properties = (const property_t[]){
+ {
+ .type = PT_U16,
+ .id = "caid",
+ .name = N_("CA ID"),
+ .desc = N_("Conditional Access Identification."),
+ .off = offsetof(constcw_t, ccw_caid),
+ .opts = PO_HEXA,
+ .def.u16 = 0x2600
+ },
+ {
+ .type = PT_U32,
+ .id = "providerid",
+ .name = N_("Provider ID"),
+ .desc = N_("The provider's ID."),
+ .off = offsetof(constcw_t, ccw_providerid),
+ .opts = PO_HEXA,
+ .def.u32 = 0
+ },
+ {
+ .type = PT_U16,
+ .id = "tsid",
+ .name = N_("Transponder ID"),
+ .desc = N_("The transponder ID."),
+ .off = offsetof(constcw_t, ccw_tsid),
+ .opts = PO_HEXA,
+ .def.u16 = 1,
+ },
+ {
+ .type = PT_U16,
+ .id = "sid",
+ .name = N_("Service ID"),
+ .desc = N_("The service ID."),
+ .off = offsetof(constcw_t, ccw_sid),
+ .opts = PO_HEXA,
+ .def.u16 = 1,
+ },
+ {
+ .type = PT_STR,
+ .id = "key_even",
+ .name = N_("Even key"),
+ .desc = N_("Even key."),
+ .set = constcw_class_key_even_set,
+ .get = constcw_class_key_even_get,
+ .opts = PO_PASSWORD,
+ .def.s = "00:00:00:00:00:00:00:00",
+ },
+ {
+ .type = PT_STR,
+ .id = "key_odd",
+ .name = N_("Odd key"),
+ .desc = N_("Odd key."),
+ .set = constcw_class_key_odd_set,
+ .get = constcw_class_key_odd_get,
+ .opts = PO_PASSWORD,
+ .def.s = "00:00:00:00:00:00:00:00",
+ },
+ { }
+ }
+};
+
+const idclass_t caclient_ccw_aes128_ecb_class =
+{
+ .ic_super = &caclient_class,
+ .ic_class = "caclient_ccw_aes128_ecb",
+ .ic_caption = N_("AES128 ECB Constant Code Word"),
.ic_properties = (const property_t[]){
{
.type = PT_U16,
th_descrambler_t *td;
tsdebugcw_service_t *ct;
tsdebugcw_request_t *ctr;
- int keylen = type == DESCRAMBLER_AES_ECB ? 16 : 8;
+ int keylen = DESCRAMBLER_KEY_SIZE(type);
LIST_FOREACH(td, &t->s_descramblers, td_service_link)
if (td->td_stop == tsdebugcw_service_destroy)
#include "input.h"
#include "input/mpegts/tsdemux.h"
+#include "descrambler/algo/libaesdec.h"
+#include "descrambler/algo/libaes128dec.h"
+#include "descrambler/algo/libdesdec.h"
+
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
const uint8_t *tsb2, *end2;
for (tsb2 = tsb, end2 = tsb + len; tsb2 < end2; tsb2 += 188)
- aes_decrypt_packet(csa->csa_aes_priv, tsb2);
+ aes_decrypt_packet(csa->csa_priv, tsb2);
+ ts_recv_packet2(s, tsb, len);
+}
+
+static void
+tvhcsa_aes128_ecb_descramble
+ ( tvhcsa_t *csa, struct mpegts_service *s, const uint8_t *tsb, int len )
+{
+ const uint8_t *tsb2, *end2;
+
+ for (tsb2 = tsb, end2 = tsb + len; tsb2 < end2; tsb2 += 188)
+ aes128_decrypt_packet(csa->csa_priv, tsb2);
ts_recv_packet2(s, tsb, len);
}
const uint8_t *tsb2, *end2;
for (tsb2 = tsb, end2 = tsb + len; tsb2 < end2; tsb2 += 188)
- des_decrypt_packet(csa->csa_des_priv, tsb2);
+ des_decrypt_packet(csa->csa_priv, tsb2);
ts_recv_packet2(s, tsb, len);
}
#endif
break;
case DESCRAMBLER_DES_NCB:
- csa->csa_des_priv = des_get_priv_struct();
+ csa->csa_priv = des_get_priv_struct();
csa->csa_descramble = tvhcsa_des_ncb_descramble;
csa->csa_flush = tvhcsa_empty_flush;
csa->csa_keylen = 8;
break;
case DESCRAMBLER_AES_ECB:
- csa->csa_aes_priv = aes_get_priv_struct();
+ csa->csa_priv = aes_get_priv_struct();
csa->csa_descramble = tvhcsa_aes_ecb_descramble;
csa->csa_flush = tvhcsa_empty_flush;
+ csa->csa_keylen = 8;
+ break;
+ case DESCRAMBLER_AES128_ECB:
+ csa->csa_priv = aes128_get_priv_struct();
+ csa->csa_descramble = tvhcsa_aes128_ecb_descramble;
+ csa->csa_flush = tvhcsa_empty_flush;
csa->csa_keylen = 16;
break;
default:
#endif
break;
case DESCRAMBLER_DES_NCB:
- des_set_even_control_word(csa->csa_des_priv, even);
+ des_set_even_control_word(csa->csa_priv, even);
break;
case DESCRAMBLER_AES_ECB:
- aes_set_even_control_word(csa->csa_aes_priv, even);
+ aes_set_even_control_word(csa->csa_priv, even);
+ break;
+ case DESCRAMBLER_AES128_ECB:
+ aes128_set_even_control_word(csa->csa_priv, even);
break;
default:
assert(0);
#endif
break;
case DESCRAMBLER_DES_NCB:
- des_set_odd_control_word(csa->csa_des_priv, odd);
+ des_set_odd_control_word(csa->csa_priv, odd);
break;
case DESCRAMBLER_AES_ECB:
- aes_set_odd_control_word(csa->csa_aes_priv, odd);
+ aes_set_odd_control_word(csa->csa_priv, odd);
+ break;
+ case DESCRAMBLER_AES128_ECB:
+ aes128_set_odd_control_word(csa->csa_priv, odd);
break;
default:
assert(0);
free(csa->csa_tsbcluster);
csa->csa_tsbcluster = NULL;
}
- if (csa->csa_aes_priv) {
- aes_free_priv_struct(csa->csa_aes_priv);
- csa->csa_aes_priv = NULL;
- }
- if (csa->csa_des_priv) {
- des_free_priv_struct(csa->csa_des_priv);
- csa->csa_des_priv = NULL;
+ if (csa->csa_priv) {
+ switch (csa->csa_type) {
+ case DESCRAMBLER_CSA_CBC:
+ break;
+ case DESCRAMBLER_DES_NCB:
+ des_free_priv_struct(csa->csa_priv);
+ break;
+ case DESCRAMBLER_AES_ECB:
+ aes_free_priv_struct(csa->csa_priv);
+ break;
+ case DESCRAMBLER_AES128_ECB:
+ aes128_free_priv_struct(csa->csa_priv);
+ break;
+ default:
+ assert(0);
+ }
+ csa->csa_priv = NULL;
}
+ csa->csa_type = 0;
+ csa->csa_keylen = 0;
}
#include "ffdecsa/FFdecsa.h"
#endif
-#include "algo/libaesdec.h"
-#include "algo/libdesdec.h"
-
typedef struct tvhcsa
{
#else
void *csa_keys;
#endif
- void *csa_aes_priv;
- void *csa_des_priv;
-
+ void *csa_priv;
+
} tvhcsa_t;
#if ENABLE_TVHCSA