Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 426518 | Differences between
and this patch

Collapse All | Expand All

(-)CMakeLists.txt (-1 / +36 lines)
Lines 101-106 Link Here
101
    ${CMAKE_CURRENT_SOURCE_DIR}/csctapi
101
    ${CMAKE_CURRENT_SOURCE_DIR}/csctapi
102
    ${CMAKE_CURRENT_SOURCE_DIR}/cscrypt
102
    ${CMAKE_CURRENT_SOURCE_DIR}/cscrypt
103
    ${CMAKE_CURRENT_SOURCE_DIR}/minilzo
103
    ${CMAKE_CURRENT_SOURCE_DIR}/minilzo
104
    ${CMAKE_CURRENT_SOURCE_DIR}/ffdecsa
104
    ${CMAKE_CURRENT_SOURCE_DIR}/extapi/cygwin
105
    ${CMAKE_CURRENT_SOURCE_DIR}/extapi/cygwin
105
    /usr/include/w32api
106
    /usr/include/w32api
106
    ${OPTIONAL_INCLUDE_DIR}
107
    ${OPTIONAL_INCLUDE_DIR}
Lines 110-115 Link Here
110
    ${CMAKE_CURRENT_SOURCE_DIR}/csctapi
111
    ${CMAKE_CURRENT_SOURCE_DIR}/csctapi
111
    ${CMAKE_CURRENT_SOURCE_DIR}/cscrypt
112
    ${CMAKE_CURRENT_SOURCE_DIR}/cscrypt
112
    ${CMAKE_CURRENT_SOURCE_DIR}/minilzo
113
    ${CMAKE_CURRENT_SOURCE_DIR}/minilzo
114
    ${CMAKE_CURRENT_SOURCE_DIR}/ffdecsa
113
    ${OPTIONAL_INCLUDE_DIR}
115
    ${OPTIONAL_INCLUDE_DIR}
114
    )
116
    )
115
endif (OSCamOperatingSystem MATCHES "Windows/Cygwin")
117
endif (OSCamOperatingSystem MATCHES "Windows/Cygwin")
Lines 420-425 Link Here
420
# Manage config.h based on command line parameters
422
# Manage config.h based on command line parameters
421
# Manipulate config file based on given parameters and read unset parameters
423
# Manipulate config file based on given parameters and read unset parameters
422
424
425
execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --enabled WITH_EMU OUTPUT_VARIABLE CONFIG_WITH_EMU OUTPUT_STRIP_TRAILING_WHITESPACE)
426
if (CONFIG_WITH_EMU MATCHES "Y" AND NOT WITH_EMU EQUAL 1)
427
	add_definitions ("-DWITH_EMU")
428
	set (WITH_EMU "1")
429
	message(STATUS "  EMU is added by config compiling with EMU")
430
endif(CONFIG_WITH_EMU MATCHES "Y" AND NOT WITH_EMU EQUAL 1)
431
423
execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --show-valid OUTPUT_VARIABLE config_vars_string OUTPUT_STRIP_TRAILING_WHITESPACE)
432
execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --show-valid OUTPUT_VARIABLE config_vars_string OUTPUT_STRIP_TRAILING_WHITESPACE)
424
string(REGEX MATCHALL "[A-Z0-9_]+" config_vars ${config_vars_string})
433
string(REGEX MATCHALL "[A-Z0-9_]+" config_vars ${config_vars_string})
425
434
Lines 449-454 Link Here
449
add_subdirectory (csctapi)
458
add_subdirectory (csctapi)
450
add_subdirectory (minilzo)
459
add_subdirectory (minilzo)
451
add_subdirectory (cscrypt)
460
add_subdirectory (cscrypt)
461
add_subdirectory (ffdecsa)
452
462
453
#----------------------- file groups ------------------------------
463
#----------------------- file groups ------------------------------
454
execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --enabled MODULE_CAMD33 OUTPUT_VARIABLE CAMD33 OUTPUT_STRIP_TRAILING_WHITESPACE)
464
execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --enabled MODULE_CAMD33 OUTPUT_VARIABLE CAMD33 OUTPUT_STRIP_TRAILING_WHITESPACE)
Lines 498-504 Link Here
498
508
499
set (exe_name "oscam")
509
set (exe_name "oscam")
500
add_executable (${exe_name} ${exe_srcs} ${exe_hdrs})
510
add_executable (${exe_name} ${exe_srcs} ${exe_hdrs})
501
target_link_libraries (${exe_name} ${csoscam} ${csmodules} ${csreaders} csctapi cscrypt minilzo)
511
target_link_libraries (${exe_name} ${csoscam} ${csmodules} ${csreaders} csctapi cscrypt minilzo ffdecsa)
502
if(HAVE_LIBRT AND HAVE_LIBUSB)
512
if(HAVE_LIBRT AND HAVE_LIBUSB)
503
   if (LIBUSBDIR)
513
   if (LIBUSBDIR)
504
	set (libusb_link "imp_libusb")
514
	set (libusb_link "imp_libusb")
Lines 647-652 Link Here
647
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine COMMAND tr -d '\n' OUTPUT_VARIABLE CS_TARGET)
657
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine COMMAND tr -d '\n' OUTPUT_VARIABLE CS_TARGET)
648
add_definitions ("-D'CS_TARGET=\"${CS_TARGET}\"'")
658
add_definitions ("-D'CS_TARGET=\"${CS_TARGET}\"'")
649
#----------------------- global compile and link options ------------------------------
659
#----------------------- global compile and link options ------------------------------
660
#enable sse2 on x86
661
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
662
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3")
663
endif (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
664
650
# disable warning about unused but set variables in gcc 4.6+
665
# disable warning about unused but set variables in gcc 4.6+
651
if (CMAKE_COMPILER_IS_GNUCC)
666
if (CMAKE_COMPILER_IS_GNUCC)
652
    execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
667
    execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
Lines 731-736 Link Here
731
746
732
#--------------------------------------------------------------------------------
747
#--------------------------------------------------------------------------------
733
748
749
if (NOT OSCamOperatingSystem MATCHES "Mac OS X")
750
if (NOT DEFINED ENV{ANDROID_NDK})
751
if (NOT DEFINED ENV{ANDROID_STANDALONE_TOOLCHAIN})
752
  if(WITH_EMU)
753
	if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key)
754
 		execute_process(COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key ${CMAKE_CURRENT_BINARY_DIR}/SoftCam.Key)
755
	else(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key)
756
		execute_process(COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/SoftCam.Key)
757
	endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key)
758
	execute_process(COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/utils/SoftCam.Key)
759
	set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--format=binary -Wl,SoftCam.Key -Wl,--format=default" ) 
760
 endif(WITH_EMU)
761
endif (NOT DEFINED ENV{ANDROID_STANDALONE_TOOLCHAIN})
762
endif (NOT DEFINED ENV{ANDROID_NDK})
763
endif (NOT OSCamOperatingSystem MATCHES "Mac OS X")
764
734
#----------------------- installation -----------------------------
765
#----------------------- installation -----------------------------
735
766
736
file (GLOB config_files "${CMAKE_CURRENT_SOURCE_DIR}/Distribution/oscam.*")
767
file (GLOB config_files "${CMAKE_CURRENT_SOURCE_DIR}/Distribution/oscam.*")
Lines 819-822 Link Here
819
 endif(STATICLIBUSB AND NOT LIBUSBDIR)
850
 endif(STATICLIBUSB AND NOT LIBUSBDIR)
820
endif (HAVE_LIBUSB)
851
endif (HAVE_LIBUSB)
821
852
853
if (WITH_EMU)
854
	message(STATUS "  Compile with EMU support")
855
endif (WITH_EMU)
856
822
message (STATUS "")
857
message (STATUS "")
(-)Makefile (-1 / +23 lines)
Lines 65-70 Link Here
65
65
66
LDFLAGS = -Wl,--gc-sections
66
LDFLAGS = -Wl,--gc-sections
67
67
68
TARGETHELP := $(shell $(CC) --target-help 2>&1)
69
ifneq (,$(findstring sse2,$(TARGETHELP)))
70
override CFLAGS += -fexpensive-optimizations -mmmx -msse -msse2 -msse3
71
else
72
override CFLAGS += -fexpensive-optimizations
73
endif
74
68
# The linker for powerpc have bug that prevents --gc-sections from working
75
# The linker for powerpc have bug that prevents --gc-sections from working
69
# Check for the linker version and if it matches disable --gc-sections
76
# Check for the linker version and if it matches disable --gc-sections
70
# For more information about the bug see:
77
# For more information about the bug see:
Lines 268-273 Link Here
268
SRC-$(CONFIG_MODULE_CCCAM) += module-cccam.c
275
SRC-$(CONFIG_MODULE_CCCAM) += module-cccam.c
269
SRC-$(CONFIG_MODULE_CCCSHARE) += module-cccshare.c
276
SRC-$(CONFIG_MODULE_CCCSHARE) += module-cccshare.c
270
SRC-$(CONFIG_MODULE_CONSTCW) += module-constcw.c
277
SRC-$(CONFIG_MODULE_CONSTCW) += module-constcw.c
278
SRC-$(CONFIG_WITH_EMU) += module-emulator.c
279
SRC-$(CONFIG_WITH_EMU) += module-emulator-osemu.c
280
SRC-$(CONFIG_WITH_EMU) += module-emulator-stream.c
281
SRC-$(CONFIG_WITH_EMU) += ffdecsa/ffdecsa.c
282
UNAME := $(shell uname -s)
283
ifneq ($(UNAME),Darwin)
284
ifndef ANDROID_NDK
285
ifndef ANDROID_STANDALONE_TOOLCHAIN
286
ifeq "$(CONFIG_WITH_EMU)" "y"
287
TOUCH_SK := $(shell touch SoftCam.Key)
288
override LDFLAGS += -Wl,--format=binary -Wl,SoftCam.Key -Wl,--format=default
289
endif
290
endif
291
endif
292
endif
271
SRC-$(CONFIG_CS_CACHEEX) += module-csp.c
293
SRC-$(CONFIG_CS_CACHEEX) += module-csp.c
272
SRC-$(CONFIG_CW_CYCLE_CHECK) += module-cw-cycle-check.c
294
SRC-$(CONFIG_CW_CYCLE_CHECK) += module-cw-cycle-check.c
273
SRC-$(CONFIG_WITH_AZBOX) += module-dvbapi-azbox.c
295
SRC-$(CONFIG_WITH_AZBOX) += module-dvbapi-azbox.c
Lines 365-371 Link Here
365
# starts the compilation.
387
# starts the compilation.
366
all:
388
all:
367
	@./config.sh --use-flags "$(USE_FLAGS)" --objdir "$(OBJDIR)" --make-config.mak
389
	@./config.sh --use-flags "$(USE_FLAGS)" --objdir "$(OBJDIR)" --make-config.mak
368
	@-mkdir -p $(OBJDIR)/cscrypt $(OBJDIR)/csctapi $(OBJDIR)/minilzo $(OBJDIR)/webif
390
	@-mkdir -p $(OBJDIR)/cscrypt $(OBJDIR)/csctapi $(OBJDIR)/minilzo $(OBJDIR)/ffdecsa $(OBJDIR)/webif
369
	@-printf "\
391
	@-printf "\
370
+-------------------------------------------------------------------------------\n\
392
+-------------------------------------------------------------------------------\n\
371
| OSCam ver: $(VER) rev: $(SVN_REV) target: $(TARGET)\n\
393
| OSCam ver: $(VER) rev: $(SVN_REV) target: $(TARGET)\n\
(-)config.h (+1 lines)
Lines 1-6 Link Here
1
#ifndef CONFIG_H_
1
#ifndef CONFIG_H_
2
#define CONFIG_H_
2
#define CONFIG_H_
3
3
4
#define WITH_EMU 1
4
#define WEBIF 1
5
#define WEBIF 1
5
#define WEBIF_LIVELOG 1
6
#define WEBIF_LIVELOG 1
6
#define WEBIF_JQUERY 1
7
#define WEBIF_JQUERY 1
(-)config.sh (-6 / +11 lines)
Lines 1-6 Link Here
1
#!/bin/sh
1
#!/bin/sh
2
2
3
addons="WEBIF WEBIF_LIVELOG WEBIF_JQUERY TOUCH WITH_SSL HAVE_DVBAPI READ_SDT_CHARSETS IRDETO_GUESSING CS_ANTICASC WITH_DEBUG MODULE_MONITOR WITH_LB CS_CACHEEX CW_CYCLE_CHECK LCDSUPPORT LEDSUPPORT CLOCKFIX IPV6SUPPORT"
3
addons="WEBIF WEBIF_LIVELOG WEBIF_JQUERY TOUCH WITH_SSL HAVE_DVBAPI READ_SDT_CHARSETS IRDETO_GUESSING CS_ANTICASC WITH_DEBUG MODULE_MONITOR WITH_LB CS_CACHEEX CW_CYCLE_CHECK LCDSUPPORT LEDSUPPORT CLOCKFIX IPV6SUPPORT WITH_EMU"
4
protocols="MODULE_CAMD33 MODULE_CAMD35 MODULE_CAMD35_TCP MODULE_NEWCAMD MODULE_CCCAM MODULE_CCCSHARE MODULE_GBOX MODULE_RADEGAST MODULE_SCAM MODULE_SERIAL MODULE_CONSTCW MODULE_PANDORA MODULE_GHTTP"
4
protocols="MODULE_CAMD33 MODULE_CAMD35 MODULE_CAMD35_TCP MODULE_NEWCAMD MODULE_CCCAM MODULE_CCCSHARE MODULE_GBOX MODULE_RADEGAST MODULE_SCAM MODULE_SERIAL MODULE_CONSTCW MODULE_PANDORA MODULE_GHTTP"
5
readers="READER_NAGRA READER_IRDETO READER_CONAX READER_CRYPTOWORKS READER_SECA READER_VIACCESS READER_VIDEOGUARD READER_DRE READER_TONGFANG READER_BULCRYPT READER_GRIFFIN READER_DGCRYPT"
5
readers="READER_NAGRA READER_IRDETO READER_CONAX READER_CRYPTOWORKS READER_SECA READER_VIACCESS READER_VIDEOGUARD READER_DRE READER_TONGFANG READER_BULCRYPT READER_GRIFFIN READER_DGCRYPT"
6
card_readers="CARDREADER_PHOENIX CARDREADER_INTERNAL CARDREADER_SC8IN1 CARDREADER_MP35 CARDREADER_SMARGO CARDREADER_DB2COM CARDREADER_STAPI CARDREADER_STAPI5 CARDREADER_STINGER CARDREADER_DRECAS"
6
card_readers="CARDREADER_PHOENIX CARDREADER_INTERNAL CARDREADER_SC8IN1 CARDREADER_MP35 CARDREADER_SMARGO CARDREADER_DB2COM CARDREADER_STAPI CARDREADER_STAPI5 CARDREADER_STINGER CARDREADER_DRECAS"
Lines 24-29 Link Here
24
# CONFIG_LEDSUPPORT=n
24
# CONFIG_LEDSUPPORT=n
25
CONFIG_CLOCKFIX=y
25
CONFIG_CLOCKFIX=y
26
# CONFIG_IPV6SUPPORT=n
26
# CONFIG_IPV6SUPPORT=n
27
CONFIG_WITH_EMU=y
27
# CONFIG_MODULE_CAMD33=n
28
# CONFIG_MODULE_CAMD33=n
28
CONFIG_MODULE_CAMD35=y
29
CONFIG_MODULE_CAMD35=y
29
CONFIG_MODULE_CAMD35_TCP=y
30
CONFIG_MODULE_CAMD35_TCP=y
Lines 289-300 Link Here
289
290
290
update_deps() {
291
update_deps() {
291
	# Calculate dependencies
292
	# Calculate dependencies
292
	enabled_any $(get_opts readers) $(get_opts card_readers) && enable_opt WITH_CARDREADER >/dev/null
293
	enabled_any $(get_opts readers) $(get_opts card_readers) WITH_EMU && enable_opt WITH_CARDREADER >/dev/null
293
	disabled_all $(get_opts readers) $(get_opts card_readers) && disable_opt WITH_CARDREADER >/dev/null
294
	disabled_all $(get_opts readers) $(get_opts card_readers) WITH_EMU && disable_opt WITH_CARDREADER >/dev/null
294
	disabled WEBIF && disable_opt WEBIF_LIVELOG >/dev/null
295
	disabled WEBIF && disable_opt WEBIF_LIVELOG >/dev/null
295
	disabled WEBIF && disable_opt WEBIF_JQUERY >/dev/null
296
	disabled WEBIF && disable_opt WEBIF_JQUERY >/dev/null
296
	enabled MODULE_CCCSHARE && enable_opt MODULE_CCCAM >/dev/null
297
	enabled MODULE_CCCSHARE && enable_opt MODULE_CCCAM >/dev/null
297
	enabled_any CARDREADER_DB2COM CARDREADER_MP35 CARDREADER_SC8IN1 CARDREADER_STINGER && enable_opt CARDREADER_PHOENIX >/dev/null
298
	enabled_any CARDREADER_DB2COM CARDREADER_MP35 CARDREADER_SC8IN1 CARDREADER_STINGER && enable_opt CARDREADER_PHOENIX >/dev/null
299
	enabled WITH_EMU && enable_opt READER_VIACCESS >/dev/null
300
	enabled WITH_EMU && enable_opt READER_DRE >/dev/null
301
	enabled WITH_EMU && enable_opt MODULE_NEWCAMD >/dev/null
298
}
302
}
299
303
300
list_config() {
304
list_config() {
Lines 344-352 Link Here
344
	not_have_flag USE_LIBCRYPTO && echo "CONFIG_LIB_AES=y" || echo "# CONFIG_LIB_AES=n"
348
	not_have_flag USE_LIBCRYPTO && echo "CONFIG_LIB_AES=y" || echo "# CONFIG_LIB_AES=n"
345
	enabled MODULE_CCCAM && echo "CONFIG_LIB_RC6=y" || echo "# CONFIG_LIB_RC6=n"
349
	enabled MODULE_CCCAM && echo "CONFIG_LIB_RC6=y" || echo "# CONFIG_LIB_RC6=n"
346
	not_have_flag USE_LIBCRYPTO && enabled MODULE_CCCAM && echo "CONFIG_LIB_SHA1=y" || echo "# CONFIG_LIB_SHA1=n"
350
	not_have_flag USE_LIBCRYPTO && enabled MODULE_CCCAM && echo "CONFIG_LIB_SHA1=y" || echo "# CONFIG_LIB_SHA1=n"
347
	enabled_any READER_DRE MODULE_SCAM READER_VIACCESS && echo "CONFIG_LIB_DES=y" || echo "# CONFIG_LIB_DES=n"
351
	enabled_any READER_DRE MODULE_SCAM READER_VIACCESS WITH_EMU && echo "CONFIG_LIB_DES=y" || echo "# CONFIG_LIB_DES=n"
348
	enabled_any MODULE_CCCAM READER_NAGRA READER_SECA && echo "CONFIG_LIB_IDEA=y" || echo "# CONFIG_LIB_IDEA=n"
352
	enabled_any MODULE_CCCAM READER_NAGRA READER_SECA WITH_EMU && echo "CONFIG_LIB_IDEA=y" || echo "# CONFIG_LIB_IDEA=n"
349
	not_have_flag USE_LIBCRYPTO && enabled_any READER_CONAX READER_CRYPTOWORKS READER_NAGRA && echo "CONFIG_LIB_BIGNUM=y" || echo "# CONFIG_LIB_BIGNUM=n"
353
	not_have_flag USE_LIBCRYPTO && enabled_any READER_CONAX READER_CRYPTOWORKS READER_NAGRA WITH_EMU && echo "CONFIG_LIB_BIGNUM=y" || echo "# CONFIG_LIB_BIGNUM=n"
350
}
354
}
351
355
352
make_config_c() {
356
make_config_c() {
Lines 457-462 Link Here
457
		LEDSUPPORT			"LED support"							$(check_test "LEDSUPPORT") \
461
		LEDSUPPORT			"LED support"							$(check_test "LEDSUPPORT") \
458
		CLOCKFIX			"Clockfix (disable on old systems!)"	$(check_test "CLOCKFIX") \
462
		CLOCKFIX			"Clockfix (disable on old systems!)"	$(check_test "CLOCKFIX") \
459
		IPV6SUPPORT			"IPv6 support (experimental)"			$(check_test "IPV6SUPPORT") \
463
		IPV6SUPPORT			"IPv6 support (experimental)"			$(check_test "IPV6SUPPORT") \
464
		WITH_EMU			"Emulator support"						$(check_test "WITH_EMU") \
460
		2> ${tempfile}
465
		2> ${tempfile}
461
466
462
	opt=${?}
467
	opt=${?}
(-)cscrypt/aes.c (+67 lines)
Lines 1250-1253 Link Here
1250
		rk[3];
1250
		rk[3];
1251
	PUTU32(out + 12, s3);
1251
	PUTU32(out + 12, s3);
1252
}
1252
}
1253
1254
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
1255
					 const unsigned long length, const AES_KEY *key,
1256
					 unsigned char *ivec, const int enc)
1257
{
1258
	unsigned long n;
1259
	unsigned long len = length;
1260
	unsigned char tmp[AES_BLOCK_SIZE];
1261
1262
	assert(in && out && key && ivec);
1263
	assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
1264
1265
	if(AES_ENCRYPT == enc)
1266
	{
1267
		while(len >= AES_BLOCK_SIZE)
1268
		{
1269
			for(n=0; n < AES_BLOCK_SIZE; ++n)
1270
				tmp[n] = in[n] ^ ivec[n];
1271
1272
			AES_encrypt(tmp, out, key);
1273
			memcpy(ivec, out, AES_BLOCK_SIZE);
1274
			len -= AES_BLOCK_SIZE;
1275
			in += AES_BLOCK_SIZE;
1276
			out += AES_BLOCK_SIZE;
1277
		}
1278
1279
		if(len)
1280
		{
1281
			for(n=0; n < len; ++n)
1282
				tmp[n] = in[n] ^ ivec[n];
1283
1284
			for(n=len; n < AES_BLOCK_SIZE; ++n)
1285
				tmp[n] = ivec[n];
1286
1287
			AES_encrypt(tmp, tmp, key);
1288
			memcpy(out, tmp, AES_BLOCK_SIZE);
1289
			memcpy(ivec, tmp, AES_BLOCK_SIZE);
1290
		}
1291
	}
1292
	else
1293
	{
1294
		while(len >= AES_BLOCK_SIZE)
1295
		{
1296
			memcpy(tmp, in, AES_BLOCK_SIZE);
1297
			AES_decrypt(in, out, key);
1298
1299
			for(n=0; n < AES_BLOCK_SIZE; ++n)
1300
				out[n] ^= ivec[n];
1301
1302
			memcpy(ivec, tmp, AES_BLOCK_SIZE);
1303
			len -= AES_BLOCK_SIZE;
1304
			in += AES_BLOCK_SIZE;
1305
			out += AES_BLOCK_SIZE;
1306
		}
1307
1308
		if(len)
1309
		{
1310
			memcpy(tmp, in, AES_BLOCK_SIZE);
1311
			AES_decrypt(tmp, tmp, key);
1312
1313
			for(n=0; n < len; ++n)
1314
				out[n] ^= ivec[n];
1315
1316
			memcpy(ivec, tmp, AES_BLOCK_SIZE);
1317
		}
1318
	}
1319
}
1253
#endif
1320
#endif
(-)cscrypt/aes.h (+3 lines)
Lines 42-47 Link Here
42
void AES_decrypt(const unsigned char *in, unsigned char *out,
42
void AES_decrypt(const unsigned char *in, unsigned char *out,
43
				 const AES_KEY *key);
43
				 const AES_KEY *key);
44
44
45
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
46
					 const unsigned long length, const AES_KEY *key,
47
					 unsigned char *ivec, const int enc);
45
#endif /* !HEADER_AES_H */
48
#endif /* !HEADER_AES_H */
46
49
47
#endif
50
#endif
(-)cscrypt/md5.c (-10 / +3 lines)
Lines 25-37 Link Here
25
25
26
#if !defined(WITH_SSL) && !defined(WITH_LIBCRYPTO)
26
#if !defined(WITH_SSL) && !defined(WITH_LIBCRYPTO)
27
27
28
typedef struct MD5Context
29
{
30
	uint32_t buf[4];
31
	uint32_t bits[2];
32
	uint32_t in[16];
33
} MD5_CTX;
34
35
#ifdef __i386__
28
#ifdef __i386__
36
#define byteReverse(a, b)
29
#define byteReverse(a, b)
37
#else
30
#else
Lines 155-161 Link Here
155
 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
148
 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
156
 * initialization constants.
149
 * initialization constants.
157
 */
150
 */
158
static void MD5_Init(MD5_CTX *ctx)
151
void MD5_Init(MD5_CTX *ctx)
159
{
152
{
160
	ctx->buf[0] = 0x67452301;
153
	ctx->buf[0] = 0x67452301;
161
	ctx->buf[1] = 0xefcdab89;
154
	ctx->buf[1] = 0xefcdab89;
Lines 170-176 Link Here
170
 * Update context to reflect the concatenation of another buffer full
163
 * Update context to reflect the concatenation of another buffer full
171
 * of bytes.
164
 * of bytes.
172
 */
165
 */
173
static void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len)
166
void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len)
174
{
167
{
175
	uint32_t t;
168
	uint32_t t;
176
169
Lines 219-225 Link Here
219
 * Final wrapup - pad to 64-byte boundary with the bit pattern
212
 * Final wrapup - pad to 64-byte boundary with the bit pattern
220
 * 1 0* (64-bit count of bits processed, MSB-first)
213
 * 1 0* (64-bit count of bits processed, MSB-first)
221
 */
214
 */
222
static void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
215
void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
223
{
216
{
224
	unsigned count;
217
	unsigned count;
225
	unsigned char *p;
218
	unsigned char *p;
(-)cscrypt/md5.h (-2 / +10 lines)
Lines 7-14 Link Here
7
#define MD5_DIGEST_LENGTH 16
7
#define MD5_DIGEST_LENGTH 16
8
8
9
unsigned char *MD5(const unsigned char *input, unsigned long len, unsigned char *output_hash);
9
unsigned char *MD5(const unsigned char *input, unsigned long len, unsigned char *output_hash);
10
#endif
11
10
12
char *__md5_crypt(const char *text_pass, const char *salt, char *crypted_passwd);
11
typedef struct MD5Context {
12
	uint32_t buf[4];
13
	uint32_t bits[2];
14
	uint32_t in[16];
15
} MD5_CTX;
13
16
17
void MD5_Init(MD5_CTX *ctx);
18
void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len);
19
void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx);
14
#endif
20
#endif
21
char *__md5_crypt(const char *text_pass, const char *salt, char *crypted_passwd);
22
#endif
(-)csctapi/cardreaders.h (+1 lines)
Lines 14-18 Link Here
14
extern const struct s_cardreader cardreader_stapi;
14
extern const struct s_cardreader cardreader_stapi;
15
extern const struct s_cardreader cardreader_stinger;
15
extern const struct s_cardreader cardreader_stinger;
16
extern const struct s_cardreader cardreader_drecas;
16
extern const struct s_cardreader cardreader_drecas;
17
extern const struct s_cardreader cardreader_emu;
17
18
18
#endif
19
#endif
(-)ffdecsa/CMakeLists.txt (+8 lines)
Line 0 Link Here
1
project (ffdecsa)
2
3
file (GLOB ffdecsa_srcs "ffdecsa.c")
4
file (GLOB ffdecsa_hdrs "*.h")
5
6
set (lib_name "ffdecsa")
7
8
add_library (${lib_name} STATIC ${ffdecsa_srcs} ${ffdecsa_hdrs})
(-)ffdecsa/COPYING (+339 lines)
Line 0 Link Here
1
		    GNU GENERAL PUBLIC LICENSE
2
		       Version 2, June 1991
3
4
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
                          675 Mass Ave, Cambridge, MA 02139, USA
6
 Everyone is permitted to copy and distribute verbatim copies
7
 of this license document, but changing it is not allowed.
8
9
			    Preamble
10
11
  The licenses for most software are designed to take away your
12
freedom to share and change it.  By contrast, the GNU General Public
13
License is intended to guarantee your freedom to share and change free
14
software--to make sure the software is free for all its users.  This
15
General Public License applies to most of the Free Software
16
Foundation's software and to any other program whose authors commit to
17
using it.  (Some other Free Software Foundation software is covered by
18
the GNU Library General Public License instead.)  You can apply it to
19
your programs, too.
20
21
  When we speak of free software, we are referring to freedom, not
22
price.  Our General Public Licenses are designed to make sure that you
23
have the freedom to distribute copies of free software (and charge for
24
this service if you wish), that you receive source code or can get it
25
if you want it, that you can change the software or use pieces of it
26
in new free programs; and that you know you can do these things.
27
28
  To protect your rights, we need to make restrictions that forbid
29
anyone to deny you these rights or to ask you to surrender the rights.
30
These restrictions translate to certain responsibilities for you if you
31
distribute copies of the software, or if you modify it.
32
33
  For example, if you distribute copies of such a program, whether
34
gratis or for a fee, you must give the recipients all the rights that
35
you have.  You must make sure that they, too, receive or can get the
36
source code.  And you must show them these terms so they know their
37
rights.
38
39
  We protect your rights with two steps: (1) copyright the software, and
40
(2) offer you this license which gives you legal permission to copy,
41
distribute and/or modify the software.
42
43
  Also, for each author's protection and ours, we want to make certain
44
that everyone understands that there is no warranty for this free
45
software.  If the software is modified by someone else and passed on, we
46
want its recipients to know that what they have is not the original, so
47
that any problems introduced by others will not reflect on the original
48
authors' reputations.
49
50
  Finally, any free program is threatened constantly by software
51
patents.  We wish to avoid the danger that redistributors of a free
52
program will individually obtain patent licenses, in effect making the
53
program proprietary.  To prevent this, we have made it clear that any
54
patent must be licensed for everyone's free use or not licensed at all.
55
56
  The precise terms and conditions for copying, distribution and
57
modification follow.
58
59
		    GNU GENERAL PUBLIC LICENSE
60
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62
  0. This License applies to any program or other work which contains
63
a notice placed by the copyright holder saying it may be distributed
64
under the terms of this General Public License.  The "Program", below,
65
refers to any such program or work, and a "work based on the Program"
66
means either the Program or any derivative work under copyright law:
67
that is to say, a work containing the Program or a portion of it,
68
either verbatim or with modifications and/or translated into another
69
language.  (Hereinafter, translation is included without limitation in
70
the term "modification".)  Each licensee is addressed as "you".
71
72
Activities other than copying, distribution and modification are not
73
covered by this License; they are outside its scope.  The act of
74
running the Program is not restricted, and the output from the Program
75
is covered only if its contents constitute a work based on the
76
Program (independent of having been made by running the Program).
77
Whether that is true depends on what the Program does.
78
79
  1. You may copy and distribute verbatim copies of the Program's
80
source code as you receive it, in any medium, provided that you
81
conspicuously and appropriately publish on each copy an appropriate
82
copyright notice and disclaimer of warranty; keep intact all the
83
notices that refer to this License and to the absence of any warranty;
84
and give any other recipients of the Program a copy of this License
85
along with the Program.
86
87
You may charge a fee for the physical act of transferring a copy, and
88
you may at your option offer warranty protection in exchange for a fee.
89
90
  2. You may modify your copy or copies of the Program or any portion
91
of it, thus forming a work based on the Program, and copy and
92
distribute such modifications or work under the terms of Section 1
93
above, provided that you also meet all of these conditions:
94
95
    a) You must cause the modified files to carry prominent notices
96
    stating that you changed the files and the date of any change.
97
98
    b) You must cause any work that you distribute or publish, that in
99
    whole or in part contains or is derived from the Program or any
100
    part thereof, to be licensed as a whole at no charge to all third
101
    parties under the terms of this License.
102
103
    c) If the modified program normally reads commands interactively
104
    when run, you must cause it, when started running for such
105
    interactive use in the most ordinary way, to print or display an
106
    announcement including an appropriate copyright notice and a
107
    notice that there is no warranty (or else, saying that you provide
108
    a warranty) and that users may redistribute the program under
109
    these conditions, and telling the user how to view a copy of this
110
    License.  (Exception: if the Program itself is interactive but
111
    does not normally print such an announcement, your work based on
112
    the Program is not required to print an announcement.)
113
114
These requirements apply to the modified work as a whole.  If
115
identifiable sections of that work are not derived from the Program,
116
and can be reasonably considered independent and separate works in
117
themselves, then this License, and its terms, do not apply to those
118
sections when you distribute them as separate works.  But when you
119
distribute the same sections as part of a whole which is a work based
120
on the Program, the distribution of the whole must be on the terms of
121
this License, whose permissions for other licensees extend to the
122
entire whole, and thus to each and every part regardless of who wrote it.
123
124
Thus, it is not the intent of this section to claim rights or contest
125
your rights to work written entirely by you; rather, the intent is to
126
exercise the right to control the distribution of derivative or
127
collective works based on the Program.
128
129
In addition, mere aggregation of another work not based on the Program
130
with the Program (or with a work based on the Program) on a volume of
131
a storage or distribution medium does not bring the other work under
132
the scope of this License.
133
134
  3. You may copy and distribute the Program (or a work based on it,
135
under Section 2) in object code or executable form under the terms of
136
Sections 1 and 2 above provided that you also do one of the following:
137
138
    a) Accompany it with the complete corresponding machine-readable
139
    source code, which must be distributed under the terms of Sections
140
    1 and 2 above on a medium customarily used for software interchange; or,
141
142
    b) Accompany it with a written offer, valid for at least three
143
    years, to give any third party, for a charge no more than your
144
    cost of physically performing source distribution, a complete
145
    machine-readable copy of the corresponding source code, to be
146
    distributed under the terms of Sections 1 and 2 above on a medium
147
    customarily used for software interchange; or,
148
149
    c) Accompany it with the information you received as to the offer
150
    to distribute corresponding source code.  (This alternative is
151
    allowed only for noncommercial distribution and only if you
152
    received the program in object code or executable form with such
153
    an offer, in accord with Subsection b above.)
154
155
The source code for a work means the preferred form of the work for
156
making modifications to it.  For an executable work, complete source
157
code means all the source code for all modules it contains, plus any
158
associated interface definition files, plus the scripts used to
159
control compilation and installation of the executable.  However, as a
160
special exception, the source code distributed need not include
161
anything that is normally distributed (in either source or binary
162
form) with the major components (compiler, kernel, and so on) of the
163
operating system on which the executable runs, unless that component
164
itself accompanies the executable.
165
166
If distribution of executable or object code is made by offering
167
access to copy from a designated place, then offering equivalent
168
access to copy the source code from the same place counts as
169
distribution of the source code, even though third parties are not
170
compelled to copy the source along with the object code.
171
172
  4. You may not copy, modify, sublicense, or distribute the Program
173
except as expressly provided under this License.  Any attempt
174
otherwise to copy, modify, sublicense or distribute the Program is
175
void, and will automatically terminate your rights under this License.
176
However, parties who have received copies, or rights, from you under
177
this License will not have their licenses terminated so long as such
178
parties remain in full compliance.
179
180
  5. You are not required to accept this License, since you have not
181
signed it.  However, nothing else grants you permission to modify or
182
distribute the Program or its derivative works.  These actions are
183
prohibited by law if you do not accept this License.  Therefore, by
184
modifying or distributing the Program (or any work based on the
185
Program), you indicate your acceptance of this License to do so, and
186
all its terms and conditions for copying, distributing or modifying
187
the Program or works based on it.
188
189
  6. Each time you redistribute the Program (or any work based on the
190
Program), the recipient automatically receives a license from the
191
original licensor to copy, distribute or modify the Program subject to
192
these terms and conditions.  You may not impose any further
193
restrictions on the recipients' exercise of the rights granted herein.
194
You are not responsible for enforcing compliance by third parties to
195
this License.
196
197
  7. If, as a consequence of a court judgment or allegation of patent
198
infringement or for any other reason (not limited to patent issues),
199
conditions are imposed on you (whether by court order, agreement or
200
otherwise) that contradict the conditions of this License, they do not
201
excuse you from the conditions of this License.  If you cannot
202
distribute so as to satisfy simultaneously your obligations under this
203
License and any other pertinent obligations, then as a consequence you
204
may not distribute the Program at all.  For example, if a patent
205
license would not permit royalty-free redistribution of the Program by
206
all those who receive copies directly or indirectly through you, then
207
the only way you could satisfy both it and this License would be to
208
refrain entirely from distribution of the Program.
209
210
If any portion of this section is held invalid or unenforceable under
211
any particular circumstance, the balance of the section is intended to
212
apply and the section as a whole is intended to apply in other
213
circumstances.
214
215
It is not the purpose of this section to induce you to infringe any
216
patents or other property right claims or to contest validity of any
217
such claims; this section has the sole purpose of protecting the
218
integrity of the free software distribution system, which is
219
implemented by public license practices.  Many people have made
220
generous contributions to the wide range of software distributed
221
through that system in reliance on consistent application of that
222
system; it is up to the author/donor to decide if he or she is willing
223
to distribute software through any other system and a licensee cannot
224
impose that choice.
225
226
This section is intended to make thoroughly clear what is believed to
227
be a consequence of the rest of this License.
228
229
  8. If the distribution and/or use of the Program is restricted in
230
certain countries either by patents or by copyrighted interfaces, the
231
original copyright holder who places the Program under this License
232
may add an explicit geographical distribution limitation excluding
233
those countries, so that distribution is permitted only in or among
234
countries not thus excluded.  In such case, this License incorporates
235
the limitation as if written in the body of this License.
236
237
  9. The Free Software Foundation may publish revised and/or new versions
238
of the General Public License from time to time.  Such new versions will
239
be similar in spirit to the present version, but may differ in detail to
240
address new problems or concerns.
241
242
Each version is given a distinguishing version number.  If the Program
243
specifies a version number of this License which applies to it and "any
244
later version", you have the option of following the terms and conditions
245
either of that version or of any later version published by the Free
246
Software Foundation.  If the Program does not specify a version number of
247
this License, you may choose any version ever published by the Free Software
248
Foundation.
249
250
  10. If you wish to incorporate parts of the Program into other free
251
programs whose distribution conditions are different, write to the author
252
to ask for permission.  For software which is copyrighted by the Free
253
Software Foundation, write to the Free Software Foundation; we sometimes
254
make exceptions for this.  Our decision will be guided by the two goals
255
of preserving the free status of all derivatives of our free software and
256
of promoting the sharing and reuse of software generally.
257
258
			    NO WARRANTY
259
260
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
262
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
266
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
267
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
REPAIR OR CORRECTION.
269
270
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
POSSIBILITY OF SUCH DAMAGES.
279
280
		     END OF TERMS AND CONDITIONS
281
282
	Appendix: How to Apply These Terms to Your New Programs
283
284
  If you develop a new program, and you want it to be of the greatest
285
possible use to the public, the best way to achieve this is to make it
286
free software which everyone can redistribute and change under these terms.
287
288
  To do so, attach the following notices to the program.  It is safest
289
to attach them to the start of each source file to most effectively
290
convey the exclusion of warranty; and each file should have at least
291
the "copyright" line and a pointer to where the full notice is found.
292
293
    <one line to give the program's name and a brief idea of what it does.>
294
    Copyright (C) 19yy  <name of author>
295
296
    This program is free software; you can redistribute it and/or modify
297
    it under the terms of the GNU General Public License as published by
298
    the Free Software Foundation; either version 2 of the License, or
299
    (at your option) any later version.
300
301
    This program is distributed in the hope that it will be useful,
302
    but WITHOUT ANY WARRANTY; without even the implied warranty of
303
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
304
    GNU General Public License for more details.
305
306
    You should have received a copy of the GNU General Public License
307
    along with this program; if not, write to the Free Software
308
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
309
310
Also add information on how to contact you by electronic and paper mail.
311
312
If the program is interactive, make it output a short notice like this
313
when it starts in an interactive mode:
314
315
    Gnomovision version 69, Copyright (C) 19yy name of author
316
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
    This is free software, and you are welcome to redistribute it
318
    under certain conditions; type `show c' for details.
319
320
The hypothetical commands `show w' and `show c' should show the appropriate
321
parts of the General Public License.  Of course, the commands you use may
322
be called something other than `show w' and `show c'; they could even be
323
mouse-clicks or menu items--whatever suits your program.
324
325
You should also get your employer (if you work as a programmer) or your
326
school, if any, to sign a "copyright disclaimer" for the program, if
327
necessary.  Here is a sample; alter the names:
328
329
  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
  `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332
  <signature of Ty Coon>, 1 April 1989
333
  Ty Coon, President of Vice
334
335
This General Public License does not permit incorporating your program into
336
proprietary programs.  If your program is a subroutine library, you may
337
consider it more useful to permit linking proprietary applications with the
338
library.  If this is what you want to do, use the GNU Library General
339
Public License instead of this License.
(-)ffdecsa/Makefile (+2 lines)
Line 0 Link Here
1
parent:
2
	@$(MAKE) --no-print-directory -C ..
(-)ffdecsa/ffdecsa.c (+926 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2003-2004  fatih89r
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
20
21
#include <sys/types.h>
22
#include <string.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
26
#include "ffdecsa.h"
27
28
#ifndef NULL
29
#define NULL 0
30
#endif
31
32
//#define DEBUG
33
#ifdef DEBUG
34
#define DBG(a) a
35
#else
36
#define DBG(a)
37
#endif
38
39
//// parallelization stuff, large speed differences are possible
40
// possible choices
41
#define PARALLEL_32_4CHAR     320
42
#define PARALLEL_32_4CHARA    321
43
#define PARALLEL_32_INT       322
44
#define PARALLEL_64_8CHAR     640
45
#define PARALLEL_64_8CHARA    641
46
#define PARALLEL_64_2INT      642
47
#define PARALLEL_64_LONG      643
48
#define PARALLEL_64_MMX       644
49
#define PARALLEL_128_16CHAR  1280
50
#define PARALLEL_128_16CHARA 1281
51
#define PARALLEL_128_4INT    1282
52
#define PARALLEL_128_2LONG   1283
53
#define PARALLEL_128_2MMX    1284
54
#define PARALLEL_128_SSE     1285
55
#define PARALLEL_128_SSE2    1286
56
57
//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice ////////
58
#ifndef PARALLEL_MODE
59
60
#if defined(__x86_64__) || defined(_M_X64)
61
#define PARALLEL_MODE PARALLEL_128_SSE2
62
63
#elif defined(__mips__) || defined(__mips) || defined(__MIPS__)
64
#define PARALLEL_MODE PARALLEL_64_LONG
65
66
#elif defined(__sh__) || defined(__SH4__)
67
#define PARALLEL_MODE PARALLEL_32_INT
68
#define COPY_UNALIGNED_PKT
69
#define MEMALIGN_VAL 4
70
71
#else
72
#define PARALLEL_MODE PARALLEL_32_INT
73
#endif
74
75
#endif
76
//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice ////////
77
78
#include "parallel_generic.h"
79
//// conditionals
80
#if PARALLEL_MODE==PARALLEL_32_4CHAR
81
#include "parallel_032_4char.h"
82
#elif PARALLEL_MODE==PARALLEL_32_4CHARA
83
#include "parallel_032_4charA.h"
84
#elif PARALLEL_MODE==PARALLEL_32_INT
85
#include "parallel_032_int.h"
86
#elif PARALLEL_MODE==PARALLEL_64_8CHAR
87
#include "parallel_064_8char.h"
88
#elif PARALLEL_MODE==PARALLEL_64_8CHARA
89
#include "parallel_064_8charA.h"
90
#elif PARALLEL_MODE==PARALLEL_64_2INT
91
#include "parallel_064_2int.h"
92
#elif PARALLEL_MODE==PARALLEL_64_LONG
93
#include "parallel_064_long.h"
94
#elif PARALLEL_MODE==PARALLEL_64_MMX
95
#include "parallel_064_mmx.h"
96
#elif PARALLEL_MODE==PARALLEL_128_16CHAR
97
#include "parallel_128_16char.h"
98
#elif PARALLEL_MODE==PARALLEL_128_16CHARA
99
#include "parallel_128_16charA.h"
100
#elif PARALLEL_MODE==PARALLEL_128_4INT
101
#include "parallel_128_4int.h"
102
#elif PARALLEL_MODE==PARALLEL_128_2LONG
103
#include "parallel_128_2long.h"
104
#elif PARALLEL_MODE==PARALLEL_128_2MMX
105
#include "parallel_128_2mmx.h"
106
#elif PARALLEL_MODE==PARALLEL_128_SSE
107
#include "parallel_128_sse.h"
108
#elif PARALLEL_MODE==PARALLEL_128_SSE2
109
#include "parallel_128_sse2.h"
110
#else
111
#error "unknown/undefined parallel mode"
112
#endif
113
114
// stuff depending on conditionals
115
116
#define BYTES_PER_GROUP (GROUP_PARALLELISM/8)
117
#define BYPG BYTES_PER_GROUP
118
#define BITS_PER_GROUP GROUP_PARALLELISM
119
#define BIPG BITS_PER_GROUP
120
121
// platform specific
122
123
#ifdef __arm__
124
#if !defined(MEMALIGN_VAL) || MEMALIGN_VAL<4
125
#undef MEMALIGN_VAL
126
#define MEMALIGN_VAL 4
127
#endif
128
#define COPY_UNALIGNED_PKT
129
#endif
130
131
//
132
133
#ifndef MALLOC
134
#define MALLOC(X) malloc(X)
135
#endif
136
#ifndef FREE
137
#define FREE(X) free(X)
138
#endif
139
#ifdef MEMALIGN_VAL
140
#define MEMALIGN __attribute__((aligned(MEMALIGN_VAL)))
141
#else
142
#define MEMALIGN
143
#endif
144
145
//// debug tool
146
147
#ifdef DEBUG
148
static void dump_mem(const char *string, const unsigned char *p, int len, int linelen){
149
  int i;
150
  for(i=0;i<len;i++){
151
    if(i%linelen==0&&i) fprintf(stderr,"\n");
152
    if(i%linelen==0) fprintf(stderr,"%s %08x:",string,i);
153
    else{
154
      if(i%8==0) fprintf(stderr," ");
155
      if(i%4==0) fprintf(stderr," ");
156
    }
157
    fprintf(stderr," %02x",p[i]);
158
  }
159
  if(i%linelen==0) fprintf(stderr,"\n");
160
}
161
#endif
162
163
//////////////////////////////////////////////////////////////////////////////////
164
165
struct csa_key_t{
166
	unsigned char ck[8];
167
// used by stream
168
        int iA[8];  // iA[0] is for A1, iA[7] is for A8
169
        int iB[8];  // iB[0] is for B1, iB[7] is for B8
170
// used by stream (group)
171
        MEMALIGN group ck_g[8][8]; // [byte][bit:0=LSB,7=MSB]
172
        MEMALIGN group iA_g[8][4]; // [0 for A1][0 for LSB]
173
        MEMALIGN group iB_g[8][4]; // [0 for B1][0 for LSB]
174
// used by block
175
	unsigned char kk[56];
176
// used by block (group)
177
	MEMALIGN batch kkmulti[56]; // many times the same byte in every batch
178
};
179
180
struct csa_keys_t{
181
  struct csa_key_t even;
182
  struct csa_key_t odd;
183
};
184
185
//-----stream cypher
186
187
//-----key schedule for stream decypher
188
static void key_schedule_stream(
189
  unsigned char *ck,    // [In]  ck[0]-ck[7]   8 bytes   | Key.
190
  int *iA,              // [Out] iA[0]-iA[7]   8 nibbles | Key schedule.
191
  int *iB)              // [Out] iB[0]-iB[7]   8 nibbles | Key schedule.
192
{
193
    iA[0]=(ck[0]>>4)&0xf;
194
    iA[1]=(ck[0]   )&0xf;
195
    iA[2]=(ck[1]>>4)&0xf;
196
    iA[3]=(ck[1]   )&0xf;
197
    iA[4]=(ck[2]>>4)&0xf;
198
    iA[5]=(ck[2]   )&0xf;
199
    iA[6]=(ck[3]>>4)&0xf;
200
    iA[7]=(ck[3]   )&0xf;
201
    iB[0]=(ck[4]>>4)&0xf;
202
    iB[1]=(ck[4]   )&0xf;
203
    iB[2]=(ck[5]>>4)&0xf;
204
    iB[3]=(ck[5]   )&0xf;
205
    iB[4]=(ck[6]>>4)&0xf;
206
    iB[5]=(ck[6]   )&0xf;
207
    iB[6]=(ck[7]>>4)&0xf;
208
    iB[7]=(ck[7]   )&0xf;
209
}
210
211
//----- stream main function
212
213
#define STREAM_INIT
214
#include "stream.c"
215
#undef STREAM_INIT
216
217
#define STREAM_NORMAL
218
#include "stream.c"
219
#undef STREAM_NORMAL
220
221
222
//-----block decypher
223
224
//-----key schedule for block decypher
225
226
static void key_schedule_block(
227
  unsigned char *ck,    // [In]  ck[0]-ck[7]   8 bytes | Key.
228
  unsigned char *kk)    // [Out] kk[0]-kk[55] 56 bytes | Key schedule.
229
{
230
  static const unsigned char key_perm[0x40] = {
231
    0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15, 0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
232
    0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01, 0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
233
    0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A, 0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
234
    0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C, 0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
235
  };
236
237
  int i,j,k;
238
  int bit[64];
239
  int newbit[64];
240
  int kb[7][8];
241
242
  // 56 steps
243
  // 56 key bytes kk(55)..kk(0) by key schedule from ck
244
245
  // kb(6,0) .. kb(6,7) = ck(0) .. ck(7)
246
  kb[6][0] = ck[0];
247
  kb[6][1] = ck[1];
248
  kb[6][2] = ck[2];
249
  kb[6][3] = ck[3];
250
  kb[6][4] = ck[4];
251
  kb[6][5] = ck[5];
252
  kb[6][6] = ck[6];
253
  kb[6][7] = ck[7];
254
255
  // calculate kb[5] .. kb[0]
256
  for(i=5; i>=0; i--){
257
    // 64 bit perm on kb
258
    for(j=0; j<8; j++){
259
      for(k=0; k<8; k++){
260
        bit[j*8+k] = (kb[i+1][j] >> (7-k)) & 1;
261
        newbit[key_perm[j*8+k]-1] = bit[j*8+k];
262
      }
263
    }
264
    for(j=0; j<8; j++){
265
      kb[i][j] = 0;
266
      for(k=0; k<8; k++){
267
        kb[i][j] |= newbit[j*8+k] << (7-k);
268
      }
269
    }
270
  }
271
272
  // xor to give kk
273
  for(i=0; i<7; i++){
274
    for(j=0; j<8; j++){
275
      kk[i*8+j] = kb[i][j] ^ i;
276
    }
277
  }
278
279
}
280
281
//-----block utils
282
283
static inline __attribute__((always_inline)) void trasp_N_8 (unsigned char *in,unsigned char* out,int count){
284
  int *ri=(int *)in;
285
  int *ibi=(int *)out;
286
  int j,i,k,g;
287
  // copy and first step
288
  for(g=0;g<count;g++){
289
    ri[g]=ibi[2*g];
290
    ri[GROUP_PARALLELISM+g]=ibi[2*g+1];
291
  }
292
//dump_mem("NE1 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
293
// now 01230123
294
#define INTS_PER_ROW (GROUP_PARALLELISM/8*2)
295
  for(j=0;j<8;j+=4){
296
    for(i=0;i<2;i++){
297
      for(k=0;k<INTS_PER_ROW;k++){
298
        unsigned int t,b;
299
        t=ri[INTS_PER_ROW*(j+i)+k];
300
        b=ri[INTS_PER_ROW*(j+i+2)+k];
301
        ri[INTS_PER_ROW*(j+i)+k]=     (t&0x0000ffff)      | ((b           )<<16);
302
        ri[INTS_PER_ROW*(j+i+2)+k]=  ((t           )>>16) |  (b&0xffff0000) ;
303
      }
304
    }
305
  }
306
//dump_mem("NE2 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
307
// now 01010101
308
  for(j=0;j<8;j+=2){
309
    for(i=0;i<1;i++){
310
      for(k=0;k<INTS_PER_ROW;k++){
311
        unsigned int t,b;
312
        t=ri[INTS_PER_ROW*(j+i)+k];
313
        b=ri[INTS_PER_ROW*(j+i+1)+k];
314
        ri[INTS_PER_ROW*(j+i)+k]=     (t&0x00ff00ff)     | ((b&0x00ff00ff)<<8);
315
        ri[INTS_PER_ROW*(j+i+1)+k]=  ((t&0xff00ff00)>>8) |  (b&0xff00ff00);
316
      }
317
    }
318
  }
319
//dump_mem("NE3 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
320
// now 00000000
321
}
322
323
static inline __attribute__((always_inline)) void trasp_8_N (unsigned char *in,unsigned char* out,int count){
324
  int *ri=(int *)in;
325
  int *bdi=(int *)out;
326
  int j,i,k,g;
327
#define INTS_PER_ROW (GROUP_PARALLELISM/8*2)
328
//dump_mem("NE1 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
329
// now 00000000
330
  for(j=0;j<8;j+=2){
331
    for(i=0;i<1;i++){
332
      for(k=0;k<INTS_PER_ROW;k++){
333
        unsigned int t,b;
334
        t=ri[INTS_PER_ROW*(j+i)+k];
335
        b=ri[INTS_PER_ROW*(j+i+1)+k];
336
        ri[INTS_PER_ROW*(j+i)+k]=     (t&0x00ff00ff)     | ((b&0x00ff00ff)<<8);
337
        ri[INTS_PER_ROW*(j+i+1)+k]=  ((t&0xff00ff00)>>8) |  (b&0xff00ff00);
338
      }
339
    }
340
  }
341
//dump_mem("NE2 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
342
// now 01010101
343
  for(j=0;j<8;j+=4){
344
    for(i=0;i<2;i++){
345
      for(k=0;k<INTS_PER_ROW;k++){
346
        unsigned int t,b;
347
        t=ri[INTS_PER_ROW*(j+i)+k];
348
        b=ri[INTS_PER_ROW*(j+i+2)+k];
349
        ri[INTS_PER_ROW*(j+i)+k]=     (t&0x0000ffff)      | ((b           )<<16);
350
        ri[INTS_PER_ROW*(j+i+2)+k]=  ((t           )>>16) |  (b&0xffff0000) ;
351
      }
352
    }
353
  }
354
//dump_mem("NE3 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
355
// now 01230123
356
  for(g=0;g<count;g++){
357
    bdi[2*g]=ri[g];
358
    bdi[2*g+1]=ri[GROUP_PARALLELISM+g];
359
  }
360
}
361
362
//-----block main function
363
364
// block group
365
static void block_decypher_group(
366
  batch *kkmulti,       // [In]  kkmulti[0]-kkmulti[55] 56 batches | Key schedule (each batch has repeated equal bytes).
367
  unsigned char *ib,    // [In]  (ib0,ib1,...ib7)...x32 32*8 bytes | Initialization vector.
368
  unsigned char *bd,    // [Out] (bd0,bd1,...bd7)...x32 32*8 bytes | Block decipher.
369
  int count)
370
{
371
  // int is faster than unsigned char. apparently not
372
  static const unsigned char block_sbox[0x100] = {
373
    0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A, 0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
374
    0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70, 0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
375
    0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3, 0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
376
    0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84, 0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
377
    0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C, 0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
378
    0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56, 0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
379
    0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6, 0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
380
    0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E, 0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
381
382
    0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B, 0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
383
    0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4, 0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
384
    0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F, 0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
385
    0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6, 0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
386
    0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91, 0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
387
    0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20, 0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
388
    0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4, 0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
389
    0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA, 0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
390
  };
391
  MEMALIGN unsigned char r[GROUP_PARALLELISM*(8+56)];  /* 56 because we will move back in memory while looping */
392
  MEMALIGN unsigned char sbox_in[GROUP_PARALLELISM],sbox_out[GROUP_PARALLELISM],perm_out[GROUP_PARALLELISM];
393
  int roff;
394
  int i,g,count_all=GROUP_PARALLELISM;
395
396
  roff=GROUP_PARALLELISM*56;
397
398
#define FASTTRASP1
399
#ifndef FASTTRASP1
400
  for(g=0;g<count;g++){
401
    // Init registers 
402
    int j;
403
    for(j=0;j<8;j++){
404
      r[roff+GROUP_PARALLELISM*j+g]=ib[8*g+j];
405
    }
406
  }
407
#else
408
  trasp_N_8((unsigned char *)&r[roff],(unsigned char *)ib,count);
409
#endif
410
//dump_mem("OLD r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
411
412
  // loop over kk[55]..kk[0]
413
  for(i=55;i>=0;i--){
414
    {
415
      MEMALIGN batch tkkmulti=kkmulti[i];
416
      batch *si=(batch *)sbox_in;
417
      batch *r6_N=(batch *)(r+roff+GROUP_PARALLELISM*6);
418
      for(g=0;g<count_all/BYTES_PER_BATCH;g++){
419
        si[g]=B_FFXOR(tkkmulti,r6_N[g]);              //FIXME: introduce FASTBATCH?
420
      }
421
    }
422
423
    // table lookup, this works on only one byte at a time
424
    // most difficult part of all
425
    // - can't be parallelized
426
    // - can't be synthetized through boolean terms (8 input bits are too many)
427
    for(g=0;g<count_all;g++){
428
      sbox_out[g]=block_sbox[sbox_in[g]];
429
    }
430
431
    // bit permutation
432
    {
433
      unsigned char *po=(unsigned char *)perm_out;
434
      unsigned char *so=(unsigned char *)sbox_out;
435
//dump_mem("pre perm ",(unsigned char *)so,GROUP_PARALLELISM,GROUP_PARALLELISM);
436
      for(g=0;g<count_all;g+=BYTES_PER_BATCH){
437
        MEMALIGN batch in,out;
438
        in=*(batch *)&so[g];
439
440
        out=B_FFOR(
441
	    B_FFOR(
442
	    B_FFOR(
443
	    B_FFOR(
444
	    B_FFOR(
445
	           B_FFSH8L(B_FFAND(in,B_FFN_ALL_29()),1),
446
	           B_FFSH8L(B_FFAND(in,B_FFN_ALL_02()),6)),
447
	           B_FFSH8L(B_FFAND(in,B_FFN_ALL_04()),3)),
448
	           B_FFSH8R(B_FFAND(in,B_FFN_ALL_10()),2)),
449
	           B_FFSH8R(B_FFAND(in,B_FFN_ALL_40()),6)),
450
	           B_FFSH8R(B_FFAND(in,B_FFN_ALL_80()),4));
451
452
        *(batch *)&po[g]=out;
453
      }
454
//dump_mem("post perm",(unsigned char *)po,GROUP_PARALLELISM,GROUP_PARALLELISM);
455
    }
456
457
    roff-=GROUP_PARALLELISM; /* virtual shift of registers */
458
459
#if 0
460
/* one by one */
461
    for(g=0;g<count_all;g++){
462
      r[roff+GROUP_PARALLELISM*0+g]=r[roff+GROUP_PARALLELISM*8+g]^sbox_out[g];
463
      r[roff+GROUP_PARALLELISM*6+g]^=perm_out[g];
464
      r[roff+GROUP_PARALLELISM*4+g]^=r[roff+GROUP_PARALLELISM*0+g];
465
      r[roff+GROUP_PARALLELISM*3+g]^=r[roff+GROUP_PARALLELISM*0+g];
466
      r[roff+GROUP_PARALLELISM*2+g]^=r[roff+GROUP_PARALLELISM*0+g];
467
    }
468
#else
469
    for(g=0;g<count_all;g+=BEST_SPAN){
470
      XOR_BEST_BY(&r[roff+GROUP_PARALLELISM*0+g],&r[roff+GROUP_PARALLELISM*8+g],&sbox_out[g]);
471
      XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*6+g],&perm_out[g]);
472
      XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*4+g],&r[roff+GROUP_PARALLELISM*0+g]);
473
      XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*3+g],&r[roff+GROUP_PARALLELISM*0+g]);
474
      XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*2+g],&r[roff+GROUP_PARALLELISM*0+g]);
475
    }
476
#endif
477
  }
478
479
#define FASTTRASP2
480
#ifndef FASTTRASP2
481
  for(g=0;g<count;g++){
482
    // Copy results
483
    int j;
484
    for(j=0;j<8;j++){
485
      bd[8*g+j]=r[roff+GROUP_PARALLELISM*j+g];
486
    }
487
  }
488
#else
489
  trasp_8_N((unsigned char *)&r[roff],(unsigned char *)bd,count);
490
#endif
491
}
492
493
//-----------------------------------EXTERNAL INTERFACE
494
495
//-----get internal parallelism
496
497
int get_internal_parallelism(void){
498
  return GROUP_PARALLELISM;
499
}
500
501
//-----get suggested cluster size
502
503
int get_suggested_cluster_size(void){
504
  int r;
505
  r=GROUP_PARALLELISM+GROUP_PARALLELISM/10;
506
  if(r<GROUP_PARALLELISM+5) r=GROUP_PARALLELISM+5;
507
  return r;
508
}
509
510
//-----key structure
511
512
void *get_key_struct(void){
513
  struct csa_keys_t *keys=(struct csa_keys_t *)MALLOC(sizeof(struct csa_keys_t));
514
  if(keys) {
515
    static const unsigned char pk[8] = { 0,0,0,0,0,0,0,0 };
516
    set_control_words(keys,pk,pk);
517
    }
518
  return keys;
519
}
520
521
void free_key_struct(void *keys){
522
  return FREE(keys);
523
}
524
525
//-----set control words
526
527
static void schedule_key(struct csa_key_t *key, const unsigned char *pk){
528
  // could be made faster, but is not run often
529
  int bi,by;
530
  int i,j;
531
// key
532
  memcpy(key->ck,pk,8);
533
// precalculations for stream
534
  key_schedule_stream(key->ck,key->iA,key->iB);
535
  for(by=0;by<8;by++){
536
    for(bi=0;bi<8;bi++){
537
      key->ck_g[by][bi]=(key->ck[by]&(1<<bi))?FF1():FF0();
538
    }
539
  }
540
  for(by=0;by<8;by++){
541
    for(bi=0;bi<4;bi++){
542
      key->iA_g[by][bi]=(key->iA[by]&(1<<bi))?FF1():FF0();
543
      key->iB_g[by][bi]=(key->iB[by]&(1<<bi))?FF1():FF0();
544
    }
545
  }
546
// precalculations for block
547
  key_schedule_block(key->ck,key->kk);
548
  for(i=0;i<56;i++){
549
    for(j=0;j<BYTES_PER_BATCH;j++){
550
      *(((unsigned char *)&key->kkmulti[i])+j)=key->kk[i];
551
    }
552
  }
553
}
554
555
void set_control_words(void *keys, const unsigned char *ev, const unsigned char *od){
556
  schedule_key(&((struct csa_keys_t *)keys)->even,ev);
557
  schedule_key(&((struct csa_keys_t *)keys)->odd,od);
558
}
559
560
void set_even_control_word(void *keys, const unsigned char *pk){
561
  schedule_key(&((struct csa_keys_t *)keys)->even,pk);
562
}
563
564
void set_odd_control_word(void *keys, const unsigned char *pk){
565
  schedule_key(&((struct csa_keys_t *)keys)->odd,pk);
566
}
567
568
//-----get control words
569
570
void get_control_words(void *keys, unsigned char *even, unsigned char *odd){
571
  memcpy(even,&((struct csa_keys_t *)keys)->even.ck,8);
572
  memcpy(odd,&((struct csa_keys_t *)keys)->odd.ck,8);
573
}
574
575
//----- decrypt
576
577
int decrypt_packets(void *keys, unsigned char **cluster){
578
  // statistics, currently unused
579
  int stat_no_scramble=0;
580
  int stat_reserved=0;
581
  int stat_decrypted[2]={0,0};
582
  int stat_decrypted_mini=0;
583
  unsigned char **clst;
584
  unsigned char **clst2;
585
  int grouped;
586
  int group_ev_od;
587
  int advanced;
588
  int can_advance;
589
  unsigned char *g_pkt[GROUP_PARALLELISM];
590
  int g_len[GROUP_PARALLELISM];
591
  int g_offset[GROUP_PARALLELISM];
592
  int g_n[GROUP_PARALLELISM];
593
  int g_residue[GROUP_PARALLELISM];
594
  unsigned char *pkt;
595
  int xc0,ev_od,len,offset,n,residue;
596
  struct csa_key_t* k;
597
  int i,j,iter,g;
598
  int t23,tsmall;
599
  int alive[24];
600
//icc craziness  int pad1=0; //////////align! FIXME
601
  unsigned char *encp[GROUP_PARALLELISM];
602
  MEMALIGN unsigned char stream_in[GROUP_PARALLELISM*8];
603
  MEMALIGN unsigned char stream_out[GROUP_PARALLELISM*8];
604
  MEMALIGN unsigned char ib[GROUP_PARALLELISM*8];
605
  MEMALIGN unsigned char block_out[GROUP_PARALLELISM*8];
606
#ifdef COPY_UNALIGNED_PKT
607
  unsigned char *unaligned[GROUP_PARALLELISM];
608
  MEMALIGN unsigned char alignedBuff[GROUP_PARALLELISM][188];
609
#endif
610
  struct stream_regs regs;
611
612
//icc craziness  i=(int)&pad1;//////////align!!! FIXME
613
614
  // build a list of packets to be processed
615
  clst=cluster;
616
  grouped=0;
617
  advanced=0;
618
  can_advance=1;
619
  group_ev_od=-1; // silence incorrect compiler warning
620
  pkt=*clst;
621
  do{ // find a new packet
622
    if(grouped==GROUP_PARALLELISM){
623
      // full
624
      break;
625
    }
626
    if(pkt==NULL){
627
      // no more ranges
628
      break;
629
    }
630
    if(pkt>=*(clst+1)){
631
      // out of this range, try next
632
      clst++;clst++;
633
      pkt=*clst;
634
      continue;
635
    }
636
637
    do{ // handle this packet
638
      xc0=pkt[3]&0xc0;
639
      DBG(fprintf(stderr,"   exam pkt=%p, xc0=%02x, can_adv=%i\n",pkt,xc0,can_advance));
640
      if(xc0==0x00){
641
        DBG(fprintf(stderr,"skip clear pkt %p (can_advance is %i)\n",pkt,can_advance));
642
        advanced+=can_advance;
643
        stat_no_scramble++;
644
        break;
645
      }
646
      if(xc0==0x40){
647
        DBG(fprintf(stderr,"skip reserved pkt %p (can_advance is %i)\n",pkt,can_advance));
648
        advanced+=can_advance;
649
        stat_reserved++;
650
        break;
651
      }
652
      if(xc0==0x80||xc0==0xc0){ // encrypted
653
        ev_od=(xc0&0x40)>>6; // 0 even, 1 odd
654
        if(grouped==0) group_ev_od=ev_od; // this group will be all even (or odd)
655
        if(group_ev_od==ev_od){ // could be added to group
656
          pkt[3]&=0x3f;  // consider it decrypted now
657
          if(pkt[3]&0x20){ // incomplete packet
658
            offset=4+pkt[4]+1;
659
            len=188-offset;
660
            n=len>>3;
661
            residue=len-(n<<3);
662
            if(n==0){ // decrypted==encrypted!
663
              DBG(fprintf(stderr,"DECRYPTED MINI! (can_advance is %i)\n",can_advance));
664
              advanced+=can_advance;
665
              stat_decrypted_mini++;
666
              break; // this doesn't need more processing
667
            }
668
          }else{
669
            len=184;
670
            offset=4;
671
            n=23;
672
            residue=0;
673
          }
674
          g_pkt[grouped]=pkt;
675
          g_len[grouped]=len;
676
          g_offset[grouped]=offset;
677
          g_n[grouped]=n;
678
          g_residue[grouped]=residue;
679
          DBG(fprintf(stderr,"%2i: eo=%i pkt=%p len=%03i n=%2i residue=%i\n",grouped,ev_od,pkt,len,n,residue));
680
          grouped++;
681
          advanced+=can_advance;
682
          stat_decrypted[ev_od]++;
683
        }
684
        else{
685
          can_advance=0;
686
          DBG(fprintf(stderr,"skip pkt %p and can_advance set to 0\n",pkt));
687
          break; // skip and go on
688
        }
689
      }
690
    } while(0);
691
692
    if(can_advance){
693
      // move range start forward
694
      *clst+=188;
695
    }
696
    // next packet, if there is one
697
    pkt+=188;
698
  } while(1);
699
  DBG(fprintf(stderr,"-- result: grouped %i pkts, advanced %i pkts\n",grouped,advanced));
700
701
  // delete empty ranges and compact list
702
  clst2=cluster;
703
  for(clst=cluster;*clst!=NULL;clst+=2){
704
    // if not empty
705
    if(*clst<*(clst+1)){
706
      // it will remain 
707
      *clst2=*clst;
708
      *(clst2+1)=*(clst+1);
709
      clst2+=2;
710
    }
711
  }
712
  *clst2=NULL;
713
714
  if(grouped==0){
715
    // no processing needed
716
    return advanced;
717
  }
718
719
  //  sort them, longest payload first
720
  //  we expect many n=23 packets and a few n<23
721
  DBG(fprintf(stderr,"PRESORTING\n"));
722
  for(i=0;i<grouped;i++){
723
    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]));
724
    }
725
  // grouped is always <= GROUP_PARALLELISM
726
727
#define g_swap(a,b) \
728
    pkt=g_pkt[a]; \
729
    g_pkt[a]=g_pkt[b]; \
730
    g_pkt[b]=pkt; \
731
\
732
    len=g_len[a]; \
733
    g_len[a]=g_len[b]; \
734
    g_len[b]=len; \
735
\
736
    offset=g_offset[a]; \
737
    g_offset[a]=g_offset[b]; \
738
    g_offset[b]=offset; \
739
\
740
    n=g_n[a]; \
741
    g_n[a]=g_n[b]; \
742
    g_n[b]=n; \
743
\
744
    residue=g_residue[a]; \
745
    g_residue[a]=g_residue[b]; \
746
    g_residue[b]=residue;
747
748
  // step 1: move n=23 packets before small packets
749
  t23=0;
750
  tsmall=grouped-1;
751
  for(;;){
752
    for(;t23<grouped;t23++){
753
      if(g_n[t23]!=23) break;
754
    }
755
DBG(fprintf(stderr,"t23 after for =%i\n",t23));
756
    
757
    for(;tsmall>=0;tsmall--){
758
      if(g_n[tsmall]==23) break;
759
    }
760
DBG(fprintf(stderr,"tsmall after for =%i\n",tsmall));
761
    
762
    if(tsmall-t23<1) break;
763
    
764
DBG(fprintf(stderr,"swap t23=%i,tsmall=%i\n",t23,tsmall));
765
766
    g_swap(t23,tsmall);
767
768
    t23++;
769
    tsmall--;
770
DBG(fprintf(stderr,"new t23=%i,tsmall=%i\n\n",t23,tsmall));
771
  }
772
  DBG(fprintf(stderr,"packets with n=23, t23=%i   grouped=%i\n",t23,grouped));
773
  DBG(fprintf(stderr,"MIDSORTING\n"));
774
  for(i=0;i<grouped;i++){
775
    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]));
776
    }
777
778
  // step 2: sort small packets in decreasing order of n (bubble sort is enough)
779
  for(i=t23;i<grouped;i++){
780
    for(j=i+1;j<grouped;j++){
781
      if(g_n[j]>g_n[i]){
782
        g_swap(i,j);
783
      }
784
    }
785
  }
786
  DBG(fprintf(stderr,"POSTSORTING\n"));
787
  for(i=0;i<grouped;i++){
788
    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]));
789
    }
790
791
  // we need to know how many packets need 23 iterations, how many 22...
792
  for(i=0;i<=23;i++){
793
    alive[i]=0;
794
  }
795
  // count
796
  alive[23-1]=t23;
797
  for(i=t23;i<grouped;i++){
798
    alive[g_n[i]-1]++;
799
  }
800
  // integrate
801
  for(i=22;i>=0;i--){
802
    alive[i]+=alive[i+1];
803
  }
804
  DBG(fprintf(stderr,"ALIVE\n"));
805
  for(i=0;i<=23;i++){
806
    DBG(fprintf(stderr,"alive%2i=%i\n",i,alive[i]));
807
    }
808
809
  // choose key
810
  if(group_ev_od==0){
811
    k=&((struct csa_keys_t *)keys)->even;
812
  }
813
  else{
814
    k=&((struct csa_keys_t *)keys)->odd;
815
  }
816
817
  //INIT
818
//#define INITIALIZE_UNUSED_INPUT
819
#ifdef INITIALIZE_UNUSED_INPUT
820
// unnecessary zeroing.
821
// without this, we operate on uninitialized memory
822
// when grouped<GROUP_PARALLELISM, but it's not a problem,
823
// as final results will be discarded.
824
// random data makes debugging sessions difficult.
825
  for(j=0;j<GROUP_PARALLELISM*8;j++) stream_in[j]=0;
826
DBG(fprintf(stderr,"--- WARNING: you could gain speed by not initializing unused memory ---\n"));
827
#else
828
DBG(fprintf(stderr,"--- WARNING: DEBUGGING IS MORE DIFFICULT WHEN PROCESSING RANDOM DATA CHANGING AT EVERY RUN! ---\n"));
829
#endif
830
831
  for(g=0;g<grouped;g++){
832
    encp[g]=g_pkt[g];
833
    DBG(fprintf(stderr,"header[%i]=%p (%02x)\n",g,encp[g],*(encp[g])));
834
    encp[g]+=g_offset[g]; // skip header
835
#ifdef COPY_UNALIGNED_PKT
836
    if(((int)encp[g])&0x03) {
837
      memcpy(alignedBuff[g],encp[g],g_len[g]);
838
      unaligned[g]=encp[g];
839
      encp[g]=alignedBuff[g];
840
      }
841
    else unaligned[g]=0;
842
#endif
843
    FFTABLEIN(stream_in,g,encp[g]);
844
  }
845
//dump_mem("stream_in",stream_in,GROUP_PARALLELISM*8,BYPG);
846
847
848
  // ITER 0
849
DBG(fprintf(stderr,">>>>>ITER 0\n"));
850
  iter=0;
851
  stream_cypher_group_init(&regs,k->iA_g,k->iB_g,stream_in);
852
  // fill first ib
853
  for(g=0;g<alive[iter];g++){
854
    COPY_8_BY(ib+8*g,encp[g]);
855
  }
856
DBG(dump_mem("IB ",ib,8*alive[iter],8));
857
  // ITER 1..N-1
858
  for (iter=1;iter<23&&alive[iter-1]>0;iter++){
859
DBG(fprintf(stderr,">>>>>ITER %i\n",iter));
860
    // alive and just dead packets: calc block
861
    block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]);
862
DBG(dump_mem("BLO_ib ",block_out,8*alive[iter-1],8));
863
    // all packets (dead too): calc stream
864
    stream_cypher_group_normal(&regs,stream_out);
865
//dump_mem("stream_out",stream_out,GROUP_PARALLELISM*8,BYPG);
866
867
    // alive packets: calc ib
868
    for(g=0;g<alive[iter];g++){
869
      FFTABLEOUT(ib+8*g,stream_out,g);
870
DBG(dump_mem("stream_out_ib ",ib+8*g,8,8));
871
// XOREQ8BY gcc bug? 2x4 ok, 8 ko    UPDATE: result ok but speed 1-2% slower (!!!???)
872
#if 1
873
      XOREQ_4_BY(ib+8*g,encp[g]+8);
874
      XOREQ_4_BY(ib+8*g+4,encp[g]+8+4);
875
#else
876
      XOREQ_8_BY(ib+8*g,encp[g]+8);
877
#endif
878
DBG(dump_mem("after_stream_xor_ib ",ib+8*g,8,8));
879
    }
880
    // alive packets: decrypt data
881
    for(g=0;g<alive[iter];g++){
882
DBG(dump_mem("before_ib_decrypt_data ",encp[g],8,8));
883
      XOR_8_BY(encp[g],ib+8*g,block_out+8*g);
884
DBG(dump_mem("after_ib_decrypt_data ",encp[g],8,8));
885
    }
886
    // just dead packets: write decrypted data
887
    for(g=alive[iter];g<alive[iter-1];g++){
888
DBG(dump_mem("jd_before_ib_decrypt_data ",encp[g],8,8));
889
      COPY_8_BY(encp[g],block_out+8*g);
890
DBG(dump_mem("jd_after_ib_decrypt_data ",encp[g],8,8));
891
    }
892
    // just dead packets: decrypt residue
893
    for(g=alive[iter];g<alive[iter-1];g++){
894
DBG(dump_mem("jd_before_decrypt_residue ",encp[g]+8,g_residue[g],g_residue[g]));
895
      FFTABLEOUTXORNBY(g_residue[g],encp[g]+8,stream_out,g);
896
DBG(dump_mem("jd_after_decrypt_residue ",encp[g]+8,g_residue[g],g_residue[g]));
897
    }
898
    // alive packets: pointers++
899
    for(g=0;g<alive[iter];g++) encp[g]+=8;
900
  };
901
  // ITER N
902
DBG(fprintf(stderr,">>>>>ITER 23\n"));
903
  iter=23;
904
  // calc block
905
  block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]);
906
DBG(dump_mem("23BLO_ib ",block_out,8*alive[iter-1],8));
907
  // just dead packets: write decrypted data
908
  for(g=alive[iter];g<alive[iter-1];g++){
909
DBG(dump_mem("23jd_before_ib_decrypt_data ",encp[g],8,8));
910
    COPY_8_BY(encp[g],block_out+8*g);
911
DBG(dump_mem("23jd_after_ib_decrypt_data ",encp[g],8,8));
912
  }
913
  // no residue possible
914
  // so do nothing
915
916
  DBG(fprintf(stderr,"returning advanced=%i\n",advanced));
917
918
#ifdef COPY_UNALIGNED_PKT
919
  for(g=0;g<grouped;g++)
920
    if(unaligned[g]) memcpy(unaligned[g],alignedBuff[g],g_len[g]);
921
#endif
922
923
  M_EMPTY(); // restore CPU multimedia state
924
925
  return advanced;
926
}
(-)ffdecsa/ffdecsa.h (+62 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2003-2004  fatih89r
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
20
21
#ifndef FFDECSA_H
22
#define FFDECSA_H
23
24
//----- public interface
25
26
// -- how many packets can be decrypted at the same time
27
// This is an info about internal decryption parallelism.
28
// You should try to call decrypt_packets with more packets than the number
29
// returned here for performance reasons (use get_suggested_cluster_size to know
30
// how many).
31
int get_internal_parallelism(void);
32
33
// -- how many packets you should have in a cluster when calling decrypt_packets
34
// This is a suggestion to achieve optimal performance; typically a little
35
// higher than what get_internal_parallelism returns.
36
// Passing less packets could slow down the decryption.
37
// Passing more packets is never bad (if you don't spend a lot of time building
38
// the list).
39
int get_suggested_cluster_size(void);
40
41
// -- alloc & free the key structure
42
void *get_key_struct(void);
43
void free_key_struct(void *keys);
44
45
// -- set control words, 8 bytes each
46
void set_control_words(void *keys, const unsigned char *even, const unsigned char *odd);
47
48
// -- set even control word, 8 bytes
49
void set_even_control_word(void *keys, const unsigned char *even);
50
51
// -- set odd control word, 8 bytes
52
void set_odd_control_word(void *keys, const unsigned char *odd);
53
54
// -- get control words, 8 bytes each
55
//void get_control_words(void *keys, unsigned char *even, unsigned char *odd);
56
57
// -- decrypt many TS packets
58
// This interface is a bit complicated because it is designed for maximum speed.
59
// Please read doc/how_to_use.txt.
60
int decrypt_packets(void *keys, unsigned char **cluster);
61
62
#endif
(-)ffdecsa/fftable.h (+56 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2007 Dark Avenger
4
 *               2003-2004  fatih89r
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
21
#ifndef FFTABLE_H
22
#define FFTABLE_H
23
24
inline static void FFTABLEIN(unsigned char *tab, int g, unsigned char *data)
25
{
26
#if 0
27
  *(((int *)tab)+2*g)=*((int *)data);
28
  *(((int *)tab)+2*g+1)=*(((int *)data)+1);
29
#else
30
  *(((long long *)tab)+g)=*((long long *)data);
31
#endif
32
}
33
34
inline static void FFTABLEOUT(unsigned char *data, unsigned char *tab, int g)
35
{
36
#if 1
37
  *((int *)data)=*(((int *)tab)+2*g);
38
  *(((int *)data)+1)=*(((int *)tab)+2*g+1);
39
#else
40
  *((long long *)data)=*(((long long *)tab)+g);
41
#endif
42
}
43
44
inline static void FFTABLEOUTXORNBY(int n, unsigned char *data, unsigned char *tab, int g)
45
{
46
  int j;
47
  for(j=0;j<n;j++) *(data+j)^=*(tab+8*g+j);
48
}
49
50
#undef XOREQ_BEST_BY
51
inline static void XOREQ_BEST_BY(unsigned char *d, unsigned char *s)
52
{
53
	XOR_BEST_BY(d, d, s);
54
}
55
56
#endif //FFTABLE_H 
(-)ffdecsa/parallel_032_int.h (+55 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2003-2004  fatih89r
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
20
#include "parallel_std_def.h"
21
22
typedef unsigned int group;
23
#define GROUP_PARALLELISM 32
24
#define FF0()      0x0
25
#define FF1()      0xffffffff
26
27
/* 64 rows of 32 bits */
28
29
inline static void FFTABLEIN(unsigned char *tab, int g, unsigned char *data){
30
  *(((int *)tab)+g)=*((int *)data);
31
  *(((int *)tab)+32+g)=*(((int *)data)+1);
32
}
33
34
inline static void FFTABLEOUT(unsigned char *data, unsigned char *tab, int g){
35
  *((int *)data)=*(((int *)tab)+g);
36
  *(((int *)data)+1)=*(((int *)tab)+32+g);
37
}
38
39
inline static void FFTABLEOUTXORNBY(int n, unsigned char *data, unsigned char *tab, int g){
40
  int j;
41
  for(j=0;j<n;j++){
42
    *(data+j)^=*(tab+4*(g+(j>=4?32-1:0))+j);
43
  }
44
}
45
46
typedef unsigned int batch;
47
#define BYTES_PER_BATCH 4
48
#define B_FFN_ALL_29() 0x29292929
49
#define B_FFN_ALL_02() 0x02020202
50
#define B_FFN_ALL_04() 0x04040404
51
#define B_FFN_ALL_10() 0x10101010
52
#define B_FFN_ALL_40() 0x40404040
53
#define B_FFN_ALL_80() 0x80808080
54
55
#define M_EMPTY()
(-)ffdecsa/parallel_064_long.h (+39 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2007 Dark Avenger
4
 *               2003-2004  fatih89r
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
21
#include "parallel_std_def.h"
22
23
typedef unsigned long long group;
24
#define GROUP_PARALLELISM 64
25
#define FF0() 0x0ULL
26
#define FF1() 0xffffffffffffffffULL
27
28
typedef unsigned long long batch;
29
#define BYTES_PER_BATCH 8
30
#define B_FFN_ALL_29() 0x2929292929292929ULL
31
#define B_FFN_ALL_02() 0x0202020202020202ULL
32
#define B_FFN_ALL_04() 0x0404040404040404ULL
33
#define B_FFN_ALL_10() 0x1010101010101010ULL
34
#define B_FFN_ALL_40() 0x4040404040404040ULL
35
#define B_FFN_ALL_80() 0x8080808080808080ULL
36
37
#define M_EMPTY()
38
39
#include "fftable.h"
(-)ffdecsa/parallel_128_sse2.h (+82 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2007 Dark Avenger
4
 *               2003-2004  fatih89r
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
21
#include <emmintrin.h>
22
23
#define MEMALIGN_VAL 16
24
25
union __u128i {
26
	unsigned int u[4];
27
	__m128i v;
28
};
29
30
static const union __u128i ff0 = {{0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U}};
31
static const union __u128i ff1 = {{0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU}};
32
33
typedef __m128i group;
34
#define GROUP_PARALLELISM 128
35
#define FF0() ff0.v
36
#define FF1() ff1.v
37
#define FFAND(a,b) _mm_and_si128((a),(b))
38
#define FFOR(a,b)  _mm_or_si128((a),(b))
39
#define FFXOR(a,b) _mm_xor_si128((a),(b))
40
#define FFNOT(a)   _mm_xor_si128((a),FF1())
41
#define MALLOC(X)  _mm_malloc(X,16)
42
#define FREE(X)    _mm_free(X)
43
44
/* BATCH */
45
46
static const union __u128i ff29 = {{0x29292929U, 0x29292929U, 0x29292929U, 0x29292929U}};
47
static const union __u128i ff02 = {{0x02020202U, 0x02020202U, 0x02020202U, 0x02020202U}};
48
static const union __u128i ff04 = {{0x04040404U, 0x04040404U, 0x04040404U, 0x04040404U}};
49
static const union __u128i ff10 = {{0x10101010U, 0x10101010U, 0x10101010U, 0x10101010U}};
50
static const union __u128i ff40 = {{0x40404040U, 0x40404040U, 0x40404040U, 0x40404040U}};
51
static const union __u128i ff80 = {{0x80808080U, 0x80808080U, 0x80808080U, 0x80808080U}};
52
53
typedef __m128i batch;
54
#define BYTES_PER_BATCH 16
55
#define B_FFN_ALL_29() ff29.v
56
#define B_FFN_ALL_02() ff02.v
57
#define B_FFN_ALL_04() ff04.v
58
#define B_FFN_ALL_10() ff10.v
59
#define B_FFN_ALL_40() ff40.v
60
#define B_FFN_ALL_80() ff80.v
61
62
#define B_FFAND(a,b) FFAND(a,b)
63
#define B_FFOR(a,b)  FFOR(a,b)
64
#define B_FFXOR(a,b) FFXOR(a,b)
65
#define B_FFSH8L(a,n) _mm_slli_epi64((a),(n))
66
#define B_FFSH8R(a,n) _mm_srli_epi64((a),(n))
67
68
#define M_EMPTY()
69
70
#undef BEST_SPAN
71
#define BEST_SPAN            16
72
73
#undef XOR_BEST_BY
74
inline static void XOR_BEST_BY(unsigned char *d, unsigned char *s1, unsigned char *s2)
75
{
76
	__m128i vs1 = _mm_load_si128((__m128i*)s1);
77
	__m128i vs2 = _mm_load_si128((__m128i*)s2);
78
	vs1 = _mm_xor_si128(vs1, vs2);
79
	_mm_store_si128((__m128i*)d, vs1);
80
}
81
82
#include "fftable.h"
(-)ffdecsa/parallel_generic.h (+102 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2003-2004  fatih89r
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
20
21
22
#if 0
23
//// generics
24
#define COPY4BY(d,s)     do{ int *pd=(int *)(d), *ps=(int *)(s); \
25
                             *pd = *ps; }while(0)
26
#define COPY8BY(d,s)     do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
27
                             *pd = *ps; }while(0)
28
#define COPY16BY(d,s)    do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
29
                             *pd = *ps; \
30
			     *(pd+1) = *(ps+1); }while(0)
31
#define COPY32BY(d,s)    do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
32
                             *pd = *ps; \
33
			     *(pd+1) = *(ps+1) \
34
			     *(pd+2) = *(ps+2) \
35
			     *(pd+3) = *(ps+3); }while(0)
36
#define XOR4BY(d,s1,s2)  do{ int *pd=(int *)(d), *ps1=(int *)(s1), *ps2=(int *)(s2); \
37
                             *pd = *ps1  ^ *ps2; }while(0)
38
#define XOR8BY(d,s1,s2)  do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
39
                             *pd = *ps1  ^ *ps2; }while(0)
40
#define XOR16BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
41
                             *pd = *ps1  ^ *ps2; \
42
                             *(pd+8) = *(ps1+8)  ^ *(ps2+8); }while(0)
43
#define XOR32BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
44
                             *pd = *ps1  ^ *ps2; \
45
                             *(pd+1) = *(ps1+1)  ^ *(ps2+1); \
46
                             *(pd+2) = *(ps1+2)  ^ *(ps2+2); \
47
                             *(pd+3) = *(ps1+3)  ^ *(ps2+3); }while(0)
48
#define XOR32BV(d,s1,s2) do{ int *const pd=(int *const)(d), *ps1=(const int *const)(s1), *ps2=(const int *const)(s2); \
49
                             int z; \
50
			     for(z=0;z<8;z++){ \
51
                               pd[z]=ps1[z]^ps2[z]; \
52
			     } \
53
                           }while(0)
54
#define XOREQ4BY(d,s)    do{ int *pd=(int *)(d), *ps=(int *)(s); \
55
                             *pd ^= *ps; }while(0)
56
#define XOREQ8BY(d,s)    do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
57
                             *pd ^= *ps; }while(0)
58
#define XOREQ16BY(d,s)   do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
59
                             *pd ^= *ps; \
60
			     *(pd+1) ^=*(ps+1); }while(0)
61
#define XOREQ32BY(d,s)   do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
62
                             *pd ^= *ps; \
63
			     *(pd+1) ^=*(ps+1); \
64
			     *(pd+2) ^=*(ps+2); \
65
			     *(pd+3) ^=*(ps+3); }while(0)
66
#define XOREQ32BY4(d,s)  do{ int *pd=(int *)(d), *ps=(int *)(s); \
67
                             *pd ^= *ps; \
68
			     *(pd+1) ^=*(ps+1); \
69
			     *(pd+2) ^=*(ps+2); \
70
			     *(pd+3) ^=*(ps+3); \
71
			     *(pd+4) ^=*(ps+4); \
72
			     *(pd+5) ^=*(ps+5); \
73
			     *(pd+6) ^=*(ps+6); \
74
			     *(pd+7) ^=*(ps+7); }while(0)
75
#define XOREQ32BV(d,s)   do{ unsigned char *pd=(unsigned char *)(d), *ps=(unsigned char *)(s); \
76
                             int z; \
77
			     for(z=0;z<32;z++){ \
78
                               pd[z]^=ps[z]; \
79
			     } \
80
                           }while(0)
81
82
#else
83
#define XOR_4_BY(d,s1,s2)    do{ int *pd=(int *)(d), *ps1=(int *)(s1), *ps2=(int *)(s2); \
84
                               *pd = *ps1  ^ *ps2; }while(0)
85
#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); \
86
                               *pd = *ps1  ^ *ps2; }while(0)
87
#define XOREQ_4_BY(d,s)      do{ int *pd=(int *)(d), *ps=(int *)(s); \
88
                               *pd ^= *ps; }while(0)
89
#define XOREQ_8_BY(d,s)      do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
90
                               *pd ^= *ps; }while(0)
91
#define COPY_4_BY(d,s)       do{ int *pd=(int *)(d), *ps=(int *)(s); \
92
                               *pd = *ps; }while(0)
93
#define COPY_8_BY(d,s)       do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
94
                               *pd = *ps; }while(0)
95
96
#define BEST_SPAN            8
97
#define XOR_BEST_BY(d,s1,s2) do{ XOR_8_BY(d,s1,s2); }while(0);
98
#define XOREQ_BEST_BY(d,s)   do{ XOREQ_8_BY(d,s); }while(0);
99
#define COPY_BEST_BY(d,s)    do{ COPY_8_BY(d,s); }while(0);
100
101
#define END_MM             do{ }while(0);
102
#endif
(-)ffdecsa/parallel_std_def.h (+29 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2003-2004  fatih89r
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
20
#define FFXOR(a,b) ((a)^(b))
21
#define FFAND(a,b) ((a)&(b))
22
#define FFOR(a,b)  ((a)|(b))
23
#define FFNOT(a)   (~(a))
24
25
#define B_FFAND(a,b) ((a)&(b))
26
#define B_FFOR(a,b)  ((a)|(b))
27
#define B_FFXOR(a,b) ((a)^(b))
28
#define B_FFSH8L(a,n) ((a)<<(n))
29
#define B_FFSH8R(a,n) ((a)>>(n))
(-)ffdecsa/stream.c (+906 lines)
Line 0 Link Here
1
/* FFdecsa -- fast decsa algorithm
2
 *
3
 * Copyright (C) 2003-2004  fatih89r
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
20
21
22
// define statics only once, when STREAM_INIT
23
#ifdef STREAM_INIT
24
struct stream_regs {
25
  group A[32+10][4]; // 32 because we will move back (virtual shift register)
26
  group B[32+10][4]; // 32 because we will move back (virtual shift register)
27
  group X[4];
28
  group Y[4];
29
  group Z[4];
30
  group D[4];
31
  group E[4];
32
  group F[4];
33
  group p;
34
  group q;
35
  group r;
36
  };
37
38
static inline void trasp64_32_88ccw(unsigned char *data){
39
/* 64 rows of 32 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
40
#define row ((unsigned int *)data)
41
  int i,j;
42
  for(j=0;j<64;j+=32){
43
    unsigned int t,b;
44
    for(i=0;i<16;i++){
45
      t=row[j+i];
46
      b=row[j+16+i];
47
      row[j+i]   = (t&0x0000ffff)      | ((b           )<<16);
48
      row[j+16+i]=((t           )>>16) |  (b&0xffff0000) ;
49
    }
50
  }
51
  for(j=0;j<64;j+=16){
52
    unsigned int t,b;
53
    for(i=0;i<8;i++){
54
      t=row[j+i];
55
      b=row[j+8+i];
56
      row[j+i]   = (t&0x00ff00ff)     | ((b&0x00ff00ff)<<8);
57
      row[j+8+i] =((t&0xff00ff00)>>8) |  (b&0xff00ff00);
58
    }
59
  }
60
  for(j=0;j<64;j+=8){
61
    unsigned int t,b;
62
    for(i=0;i<4;i++){
63
      t=row[j+i];
64
      b=row[j+4+i];
65
      row[j+i]   =((t&0x0f0f0f0f)<<4) |  (b&0x0f0f0f0f);
66
      row[j+4+i] = (t&0xf0f0f0f0)     | ((b&0xf0f0f0f0)>>4);
67
    }
68
  }
69
  for(j=0;j<64;j+=4){
70
    unsigned int t,b;
71
    for(i=0;i<2;i++){
72
      t=row[j+i];
73
      b=row[j+2+i];
74
      row[j+i]   =((t&0x33333333)<<2) |  (b&0x33333333);
75
      row[j+2+i] = (t&0xcccccccc)     | ((b&0xcccccccc)>>2);
76
    }
77
  }
78
  for(j=0;j<64;j+=2){
79
    unsigned int t,b;
80
    for(i=0;i<1;i++){
81
      t=row[j+i];
82
      b=row[j+1+i];
83
      row[j+i]   =((t&0x55555555)<<1) |  (b&0x55555555);
84
      row[j+1+i] = (t&0xaaaaaaaa)     | ((b&0xaaaaaaaa)>>1);
85
    }
86
  }
87
#undef row
88
}
89
90
static inline void trasp64_32_88cw(unsigned char *data){
91
/* 64 rows of 32 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
92
#define row ((unsigned int *)data)
93
  int i,j;
94
  for(j=0;j<64;j+=32){
95
    unsigned int t,b;
96
    for(i=0;i<16;i++){
97
      t=row[j+i];
98
      b=row[j+16+i];
99
      row[j+i]   = (t&0x0000ffff)      | ((b           )<<16);
100
      row[j+16+i]=((t           )>>16) |  (b&0xffff0000) ;
101
    }
102
  }
103
  for(j=0;j<64;j+=16){
104
    unsigned int t,b;
105
    for(i=0;i<8;i++){
106
      t=row[j+i];
107
      b=row[j+8+i];
108
      row[j+i]   = (t&0x00ff00ff)     | ((b&0x00ff00ff)<<8);
109
      row[j+8+i] =((t&0xff00ff00)>>8) |  (b&0xff00ff00);
110
    }
111
  }
112
  for(j=0;j<64;j+=8){
113
    unsigned int t,b;
114
    for(i=0;i<4;i++){
115
      t=row[j+i];
116
      b=row[j+4+i];
117
      row[j+i]  =((t&0xf0f0f0f0)>>4) |   (b&0xf0f0f0f0);
118
      row[j+4+i]= (t&0x0f0f0f0f)     |  ((b&0x0f0f0f0f)<<4);
119
    }
120
  }
121
  for(j=0;j<64;j+=4){
122
    unsigned int t,b;
123
    for(i=0;i<2;i++){
124
      t=row[j+i];
125
      b=row[j+2+i];
126
      row[j+i]  =((t&0xcccccccc)>>2) |  (b&0xcccccccc);
127
      row[j+2+i]= (t&0x33333333)     | ((b&0x33333333)<<2);
128
    }
129
  }
130
  for(j=0;j<64;j+=2){
131
    unsigned int t,b;
132
    for(i=0;i<1;i++){
133
      t=row[j+i];
134
      b=row[j+1+i];
135
      row[j+i]  =((t&0xaaaaaaaa)>>1) |  (b&0xaaaaaaaa);
136
      row[j+1+i]= (t&0x55555555)     | ((b&0x55555555)<<1);
137
    }
138
  }
139
#undef row
140
}
141
142
//64-64----------------------------------------------------------
143
static inline void trasp64_64_88ccw(unsigned char *data){
144
/* 64 rows of 64 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
145
#define row ((unsigned long long int *)data)
146
  int i,j;
147
  for(j=0;j<64;j+=64){
148
    unsigned long long int t,b;
149
    for(i=0;i<32;i++){
150
      t=row[j+i];
151
      b=row[j+32+i];
152
      row[j+i]   = (t&0x00000000ffffffffULL)      | ((b                      )<<32);
153
      row[j+32+i]=((t                      )>>32) |  (b&0xffffffff00000000ULL) ;
154
    }
155
  }
156
  for(j=0;j<64;j+=32){
157
    unsigned long long int t,b;
158
    for(i=0;i<16;i++){
159
      t=row[j+i];
160
      b=row[j+16+i];
161
      row[j+i]   = (t&0x0000ffff0000ffffULL)      | ((b&0x0000ffff0000ffffULL)<<16);
162
      row[j+16+i]=((t&0xffff0000ffff0000ULL)>>16) |  (b&0xffff0000ffff0000ULL) ;
163
    }
164
  }
165
  for(j=0;j<64;j+=16){
166
    unsigned long long int t,b;
167
    for(i=0;i<8;i++){
168
      t=row[j+i];
169
      b=row[j+8+i];
170
      row[j+i]   = (t&0x00ff00ff00ff00ffULL)     | ((b&0x00ff00ff00ff00ffULL)<<8);
171
      row[j+8+i] =((t&0xff00ff00ff00ff00ULL)>>8) |  (b&0xff00ff00ff00ff00ULL);
172
    }
173
  }
174
  for(j=0;j<64;j+=8){
175
    unsigned long long int t,b;
176
    for(i=0;i<4;i++){
177
      t=row[j+i];
178
      b=row[j+4+i];
179
      row[j+i]   =((t&0x0f0f0f0f0f0f0f0fULL)<<4) |  (b&0x0f0f0f0f0f0f0f0fULL);
180
      row[j+4+i] = (t&0xf0f0f0f0f0f0f0f0ULL)     | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
181
    }
182
  }
183
  for(j=0;j<64;j+=4){
184
    unsigned long long int t,b;
185
    for(i=0;i<2;i++){
186
      t=row[j+i];
187
      b=row[j+2+i];
188
      row[j+i]   =((t&0x3333333333333333ULL)<<2) |  (b&0x3333333333333333ULL);
189
      row[j+2+i] = (t&0xccccccccccccccccULL)     | ((b&0xccccccccccccccccULL)>>2);
190
    }
191
  }
192
  for(j=0;j<64;j+=2){
193
    unsigned long long int t,b;
194
    for(i=0;i<1;i++){
195
      t=row[j+i];
196
      b=row[j+1+i];
197
      row[j+i]   =((t&0x5555555555555555ULL)<<1) |  (b&0x5555555555555555ULL);
198
      row[j+1+i] = (t&0xaaaaaaaaaaaaaaaaULL)     | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
199
    }
200
  }
201
#undef row
202
}
203
204
static inline void trasp64_64_88cw(unsigned char *data){
205
/* 64 rows of 64 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
206
#define row ((unsigned long long int *)data)
207
  int i,j;
208
  for(j=0;j<64;j+=64){
209
    unsigned long long int t,b;
210
    for(i=0;i<32;i++){
211
      t=row[j+i];
212
      b=row[j+32+i];
213
      row[j+i]   = (t&0x00000000ffffffffULL)      | ((b                      )<<32);
214
      row[j+32+i]=((t                      )>>32) |  (b&0xffffffff00000000ULL) ;
215
    }
216
  }
217
  for(j=0;j<64;j+=32){
218
    unsigned long long int t,b;
219
    for(i=0;i<16;i++){
220
      t=row[j+i];
221
      b=row[j+16+i];
222
      row[j+i]   = (t&0x0000ffff0000ffffULL)      | ((b&0x0000ffff0000ffffULL)<<16);
223
      row[j+16+i]=((t&0xffff0000ffff0000ULL)>>16) |  (b&0xffff0000ffff0000ULL) ;
224
    }
225
  }
226
  for(j=0;j<64;j+=16){
227
    unsigned long long int t,b;
228
    for(i=0;i<8;i++){
229
      t=row[j+i];
230
      b=row[j+8+i];
231
      row[j+i]   = (t&0x00ff00ff00ff00ffULL)     | ((b&0x00ff00ff00ff00ffULL)<<8);
232
      row[j+8+i] =((t&0xff00ff00ff00ff00ULL)>>8) |  (b&0xff00ff00ff00ff00ULL);
233
    }
234
  }
235
  for(j=0;j<64;j+=8){
236
    unsigned long long int t,b;
237
    for(i=0;i<4;i++){
238
      t=row[j+i];
239
      b=row[j+4+i];
240
      row[j+i]   =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) |   (b&0xf0f0f0f0f0f0f0f0ULL);
241
      row[j+4+i] = (t&0x0f0f0f0f0f0f0f0fULL)     |  ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
242
    }
243
  }
244
  for(j=0;j<64;j+=4){
245
    unsigned long long int t,b;
246
    for(i=0;i<2;i++){
247
      t=row[j+i];
248
      b=row[j+2+i];
249
      row[j+i]   =((t&0xccccccccccccccccULL)>>2) |  (b&0xccccccccccccccccULL);
250
      row[j+2+i] = (t&0x3333333333333333ULL)     | ((b&0x3333333333333333ULL)<<2);
251
    }
252
  }
253
  for(j=0;j<64;j+=2){
254
    unsigned long long int t,b;
255
    for(i=0;i<1;i++){
256
      t=row[j+i];
257
      b=row[j+1+i];
258
      row[j+i]   =((t&0xaaaaaaaaaaaaaaaaULL)>>1) |  (b&0xaaaaaaaaaaaaaaaaULL);
259
      row[j+1+i] = (t&0x5555555555555555ULL)     | ((b&0x5555555555555555ULL)<<1);
260
    }
261
  }
262
#undef row
263
}
264
265
//64-128----------------------------------------------------------
266
static inline void trasp64_128_88ccw(unsigned char *data){
267
/* 64 rows of 128 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
268
#define halfrow ((unsigned long long int *)data)
269
  int i,j;
270
  for(j=0;j<64;j+=64){
271
    unsigned long long int t,b;
272
    for(i=0;i<32;i++){
273
      t=halfrow[2*(j+i)];
274
      b=halfrow[2*(j+32+i)];
275
      halfrow[2*(j+i)]   = (t&0x00000000ffffffffULL)      | ((b                      )<<32);
276
      halfrow[2*(j+32+i)]=((t                      )>>32) |  (b&0xffffffff00000000ULL) ;
277
      t=halfrow[2*(j+i)+1];
278
      b=halfrow[2*(j+32+i)+1];
279
      halfrow[2*(j+i)+1]   = (t&0x00000000ffffffffULL)      | ((b                      )<<32);
280
      halfrow[2*(j+32+i)+1]=((t                      )>>32) |  (b&0xffffffff00000000ULL) ;
281
    }
282
  }
283
  for(j=0;j<64;j+=32){
284
    unsigned long long int t,b;
285
    for(i=0;i<16;i++){
286
      t=halfrow[2*(j+i)];
287
      b=halfrow[2*(j+16+i)];
288
      halfrow[2*(j+i)]   = (t&0x0000ffff0000ffffULL)      | ((b&0x0000ffff0000ffffULL)<<16);
289
      halfrow[2*(j+16+i)]=((t&0xffff0000ffff0000ULL)>>16) |  (b&0xffff0000ffff0000ULL) ;
290
      t=halfrow[2*(j+i)+1];
291
      b=halfrow[2*(j+16+i)+1];
292
      halfrow[2*(j+i)+1]   = (t&0x0000ffff0000ffffULL)      | ((b&0x0000ffff0000ffffULL)<<16);
293
      halfrow[2*(j+16+i)+1]=((t&0xffff0000ffff0000ULL)>>16) |  (b&0xffff0000ffff0000ULL) ;
294
    }
295
  }
296
  for(j=0;j<64;j+=16){
297
    unsigned long long int t,b;
298
    for(i=0;i<8;i++){
299
      t=halfrow[2*(j+i)];
300
      b=halfrow[2*(j+8+i)];
301
      halfrow[2*(j+i)]   = (t&0x00ff00ff00ff00ffULL)     | ((b&0x00ff00ff00ff00ffULL)<<8);
302
      halfrow[2*(j+8+i)] =((t&0xff00ff00ff00ff00ULL)>>8) |  (b&0xff00ff00ff00ff00ULL);
303
      t=halfrow[2*(j+i)+1];
304
      b=halfrow[2*(j+8+i)+1];
305
      halfrow[2*(j+i)+1]   = (t&0x00ff00ff00ff00ffULL)     | ((b&0x00ff00ff00ff00ffULL)<<8);
306
      halfrow[2*(j+8+i)+1] =((t&0xff00ff00ff00ff00ULL)>>8) |  (b&0xff00ff00ff00ff00ULL);
307
    }
308
  }
309
  for(j=0;j<64;j+=8){
310
    unsigned long long int t,b;
311
    for(i=0;i<4;i++){
312
      t=halfrow[2*(j+i)];
313
      b=halfrow[2*(j+4+i)];
314
      halfrow[2*(j+i)]   =((t&0x0f0f0f0f0f0f0f0fULL)<<4) |  (b&0x0f0f0f0f0f0f0f0fULL);
315
      halfrow[2*(j+4+i)] = (t&0xf0f0f0f0f0f0f0f0ULL)     | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
316
      t=halfrow[2*(j+i)+1];
317
      b=halfrow[2*(j+4+i)+1];
318
      halfrow[2*(j+i)+1]   =((t&0x0f0f0f0f0f0f0f0fULL)<<4) |  (b&0x0f0f0f0f0f0f0f0fULL);
319
      halfrow[2*(j+4+i)+1] = (t&0xf0f0f0f0f0f0f0f0ULL)     | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
320
    }
321
  }
322
  for(j=0;j<64;j+=4){
323
    unsigned long long int t,b;
324
    for(i=0;i<2;i++){
325
      t=halfrow[2*(j+i)];
326
      b=halfrow[2*(j+2+i)];
327
      halfrow[2*(j+i)]   =((t&0x3333333333333333ULL)<<2) |  (b&0x3333333333333333ULL);
328
      halfrow[2*(j+2+i)] = (t&0xccccccccccccccccULL)     | ((b&0xccccccccccccccccULL)>>2);
329
      t=halfrow[2*(j+i)+1];
330
      b=halfrow[2*(j+2+i)+1];
331
      halfrow[2*(j+i)+1]   =((t&0x3333333333333333ULL)<<2) |  (b&0x3333333333333333ULL);
332
      halfrow[2*(j+2+i)+1] = (t&0xccccccccccccccccULL)     | ((b&0xccccccccccccccccULL)>>2);
333
    }
334
  }
335
  for(j=0;j<64;j+=2){
336
    unsigned long long int t,b;
337
    for(i=0;i<1;i++){
338
      t=halfrow[2*(j+i)];
339
      b=halfrow[2*(j+1+i)];
340
      halfrow[2*(j+i)]   =((t&0x5555555555555555ULL)<<1) |  (b&0x5555555555555555ULL);
341
      halfrow[2*(j+1+i)] = (t&0xaaaaaaaaaaaaaaaaULL)     | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
342
      t=halfrow[2*(j+i)+1];
343
      b=halfrow[2*(j+1+i)+1];
344
      halfrow[2*(j+i)+1]   =((t&0x5555555555555555ULL)<<1) |  (b&0x5555555555555555ULL);
345
      halfrow[2*(j+1+i)+1] = (t&0xaaaaaaaaaaaaaaaaULL)     | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
346
    }
347
  }
348
#undef halfrow
349
}
350
351
static inline void trasp64_128_88cw(unsigned char *data){
352
/* 64 rows of 128 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
353
#define halfrow ((unsigned long long int *)data)
354
  int i,j;
355
  for(j=0;j<64;j+=64){
356
    unsigned long long int t,b;
357
    for(i=0;i<32;i++){
358
      t=halfrow[2*(j+i)];
359
      b=halfrow[2*(j+32+i)];
360
      halfrow[2*(j+i)]   = (t&0x00000000ffffffffULL)      | ((b                      )<<32);
361
      halfrow[2*(j+32+i)]=((t                      )>>32) |  (b&0xffffffff00000000ULL) ;
362
      t=halfrow[2*(j+i)+1];
363
      b=halfrow[2*(j+32+i)+1];
364
      halfrow[2*(j+i)+1]   = (t&0x00000000ffffffffULL)      | ((b                      )<<32);
365
      halfrow[2*(j+32+i)+1]=((t                      )>>32) |  (b&0xffffffff00000000ULL) ;
366
    }
367
  }
368
  for(j=0;j<64;j+=32){
369
    unsigned long long int t,b;
370
    for(i=0;i<16;i++){
371
      t=halfrow[2*(j+i)];
372
      b=halfrow[2*(j+16+i)];
373
      halfrow[2*(j+i)]   = (t&0x0000ffff0000ffffULL)      | ((b&0x0000ffff0000ffffULL)<<16);
374
      halfrow[2*(j+16+i)]=((t&0xffff0000ffff0000ULL)>>16) |  (b&0xffff0000ffff0000ULL) ;
375
      t=halfrow[2*(j+i)+1];
376
      b=halfrow[2*(j+16+i)+1];
377
      halfrow[2*(j+i)+1]   = (t&0x0000ffff0000ffffULL)      | ((b&0x0000ffff0000ffffULL)<<16);
378
      halfrow[2*(j+16+i)+1]=((t&0xffff0000ffff0000ULL)>>16) |  (b&0xffff0000ffff0000ULL) ;
379
    }
380
  }
381
  for(j=0;j<64;j+=16){
382
    unsigned long long int t,b;
383
    for(i=0;i<8;i++){
384
      t=halfrow[2*(j+i)];
385
      b=halfrow[2*(j+8+i)];
386
      halfrow[2*(j+i)]   = (t&0x00ff00ff00ff00ffULL)     | ((b&0x00ff00ff00ff00ffULL)<<8);
387
      halfrow[2*(j+8+i)] =((t&0xff00ff00ff00ff00ULL)>>8) |  (b&0xff00ff00ff00ff00ULL);
388
      t=halfrow[2*(j+i)+1];
389
      b=halfrow[2*(j+8+i)+1];
390
      halfrow[2*(j+i)+1]   = (t&0x00ff00ff00ff00ffULL)     | ((b&0x00ff00ff00ff00ffULL)<<8);
391
      halfrow[2*(j+8+i)+1] =((t&0xff00ff00ff00ff00ULL)>>8) |  (b&0xff00ff00ff00ff00ULL);
392
    }
393
  }
394
  for(j=0;j<64;j+=8){
395
    unsigned long long int t,b;
396
    for(i=0;i<4;i++){
397
      t=halfrow[2*(j+i)];
398
      b=halfrow[2*(j+4+i)];
399
      halfrow[2*(j+i)]   =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) |   (b&0xf0f0f0f0f0f0f0f0ULL);
400
      halfrow[2*(j+4+i)] = (t&0x0f0f0f0f0f0f0f0fULL)     |  ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
401
      t=halfrow[2*(j+i)+1];
402
      b=halfrow[2*(j+4+i)+1];
403
      halfrow[2*(j+i)+1]   =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) |   (b&0xf0f0f0f0f0f0f0f0ULL);
404
      halfrow[2*(j+4+i)+1] = (t&0x0f0f0f0f0f0f0f0fULL)     |  ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
405
    }
406
  }
407
  for(j=0;j<64;j+=4){
408
    unsigned long long int t,b;
409
    for(i=0;i<2;i++){
410
      t=halfrow[2*(j+i)];
411
      b=halfrow[2*(j+2+i)];
412
      halfrow[2*(j+i)]   =((t&0xccccccccccccccccULL)>>2) |  (b&0xccccccccccccccccULL);
413
      halfrow[2*(j+2+i)] = (t&0x3333333333333333ULL)     | ((b&0x3333333333333333ULL)<<2);
414
      t=halfrow[2*(j+i)+1];
415
      b=halfrow[2*(j+2+i)+1];
416
      halfrow[2*(j+i)+1]   =((t&0xccccccccccccccccULL)>>2) |  (b&0xccccccccccccccccULL);
417
      halfrow[2*(j+2+i)+1] = (t&0x3333333333333333ULL)     | ((b&0x3333333333333333ULL)<<2);
418
    }
419
  }
420
  for(j=0;j<64;j+=2){
421
    unsigned long long int t,b;
422
    for(i=0;i<1;i++){
423
      t=halfrow[2*(j+i)];
424
      b=halfrow[2*(j+1+i)];
425
      halfrow[2*(j+i)]   =((t&0xaaaaaaaaaaaaaaaaULL)>>1) |  (b&0xaaaaaaaaaaaaaaaaULL);
426
      halfrow[2*(j+1+i)] = (t&0x5555555555555555ULL)     | ((b&0x5555555555555555ULL)<<1);
427
      t=halfrow[2*(j+i)+1];
428
      b=halfrow[2*(j+1+i)+1];
429
      halfrow[2*(j+i)+1]   =((t&0xaaaaaaaaaaaaaaaaULL)>>1) |  (b&0xaaaaaaaaaaaaaaaaULL);
430
      halfrow[2*(j+1+i)+1] = (t&0x5555555555555555ULL)     | ((b&0x5555555555555555ULL)<<1);
431
    }
432
  }
433
#undef halfrow
434
}
435
#endif
436
437
438
#ifdef STREAM_INIT
439
void stream_cypher_group_init(
440
  struct stream_regs *regs,
441
  group         iA[8][4], // [In]  iA00,iA01,...iA73 32 groups  | Derived from key.
442
  group         iB[8][4], // [In]  iB00,iB01,...iB73 32 groups  | Derived from key.
443
  unsigned char *sb)      // [In]  (SB0,SB1,...SB7)...x32 32*8 bytes | Extra input.
444
#endif
445
#ifdef STREAM_NORMAL
446
void stream_cypher_group_normal(
447
  struct stream_regs *regs,
448
  unsigned char *cb)    // [Out] (CB0,CB1,...CB7)...x32 32*8 bytes | Output.
449
#endif
450
{
451
#ifdef STREAM_INIT
452
  group in1[4];
453
  group in2[4];
454
#endif
455
  group extra_B[4];
456
  group fa,fb,fc,fd,fe;
457
  group s1a,s1b,s2a,s2b,s3a,s3b,s4a,s4b,s5a,s5b,s6a,s6b,s7a,s7b;
458
  group next_E[4];
459
  group tmp0,tmp1,tmp2,tmp3,tmp4;
460
#ifdef STREAM_INIT
461
  group *sb_g=(group *)sb;
462
#endif
463
#ifdef STREAM_NORMAL
464
  group *cb_g=(group *)cb;
465
#endif
466
  int aboff;
467
  int i,j,k,b;
468
  int dbg;
469
470
#ifdef STREAM_INIT
471
  DBG(fprintf(stderr,":::::::::: BEGIN STREAM INIT\n"));
472
#endif
473
#ifdef STREAM_NORMAL
474
  DBG(fprintf(stderr,":::::::::: BEGIN STREAM NORMAL\n"));
475
#endif
476
#ifdef STREAM_INIT
477
for(j=0;j<64;j++){
478
  DBG(fprintf(stderr,"precall prerot stream_in[%2i]=",j));
479
  DBG(dump_mem("",sb+BYPG*j,BYPG,BYPG));
480
}
481
482
DBG(dump_mem("stream_prerot ",sb,GROUP_PARALLELISM*8,BYPG));
483
#if GROUP_PARALLELISM==32
484
trasp64_32_88ccw(sb);
485
#endif
486
#if GROUP_PARALLELISM==64
487
trasp64_64_88ccw(sb);
488
#endif
489
#if GROUP_PARALLELISM==128
490
trasp64_128_88ccw(sb);
491
#endif
492
DBG(dump_mem("stream_postrot",sb,GROUP_PARALLELISM*8,BYPG));
493
494
for(j=0;j<64;j++){
495
  DBG(fprintf(stderr,"precall stream_in[%2i]=",j));
496
  DBG(dump_mem("",sb+BYPG*j,BYPG,BYPG));
497
}
498
#endif
499
500
  aboff=32;
501
502
#ifdef STREAM_INIT
503
  // load first 32 bits of ck into A[aboff+0]..A[aboff+7]
504
  // load last  32 bits of ck into B[aboff+0]..B[aboff+7]
505
  // all other regs = 0
506
  for(i=0;i<8;i++){
507
    for(b=0;b<4;b++){
508
DBG(fprintf(stderr,"dbg from iA A[%i][%i]=",i,b));
509
DBG(dump_mem("",(unsigned char *)&iA[i][b],BYPG,BYPG));
510
DBG(fprintf(stderr,"                                       dbg from iB B[%i][%i]=",i,b));
511
DBG(dump_mem("",(unsigned char *)&iB[i][b],BYPG,BYPG));
512
      regs->A[aboff+i][b]=iA[i][b];
513
      regs->B[aboff+i][b]=iB[i][b];
514
    }
515
  }
516
  for(b=0;b<4;b++){
517
    regs->A[aboff+8][b]=FF0();
518
    regs->A[aboff+9][b]=FF0();
519
    regs->B[aboff+8][b]=FF0();
520
    regs->B[aboff+9][b]=FF0();
521
  }
522
  for(b=0;b<4;b++){
523
    regs->X[b]=FF0();
524
    regs->Y[b]=FF0();
525
    regs->Z[b]=FF0();
526
    regs->D[b]=FF0();
527
    regs->E[b]=FF0();
528
    regs->F[b]=FF0();
529
  }
530
  regs->p=FF0();
531
  regs->q=FF0();
532
  regs->r=FF0();
533
#endif
534
535
for(dbg=0;dbg<4;dbg++){
536
  DBG(fprintf(stderr,"dbg A0[%i]=",dbg));
537
  DBG(dump_mem("",(unsigned char *)&regs->A[aboff+0][dbg],BYPG,BYPG));
538
  DBG(fprintf(stderr,"dbg B0[%i]=",dbg));
539
  DBG(dump_mem("",(unsigned char *)&regs->B[aboff+0][dbg],BYPG,BYPG));
540
}
541
542
////////////////////////////////////////////////////////////////////////////////
543
544
  // EXTERNAL LOOP - 8 bytes per operation
545
  for(i=0;i<8;i++){
546
547
    DBG(fprintf(stderr,"--BEGIN EXTERNAL LOOP %i\n",i));
548
549
#ifdef STREAM_INIT
550
    for(b=0;b<4;b++){
551
      in1[b]=sb_g[8*i+4+b];
552
      in2[b]=sb_g[8*i+b];
553
    }
554
#endif
555
556
    // INTERNAL LOOP - 2 bits per iteration
557
    for(j=0; j<4; j++){
558
559
      DBG(fprintf(stderr,"---BEGIN INTERNAL LOOP %i (EXT %i, INT %i)\n",j,i,j));
560
561
      // from A0..A9, 35 bits are selected as inputs to 7 s-boxes
562
      // 5 bits input per s-box, 2 bits output per s-box
563
564
      // we can select bits with zero masking and shifting operations
565
      // and synthetize s-boxes with optimized boolean functions.
566
      // this is the actual reason we do all the crazy transposition
567
      // stuff to switch between normal and bit slice representations.
568
      // this code really flies.
569
570
      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];
571
/* 1000 1110  1110 0001   : lev  7: */ //tmp0=( fa^( fb^( ( ( ( fa|fb )^fc )|( fc^fd ) )^ALL_ONES ) ) );
572
/* 1110 0010  0011 0011   : lev  6: */ //tmp1=( ( fa|fb )^( ( fc&( fa|( fb^fd ) ) )^ALL_ONES ) );
573
/* 0011 0110  1000 1101   : lev  5: */ //tmp2=( fa^( ( fb&fd )^( ( fa&fd )|fc ) ) );
574
/* 0101 0101  1001 0011   : lev  5: */ //tmp3=( ( fa&fc )^( fa^( ( fa&fb )|fd ) ) );
575
/* 1000 1110  1110 0001   : lev  7: */ tmp0=FFXOR(fa,FFXOR(fb,FFXOR(FFOR(FFXOR(FFOR(fa,fb),fc),FFXOR(fc,fd)),FF1())));
576
/* 1110 0010  0011 0011   : lev  6: */ tmp1=FFXOR(FFOR(fa,fb),FFXOR(FFAND(fc,FFOR(fa,FFXOR(fb,fd))),FF1()));
577
/* 0011 0110  1000 1101   : lev  5: */ tmp2=FFXOR(fa,FFXOR(FFAND(fb,fd),FFOR(FFAND(fa,fd),fc)));
578
/* 0101 0101  1001 0011   : lev  5: */ tmp3=FFXOR(FFAND(fa,fc),FFXOR(fa,FFOR(FFAND(fa,fb),fd)));
579
      s1a=FFXOR(tmp0,FFAND(fe,tmp1));
580
      s1b=FFXOR(tmp2,FFAND(fe,tmp3));
581
//dump_mem("s1as1b-fe",&fe,BYPG,BYPG);
582
//dump_mem("s1as1b-fa",&fa,BYPG,BYPG);
583
//dump_mem("s1as1b-fb",&fb,BYPG,BYPG);
584
//dump_mem("s1as1b-fc",&fc,BYPG,BYPG);
585
//dump_mem("s1as1b-fd",&fd,BYPG,BYPG);
586
587
      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];
588
/* 1001 1110  0110 0001   : lev  6: */ //tmp0=( fa^( ( fb&( fc|fd ) )^( fc^( fd^ALL_ONES ) ) ) );
589
/* 0000 0011  0111 1011   : lev  5: */ //tmp1=( ( fa&( fb^fd ) )|( ( fa|fb )&fc ) );
590
/* 1100 0110  1101 0010   : lev  6: */ //tmp2=( ( fb&fd )^( ( fa&fd )|( fb^( fc^ALL_ONES ) ) ) );
591
/* 0001 1110  1111 0101   : lev  5: */ //tmp3=( ( fa&fd )|( fa^( fb^( fc&fd ) ) ) );
592
/* 1001 1110  0110 0001   : lev  6: */ tmp0=FFXOR(fa,FFXOR(FFAND(fb,FFOR(fc,fd)),FFXOR(fc,FFXOR(fd,FF1()))));
593
/* 0000 0011  0111 1011   : lev  5: */ tmp1=FFOR(FFAND(fa,FFXOR(fb,fd)),FFAND(FFOR(fa,fb),fc));
594
/* 1100 0110  1101 0010   : lev  6: */ tmp2=FFXOR(FFAND(fb,fd),FFOR(FFAND(fa,fd),FFXOR(fb,FFXOR(fc,FF1()))));
595
/* 0001 1110  1111 0101   : lev  5: */ tmp3=FFOR(FFAND(fa,fd),FFXOR(fa,FFXOR(fb,FFAND(fc,fd))));
596
      s2a=FFXOR(tmp0,FFAND(fe,tmp1));
597
      s2b=FFXOR(tmp2,FFAND(fe,tmp3));
598
599
      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];
600
/* 0100 1011  1001 0110   : lev  5: */ //tmp0=( fa^( fb^( ( fc&( fa|fd ) )^fd ) ) );
601
/* 1101 0101  1000 1100   : lev  7: */ //tmp1=( ( fa&fc )^( ( fa^fd )|( ( fb|fc )^( fd^ALL_ONES ) ) ) );
602
/* 0010 0111  1101 1000   : lev  4: */ //tmp2=( fa^( ( ( fb^fc )&fd )^fc ) );
603
/* 1111 1111  1111 1111   : lev  0: */ //tmp3=ALL_ONES;
604
/* 0100 1011  1001 0110   : lev  5: */ tmp0=FFXOR(fa,FFXOR(fb,FFXOR(FFAND(fc,FFOR(fa,fd)),fd)));
605
/* 1101 0101  1000 1100   : lev  7: */ tmp1=FFXOR(FFAND(fa,fc),FFOR(FFXOR(fa,fd),FFXOR(FFOR(fb,fc),FFXOR(fd,FF1()))));
606
/* 0010 0111  1101 1000   : lev  4: */ tmp2=FFXOR(fa,FFXOR(FFAND(FFXOR(fb,fc),fd),fc));
607
/* 1111 1111  1111 1111   : lev  0: */ tmp3=FF1();
608
      s3a=FFXOR(tmp0,FFAND(FFNOT(fe),tmp1));
609
      s3b=FFXOR(tmp2,FFAND(fe,tmp3));
610
611
      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];
612
/* 1011 0101  0100 1001   : lev  7: */ //tmp0=( fa^( ( fc&( fa^fd ) )|( fb^( fc|( fd^ALL_ONES ) ) ) ) );
613
/* 0010 1101  0110 0110   : lev  6: */ //tmp1=( ( fa&fb )^( fb^( ( ( fa|fc )&fd )^fc ) ) );
614
/* 0110 0111  1101 0000   : lev  7: */ //tmp2=( fa^( ( fb&fc )|( ( ( fa&( fb^fd ) )|fc )^fd ) ) );
615
/* 1111 1111  1111 1111   : lev  0: */ //tmp3=ALL_ONES;
616
/* 1011 0101  0100 1001   : lev  7: */ tmp0=FFXOR(fa,FFOR(FFAND(fc,FFXOR(fa,fd)),FFXOR(fb,FFOR(fc,FFXOR(fd,FF1())))));
617
/* 0010 1101  0110 0110   : lev  6: */ tmp1=FFXOR(FFAND(fa,fb),FFXOR(fb,FFXOR(FFAND(FFOR(fa,fc),fd),fc)));
618
/* 0110 0111  1101 0000   : lev  7: */ tmp2=FFXOR(fa,FFOR(FFAND(fb,fc),FFXOR(FFOR(FFAND(fa,FFXOR(fb,fd)),fc),fd)));
619
/* 1111 1111  1111 1111   : lev  0: */ tmp3=FF1();
620
      s4a=FFXOR(tmp0,FFAND(fe,FFXOR(tmp1,tmp0)));
621
      s4b=FFXOR(FFXOR(s4a,tmp2),FFAND(fe,tmp3));
622
623
      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];
624
/* 1000 1111  0011 0010   : lev  7: */ //tmp0=( ( ( fa&( fb|fc ) )^fb )|( ( ( fa^fc )|fd )^ALL_ONES ) );
625
/* 0110 1011  0000 1011   : lev  6: */ //tmp1=( fb^( ( fc^fd )&( fc^( fb|( fa^fd ) ) ) ) );
626
/* 0001 1010  0111 1001   : lev  6: */ //tmp2=( ( fa&fc )^( fb^( ( fb|( fa^fc ) )&fd ) ) );
627
/* 0101 1101  1101 0101   : lev  4: */ //tmp3=( ( ( fa^fb )&( fc^ALL_ONES ) )|fd );
628
/* 1000 1111  0011 0010   : lev  7: */ tmp0=FFOR(FFXOR(FFAND(fa,FFOR(fb,fc)),fb),FFXOR(FFOR(FFXOR(fa,fc),fd),FF1()));
629
/* 0110 1011  0000 1011   : lev  6: */ tmp1=FFXOR(fb,FFAND(FFXOR(fc,fd),FFXOR(fc,FFOR(fb,FFXOR(fa,fd)))));
630
/* 0001 1010  0111 1001   : lev  6: */ tmp2=FFXOR(FFAND(fa,fc),FFXOR(fb,FFAND(FFOR(fb,FFXOR(fa,fc)),fd)));
631
/* 0101 1101  1101 0101   : lev  4: */ tmp3=FFOR(FFAND(FFXOR(fa,fb),FFXOR(fc,FF1())),fd);
632
      s5a=FFXOR(tmp0,FFAND(fe,tmp1));
633
      s5b=FFXOR(tmp2,FFAND(fe,tmp3));
634
635
      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];
636
/* 0011 0110  0010 1101   : lev  6: */ //tmp0=( ( ( fa&fc )&fd )^( ( fb&( fa|fd ) )^fc ) );
637
/* 1110 1110  1011 1011   : lev  3: */ //tmp1=( ( ( fa^fc )&fd )^ALL_ONES );
638
/* 0101 1000  0110 0111   : lev  6: */ //tmp2=( ( fa&( fb|fc ) )^( fb^( ( fb&fc )|fd ) ) );
639
/* 0001 0011  0000 0001   : lev  5: */ //tmp3=( fc&( ( fa&( fb^fd ) )^( fb|fd ) ) );
640
/* 0011 0110  0010 1101   : lev  6: */ tmp0=FFXOR(FFAND(FFAND(fa,fc),fd),FFXOR(FFAND(fb,FFOR(fa,fd)),fc));
641
/* 1110 1110  1011 1011   : lev  3: */ tmp1=FFXOR(FFAND(FFXOR(fa,fc),fd),FF1());
642
/* 0101 1000  0110 0111   : lev  6: */ tmp2=FFXOR(FFAND(fa,FFOR(fb,fc)),FFXOR(fb,FFOR(FFAND(fb,fc),fd)));
643
/* 0001 0011  0000 0001   : lev  5: */ tmp3=FFAND(fc,FFXOR(FFAND(fa,FFXOR(fb,fd)),FFOR(fb,fd)));
644
      s6a=FFXOR(tmp0,FFAND(fe,tmp1));
645
      s6b=FFXOR(tmp2,FFAND(fe,tmp3));
646
647
      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];
648
/* 0111 1000  1001 0110   : lev  5: */ //tmp0=( fb^( ( fc&fd )|( fa^( fc^fd ) ) ) );
649
/* 0100 1001  0101 1011   : lev  6: */ //tmp1=( ( fb|fd )&( ( fa&fc )|( fb^( fc^fd ) ) ) );
650
/* 0100 1001  1011 1001   : lev  5: */ //tmp2=( ( fa|fb )^( ( fc&( fb|fd ) )^fd ) );
651
/* 1111 1111  1101 1101   : lev  3: */ //tmp3=( fd|( ( fa&fc )^ALL_ONES ) );
652
/* 0111 1000  1001 0110   : lev  5: */ tmp0=FFXOR(fb,FFOR(FFAND(fc,fd),FFXOR(fa,FFXOR(fc,fd))));
653
/* 0100 1001  0101 1011   : lev  6: */ tmp1=FFAND(FFOR(fb,fd),FFOR(FFAND(fa,fc),FFXOR(fb,FFXOR(fc,fd))));
654
/* 0100 1001  1011 1001   : lev  5: */ tmp2=FFXOR(FFOR(fa,fb),FFXOR(FFAND(fc,FFOR(fb,fd)),fd));
655
/* 1111 1111  1101 1101   : lev  3: */ tmp3=FFOR(fd,FFXOR(FFAND(fa,fc),FF1()));
656
      s7a=FFXOR(tmp0,FFAND(fe,tmp1));
657
      s7b=FFXOR(tmp2,FFAND(fe,tmp3));
658
659
660
/*
661
      we have just done this:
662
      
663
      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};
664
      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};
665
      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};
666
      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};
667
      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};
668
      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};
669
      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};
670
671
      s12 = sbox1[ (((A3>>0)&1)<<4) | (((A0>>2)&1)<<3) | (((A5>>1)&1)<<2) | (((A6>>3)&1)<<1) | (((A8>>0)&1)<<0) ]
672
           |sbox2[ (((A1>>1)&1)<<4) | (((A2>>2)&1)<<3) | (((A5>>3)&1)<<2) | (((A6>>0)&1)<<1) | (((A8>>1)&1)<<0) ];
673
      s34 = sbox3[ (((A0>>3)&1)<<4) | (((A1>>0)&1)<<3) | (((A4>>1)&1)<<2) | (((A4>>3)&1)<<1) | (((A5>>2)&1)<<0) ]
674
           |sbox4[ (((A2>>3)&1)<<4) | (((A0>>1)&1)<<3) | (((A1>>3)&1)<<2) | (((A3>>2)&1)<<1) | (((A7>>0)&1)<<0) ];
675
      s56 = sbox5[ (((A4>>2)&1)<<4) | (((A3>>3)&1)<<3) | (((A5>>0)&1)<<2) | (((A7>>1)&1)<<1) | (((A8>>2)&1)<<0) ]
676
           |sbox6[ (((A2>>1)&1)<<4) | (((A3>>1)&1)<<3) | (((A4>>0)&1)<<2) | (((A6>>2)&1)<<1) | (((A8>>3)&1)<<0) ];
677
      s7 =  sbox7[ (((A1>>2)&1)<<4) | (((A2>>0)&1)<<3) | (((A6>>1)&1)<<2) | (((A7>>2)&1)<<1) | (((A7>>3)&1)<<0) ];
678
*/
679
680
      // use 4x4 xor to produce extra nibble for T3
681
682
      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]);
683
      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]);
684
      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]);
685
      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]);
686
for(dbg=0;dbg<4;dbg++){
687
  DBG(fprintf(stderr,"extra_B[%i]=",dbg));
688
  DBG(dump_mem("",(unsigned char *)&extra_B[dbg],BYPG,BYPG));
689
}
690
691
      // T1 = xor all inputs
692
      // in1, in2, D are only used in T1 during initialisation, not generation
693
      for(b=0;b<4;b++){
694
        regs->A[aboff-1][b]=FFXOR(regs->A[aboff+9][b],regs->X[b]);
695
      }
696
697
#ifdef STREAM_INIT
698
      for(b=0;b<4;b++){
699
        regs->A[aboff-1][b]=FFXOR(FFXOR(regs->A[aboff-1][b],regs->D[b]),((j % 2) ? in2[b] : in1[b]));
700
      }
701
#endif
702
703
for(dbg=0;dbg<4;dbg++){
704
  DBG(fprintf(stderr,"next_A0[%i]=",dbg));
705
  DBG(dump_mem("",(unsigned char *)&regs->A[aboff-1][dbg],BYPG,BYPG));
706
}
707
708
      // T2 =  xor all inputs
709
      // in1, in2 are only used in T1 during initialisation, not generation
710
      // if p=0, use this, if p=1, rotate the result left
711
      for(b=0;b<4;b++){
712
        regs->B[aboff-1][b]=FFXOR(FFXOR(regs->B[aboff+6][b],regs->B[aboff+9][b]),regs->Y[b]);
713
      }
714
715
#ifdef STREAM_INIT
716
      for(b=0;b<4;b++){
717
        regs->B[aboff-1][b]=FFXOR(regs->B[aboff-1][b],((j % 2) ? in1[b] : in2[b]));
718
      }
719
#endif
720
721
for(dbg=0;dbg<4;dbg++){
722
  DBG(fprintf(stderr,"next_B0[%i]=",dbg));
723
  DBG(dump_mem("",(unsigned char *)&regs->B[aboff-1][dbg],BYPG,BYPG));
724
}
725
726
      // if p=1, rotate left (yes, this is what we're doing)
727
      tmp3=regs->B[aboff-1][3];
728
      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));
729
      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));
730
      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));
731
      regs->B[aboff-1][0]=FFXOR(regs->B[aboff-1][0],FFAND(FFXOR(regs->B[aboff-1][0],tmp3),regs->p));
732
733
for(dbg=0;dbg<4;dbg++){
734
  DBG(fprintf(stderr,"next_B0[%i]=",dbg));
735
  DBG(dump_mem("",(unsigned char *)&regs->B[aboff-1][dbg],BYPG,BYPG));
736
}
737
738
      // T3 = xor all inputs
739
      for(b=0;b<4;b++){
740
        regs->D[b]=FFXOR(FFXOR(regs->E[b],regs->Z[b]),extra_B[b]);
741
      }
742
743
for(dbg=0;dbg<4;dbg++){
744
  DBG(fprintf(stderr,"D[%i]=",dbg));
745
  DBG(dump_mem("",(unsigned char *)&regs->D[dbg],BYPG,BYPG));
746
}
747
748
      // T4 = sum, carry of Z + E + r
749
      for(b=0;b<4;b++){
750
        next_E[b]=regs->F[b];
751
      }
752
753
      tmp0=FFXOR(regs->Z[0],regs->E[0]);
754
      tmp1=FFAND(regs->Z[0],regs->E[0]);
755
      regs->F[0]=FFXOR(regs->E[0],FFAND(regs->q,FFXOR(regs->Z[0],regs->r)));
756
      tmp3=FFAND(tmp0,regs->r);
757
      tmp4=FFOR(tmp1,tmp3);
758
759
      tmp0=FFXOR(regs->Z[1],regs->E[1]);
760
      tmp1=FFAND(regs->Z[1],regs->E[1]);
761
      regs->F[1]=FFXOR(regs->E[1],FFAND(regs->q,FFXOR(regs->Z[1],tmp4)));
762
      tmp3=FFAND(tmp0,tmp4);
763
      tmp4=FFOR(tmp1,tmp3);
764
765
      tmp0=FFXOR(regs->Z[2],regs->E[2]);
766
      tmp1=FFAND(regs->Z[2],regs->E[2]);
767
      regs->F[2]=FFXOR(regs->E[2],FFAND(regs->q,FFXOR(regs->Z[2],tmp4)));
768
      tmp3=FFAND(tmp0,tmp4);
769
      tmp4=FFOR(tmp1,tmp3);
770
771
      tmp0=FFXOR(regs->Z[3],regs->E[3]);
772
      tmp1=FFAND(regs->Z[3],regs->E[3]);
773
      regs->F[3]=FFXOR(regs->E[3],FFAND(regs->q,FFXOR(regs->Z[3],tmp4)));
774
      tmp3=FFAND(tmp0,tmp4);
775
      regs->r=FFXOR(regs->r,FFAND(regs->q,FFXOR(FFOR(tmp1,tmp3),regs->r))); // ultimate carry
776
777
/*
778
      we have just done this: (believe it or not)
779
      
780
      if (q) {
781
        F = Z + E + r;
782
        r = (F >> 4) & 1;
783
        F = F & 0x0f;
784
      }
785
      else {
786
          F = E;
787
      }
788
*/
789
      for(b=0;b<4;b++){
790
        regs->E[b]=next_E[b];
791
      }
792
for(dbg=0;dbg<4;dbg++){
793
  DBG(fprintf(stderr,"F[%i]=",dbg));
794
  DBG(dump_mem("",(unsigned char *)&regs->F[dbg],BYPG,BYPG));
795
}
796
DBG(fprintf(stderr,"r="));
797
DBG(dump_mem("",(unsigned char *)&regs->r,BYPG,BYPG));
798
for(dbg=0;dbg<4;dbg++){
799
  DBG(fprintf(stderr,"E[%i]=",dbg));
800
  DBG(dump_mem("",(unsigned char *)&regs->E[dbg],BYPG,BYPG));
801
}
802
803
      // this simple instruction is virtually shifting all the shift registers
804
      aboff--;
805
806
/*
807
      we've just done this:
808
809
      A9=A8;A8=A7;A7=A6;A6=A5;A5=A4;A4=A3;A3=A2;A2=A1;A1=A0;A0=next_A0;
810
      B9=B8;B8=B7;B7=B6;B6=B5;B5=B4;B4=B3;B3=B2;B2=B1;B1=B0;B0=next_B0;
811
*/
812
813
      regs->X[0]=s1a;
814
      regs->X[1]=s2a;
815
      regs->X[2]=s3b;
816
      regs->X[3]=s4b;
817
      regs->Y[0]=s3a;
818
      regs->Y[1]=s4a;
819
      regs->Y[2]=s5b;
820
      regs->Y[3]=s6b;
821
      regs->Z[0]=s5a;
822
      regs->Z[1]=s6a;
823
      regs->Z[2]=s1b;
824
      regs->Z[3]=s2b;
825
      regs->p=s7a;
826
      regs->q=s7b;
827
for(dbg=0;dbg<4;dbg++){
828
  DBG(fprintf(stderr,"X[%i]=",dbg));
829
  DBG(dump_mem("",(unsigned char *)&regs->X[dbg],BYPG,BYPG));
830
}
831
for(dbg=0;dbg<4;dbg++){
832
  DBG(fprintf(stderr,"Y[%i]=",dbg));
833
  DBG(dump_mem("",(unsigned char *)&regs->Y[dbg],BYPG,BYPG));
834
}
835
for(dbg=0;dbg<4;dbg++){
836
  DBG(fprintf(stderr,"Z[%i]=",dbg));
837
  DBG(dump_mem("",(unsigned char *)&regs->Z[dbg],BYPG,BYPG));
838
}
839
DBG(fprintf(stderr,"p="));
840
DBG(dump_mem("",(unsigned char *)&regs->p,BYPG,BYPG));
841
DBG(fprintf(stderr,"q="));
842
DBG(dump_mem("",(unsigned char *)&regs->q,BYPG,BYPG));
843
844
#ifdef STREAM_NORMAL
845
      // require 4 loops per output byte
846
      // 2 output bits are a function of the 4 bits of D
847
      // xor 2 by 2
848
      cb_g[8*i+7-2*j]=FFXOR(regs->D[2],regs->D[3]);
849
      cb_g[8*i+6-2*j]=FFXOR(regs->D[0],regs->D[1]);
850
for(dbg=0;dbg<8;dbg++){
851
  DBG(fprintf(stderr,"op[%i]=",dbg));
852
  DBG(dump_mem("",(unsigned char *)&cb_g[8*i+dbg],BYPG,BYPG));
853
}
854
#endif
855
856
DBG(fprintf(stderr,"---END INTERNAL LOOP\n"));
857
858
    } // INTERNAL LOOP
859
860
DBG(fprintf(stderr,"--END EXTERNAL LOOP\n"));
861
862
  } // EXTERNAL LOOP
863
864
  // move 32 steps forward, ready for next call
865
  for(k=0;k<10;k++){
866
    for(b=0;b<4;b++){
867
DBG(fprintf(stderr,"moving forward AB k=%i b=%i\n",k,b));
868
      regs->A[32+k][b]=regs->A[k][b];
869
      regs->B[32+k][b]=regs->B[k][b];
870
    }
871
  }
872
873
874
////////////////////////////////////////////////////////////////////////////////
875
876
#ifdef STREAM_NORMAL
877
for(j=0;j<64;j++){
878
  DBG(fprintf(stderr,"postcall prerot cb[%2i]=",j));
879
  DBG(dump_mem("",(unsigned char *)(cb+BYPG*j),BYPG,BYPG));
880
}
881
882
#if GROUP_PARALLELISM==32
883
trasp64_32_88cw(cb);
884
#endif
885
#if GROUP_PARALLELISM==64
886
trasp64_64_88cw(cb);
887
#endif
888
#if GROUP_PARALLELISM==128
889
trasp64_128_88cw(cb);
890
#endif
891
892
for(j=0;j<64;j++){
893
  DBG(fprintf(stderr,"postcall postrot cb[%2i]=",j));
894
  DBG(dump_mem("",(unsigned char *)(cb+BYPG*j),BYPG,BYPG));
895
}
896
#endif
897
898
#ifdef STREAM_INIT
899
  DBG(fprintf(stderr,":::::::::: END STREAM INIT\n"));
900
#endif
901
#ifdef STREAM_NORMAL
902
  DBG(fprintf(stderr,":::::::::: END STREAM NORMAL\n"));
903
#endif
904
905
}
906
(-)globals.h (-4 / +38 lines)
Lines 389-405 Link Here
389
#define CS_ECM_RINGBUFFER_MAX 0x10 // max size for ECM last responsetimes ringbuffer. Keep this set to power of 2 values!
389
#define CS_ECM_RINGBUFFER_MAX 0x10 // max size for ECM last responsetimes ringbuffer. Keep this set to power of 2 values!
390
390
391
// Support for multiple CWs per channel and other encryption algos
391
// Support for multiple CWs per channel and other encryption algos
392
//#define WITH_EXTENDED_CW 1
392
#define WITH_EXTENDED_CW 1
393
393
394
#if defined(READER_DRE) || defined(READER_DRECAS) || defined(READER_VIACCESS)
394
#if defined(READER_DRE) || defined(READER_DRECAS) || defined(READER_VIACCESS)
395
#define MAX_ECM_SIZE 1024
395
#define MAX_ECM_SIZE 1024
396
#define MAX_EMM_SIZE 1024
396
#define MAX_EMM_SIZE 1024
397
#else
397
#else
398
#define MAX_ECM_SIZE 596
398
#define MAX_ECM_SIZE 1024
399
#define MAX_EMM_SIZE 512
399
#define MAX_EMM_SIZE 1024
400
#endif
400
#endif
401
401
402
#define CS_EMMCACHESIZE  512 //nr of EMMs that each reader will cache
402
#define CS_EMMCACHESIZE  1024 //nr of EMMs that each reader will cache
403
#define MSGLOGSIZE 64   //size of string buffer for a ecm to return messages
403
#define MSGLOGSIZE 64   //size of string buffer for a ecm to return messages
404
404
405
#define D_TRACE     0x0001  // Generate very detailed error/trace messages per routine
405
#define D_TRACE     0x0001  // Generate very detailed error/trace messages per routine
Lines 431-436 Link Here
431
#define R_SMART     0x7 // Smartreader+
431
#define R_SMART     0x7 // Smartreader+
432
#define R_PCSC      0x8 // PCSC
432
#define R_PCSC      0x8 // PCSC
433
#define R_DRECAS    0x9 // Reader DRECAS
433
#define R_DRECAS    0x9 // Reader DRECAS
434
#define R_EMU       0x17 // Reader EMU
434
/////////////////// proxy readers after R_CS378X
435
/////////////////// proxy readers after R_CS378X
435
#define R_CAMD35    0x20  // Reader cascading camd 3.5x
436
#define R_CAMD35    0x20  // Reader cascading camd 3.5x
436
#define R_CAMD33    0x21  // Reader cascading camd 3.3x
437
#define R_CAMD33    0x21  // Reader cascading camd 3.3x
Lines 858-863 Link Here
858
	uint32_t        class;              // the class needed for some systems
859
	uint32_t        class;              // the class needed for some systems
859
	time_t          start;              // startdate
860
	time_t          start;              // startdate
860
	time_t          end;                // enddate
861
	time_t          end;                // enddate
862
#ifdef WITH_EMU
863
	bool            isKey;
864
	bool            isData;
865
	char            name[8];
866
	uint8_t         *key;
867
	uint32_t        keyLength;
868
#endif
861
} S_ENTITLEMENT;
869
} S_ENTITLEMENT;
862
870
863
struct s_client ;
871
struct s_client ;
Lines 982-987 Link Here
982
	void (*post_process)(struct s_reader *);
990
	void (*post_process)(struct s_reader *);
983
	int32_t (*get_emm_type)(struct emm_packet_t *, struct s_reader *);
991
	int32_t (*get_emm_type)(struct emm_packet_t *, struct s_reader *);
984
	int32_t (*get_emm_filter)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *);
992
	int32_t (*get_emm_filter)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *);
993
	int32_t (*get_emm_filter_adv)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *, uint16_t, uint32_t, uint16_t);
985
	int32_t (*get_tunemm_filter)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *);
994
	int32_t (*get_tunemm_filter)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *);
986
};
995
};
987
996
Lines 1714-1719 Link Here
1714
#ifdef MODULE_GHTTP
1723
#ifdef MODULE_GHTTP
1715
	uint8_t         ghttp_use_ssl;
1724
	uint8_t         ghttp_use_ssl;
1716
#endif
1725
#endif
1726
#ifdef WITH_EMU
1727
	FTAB            emu_auproviders;                // AU providers for Emu reader
1728
	int8_t          emu_datecodedenabled;           // date-coded keys for BISS
1729
	char            *extee36;                       // path to "ee36.bin" - Set by the user via the webif
1730
	char            *extee56;                       // path to "ee56.bin" - Set by the user via the webif
1731
	uint8_t         dre36_force_group;
1732
	uint8_t         dre56_force_group;
1733
#endif
1717
	uint8_t cnxlastecm; // == 0 - las ecm has not been paired ecm, > 0 last ecm has been paired ecm
1734
	uint8_t cnxlastecm; // == 0 - las ecm has not been paired ecm, > 0 last ecm has been paired ecm
1718
	LLIST           *emmstat; //emm stats
1735
	LLIST           *emmstat; //emm stats
1719
	CS_MUTEX_LOCK   emmstat_lock;
1736
	CS_MUTEX_LOCK   emmstat_lock;
Lines 2161-2166 Link Here
2161
	int8_t      dvbapi_read_sdt;
2178
	int8_t      dvbapi_read_sdt;
2162
	int8_t      dvbapi_write_sdt_prov;
2179
	int8_t      dvbapi_write_sdt_prov;
2163
	int8_t      dvbapi_extended_cw_api;
2180
	int8_t      dvbapi_extended_cw_api;
2181
	int8_t      dvbapi_extended_cw_pids;            // pid limiter
2164
#endif
2182
#endif
2165
2183
2166
#ifdef CS_ANTICASC
2184
#ifdef CS_ANTICASC
Lines 2207-2212 Link Here
2207
	IN_ADDR_T   scam_srvip;
2225
	IN_ADDR_T   scam_srvip;
2208
	struct s_ip *scam_allowed;
2226
	struct s_ip *scam_allowed;
2209
#endif
2227
#endif
2228
2229
#ifdef WITH_EMU
2230
	char        *emu_stream_source_host;
2231
	int32_t     emu_stream_source_port;
2232
	char        *emu_stream_source_auth_user;
2233
	char        *emu_stream_source_auth_password;
2234
	int32_t     emu_stream_relay_port;
2235
	uint32_t    emu_stream_ecm_delay;
2236
	int8_t      emu_stream_relay_enabled;
2237
	int8_t      emu_stream_emm_enabled;
2238
#endif
2239
2210
	int32_t    max_cache_time;  //seconds ecms are stored in ecmcwcache
2240
	int32_t    max_cache_time;  //seconds ecms are stored in ecmcwcache
2211
	int32_t    max_hitcache_time;  //seconds hits are stored in cspec_hitcache (to detect dyn wait_time)
2241
	int32_t    max_hitcache_time;  //seconds hits are stored in cspec_hitcache (to detect dyn wait_time)
2212
2242
Lines 2388-2391 Link Here
2388
static inline bool caid_is_dre(uint16_t caid) { return caid == 0x4AE0 || caid == 0x4AE1 || caid == 0x2710;}
2418
static inline bool caid_is_dre(uint16_t caid) { return caid == 0x4AE0 || caid == 0x4AE1 || caid == 0x2710;}
2389
const char *get_cardsystem_desc_by_caid(uint16_t caid);
2419
const char *get_cardsystem_desc_by_caid(uint16_t caid);
2390
2420
2421
#ifdef WITH_EMU
2422
FILTER* get_emu_prids_for_caid(struct s_reader *rdr, uint16_t caid);
2423
#endif
2424
2391
#endif
2425
#endif
(-)module-dvbapi.c (-8 / +96 lines)
Lines 1471-1477 Link Here
1471
			}
1471
			}
1472
			if(match)
1472
			if(match)
1473
			{
1473
			{
1474
				csystem = get_cardsystem_by_caid(caid);
1474
				if(rdr->typ == R_EMU)
1475
				{
1476
					csystem = rdr->csystem;
1477
				}
1478
				else
1479
				{
1480
					csystem = get_cardsystem_by_caid(caid);	
1481
				}
1482
				
1475
				if(csystem)
1483
				if(csystem)
1476
				{
1484
				{
1477
					if(caid != ncaid)
1485
					if(caid != ncaid)
Lines 1490-1496 Link Here
1490
					}
1498
					}
1491
					else if (csystem->get_emm_filter)
1499
					else if (csystem->get_emm_filter)
1492
					{
1500
					{
1493
						csystem->get_emm_filter(rdr, &dmx_filter, &filter_count);
1501
						if(rdr->typ == R_EMU)
1502
						{
1503
							csystem->get_emm_filter_adv(rdr, &dmx_filter, &filter_count, caid, provid, demux[demux_index].program_number);
1504
						}
1505
						else
1506
						{
1507
							csystem->get_emm_filter(rdr, &dmx_filter, &filter_count);
1508
						}
1494
					}
1509
					}
1495
				}
1510
				}
1496
				else
1511
				else
Lines 2076-2081 Link Here
2076
	er->vpid  = demux[demux_id].ECMpids[pid].VPID;
2091
	er->vpid  = demux[demux_id].ECMpids[pid].VPID;
2077
	er->pmtpid  = demux[demux_id].pmtpid;
2092
	er->pmtpid  = demux[demux_id].pmtpid;
2078
	er->onid = demux[demux_id].onid;
2093
	er->onid = demux[demux_id].onid;
2094
	er->tsid = demux[demux_id].tsid;
2095
	er->ens  = demux[demux_id].enigma_namespace;
2079
	er->msgid = msgid;
2096
	er->msgid = msgid;
2080
2097
2081
#ifdef WITH_STAPI5
2098
#ifdef WITH_STAPI5
Lines 2113-2131 Link Here
2113
		if(caid_is_fake(demux[demux_id].ECMpids[pid].CAID) || caid_is_biss(demux[demux_id].ECMpids[pid].CAID))
2130
		if(caid_is_fake(demux[demux_id].ECMpids[pid].CAID) || caid_is_biss(demux[demux_id].ECMpids[pid].CAID))
2114
		{
2131
		{
2115
			int32_t j, n;
2132
			int32_t j, n;
2116
			er->ecmlen = 5;
2133
			er->ecmlen = 7;
2117
			er->ecm[0] = 0x80; // to pass the cache check it must be 0x80 or 0x81
2134
			er->ecm[0] = 0x80; // to pass the cache check it must be 0x80 or 0x81
2118
			er->ecm[1] = 0x00;
2135
			er->ecm[1] = 0x00;
2119
			er->ecm[2] = 0x02;
2136
			er->ecm[2] = 0x04;
2120
			i2b_buf(2, er->srvid, er->ecm + 3);
2137
			i2b_buf(2, er->srvid, er->ecm + 3);
2138
			i2b_buf(2, er->pmtpid, er->ecm + 5);
2121
2139
2122
			for(j = 0, n = 5; j < demux[demux_id].STREAMpidcount; j++, n += 2)
2140
			for(j = 0, n = 7; j < demux[demux_id].STREAMpidcount; j++, n += 2)
2123
			{
2141
			{
2124
				i2b_buf(2, demux[demux_id].STREAMpids[j], er->ecm + n);
2142
				i2b_buf(2, demux[demux_id].STREAMpids[j], er->ecm + n);
2125
				er->ecm[2] += 2;
2143
				er->ecm[2] += 2;
2126
				er->ecmlen += 2;
2144
				er->ecmlen += 2;
2127
			}
2145
			}
2128
2146
2147
			er->ens &= 0x0FFFFFFF; // clear top 4 bits (in case of DVB-T/C or garbage), prepare for flagging
2148
			er->ens |= 0xA0000000; // flag to emu: this is the namespace, not a pid
2149
2150
			i2b_buf(2, er->tsid, er->ecm + 3 + er->ecm[2]);     // place tsid after the last stream pid
2151
			i2b_buf(2, er->onid, er->ecm + 3 + er->ecm[2] + 2); // place onid right after tsid
2152
			i2b_buf(4, er->ens, er->ecm + 3 + er->ecm[2] + 4);  // place namespace at the end of the ecm
2153
2154
			er->ecm[2] += 8;
2155
			er->ecmlen += 8;
2156
2129
			cs_log("Demuxer %d trying to descramble PID %d CAID %04X PROVID %06X ECMPID %04X ANY CHID PMTPID %04X VPID %04X", demux_id, pid,
2157
			cs_log("Demuxer %d trying to descramble PID %d CAID %04X PROVID %06X ECMPID %04X ANY CHID PMTPID %04X VPID %04X", demux_id, pid,
2130
				   demux[demux_id].ECMpids[pid].CAID, demux[demux_id].ECMpids[pid].PROVID, demux[demux_id].ECMpids[pid].ECM_PID,
2158
				   demux[demux_id].ECMpids[pid].CAID, demux[demux_id].ECMpids[pid].PROVID, demux[demux_id].ECMpids[pid].ECM_PID,
2131
				   demux[demux_id].pmtpid, demux[demux_id].ECMpids[pid].VPID);
2159
				   demux[demux_id].pmtpid, demux[demux_id].ECMpids[pid].VPID);
Lines 3192-3197 Link Here
3192
{
3220
{
3193
	uint32_t i = 0, start_descrambling = 0;
3221
	uint32_t i = 0, start_descrambling = 0;
3194
	int32_t j = 0;
3222
	int32_t j = 0;
3223
	int32_t max_pids = 64;
3195
	int32_t demux_id = -1;
3224
	int32_t demux_id = -1;
3196
	uint16_t demux_index, adapter_index, pmtpid;
3225
	uint16_t demux_index, adapter_index, pmtpid;
3197
	uint32_t ca_mask;
3226
	uint32_t ca_mask;
Lines 3354-3359 Link Here
3354
	uint32_t es_info_length = 0, vpid = 0;
3383
	uint32_t es_info_length = 0, vpid = 0;
3355
	struct s_dvbapi_priority *addentry;
3384
	struct s_dvbapi_priority *addentry;
3356
3385
3386
	// pid limiter for PowerVu
3387
	if(demux[demux_id].ECMpids[0].CAID >> 8 == 0x0E)
3388
	{
3389
		max_pids = cfg.dvbapi_extended_cw_pids;
3390
	}
3391
3357
	for(i = program_info_length + program_info_start; i + 4 < length; i += es_info_length + 5)
3392
	for(i = program_info_length + program_info_start; i + 4 < length; i += es_info_length + 5)
3358
	{
3393
	{
3359
		uint8_t stream_type = buffer[i];
3394
		uint8_t stream_type = buffer[i];
Lines 3361-3367 Link Here
3361
		uint8_t is_audio = 0;
3396
		uint8_t is_audio = 0;
3362
		es_info_length = b2i(2, buffer + i +3)&0x0FFF;
3397
		es_info_length = b2i(2, buffer + i +3)&0x0FFF;
3363
3398
3364
		if(demux[demux_id].STREAMpidcount < ECM_PIDS)
3399
		if(demux[demux_id].STREAMpidcount < max_pids) // was "ECM_PIDS" (pid limiter)
3365
		{
3400
		{
3366
3401
3367
			demux[demux_id].STREAMpids[demux[demux_id].STREAMpidcount] = elementary_pid;
3402
			demux[demux_id].STREAMpids[demux[demux_id].STREAMpidcount] = elementary_pid;
Lines 4375-4380 Link Here
4375
	if(filtertype == TYPE_ECM)
4410
	if(filtertype == TYPE_ECM)
4376
	{
4411
	{
4377
		uint32_t chid = 0x10000;
4412
		uint32_t chid = 0x10000;
4413
		int8_t pvu_skip = 0;
4378
		ECM_REQUEST *er;
4414
		ECM_REQUEST *er;
4379
4415
4380
		if(len != 0)  // len = 0 receiver encountered an internal bufferoverflow!
4416
		if(len != 0)  // len = 0 receiver encountered an internal bufferoverflow!
Lines 4401-4409 Link Here
4401
				return;
4437
				return;
4402
			}
4438
			}
4403
4439
4404
			if(curpid->table == buffer[0] && !caid_is_irdeto(curpid->CAID))  // wait for odd / even ecm change (only not for irdeto!)
4440
			if(curpid->CAID >> 8 == 0x0E)
4405
			{
4441
			{
4406
4442
				pvu_skip = 1;
4443
				
4444
				if(sctlen - 11 > buffer[9])
4445
				{
4446
					if(buffer[11 + buffer[9]] > curpid->pvu_counter || (curpid->pvu_counter == 255 && buffer[11 + buffer[9]] == 0)
4447
							|| ((curpid->pvu_counter - buffer[11 + buffer[9]]) > 5))
4448
					{
4449
						curpid->pvu_counter = buffer[11 + buffer[9]];
4450
						pvu_skip = 0;
4451
					}
4452
				}
4453
			}
4454
			
4455
			if((curpid->table == buffer[0] && !caid_is_irdeto(curpid->CAID)) || pvu_skip)  // wait for odd / even ecm change (only not for irdeto!)
4456
			{
4457
				
4407
				if(!(er = get_ecmtask()))
4458
				if(!(er = get_ecmtask()))
4408
				{
4459
				{
4409
					return;
4460
					return;
Lines 4685-4690 Link Here
4685
			dvbapi_stop_filternum(demux_id, filter_num, msgid);
4736
			dvbapi_stop_filternum(demux_id, filter_num, msgid);
4686
			return;
4737
			return;
4687
		}
4738
		}
4739
		
4740
#ifdef WITH_EMU
4741
		if((demux[demux_id].demux_fd[filter_num].caid>>8) == 0x10)
4742
		{
4743
			uint32_t i;
4744
			uint32_t emmhash;
4745
			
4746
			if(sctlen < 4)
4747
			{
4748
				return;
4749
			}
4750
			
4751
			for(i=0; i+2<sctlen; i++)
4752
			{
4753
				if(buffer[i] == 0xF0 && (buffer[i+2] == 0xE1 || buffer[i+2] == 0xE4))
4754
				{
4755
					emmhash = (buffer[3]<<8) | buffer[sctlen-2];
4756
					
4757
					if(demux[demux_id].demux_fd[filter_num].cadata == emmhash)
4758
					{
4759
						return;
4760
					}
4761
					
4762
					demux[demux_id].demux_fd[filter_num].cadata = emmhash;
4763
					
4764
					dvbapi_process_emm(demux_id, filter_num, buffer, sctlen);
4765
					return;
4766
				}
4767
			}
4768
			
4769
			return;
4770
		}
4771
#endif
4772
		
4688
		dvbapi_process_emm(demux_id, filter_num, buffer, sctlen);
4773
		dvbapi_process_emm(demux_id, filter_num, buffer, sctlen);
4689
	}
4774
	}
4690
4775
Lines 6203-6208 Link Here
6203
6288
6204
		delayer(er, delay);
6289
		delayer(er, delay);
6205
6290
6291
#ifdef WITH_EMU
6292
		if(er->caid>>8 != 0x0E || !cfg.emu_stream_relay_enabled)
6293
#endif
6206
		switch(selected_api)
6294
		switch(selected_api)
6207
		{
6295
		{
6208
#if defined(WITH_STAPI) || defined(WITH_STAPI5)
6296
#if defined(WITH_STAPI) || defined(WITH_STAPI5)
(-)module-dvbapi.h (+4 lines)
Lines 136-141 Link Here
136
	int8_t useMultipleIndices;
136
	int8_t useMultipleIndices;
137
	uint32_t streams;
137
	uint32_t streams;
138
	uint32_t cadata;
138
	uint32_t cadata;
139
	int16_t pvu_counter;
139
};
140
};
140
141
141
typedef struct filter_s
142
typedef struct filter_s
Lines 158-163 Link Here
158
	uint32_t    SlotHandle[10];
159
	uint32_t    SlotHandle[10];
159
	uint32_t    BufferHandle[10];
160
	uint32_t    BufferHandle[10];
160
#endif
161
#endif
162
#ifdef WITH_EMU
163
	uint32_t cadata;
164
#endif
161
} FILTERTYPE;
165
} FILTERTYPE;
162
166
163
struct s_emmpids
167
struct s_emmpids
(-)module-emulator-osemu.c (+6461 lines)
Line 0 Link Here
1
#define MODULE_LOG_PREFIX "emu"
2
3
#include "globals.h"
4
#include "ffdecsa/ffdecsa.h"
5
#include "cscrypt/bn.h"
6
#include "cscrypt/des.h"
7
#include "cscrypt/idea.h"
8
#include "cscrypt/md5.h"
9
10
#ifdef WITH_EMU
11
#include "oscam-aes.h"
12
#include "oscam-string.h"
13
#include "oscam-config.h"
14
#include "oscam-conf-chk.h"
15
#include "oscam-time.h"
16
#include "module-newcamd-des.h"
17
#include "reader-dre-common.h"
18
// from reader-viaccess.c:
19
void hdSurEncPhase1_D2_0F_11(uint8_t *CWs);
20
void hdSurEncPhase2_D2_0F_11(uint8_t *CWs);
21
void hdSurEncPhase1_D2_13_15(uint8_t *cws);
22
void hdSurEncPhase2_D2_13_15(uint8_t *cws);
23
#else
24
#include "cscrypt/viades.h"
25
#include "via3surenc.h"
26
#include "dre2overcrypt.h"
27
#endif
28
29
#include "module-emulator-osemu.h"
30
#include "module-emulator-stream.h"
31
32
// Version info
33
uint32_t GetOSemuVersion(void)
34
{
35
	return atoi("$Version: 766 $"+10);
36
}
37
38
/*
39
 * Key DB
40
 *
41
 * The Emu reader gets keys from the OSCcam-Emu binary and the "SoftCam.Key" file.
42
 *
43
 * The keys are stored in structures of type "KeyDataContainer", one per CAS. Each
44
 * container points to a dynamically allocated array of type "KeyData", which holds
45
 * the actual keys. The array initially holds up to 64 keys (64 * KeyData), and it
46
 * is expanded by 16 every time it's filled with keys. The "KeyDataContainer" also
47
 * includes info about the number of keys it contains ("KeyCount") and the maximum
48
 * number of keys it can store ("KeyMax").
49
 *
50
 * The "KeyData" structure on the other hand, stores the actual key information,
51
 * including the "identifier", "provider", "keyName", "key" and "keyLength". There
52
 * is also a "nextKey" pointer to a similar "KeyData" structure which is only used
53
 * for Irdeto multiple keys, in a linked list style structure. For all other CAS,
54
 * the "nextKey" is a "NULL" pointer.
55
 *
56
 * For storing keys, the "SetKey" function is used. Duplicate keys are not allowed.
57
 * When storing a key that is already present in the database, its "key" value is
58
 * updated with the new one. For reading keys from the database, the "FindKey"
59
 * function is used. To delete all keys in a container, the "DeleteKeysInContainer"
60
 * function can be called.
61
*/
62
63
static char *emu_keyfile_path = NULL;
64
65
void set_emu_keyfile_path(const char *path)
66
{
67
	if(emu_keyfile_path != NULL) {
68
		free(emu_keyfile_path);
69
	}
70
	emu_keyfile_path = (char*)malloc(strlen(path)+1);
71
	if(emu_keyfile_path == NULL) {
72
		return;
73
	}
74
	memcpy(emu_keyfile_path, path, strlen(path));
75
	emu_keyfile_path[strlen(path)] = 0;
76
}
77
78
int32_t CharToBin(uint8_t *out, const char *in, uint32_t inLen)
79
{
80
	uint32_t i, tmp;
81
	for(i=0; i<inLen/2; i++) {
82
		if(sscanf(in + i*2, "%02X", &tmp) != 1) {
83
			return 0;
84
		}
85
		out[i] = (uint8_t)tmp;
86
	}
87
	return 1;
88
}
89
90
KeyDataContainer CwKeys = { NULL, 0, 0 };
91
KeyDataContainer ViKeys = { NULL, 0, 0 };
92
KeyDataContainer NagraKeys = { NULL, 0, 0 };
93
KeyDataContainer IrdetoKeys = { NULL, 0, 0 };
94
KeyDataContainer NDSKeys = { NULL, 0, 0 };
95
KeyDataContainer BissKeys = { NULL, 0, 0 };
96
KeyDataContainer PowervuKeys = { NULL, 0, 0 };
97
KeyDataContainer DreKeys = { NULL, 0, 0 };
98
KeyDataContainer TandbergKeys = { NULL, 0, 0 };
99
100
static KeyDataContainer *GetKeyContainer(char identifier)
101
{
102
	switch(identifier) {
103
	case 'W':
104
		return &CwKeys;
105
	case 'V':
106
		return &ViKeys;
107
	case 'N':
108
		return &NagraKeys;
109
	case 'I':
110
		return &IrdetoKeys;
111
	case 'S':
112
		return &NDSKeys;
113
	case 'F':
114
		return &BissKeys;
115
	case 'P':
116
		return &PowervuKeys;
117
	case 'D':
118
		return &DreKeys;
119
	case 'T':
120
		return &TandbergKeys;
121
	default:
122
		return NULL;
123
	}
124
}
125
126
static void Date2Str(char *dateStr, uint8_t len, int8_t offset, uint8_t format)
127
{
128
	// Creates a formatted date string for use in various functions.
129
	// A positive or negative time offset (in hours) can be set as well
130
	// as the format of the output string.
131
132
	time_t rawtime;
133
	struct tm timeinfo;
134
135
	time(&rawtime);
136
	rawtime += (time_t) offset * 60 * 60; // Add a positive or negative offset
137
	localtime_r(&rawtime, &timeinfo);
138
139
	switch (format)
140
	{
141
		case 1: // Use in WriteKeyToFile()
142
			strftime(dateStr, len, "%c", &timeinfo);
143
			break;
144
145
		case 2: // Used in BissAnnotate()
146
			strftime(dateStr, len, "%F @ %R", &timeinfo);
147
			break;
148
149
		case 3: // Used in SetKey(), BissAnnotate()
150
			strftime(dateStr, len, "%y%m%d%H", &timeinfo);
151
			break;
152
	}
153
}
154
155
static void WriteKeyToFile(char identifier, uint32_t provider, const char *keyName, uint8_t *key, uint32_t keyLength, char* comment)
156
{
157
	char line[1200], dateText[100];
158
	uint32_t pathLength;
159
	struct dirent *pDirent;
160
	DIR *pDir;
161
	char *path, *filepath, filename[EMU_KEY_FILENAME_MAX_LEN+1], *keyValue;
162
	FILE *file = NULL;
163
	uint8_t fileNameLen = strlen(EMU_KEY_FILENAME);
164
165
	pathLength = strlen(emu_keyfile_path);
166
	path = (char*)malloc(pathLength+1);
167
	if(path == NULL) {
168
		return;
169
	}
170
	strncpy(path, emu_keyfile_path, pathLength+1);
171
172
	pathLength = strlen(path);
173
	if(pathLength >= fileNameLen && strcasecmp(path+pathLength-fileNameLen, EMU_KEY_FILENAME) == 0) {
174
		// cut file name
175
		path[pathLength-fileNameLen] = '\0';
176
	}
177
178
	pathLength = strlen(path);
179
	if(path[pathLength-1] == '/' || path[pathLength-1] == '\\') {
180
		// cut trailing /
181
		path[pathLength-1] = '\0';
182
	}
183
184
	pDir = opendir(path);
185
	if (pDir == NULL) {
186
		cs_log("Cannot open key file path: %s", path);
187
		free(path);
188
		return;
189
	}
190
191
	while((pDirent = readdir(pDir)) != NULL) {
192
		if(strcasecmp(pDirent->d_name, EMU_KEY_FILENAME) == 0) {
193
			strncpy(filename, pDirent->d_name, sizeof(filename));
194
			break;
195
		}
196
	}
197
	closedir(pDir);
198
199
	if(pDirent == NULL) {
200
		strncpy(filename, EMU_KEY_FILENAME, sizeof(filename));
201
	}
202
203
	pathLength = strlen(path)+1+strlen(filename)+1;
204
	filepath = (char*)malloc(pathLength);
205
	if(filepath == NULL) {
206
		free(path);
207
		return;
208
	}
209
	snprintf(filepath, pathLength, "%s/%s", path, filename);
210
	free(path);
211
212
	cs_log("Writing key file: %s", filepath);
213
214
	file = fopen(filepath, "a");
215
	free(filepath);
216
	if(file == NULL) {
217
		return;
218
	}
219
220
	Date2Str(dateText, sizeof(dateText), 0, 1);
221
222
	keyValue = (char*)malloc((keyLength*2)+1);
223
	if(keyValue == NULL) {
224
		fclose(file);
225
		return;
226
	}
227
	cs_hexdump(0, key, keyLength, keyValue, (keyLength*2)+1);
228
229
	if(comment)
230
	{
231
		snprintf(line, sizeof(line), "\n%c %.4X %s %s ; added by OSEmu %s %s\n", identifier, provider, keyName, keyValue, dateText, comment);
232
	}
233
	else
234
	{
235
		snprintf(line, sizeof(line), "\n%c %.4X %s %s ; added by OSEmu %s\n", identifier, provider, keyName, keyValue, dateText);
236
	}
237
	
238
	cs_log("Key written: %c %.4X %s %s", identifier, provider, keyName, keyValue);
239
	
240
	free(keyValue);
241
242
	fwrite(line, strlen(line), 1, file);
243
	fclose(file);
244
}
245
246
int32_t SetKey(char identifier, uint32_t provider, char *keyName, uint8_t *orgKey, uint32_t keyLength,
247
				uint8_t writeKey, char *comment, struct s_reader *rdr)
248
{
249
	uint32_t i, j;
250
	uint8_t *tmpKey = NULL;
251
	KeyDataContainer *KeyDB;
252
	KeyData *tmpKeyData, *newKeyData;
253
	identifier = (char)toupper((int)identifier);
254
255
	KeyDB = GetKeyContainer(identifier);
256
	if(KeyDB == NULL) {
257
		return 0;
258
	}
259
260
	keyName = strtoupper(keyName);
261
262
	if (identifier == 'F') // Prepare BISS keys before saving to the db
263
	{
264
		// Convert legacy BISS "00" & "01" keynames
265
		if (0 == strcmp(keyName, "00") || 0 == strcmp(keyName, "01"))
266
		{
267
			keyName = "00000000";
268
		}
269
270
		// All keyNames should have a length of 8 after converting
271
		if (strlen(keyName) != 8)
272
		{
273
			cs_log("WARNING: Wrong key format in %s: F %08X %s", EMU_KEY_FILENAME, provider, keyName);
274
			return 0;
275
		}
276
277
		// Verify date-coded keyName (if enabled), ignoring old (expired) keys
278
		if (rdr->emu_datecodedenabled)
279
		{
280
			char timeStr[9];
281
			Date2Str(timeStr, sizeof(timeStr), 0, 3);
282
283
			// Reject old date-coded keys, but allow our "00000000" evergreen label
284
			if (strcmp("00000000", keyName) != 0 && strcmp(timeStr, keyName) >= 0)
285
			{
286
				return 0;
287
			}
288
		}
289
	}
290
291
	// fix checksum for BISS keys with a length of 6
292
	if (identifier == 'F' && keyLength == 6)
293
	{
294
		tmpKey = (uint8_t*)malloc(8*sizeof(uint8_t));
295
		if(tmpKey == NULL) {
296
			return 0;
297
		}
298
299
		tmpKey[0] = orgKey[0];
300
		tmpKey[1] = orgKey[1];
301
		tmpKey[2] = orgKey[2];
302
		tmpKey[3] = ((orgKey[0] + orgKey[1] + orgKey[2]) & 0xff);
303
		tmpKey[4] = orgKey[3];
304
		tmpKey[5] = orgKey[4];
305
		tmpKey[6] = orgKey[5];
306
		tmpKey[7] = ((orgKey[3] + orgKey[4] + orgKey[5]) & 0xff);
307
308
		keyLength = 8;
309
	}
310
	else // All keys with a length of 8, including BISS
311
	{
312
		tmpKey = (uint8_t*)malloc(keyLength*sizeof(uint8_t));
313
		if(tmpKey == NULL) {
314
			return 0;
315
		}
316
317
		memcpy(tmpKey, orgKey, keyLength);
318
	}
319
320
	// fix patched mgcamd format for Irdeto
321
	if(identifier == 'I' && provider < 0xFFFF) {
322
		provider = provider<<8;
323
	}
324
325
	// key already exists on db, update its value
326
	for(i=0; i<KeyDB->keyCount; i++) {
327
		
328
		if(KeyDB->EmuKeys[i].provider != provider) {
329
			continue;
330
		}
331
332
		// Don't match keyName (i.e. expiration date) for BISS
333
		if(identifier != 'F' && strcmp(KeyDB->EmuKeys[i].keyName, keyName)) {
334
			continue;
335
		}
336
	
337
		// allow multiple keys for Irdeto
338
		if(identifier == 'I')
339
		{
340
			// reject duplicates
341
			tmpKeyData = &KeyDB->EmuKeys[i];
342
			do {
343
				if(memcmp(tmpKeyData->key, tmpKey, tmpKeyData->keyLength < keyLength ? tmpKeyData->keyLength : keyLength) == 0) {
344
					free(tmpKey);
345
					return 0;
346
				}
347
				tmpKeyData = tmpKeyData->nextKey;
348
			}
349
			while(tmpKeyData != NULL);
350
351
			// add new key
352
			newKeyData = (KeyData*)malloc(sizeof(KeyData));
353
			if(newKeyData == NULL) {
354
				free(tmpKey);
355
				return 0;
356
			}
357
			newKeyData->identifier = identifier;
358
			newKeyData->provider = provider;
359
			if(strlen(keyName) < EMU_MAX_CHAR_KEYNAME) {
360
				strncpy(newKeyData->keyName, keyName, EMU_MAX_CHAR_KEYNAME);
361
			}
362
			else {
363
				memcpy(newKeyData->keyName, keyName, EMU_MAX_CHAR_KEYNAME);
364
			}
365
			newKeyData->keyName[EMU_MAX_CHAR_KEYNAME-1] = 0;
366
			newKeyData->key = tmpKey;
367
			newKeyData->keyLength = keyLength;
368
			newKeyData->nextKey = NULL;
369
370
			tmpKeyData = &KeyDB->EmuKeys[i];
371
			j = 0;
372
			while(tmpKeyData->nextKey != NULL) {
373
				if(j == 0xFE)
374
				{
375
					break;
376
				}
377
				tmpKeyData = tmpKeyData->nextKey;
378
				j++;
379
			}
380
			if(tmpKeyData->nextKey)
381
			{
382
				NULLFREE(tmpKeyData->nextKey->key);
383
				NULLFREE(tmpKeyData->nextKey);
384
			}
385
			tmpKeyData->nextKey = newKeyData;
386
387
			if(writeKey) {
388
				WriteKeyToFile(identifier, provider, keyName, tmpKey, keyLength, comment);
389
			}
390
		}
391
		else // identifier != 'I'
392
		{
393
			free(KeyDB->EmuKeys[i].key);
394
			KeyDB->EmuKeys[i].key = tmpKey;
395
			KeyDB->EmuKeys[i].keyLength = keyLength;
396
397
			if (identifier == 'F') // Update keyName (i.e. expiration date) for BISS
398
			{
399
				strncpy(KeyDB->EmuKeys[i].keyName, keyName, EMU_MAX_CHAR_KEYNAME);
400
			}
401
402
			if(writeKey) {
403
				WriteKeyToFile(identifier, provider, keyName, tmpKey, keyLength, comment);
404
			}
405
		}
406
		
407
		return 1;
408
	}
409
410
	// key does not exist on db
411
	if(KeyDB->keyCount+1 > KeyDB->keyMax)
412
	{
413
		if(KeyDB->EmuKeys == NULL) // db is empty
414
		{
415
			KeyDB->EmuKeys = (KeyData*)malloc(sizeof(KeyData)*(KeyDB->keyMax+64));
416
			if(KeyDB->EmuKeys == NULL) {
417
				free(tmpKey);
418
				return 0;
419
			}
420
			KeyDB->keyMax+=64;
421
		}
422
		else // db is full, expand it
423
		{
424
			tmpKeyData = (KeyData*)realloc(KeyDB->EmuKeys, sizeof(KeyData)*(KeyDB->keyMax+16));
425
			if(tmpKeyData == NULL) {
426
				free(tmpKey);
427
				return 0;
428
			}
429
			KeyDB->EmuKeys = tmpKeyData;
430
			KeyDB->keyMax+=16;
431
		}
432
	}
433
434
	KeyDB->EmuKeys[KeyDB->keyCount].identifier = identifier;
435
	KeyDB->EmuKeys[KeyDB->keyCount].provider = provider;
436
	if(strlen(keyName) < EMU_MAX_CHAR_KEYNAME) {
437
		strncpy(KeyDB->EmuKeys[KeyDB->keyCount].keyName, keyName, EMU_MAX_CHAR_KEYNAME);
438
	}
439
	else {
440
		memcpy(KeyDB->EmuKeys[KeyDB->keyCount].keyName, keyName, EMU_MAX_CHAR_KEYNAME);
441
	}
442
	KeyDB->EmuKeys[KeyDB->keyCount].keyName[EMU_MAX_CHAR_KEYNAME-1] = 0;
443
	KeyDB->EmuKeys[KeyDB->keyCount].key = tmpKey;
444
	KeyDB->EmuKeys[KeyDB->keyCount].keyLength = keyLength;
445
	KeyDB->EmuKeys[KeyDB->keyCount].nextKey = NULL;
446
	KeyDB->keyCount++;
447
448
	if(writeKey) {
449
		WriteKeyToFile(identifier, provider, keyName, tmpKey, keyLength, comment);
450
	}
451
	
452
	return 1;
453
}
454
455
int32_t FindKey(char identifier, uint32_t provider, uint32_t providerIgnoreMask, char *keyName, uint8_t *key,
456
				uint32_t maxKeyLength, uint8_t isCriticalKey, uint32_t keyRef, uint8_t matchLength, uint32_t *getProvider)
457
{
458
	uint32_t i;
459
	uint16_t j;
460
	uint8_t provider_matching_key_count = 0;
461
	KeyDataContainer *KeyDB;
462
	KeyData *tmpKeyData;
463
464
	KeyDB = GetKeyContainer(identifier);
465
	if(KeyDB == NULL) {
466
		return 0;
467
	}
468
	
469
	for(i=0; i<KeyDB->keyCount; i++) {
470
		
471
		if((KeyDB->EmuKeys[i].provider & ~providerIgnoreMask) != provider) {
472
			continue;
473
		}
474
475
		// Don't match keyName (i.e. expiration date) for BISS
476
		if(identifier != 'F' && strcmp(KeyDB->EmuKeys[i].keyName, keyName)) {
477
			continue;
478
		}
479
480
		//matchLength cannot be used when multiple keys are allowed
481
		//for a single provider/keyName combination.
482
		//Currently this is only the case for Irdeto keys.
483
		if(matchLength && KeyDB->EmuKeys[i].keyLength != maxKeyLength) {
484
			continue;
485
		}
486
487
		if(providerIgnoreMask) {
488
			if(provider_matching_key_count < keyRef) {
489
				provider_matching_key_count++;
490
				continue;
491
			}
492
			else {
493
				keyRef = 0;
494
			}
495
		}
496
497
		tmpKeyData = &KeyDB->EmuKeys[i];
498
499
		j = 0;
500
		while(j<keyRef && tmpKeyData->nextKey != NULL) {
501
			j++;
502
			tmpKeyData = tmpKeyData->nextKey;
503
		}
504
505
		if(j == keyRef) {
506
			memcpy(key, tmpKeyData->key, tmpKeyData->keyLength > maxKeyLength ? maxKeyLength : tmpKeyData->keyLength);
507
			if(tmpKeyData->keyLength < maxKeyLength) {
508
				memset(key+tmpKeyData->keyLength, 0, maxKeyLength - tmpKeyData->keyLength);
509
			}
510
511
			if (identifier == 'F') // Report the keyName of found key back to BissGetKey()
512
			{
513
				strncpy(keyName, tmpKeyData->keyName, EMU_MAX_CHAR_KEYNAME);
514
			}
515
516
			if(getProvider != NULL) {
517
				(*getProvider) = tmpKeyData->provider;
518
			}
519
			return 1;
520
		}
521
		else {
522
			break;
523
		}
524
	}
525
526
	if (isCriticalKey)
527
	{
528
		cs_log("Key not found: %c %X %s", identifier, provider, keyName);
529
	}
530
531
	return 0;
532
}
533
534
static int32_t UpdateKey(char identifier, uint32_t provider, char *keyName, uint8_t *key, uint32_t keyLength, uint8_t writeKey, char *comment)
535
{
536
	uint32_t keyRef = 0;
537
	uint8_t *tmpKey = (uint8_t*)malloc(sizeof(uint8_t)*keyLength);
538
	if(tmpKey == NULL)
539
	{
540
		return 0;
541
	}
542
		
543
	while(FindKey(identifier, provider, 0, keyName, tmpKey, keyLength, 0, keyRef, 0, NULL))
544
	{
545
		if(memcmp(tmpKey, key, keyLength) == 0)
546
		{		
547
			free(tmpKey);
548
			return 0;
549
		}
550
		
551
		keyRef++;
552
	}
553
554
	free(tmpKey);
555
	return SetKey(identifier, provider, keyName, key, keyLength, writeKey, comment, NULL);
556
}
557
558
static int32_t UpdateKeysByProviderMask(char identifier, uint32_t provider, uint32_t providerIgnoreMask, char *keyName, uint8_t *key, 
559
													uint32_t keyLength, char *comment)
560
{
561
	int32_t ret = 0;
562
	uint32_t foundProvider = 0;
563
	uint32_t keyRef = 0;
564
	uint8_t *tmpKey = (uint8_t*)malloc(sizeof(uint8_t)*keyLength);
565
	if(tmpKey == NULL)
566
	{
567
		return 0;
568
	}
569
	
570
	while(FindKey(identifier, (provider & ~providerIgnoreMask), providerIgnoreMask, keyName, tmpKey, keyLength, 0, keyRef, 0, &foundProvider))
571
	{
572
		keyRef++;
573
		
574
		if(memcmp(tmpKey, key, keyLength) == 0)
575
		{	
576
			continue;
577
		}
578
		
579
		if(SetKey(identifier, foundProvider, keyName, key, keyLength, 1, comment, NULL))
580
		{
581
			ret = 1;
582
		}
583
	}
584
585
	free(tmpKey);
586
	return ret;
587
}
588
589
int32_t DeleteKeysInContainer(char identifier)
590
{
591
	// Deletes all keys stored in memory for the specified identifier,
592
	// but keeps the container itself, re-initialized at { NULL, 0, 0 }.
593
	// Returns the count of deleted keys.
594
595
	uint32_t oldKeyCount, i;
596
	KeyData *tmpKeyData;
597
	KeyDataContainer *KeyDB = GetKeyContainer(identifier);
598
599
	if (KeyDB == NULL || KeyDB->EmuKeys == NULL || KeyDB->keyCount == 0)
600
	{
601
		return 0;
602
	}
603
604
	for (i = 0; i < KeyDB->keyCount; i++)
605
	{
606
		// For Irdeto multiple keys only (linked list structure)
607
		while (KeyDB->EmuKeys[i].nextKey != NULL)
608
		{
609
			tmpKeyData = KeyDB->EmuKeys[i].nextKey;
610
			KeyDB->EmuKeys[i].nextKey = KeyDB->EmuKeys[i].nextKey->nextKey;
611
			free(tmpKeyData->key); // Free key
612
			free(tmpKeyData); // Free KeyData
613
		}
614
615
		// For single keys (all identifiers, including Irdeto)
616
		free(KeyDB->EmuKeys[i].key); // Free key
617
	}
618
619
	// Free the KeyData array
620
	NULLFREE(KeyDB->EmuKeys);
621
	oldKeyCount = KeyDB->keyCount;
622
	KeyDB->keyCount = 0;
623
	KeyDB->keyMax = 0;
624
625
	return oldKeyCount;
626
}
627
628
void clear_emu_keydata(void)
629
{
630
	uint32_t total = 0;
631
632
	total  = CwKeys.keyCount;
633
	total += ViKeys.keyCount;
634
	total += NagraKeys.keyCount;
635
	total += IrdetoKeys.keyCount;
636
	total += NDSKeys.keyCount;
637
	total += BissKeys.keyCount;
638
	total += PowervuKeys.keyCount;
639
	total += DreKeys.keyCount;
640
	total += TandbergKeys.keyCount;
641
642
	if (total != 0)
643
	{
644
		cs_log("Freeing keys in memory: W:%d V:%d N:%d I:%d S:%d F:%d P:%d D:%d T:%d", \
645
						CwKeys.keyCount, ViKeys.keyCount, NagraKeys.keyCount, \
646
						IrdetoKeys.keyCount, NDSKeys.keyCount, BissKeys.keyCount, \
647
						PowervuKeys.keyCount, DreKeys.keyCount, TandbergKeys.keyCount);
648
649
		DeleteKeysInContainer('W');
650
		DeleteKeysInContainer('V');
651
		DeleteKeysInContainer('N');
652
		DeleteKeysInContainer('I');
653
		DeleteKeysInContainer('S');
654
		DeleteKeysInContainer('F');
655
		DeleteKeysInContainer('P');
656
		DeleteKeysInContainer('D');
657
		DeleteKeysInContainer('T');
658
	}
659
}
660
661
uint8_t read_emu_keyfile(struct s_reader *rdr, const char *opath)
662
{
663
	char line[1200], keyName[EMU_MAX_CHAR_KEYNAME], keyString[1026];
664
	uint32_t pathLength, provider, keyLength;
665
	uint8_t *key;
666
	struct dirent *pDirent;
667
	DIR *pDir;
668
	char *path, *filepath, filename[EMU_KEY_FILENAME_MAX_LEN+1];
669
	FILE *file = NULL;
670
	char identifier;
671
	uint8_t fileNameLen = strlen(EMU_KEY_FILENAME);
672
673
	pathLength = strlen(opath);
674
	path = (char*)malloc(pathLength+1);
675
	if(path == NULL) {
676
		return 0;
677
	}
678
	strncpy(path, opath, pathLength+1);
679
680
	pathLength = strlen(path);
681
	if(pathLength >= fileNameLen && strcasecmp(path+pathLength-fileNameLen, EMU_KEY_FILENAME) == 0) {
682
		// cut file name
683
		path[pathLength-fileNameLen] = '\0';
684
	}
685
686
	pathLength = strlen(path);
687
	if(path[pathLength-1] == '/' || path[pathLength-1] == '\\') {
688
		// cut trailing /
689
		path[pathLength-1] = '\0';
690
	}
691
692
	pDir = opendir(path);
693
	if (pDir == NULL) {
694
		cs_log("Cannot open key file path: %s", path);
695
		free(path);
696
		return 0;
697
	}
698
699
	while((pDirent = readdir(pDir)) != NULL) {
700
		if(strcasecmp(pDirent->d_name, EMU_KEY_FILENAME) == 0) {
701
			strncpy(filename, pDirent->d_name, sizeof(filename));
702
			break;
703
		}
704
	}
705
	closedir(pDir);
706
707
	if(pDirent == NULL) {
708
		cs_log("Key file not found in: %s", path);
709
		free(path);
710
		return 0;
711
	}
712
713
	pathLength = strlen(path)+1+strlen(filename)+1;
714
	filepath = (char*)malloc(pathLength);
715
	if(filepath == NULL) {
716
		free(path);
717
		return 0;
718
	}
719
	snprintf(filepath, pathLength, "%s/%s", path, filename);
720
	free(path);
721
722
	cs_log("Reading key file: %s", filepath);
723
724
	file = fopen(filepath, "r");
725
	free(filepath);
726
	if(file == NULL) {
727
		return 0;
728
	}
729
730
	set_emu_keyfile_path(opath);
731
732
	while(fgets(line, 1200, file)) {
733
		if(sscanf(line, "%c %8x %11s %1024s", &identifier, &provider, keyName, keyString) != 4) {
734
			continue;
735
		}
736
737
		keyLength = strlen(keyString)/2;
738
		key = (uint8_t*)malloc(keyLength);
739
		if(key == NULL) {
740
			fclose(file);
741
			return 0;
742
		}
743
744
		if (CharToBin(key, keyString, strlen(keyString))) // Conversion OK
745
		{
746
			SetKey(identifier, provider, keyName, key, keyLength, 0, NULL, rdr);
747
		}
748
		else // Non-hex characters in keyString
749
		{
750
			if ((identifier != ';' && identifier != '#' && // Skip warning for comments, etc.
751
				 identifier != '=' && identifier != '-' &&
752
				 identifier != ' ') &&
753
				!(identifier == 'F' && 0 == strncmp(keyString, "XXXXXXXXXXXX", 12))) // Skip warning for BISS 'Example key' lines
754
			{
755
				// Alert user regarding faulty line
756
				cs_log("WARNING: non-hex value in %s at %c %04X %s %s", EMU_KEY_FILENAME, identifier, provider, keyName, keyString);
757
			}
758
		}
759
		free(key);
760
	}
761
	fclose(file);
762
763
	return 1;
764
}
765
766
#if !defined(__APPLE__) && !defined(__ANDROID__)
767
extern uint8_t SoftCamKey_Data[]    __asm__("_binary_SoftCam_Key_start");
768
extern uint8_t SoftCamKey_DataEnd[] __asm__("_binary_SoftCam_Key_end");
769
770
void read_emu_keymemory(struct s_reader *rdr)
771
{
772
	char *keyData, *line, *saveptr, keyName[EMU_MAX_CHAR_KEYNAME], keyString[1026];
773
	uint32_t provider, keyLength;
774
	uint8_t *key;
775
	char identifier;
776
777
	keyData = (char*)malloc(SoftCamKey_DataEnd-SoftCamKey_Data+1);
778
	if(keyData == NULL) {
779
		return;
780
	}
781
	memcpy(keyData, SoftCamKey_Data, SoftCamKey_DataEnd-SoftCamKey_Data);
782
	keyData[SoftCamKey_DataEnd-SoftCamKey_Data] = 0x00;
783
784
	line = strtok_r(keyData, "\n", &saveptr);
785
	while(line != NULL) {
786
		if(sscanf(line, "%c %8x %11s %1024s", &identifier, &provider, keyName, keyString) != 4) {
787
			line = strtok_r(NULL, "\n", &saveptr);
788
			continue;
789
		}
790
		keyLength = strlen(keyString)/2;
791
		key = (uint8_t*)malloc(keyLength);
792
		if(key == NULL) {
793
			free(keyData);
794
			return;
795
		}
796
797
		if (CharToBin(key, keyString, strlen(keyString))) // Conversion OK
798
		{
799
			SetKey(identifier, provider, keyName, key, keyLength, 0, NULL, rdr);
800
		}
801
		else // Non-hex characters in keyString
802
		{
803
			if ((identifier != ';' && identifier != '#' && // Skip warning for comments, etc.
804
				 identifier != '=' && identifier != '-' &&
805
				 identifier != ' ') &&
806
				!(identifier == 'F' && 0 == strncmp(keyString, "XXXXXXXXXXXX", 12))) // Skip warning for BISS 'Example key' lines
807
			{
808
				// Alert user regarding faulty line
809
				cs_log("WARNING: non-hex value in internal keyfile at %c %04X %s %s", identifier, provider, keyName, keyString);
810
			}
811
		}
812
		free(key);
813
		line = strtok_r(NULL, "\n", &saveptr);
814
	}
815
	free(keyData);
816
}
817
#endif
818
819
void read_emu_eebin(const char *path, const char *name)
820
{
821
	char tmp[256];
822
	FILE *file = NULL;
823
	uint8_t i, buffer[64][32], dummy[2][32];
824
	uint32_t prvid;
825
826
	// Set path
827
	if (path != NULL)
828
	{
829
		snprintf(tmp, 256, "%s%s", path, name);
830
	}
831
	else // No path set, use SoftCam.Keys's path
832
	{
833
		snprintf(tmp, 256, "%s%s", emu_keyfile_path, name);
834
	}
835
836
	// Read file to buffer
837
	if ((file = fopen(tmp, "rb")) != NULL)
838
	{
839
		cs_log("Reading key file: %s", tmp);
840
841
		if (fread(buffer, 1, sizeof(buffer), file) != sizeof(buffer))
842
		{
843
			cs_log("Corrupt key file: %s", tmp);
844
			fclose(file);
845
			return;
846
		}
847
848
		fclose(file);
849
	}
850
	else
851
	{
852
		if (path != NULL)
853
		{
854
			cs_log("Cannot open key file: %s", tmp);
855
		}
856
857
		return;
858
	}
859
860
	// Save keys to db
861
	memset(dummy[0], 0x00, 32);
862
	memset(dummy[1], 0xFF, 32);
863
	prvid = (strncmp(name, "ee36.bin", 9) == 0) ? 0x4AE111 : 0x4AE114;
864
865
	for (i = 0; i < 32; i++) // Set "3B" type keys
866
	{
867
		// Write keys if they have "real" values
868
		if ((memcmp(buffer[i], dummy[0], 32) !=0) && (memcmp(buffer[i], dummy[1], 32) != 0))
869
		{
870
			snprintf(tmp, 5, "3B%02X", i);
871
			SetKey('D', prvid, tmp, buffer[i], 32, 0, NULL, NULL);
872
		}
873
	}
874
875
	for (i = 0; i < 32; i++) // Set "56" type keys
876
	{
877
		// Write keys if they have "real" values
878
		if ((memcmp(buffer[32 + i], dummy[0], 32) !=0) && (memcmp(buffer[32 + i], dummy[1], 32) != 0))
879
		{
880
			snprintf(tmp, 5, "56%02X", i);
881
			SetKey('D', prvid, tmp, buffer[32 + i], 32, 0, NULL, NULL);
882
		}
883
	}
884
}
885
886
void read_emu_deskey(uint8_t *dreOverKey, uint8_t len)
887
{
888
	uint8_t i;
889
890
	if (len == 128)
891
	{
892
		cs_log("Reading DreCrypt overcrypt (ADEC) key");
893
894
		for (i = 0; i < 16; i++)
895
		{
896
			SetKey('D', i, "OVER", dreOverKey + (i * 8), 8, 0, NULL, NULL);
897
		}
898
	}
899
	else if ((len != 0 && len < 128) || len > 128)
900
	{
901
		cs_log("DreCrypt overcrypt (ADEC) key has wrong length");
902
	}
903
}
904
905
// Shared functions
906
907
static inline uint16_t GetEcmLen(const uint8_t *ecm)
908
{
909
	return (((ecm[1] & 0x0f)<< 8) | ecm[2]) +3;
910
}
911
912
static void ReverseMem(uint8_t *in, int32_t len)
913
{
914
	uint8_t temp;
915
	int32_t i;
916
	for(i = 0; i < (len / 2); i++) {
917
		temp = in[i];
918
		in[i] = in[len - i - 1];
919
		in[len - i - 1] = temp;
920
	}
921
}
922
923
static void ReverseMemInOut(uint8_t *out, const uint8_t *in, int32_t n)
924
{
925
	if(n>0) {
926
		out+=n;
927
		do {
928
			*(--out)=*(in++);
929
		}
930
		while(--n);
931
	}
932
}
933
934
static int8_t EmuRSAInput(BIGNUM *d, const uint8_t *in, int32_t n, int8_t le)
935
{
936
	int8_t result = 0;
937
938
	if(le) {
939
		uint8_t *tmp = (uint8_t *)malloc(sizeof(uint8_t)*n);
940
		if(tmp == NULL) {
941
			return 0;
942
		}
943
		ReverseMemInOut(tmp,in,n);
944
		result = BN_bin2bn(tmp,n,d)!=0;
945
		free(tmp);
946
	}
947
	else {
948
		result = BN_bin2bn(in,n,d)!=0;
949
	}
950
	return result;
951
}
952
953
static int32_t EmuRSAOutput(uint8_t *out, int32_t n, BIGNUM *r, int8_t le)
954
{
955
	int32_t s = BN_num_bytes(r);
956
	if(s>n) {
957
		uint8_t *buff = (uint8_t *)malloc(sizeof(uint8_t)*s);
958
		if(buff == NULL) {
959
			return 0;
960
		}
961
		BN_bn2bin(r,buff);
962
		memcpy(out,buff+s-n,n);
963
		free(buff);
964
	}
965
	else if(s<n) {
966
		int32_t l=n-s;
967
		memset(out,0,l);
968
		BN_bn2bin(r,out+l);
969
	}
970
	else {
971
		BN_bn2bin(r,out);
972
	}
973
	if(le) {
974
		ReverseMem(out,n);
975
	}
976
	return s;
977
}
978
979
static int32_t EmuRSA(uint8_t *out, const uint8_t *in, int32_t n, BIGNUM *exp, BIGNUM *mod, int8_t le)
980
{
981
	BN_CTX *ctx;
982
	BIGNUM *r, *d;
983
	int32_t result = 0;
984
985
	ctx = BN_CTX_new();
986
	r = BN_new();
987
	d = BN_new();
988
989
	if(EmuRSAInput(d,in,n,le) && BN_mod_exp(r,d,exp,mod,ctx)) {
990
		result = EmuRSAOutput(out,n,r,le);
991
	}
992
993
	BN_free(d);
994
	BN_free(r);
995
	BN_CTX_free(ctx);
996
	return result;
997
}
998
999
static inline void xxor(uint8_t *data, int32_t len, const uint8_t *v1, const uint8_t *v2)
1000
{
1001
	uint32_t i;
1002
	switch(len)
1003
	{
1004
	case 16:
1005
		for(i = 8; i < 16; ++i)
1006
		{
1007
			data[i] = v1[i] ^ v2[i];
1008
		}
1009
	case 8:
1010
		for(i = 4; i < 8; ++i)
1011
		{
1012
			data[i] = v1[i] ^ v2[i];
1013
		}
1014
	case 4:
1015
		for(i = 0; i < 4; ++i)
1016
		{
1017
			data[i] = v1[i] ^ v2[i];
1018
		}
1019
		break;
1020
	default:
1021
		while(len--) { *data++ = *v1++ ^ *v2++; }
1022
		break;
1023
	}
1024
}
1025
1026
static int8_t isValidDCW(uint8_t *dw)
1027
{
1028
	if (((dw[0]+dw[1]+dw[2]) & 0xFF) != dw[3]) {
1029
		return 0;
1030
	}
1031
	if (((dw[4]+dw[5]+dw[6]) & 0xFF) != dw[7]) {
1032
		return 0;
1033
	}
1034
	if (((dw[8]+dw[9]+dw[10]) & 0xFF) != dw[11]) {
1035
		return 0;
1036
	}
1037
	if (((dw[12]+dw[13]+dw[14]) & 0xFF) != dw[15]) {
1038
		return 0;
1039
	}
1040
	return 1;
1041
}
1042
1043
static inline uint8_t GetBit(uint8_t byte, uint8_t bitnb)
1044
{
1045
	return ((byte&(1<<bitnb)) ? 1: 0);
1046
}
1047
1048
static inline uint8_t SetBit(uint8_t val, uint8_t bitnb, uint8_t biton)
1049
{
1050
	return (biton ? (val | (1<<bitnb)) : (val & ~(1<<bitnb)));
1051
}
1052
1053
static void ExpandDesKey(unsigned char *key)
1054
{
1055
	uint8_t i, j, parity;
1056
	uint8_t tmpKey[7];
1057
1058
	memcpy(tmpKey, key, 7);
1059
1060
	key[0] = (tmpKey[0] & 0xFE);
1061
	key[1] = ((tmpKey[0] << 7) | ((tmpKey[1] >> 1) & 0xFE));
1062
	key[2] = ((tmpKey[1] << 6) | ((tmpKey[2] >> 2) & 0xFE));
1063
	key[3] = ((tmpKey[2] << 5) | ((tmpKey[3] >> 3) & 0xFE));
1064
	key[4] = ((tmpKey[3] << 4) | ((tmpKey[4] >> 4) & 0xFE));
1065
	key[5] = ((tmpKey[4] << 3) | ((tmpKey[5] >> 5) & 0xFE));
1066
	key[6] = ((tmpKey[5] << 2) | ((tmpKey[6] >> 6) & 0xFE));
1067
	key[7] = (tmpKey[6] << 1);
1068
1069
	for (i = 0; i < 8; i++)
1070
	{
1071
		parity = 1;
1072
		for (j = 1; j < 8; j++) if ((key[i] >> j) & 0x1) { parity = ~parity & 0x01; }
1073
		key[i] |= parity;
1074
	}
1075
}
1076
1077
// Cryptoworks EMU
1078
static int8_t GetCwKey(uint8_t *buf,uint32_t ident, uint8_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey)
1079
{
1080
1081
	char keyName[EMU_MAX_CHAR_KEYNAME];
1082
	uint32_t tmp;
1083
1084
	if((ident >> 4) == 0xD02A) {
1085
		keyIndex &=0xFE; // map to even number key indexes
1086
	}
1087
	if((ident >> 4) == 0xD00C) {
1088
		ident = 0x0D00C0; // map provider C? to C0
1089
	}
1090
	else if(keyIndex == 6 && ((ident >> 8) == 0x0D05)) {
1091
		ident = 0x0D0504; // always use provider 04 system key
1092
	}
1093
1094
	tmp = keyIndex;
1095
	snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.2X", tmp);
1096
	if(FindKey('W', ident, 0, keyName, buf, keyLength, isCriticalKey, 0, 0, NULL)) {
1097
		return 1;
1098
	}
1099
1100
	return 0;
1101
}
1102
1103
static const uint8_t cw_sbox1[64] = {
1104
	0xD8,0xD7,0x83,0x3D,0x1C,0x8A,0xF0,0xCF,0x72,0x4C,0x4D,0xF2,0xED,0x33,0x16,0xE0,
1105
	0x8F,0x28,0x7C,0x82,0x62,0x37,0xAF,0x59,0xB7,0xE0,0x00,0x3F,0x09,0x4D,0xF3,0x94,
1106
	0x16,0xA5,0x58,0x83,0xF2,0x4F,0x67,0x30,0x49,0x72,0xBF,0xCD,0xBE,0x98,0x81,0x7F,
1107
	0xA5,0xDA,0xA7,0x7F,0x89,0xC8,0x78,0xA7,0x8C,0x05,0x72,0x84,0x52,0x72,0x4D,0x38
1108
};
1109
static const uint8_t cw_sbox2[64] = {
1110
	0xD8,0x35,0x06,0xAB,0xEC,0x40,0x79,0x34,0x17,0xFE,0xEA,0x47,0xA3,0x8F,0xD5,0x48,
1111
	0x0A,0xBC,0xD5,0x40,0x23,0xD7,0x9F,0xBB,0x7C,0x81,0xA1,0x7A,0x14,0x69,0x6A,0x96,
1112
	0x47,0xDA,0x7B,0xE8,0xA1,0xBF,0x98,0x46,0xB8,0x41,0x45,0x9E,0x5E,0x20,0xB2,0x35,
1113
	0xE4,0x2F,0x9A,0xB5,0xDE,0x01,0x65,0xF8,0x0F,0xB2,0xD2,0x45,0x21,0x4E,0x2D,0xDB
1114
};
1115
static const uint8_t cw_sbox3[64] = {
1116
	0xDB,0x59,0xF4,0xEA,0x95,0x8E,0x25,0xD5,0x26,0xF2,0xDA,0x1A,0x4B,0xA8,0x08,0x25,
1117
	0x46,0x16,0x6B,0xBF,0xAB,0xE0,0xD4,0x1B,0x89,0x05,0x34,0xE5,0x74,0x7B,0xBB,0x44,
1118
	0xA9,0xC6,0x18,0xBD,0xE6,0x01,0x69,0x5A,0x99,0xE0,0x87,0x61,0x56,0x35,0x76,0x8E,
1119
	0xF7,0xE8,0x84,0x13,0x04,0x7B,0x9B,0xA6,0x7A,0x1F,0x6B,0x5C,0xA9,0x86,0x54,0xF9
1120
};
1121
static const uint8_t cw_sbox4[64] = {
1122
	0xBC,0xC1,0x41,0xFE,0x42,0xFB,0x3F,0x10,0xB5,0x1C,0xA6,0xC9,0xCF,0x26,0xD1,0x3F,
1123
	0x02,0x3D,0x19,0x20,0xC1,0xA8,0xBC,0xCF,0x7E,0x92,0x4B,0x67,0xBC,0x47,0x62,0xD0,
1124
	0x60,0x9A,0x9E,0x45,0x79,0x21,0x89,0xA9,0xC3,0x64,0x74,0x9A,0xBC,0xDB,0x43,0x66,
1125
	0xDF,0xE3,0x21,0xBE,0x1E,0x16,0x73,0x5D,0xA2,0xCD,0x8C,0x30,0x67,0x34,0x9C,0xCB
1126
};
1127
static const uint8_t AND_bit1[8] = {0x00,0x40,0x04,0x80,0x21,0x10,0x02,0x08};
1128
static const uint8_t AND_bit2[8] = {0x80,0x08,0x01,0x40,0x04,0x20,0x10,0x02};
1129
static const uint8_t AND_bit3[8] = {0x82,0x40,0x01,0x10,0x00,0x20,0x04,0x08};
1130
static const uint8_t AND_bit4[8] = {0x02,0x10,0x04,0x40,0x80,0x08,0x01,0x20};
1131
1132
static void CW_SWAP_KEY(uint8_t *key)
1133
{
1134
	uint8_t k[8];
1135
	memcpy(k, key, 8);
1136
	memcpy(key, key + 8, 8);
1137
	memcpy(key + 8, k, 8);
1138
}
1139
1140
static void CW_SWAP_DATA(uint8_t *k)
1141
{
1142
	uint8_t d[4];
1143
	memcpy(d, k + 4, 4);
1144
	memcpy(k + 4 ,k ,4);
1145
	memcpy(k, d, 4);
1146
}
1147
1148
static void CW_DES_ROUND(uint8_t *d, uint8_t *k)
1149
{
1150
	uint8_t aa[44] = {1,0,3,1,2,2,3,2,1,3,1,1,3,0,1,2,3,1,3,2,2,0,7,6,5,4,7,6,5,7,6,5,6,7,5,7,5,7,6,6,7,5,4,4};
1151
	uint8_t bb[44] = {0x80,0x08,0x10,0x02,0x08,0x40,0x01,0x20,0x40,0x80,0x04,0x10,0x04,0x01,0x01,0x02,0x20,0x20,0x02,0x01,
1152
					  0x80,0x04,0x02,0x02,0x08,0x02,0x10,0x80,0x01,0x20,0x08,0x80,0x01,0x08,0x40,0x01,0x02,0x80,0x10,0x40,0x40,0x10,0x08,0x01
1153
					 };
1154
	uint8_t ff[4] = {0x02,0x10,0x04,0x04};
1155
	uint8_t l[24] = {0,2,4,6,7,5,3,1,4,5,6,7,7,6,5,4,7,4,5,6,4,7,6,5};
1156
1157
	uint8_t des_td[8], i, o, n, c = 1, m = 0, r = 0, *a = aa, *b = bb, *f = ff, *p1 = l, *p2 = l+8, *p3 = l+16;
1158
1159
	for (m = 0; m < 2; m++) {
1160
		for(i = 0; i < 4; i++) {
1161
			des_td[*p1++] =
1162
				(m) ? ((d[*p2++]*2) & 0x3F) | ((d[*p3++] & 0x80) ? 0x01 : 0x00): (d[*p2++]/2) | ((d[*p3++] & 0x01) ? 0x80 : 0x00);
1163
		}
1164
	}
1165
1166
	for (i = 0; i < 8; i++) {
1167
		c = (c) ? 0 : 1;
1168
		r = (c) ? 6 : 7;
1169
		n = (i) ? i-1 : 1;
1170
		o = (c) ? ((k[n] & *f++) ? 1 : 0) : des_td[n];
1171
		for (m = 1; m < r; m++) {
1172
			o = (c) ? (o*2) | ((k[*a++] & *b++) ? 0x01 : 0x00) : (o/2) | ((k[*a++] & *b++) ? 0x80 : 0x00);
1173
		}
1174
		n = (i) ? n+1 : 0;
1175
		des_td[n] = (c) ? des_td[n] ^ o : (o ^ des_td[n] )/4;
1176
	}
1177
1178
	for( i = 0; i < 8; i++) {
1179
		d[0] ^= (AND_bit1[i] & cw_sbox1[des_td[i]]);
1180
		d[1] ^= (AND_bit2[i] & cw_sbox2[des_td[i]]);
1181
		d[2] ^= (AND_bit3[i] & cw_sbox3[des_td[i]]);
1182
		d[3] ^= (AND_bit4[i] & cw_sbox4[des_td[i]]);
1183
	}
1184
1185
	CW_SWAP_DATA(d);
1186
}
1187
1188
static void CW_48_Key(uint8_t *inkey, uint8_t *outkey, uint8_t algotype)
1189
{
1190
	uint8_t Round_Counter, i = 8, *key128 = inkey, *key48 = inkey + 0x10;
1191
	Round_Counter = 7 - (algotype & 7);
1192
1193
	memset(outkey, 0, 16);
1194
	memcpy(outkey, key48, 6);
1195
1196
	for( ; i > Round_Counter; i--) {
1197
		if (i > 1) {
1198
			outkey[i-2] = key128[i];
1199
		}
1200
	}
1201
}
1202
1203
static void CW_LS_DES_KEY(uint8_t *key,uint8_t Rotate_Counter)
1204
{
1205
	uint8_t round[] = {1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,1};
1206
	uint8_t i, n;
1207
	uint16_t k[8];
1208
1209
	n = round[Rotate_Counter];
1210
1211
	for (i = 0; i < 8; i++) {
1212
		k[i] = key[i];
1213
	}
1214
1215
	for (i = 1; i < n + 1; i++) {
1216
		k[7] = (k[7]*2) | ((k[4] & 0x008) ? 1 : 0);
1217
		k[6] = (k[6]*2) | ((k[7] & 0xF00) ? 1 : 0);
1218
		k[7] &=0xff;
1219
		k[5] = (k[5]*2) | ((k[6] & 0xF00) ? 1 : 0);
1220
		k[6] &=0xff;
1221
		k[4] = ((k[4]*2) | ((k[5] & 0xF00) ? 1 : 0)) & 0xFF;
1222
		k[5] &= 0xff;
1223
		k[3] = (k[3]*2) | ((k[0] & 0x008) ? 1 : 0);
1224
		k[2] = (k[2]*2) | ((k[3] & 0xF00) ? 1 : 0);
1225
		k[3] &= 0xff;
1226
		k[1] = (k[1]*2) | ((k[2] & 0xF00) ? 1 : 0);
1227
		k[2] &= 0xff;
1228
		k[0] = ((k[0]*2) | ((k[1] & 0xF00) ? 1 : 0)) & 0xFF;
1229
		k[1] &= 0xff;
1230
	}
1231
	for (i = 0; i < 8; i++) {
1232
		key[i] = (uint8_t) k[i];
1233
	}
1234
}
1235
1236
static void CW_RS_DES_KEY(uint8_t *k, uint8_t Rotate_Counter)
1237
{
1238
	uint8_t i,c;
1239
	for (i = 1; i < Rotate_Counter+1; i++) {
1240
		c = (k[3] & 0x10) ? 0x80 : 0;
1241
		k[3] /= 2;
1242
		if (k[2] & 1) {
1243
			k[3] |= 0x80;
1244
		}
1245
		k[2] /= 2;
1246
		if (k[1] & 1) {
1247
			k[2] |= 0x80;
1248
		}
1249
		k[1] /= 2;
1250
		if (k[0] & 1) {
1251
			k[1] |= 0x80;
1252
		}
1253
		k[0] /= 2;
1254
		k[0] |= c ;
1255
		c = (k[7] & 0x10) ? 0x80 : 0;
1256
		k[7] /= 2;
1257
		if (k[6] & 1) {
1258
			k[7] |= 0x80;
1259
		}
1260
		k[6] /= 2;
1261
		if (k[5] & 1) {
1262
			k[6] |= 0x80;
1263
		}
1264
		k[5] /= 2;
1265
		if (k[4] & 1) {
1266
			k[5] |= 0x80;
1267
		}
1268
		k[4] /= 2;
1269
		k[4] |= c;
1270
	}
1271
}
1272
1273
static void CW_RS_DES_SUBKEY(uint8_t *k, uint8_t Rotate_Counter)
1274
{
1275
	uint8_t round[] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
1276
	CW_RS_DES_KEY(k, round[Rotate_Counter]);
1277
}
1278
1279
static void CW_PREP_KEY(uint8_t *key )
1280
{
1281
	uint8_t DES_key[8],j;
1282
	int32_t Round_Counter = 6,i,a;
1283
	key[7] = 6;
1284
	memset(DES_key, 0 , 8);
1285
	do {
1286
		a = 7;
1287
		i = key[7];
1288
		j = key[Round_Counter];
1289
		do {
1290
			DES_key[i] = ( (DES_key[i] * 2) | ((j & 1) ? 1: 0) ) & 0xFF;
1291
			j /=2;
1292
			i--;
1293
			if (i < 0) {
1294
				i = 6;
1295
			}
1296
			a--;
1297
		}
1298
		while (a >= 0);
1299
		key[7] = i;
1300
		Round_Counter--;
1301
	}
1302
	while ( Round_Counter >= 0 );
1303
	a = DES_key[4];
1304
	DES_key[4] = DES_key[6];
1305
	DES_key[6] = a;
1306
	DES_key[7] = (DES_key[3] * 16) & 0xFF;
1307
	memcpy(key,DES_key,8);
1308
	CW_RS_DES_KEY(key,4);
1309
}
1310
1311
static void CW_L2DES(uint8_t *data, uint8_t *key, uint8_t algo)
1312
{
1313
	uint8_t i, k0[22], k1[22];
1314
	memcpy(k0,key,22);
1315
	memcpy(k1,key,22);
1316
	CW_48_Key(k0, k1,algo);
1317
	CW_PREP_KEY(k1);
1318
	for (i = 0; i< 2; i++) {
1319
		CW_LS_DES_KEY( k1,15);
1320
		CW_DES_ROUND( data ,k1);
1321
	}
1322
}
1323
1324
static void CW_R2DES(uint8_t *data, uint8_t *key, uint8_t algo)
1325
{
1326
	uint8_t i, k0[22],k1[22];
1327
	memcpy(k0,key,22);
1328
	memcpy(k1,key,22);
1329
	CW_48_Key(k0, k1, algo);
1330
	CW_PREP_KEY(k1);
1331
	for (i = 0; i< 2; i++) {
1332
		CW_LS_DES_KEY(k1,15);
1333
	}
1334
	for (i = 0; i< 2; i++) {
1335
		CW_DES_ROUND( data ,k1);
1336
		CW_RS_DES_SUBKEY(k1,1);
1337
	}
1338
	CW_SWAP_DATA(data);
1339
}
1340
1341
static void CW_DES(uint8_t *data, uint8_t *inkey, uint8_t m)
1342
{
1343
	uint8_t key[22], i;
1344
	memcpy(key, inkey + 9, 8);
1345
	CW_PREP_KEY( key );
1346
	for (i = 16; i > 0; i--) {
1347
		if (m == 1) {
1348
			CW_LS_DES_KEY(key, (uint8_t) (i-1));
1349
		}
1350
		CW_DES_ROUND( data ,key);
1351
		if (m == 0) {
1352
			CW_RS_DES_SUBKEY(key, (uint8_t) (i-1));
1353
		}
1354
	}
1355
}
1356
1357
static void CW_DEC_ENC(uint8_t *d, uint8_t *k, uint8_t a,uint8_t m)
1358
{
1359
	uint8_t n = m & 1;
1360
	CW_L2DES(d , k, a);
1361
	CW_DES (d , k, n);
1362
	CW_R2DES(d , k, a);
1363
	if (m & 2) {
1364
		CW_SWAP_KEY(k);
1365
	}
1366
}
1367
1368
static void Cryptoworks3DES(uint8_t *data, uint8_t *key)
1369
{
1370
	uint32_t ks1[32], ks2[32];
1371
	
1372
	des_set_key(key, ks1);
1373
	des_set_key(key+8, ks2);
1374
	
1375
	des(data, ks1, 0);
1376
	des(data, ks2, 1);
1377
	des(data, ks1, 0);
1378
}
1379
1380
static uint8_t CryptoworksProcessNano80(uint8_t *data, uint32_t caid, int32_t provider, uint8_t *opKey, uint8_t nanoLength, uint8_t nano80Algo)
1381
{
1382
	int32_t i, j;
1383
	uint8_t key[16], desKey[16], t[8], dat1[8], dat2[8], k0D00C000[16];
1384
	if(nanoLength < 11) {
1385
		return 0;
1386
	}
1387
	if(caid == 0x0D00 && provider != 0xA0 && !GetCwKey(k0D00C000, 0x0D00C0, 0, 16, 1)) {
1388
		return 0;
1389
	}
1390
1391
	if(nano80Algo > 1) {
1392
		return 0;
1393
	}
1394
1395
	memset(t, 0, 8);
1396
	memcpy(dat1, data, 8);
1397
1398
	if(caid == 0x0D00 && provider != 0xA0) {
1399
		memcpy(key, k0D00C000, 16);
1400
	}
1401
	else {
1402
		memcpy(key, opKey, 16);
1403
	}
1404
	Cryptoworks3DES(data, key);
1405
	memcpy(desKey, data, 8);
1406
1407
	memcpy(data, dat1, 8);
1408
	if(caid == 0x0D00 && provider != 0xA0) {
1409
		memcpy(key, &k0D00C000[8], 8);
1410
		memcpy(&key[8], k0D00C000, 8);
1411
	}
1412
	else {
1413
		memcpy(key, &opKey[8], 8);
1414
		memcpy(&key[8], opKey, 8);
1415
	}
1416
	Cryptoworks3DES(data, key);
1417
	memcpy(&desKey[8], data, 8);
1418
1419
	for(i=8; i+7<nanoLength; i+=8) {
1420
		memcpy(dat1, &data[i], 8);
1421
		memcpy(dat2, dat1, 8);
1422
		memcpy(key, desKey, 16);
1423
		Cryptoworks3DES(dat1, key);
1424
		for(j=0; j<8; j++) {
1425
			dat1[j] ^= t[j];
1426
		}
1427
		memcpy(&data[i], dat1, 8);
1428
		memcpy(t, dat2, 8);
1429
	}
1430
1431
	return data[10] + 5;
1432
}
1433
1434
static void CryptoworksSignature(const uint8_t *data, uint32_t length, uint8_t *key, uint8_t *signature)
1435
{
1436
	uint32_t i, sigPos;
1437
	int8_t algo, first;
1438
1439
	algo = data[0] & 7;
1440
	if(algo == 7) {
1441
		algo = 6;
1442
	}
1443
	memset(signature, 0, 8);
1444
	first = 1;
1445
	sigPos = 0;
1446
	for(i=0; i<length; i++) {
1447
		signature[sigPos] ^= data[i];
1448
		sigPos++;
1449
1450
		if(sigPos > 7) {
1451
			if (first) {
1452
				CW_L2DES(signature, key, algo);
1453
			}
1454
			CW_DES(signature, key, 1);
1455
1456
			sigPos = 0;
1457
			first = 0;
1458
		}
1459
	}
1460
	if(sigPos > 0) {
1461
		CW_DES(signature, key, 1);
1462
	}
1463
	CW_R2DES(signature, key, algo);
1464
}
1465
1466
static void CryptoworksDecryptDes(uint8_t *data, uint8_t algo, uint8_t *key)
1467
{
1468
	int32_t i;
1469
	uint8_t k[22], t[8];
1470
1471
	algo &= 7;
1472
	if(algo<7) {
1473
		CW_DEC_ENC(data, key, algo, 0);
1474
	}
1475
	else {
1476
		memcpy(k, key, 22);
1477
		for(i=0; i<3; i++) {
1478
			CW_DEC_ENC(data, k, algo, i&1);
1479
			memcpy(t,k,8);
1480
			memcpy(k,k+8,8);
1481
			memcpy(k+8,t,8);
1482
		}
1483
	}
1484
}
1485
1486
static int8_t CryptoworksECM(uint32_t caid, uint8_t *ecm, uint8_t *cw)
1487
{
1488
	uint32_t ident;
1489
	uint8_t keyIndex = 0, nanoLength, newEcmLength, key[22], signature[8], nano80Algo = 1;
1490
	int32_t provider = -1;
1491
	uint16_t i, j, ecmLen = GetEcmLen(ecm);
1492
1493
	if(ecmLen < 8) {
1494
		return 1;
1495
	}
1496
	if(ecm[7] != ecmLen - 8) {
1497
		return 1;
1498
	}
1499
1500
	memset(key, 0, 22);
1501
1502
	for(i = 8; i+1 < ecmLen; i += ecm[i+1] + 2) {
1503
		if(ecm[i] == 0x83 && i+2 < ecmLen) {
1504
			provider = ecm[i+2] & 0xFC;
1505
			keyIndex = ecm[i+2] & 3;
1506
			keyIndex = keyIndex ? 1 : 0;
1507
		}
1508
		else if(ecm[i] == 0x84 && i+3 < ecmLen) {
1509
			//nano80Provider = ecm[i+2] & 0xFC;
1510
			//nano80KeyIndex = ecm[i+2] & 3;
1511
			//nano80KeyIndex = nano80KeyIndex ? 1 : 0;
1512
			nano80Algo = ecm[i+3];
1513
		}
1514
	}
1515
1516
	if(provider < 0) {
1517
		switch(caid) {
1518
		case 0x0D00:
1519
			provider = 0xC0;
1520
			break;
1521
		case 0x0D02:
1522
			provider = 0xA0;
1523
			break;
1524
		case 0x0D03:
1525
			provider = 0x04;
1526
			break;
1527
		case 0x0D05:
1528
			provider = 0x04;
1529
			break;
1530
		default:
1531
			return 1;
1532
		}
1533
	}
1534
1535
	ident = (caid << 8) | provider;
1536
	if(!GetCwKey(key, ident, keyIndex, 16, 1)) {
1537
		return 2;
1538
	}
1539
	if(!GetCwKey(&key[16], ident, 6, 6, 1)) {
1540
		return 2;
1541
	}
1542
1543
	for(i = 8; i+1 < ecmLen; i += ecm[i+1] + 2) {
1544
		if(ecm[i] == 0x80 && i+2+7 < ecmLen && i+2+ecm[i+1] <= ecmLen
1545
				&& (provider == 0xA0 || provider == 0xC0 || provider == 0xC4 || provider == 0xC8)) {
1546
			nanoLength = ecm[i+1];
1547
			newEcmLength = CryptoworksProcessNano80(ecm+i+2, caid, provider, key, nanoLength, nano80Algo);
1548
			if(newEcmLength == 0 || newEcmLength > ecmLen-(i+2+3)) {
1549
				return 1;
1550
			}
1551
			ecm[i+2+3] = 0x81;
1552
			ecm[i+2+4] = 0x70;
1553
			ecm[i+2+5] = newEcmLength;
1554
			ecm[i+2+6] = 0x81;
1555
			ecm[i+2+7] = 0xFF;
1556
			return CryptoworksECM(caid, ecm+i+2+3, cw);
1557
		}
1558
	}
1559
1560
	if(ecmLen - 15 < 1) {
1561
		return 1;
1562
	}
1563
	CryptoworksSignature(ecm + 5, ecmLen - 15, key, signature);
1564
	for(i = 8; i+1 < ecmLen; i += ecm[i+1]+2) {
1565
		switch(ecm[i]) {
1566
		case 0xDA:
1567
		case 0xDB:
1568
		case 0xDC:
1569
			if(i+2+ecm[i+1] > ecmLen) {
1570
				break;
1571
			}
1572
			for(j=0; j+7<ecm[i+1]; j+=8) {
1573
				CryptoworksDecryptDes(&ecm[i+2+j], ecm[5], key);
1574
			}
1575
			break;
1576
		case 0xDF:
1577
			if(i+2+8 > ecmLen) {
1578
				break;
1579
			}
1580
			if(memcmp(&ecm[i+2], signature, 8)) {
1581
				return 6;
1582
			}
1583
			break;
1584
		}
1585
	}
1586
1587
	for(i = 8; i+1 < ecmLen; i += ecm[i+1]+2) {
1588
		switch(ecm[i]) {
1589
		case 0xDB:
1590
			if(i+2+ecm[i+1] <= ecmLen && ecm[i+1] == 16) {
1591
				memcpy(cw, &ecm[i+2], 16);
1592
				return 0;
1593
			}
1594
			break;
1595
		}
1596
	}
1597
1598
	return 5;
1599
}
1600
1601
// SoftNDS EMU
1602
static const uint8_t nds_const[]= {0x0F,0x1E,0x2D,0x3C,0x4B,0x5A,0x69,0x78,0x87,0x96,0xA5,0xB4,0xC3,0xD2,0xE1,0xF0};
1603
1604
uint8_t viasat_const[]= {
1605
	0x15,0x85,0xC5,0xE4,0xB8,0x52,0xEC,0xF7,0xC3,0xD9,0x08,0xBA,0x22,0x4A,0x66,0xF2,
1606
	0x82,0x15,0x4F,0xB2,0x18,0x48,0x63,0x97,0xDC,0x19,0xD8,0x51,0x9A,0x39,0xFC,0xCA,
1607
	0x1C,0x24,0xD0,0x65,0xA9,0x66,0x2D,0xD6,0x53,0x3B,0x86,0xBA,0x40,0xEA,0x4C,0x6D,
1608
	0xD9,0x1E,0x41,0x14,0xFE,0x15,0xAF,0xC3,0x18,0xC5,0xF8,0xA7,0xA8,0x01,0x00,0x01,
1609
};
1610
1611
static int8_t SoftNDSECM(uint16_t caid, uint8_t *ecm, uint8_t *dw)
1612
{
1613
	int32_t i;
1614
	uint8_t *tDW, irdEcmLen, offsetCw = 0, offsetP2 = 0;
1615
	uint8_t digest[16], md5_const[64];
1616
	MD5_CTX mdContext;
1617
	uint16_t ecmLen = GetEcmLen(ecm);
1618
1619
	if(ecmLen < 7) {
1620
		return 1;
1621
	}
1622
1623
	if(ecm[3] != 0x00 || ecm[4] != 0x00 || ecm[5] != 0x01) {
1624
		return 1;
1625
	}
1626
1627
	irdEcmLen = ecm[6];
1628
	if(irdEcmLen < (10+3+8+4) || irdEcmLen+6 >= ecmLen) {
1629
		return 1;
1630
	}
1631
1632
	for(i=0; 10+i+2 < irdEcmLen; i++) {
1633
		if(ecm[17+i] == 0x0F && ecm[17+i+1] == 0x40 && ecm[17+i+2] == 0x00) {
1634
			offsetCw = 17+i+3;
1635
			offsetP2 = offsetCw+9;
1636
		}
1637
	}
1638
1639
	if(offsetCw == 0 || offsetP2 == 0) {
1640
		return 1;
1641
	}
1642
1643
	if(offsetP2-7+4 > irdEcmLen) {
1644
		return 1;
1645
	}
1646
1647
	if(caid == 0x090F || caid == 0x093E) {
1648
		memcpy(md5_const, viasat_const, 64);
1649
	}
1650
	else if(!FindKey('S', caid, 0, "00", md5_const, 64, 1, 0, 0, NULL)) {
1651
		return 2;
1652
	}
1653
1654
	memset(dw,0,16);
1655
	tDW = &dw[ecm[0] == 0x81 ? 8 : 0];
1656
1657
	MD5_Init(&mdContext);
1658
	MD5_Update(&mdContext, ecm+7, 10);
1659
	MD5_Update(&mdContext, ecm+offsetP2, 4);
1660
	MD5_Update(&mdContext, md5_const, 64);
1661
	MD5_Update(&mdContext, nds_const, 16);
1662
	MD5_Final(digest, &mdContext);
1663
1664
	for (i=0; i<8; i++) {
1665
		tDW[i] = digest[i+8] ^ ecm[offsetCw+i];
1666
	}
1667
1668
	if(((tDW[0]+tDW[1]+tDW[2])&0xFF)-tDW[3]) {
1669
		return 6;
1670
	}
1671
	if(((tDW[4]+tDW[5]+tDW[6])&0xFF)-tDW[7]) {
1672
		return 6;
1673
	}
1674
1675
	return 0;
1676
}
1677
1678
// Viaccess EMU
1679
static int8_t GetViaKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey)
1680
{
1681
1682
	char keyStr[EMU_MAX_CHAR_KEYNAME];
1683
	snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
1684
	if(FindKey('V', ident, 0, keyStr, buf, keyLength, isCriticalKey, 0, 0, NULL)) {
1685
		return 1;
1686
	}
1687
1688
	if(ident == 0xD00040 && FindKey('V', 0x030B00, 0, keyStr, buf, keyLength, isCriticalKey, 0, 0, NULL)) {
1689
		return 1;
1690
	}
1691
1692
	return 0;
1693
}
1694
1695
static void Via1Mod(const uint8_t* key2, uint8_t* data)
1696
{
1697
	int32_t kb, db;
1698
	for (db=7; db>=0; db--) {
1699
		for (kb=7; kb>3; kb--) {
1700
			int32_t a0=kb^db;
1701
			int32_t pos=7;
1702
			if (a0&4) {
1703
				a0^=7;
1704
				pos^=7;
1705
			}
1706
			a0=(a0^(kb&3)) + (kb&3);
1707
			if (!(a0&4)) {
1708
				data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF));
1709
			}
1710
		}
1711
	}
1712
	for (db=0; db<8; db++) {
1713
		for (kb=0; kb<4; kb++) {
1714
			int32_t a0=kb^db;
1715
			int32_t pos=7;
1716
			if (a0&4) {
1717
				a0^=7;
1718
				pos^=7;
1719
			}
1720
			a0=(a0^(kb&3)) + (kb&3);
1721
			if (!(a0&4)) {
1722
				data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF));
1723
			}
1724
		}
1725
	}
1726
}
1727
1728
static void Via1Decode(uint8_t *data, uint8_t *key)
1729
{
1730
	Via1Mod(key+8, data);
1731
	nc_des(key, DES_ECM_CRYPT, data);
1732
	Via1Mod(key+8, data);
1733
}
1734
1735
static void Via1Hash(uint8_t *data, uint8_t *key)
1736
{
1737
	Via1Mod(key+8, data);
1738
	nc_des(key, DES_ECM_HASH, data);
1739
	Via1Mod(key+8, data);
1740
}
1741
1742
static inline void Via1DoHash(uint8_t *hashbuffer, uint8_t *pH, uint8_t data, uint8_t *hashkey)
1743
{
1744
	hashbuffer[*pH] ^= data;
1745
	(*pH)++;
1746
1747
	if(*pH == 8) {
1748
		Via1Hash(hashbuffer, hashkey);
1749
		*pH = 0;
1750
	}
1751
}
1752
1753
static int8_t Via1Decrypt(uint8_t* ecm, uint8_t* dw, uint32_t ident, uint8_t desKeyIndex)
1754
{
1755
	uint8_t work_key[16];
1756
	uint8_t *data, *des_data1, *des_data2;
1757
	uint16_t ecmLen = GetEcmLen(ecm);
1758
	int32_t msg_pos;
1759
	int32_t encStart = 0, hash_start, i;
1760
	uint8_t signature[8], hashbuffer[8], prepared_key[16], hashkey[16];
1761
	uint8_t tmp, k, pH, foundData = 0;
1762
1763
	if (ident == 0) {
1764
		return 4;
1765
	}
1766
	memset(work_key, 0, 16);
1767
	if(!GetViaKey(work_key, ident, '0', desKeyIndex, 8, 1)) {
1768
		return 2;
1769
	}
1770
1771
	if(ecmLen < 11) {
1772
		return 1;
1773
	}
1774
	data = ecm+9;
1775
	des_data1 = dw;
1776
	des_data2 = dw+8;
1777
1778
	msg_pos = 0;
1779
	pH = 0;
1780
	memset(hashbuffer, 0, sizeof(hashbuffer));
1781
	memcpy(hashkey, work_key, sizeof(hashkey));
1782
	memset(signature, 0, 8);
1783
1784
	while(9+msg_pos+2 < ecmLen) {
1785
		switch (data[msg_pos]) {
1786
		case 0xea:
1787
			if(9+msg_pos+2+15 < ecmLen) {
1788
				encStart = msg_pos + 2;
1789
				memcpy(des_data1, &data[msg_pos+2], 8);
1790
				memcpy(des_data2, &data[msg_pos+2+8], 8);
1791
				foundData |= 1;
1792
			}
1793
			break;
1794
		case 0xf0:
1795
			if(9+msg_pos+2+7 < ecmLen) {
1796
				memcpy(signature, &data[msg_pos+2], 8);
1797
				foundData |= 2;
1798
			}
1799
			break;
1800
		}
1801
		msg_pos += data[msg_pos+1]+2;
1802
	}
1803
1804
	if(foundData != 3) {
1805
		return 1;
1806
	}
1807
1808
	pH=i=0;
1809
1810
	if(data[0] == 0x9f && 10+data[1] <= ecmLen) {
1811
		Via1DoHash(hashbuffer, &pH, data[i++], hashkey);
1812
		Via1DoHash(hashbuffer, &pH, data[i++], hashkey);
1813
1814
		for (hash_start=0; hash_start < data[1]; hash_start++) {
1815
			Via1DoHash(hashbuffer, &pH, data[i++], hashkey);
1816
		}
1817
1818
		while (pH != 0) {
1819
			Via1DoHash(hashbuffer, &pH, 0, hashkey);
1820
		}
1821
	}
1822
1823
	if (work_key[7] == 0) {
1824
		for (; i < encStart + 16; i++) {
1825
			Via1DoHash(hashbuffer, &pH, data[i], hashkey);
1826
		}
1827
		memcpy(prepared_key, work_key, 8);
1828
	}
1829
	else {
1830
		prepared_key[0] = work_key[2];
1831
		prepared_key[1] = work_key[3];
1832
		prepared_key[2] = work_key[4];
1833
		prepared_key[3] = work_key[5];
1834
		prepared_key[4] = work_key[6];
1835
		prepared_key[5] = work_key[0];
1836
		prepared_key[6] = work_key[1];
1837
		prepared_key[7] = work_key[7];
1838
		memcpy(prepared_key+8, work_key+8, 8);
1839
1840
		if (work_key[7] & 1) {
1841
			for (; i < encStart; i++) {
1842
				Via1DoHash(hashbuffer, &pH, data[i], hashkey);
1843
			}
1844
1845
			k = ((work_key[7] & 0xf0) == 0) ? 0x5a : 0xa5;
1846
1847
			for (i=0; i<8; i++) {
1848
				tmp = des_data1[i];
1849
				des_data1[i] = (k & hashbuffer[pH] ) ^ tmp;
1850
				Via1DoHash(hashbuffer, &pH, tmp, hashkey);
1851
			}
1852
1853
			for (i = 0; i < 8; i++) {
1854
				tmp = des_data2[i];
1855
				des_data2[i] = (k & hashbuffer[pH] ) ^ tmp;
1856
				Via1DoHash(hashbuffer, &pH, tmp, hashkey);
1857
			}
1858
		}
1859
		else {
1860
			for (; i < encStart + 16; i++) {
1861
				Via1DoHash(hashbuffer, &pH, data[i], hashkey);
1862
			}
1863
		}
1864
	}
1865
	Via1Decode(des_data1, prepared_key);
1866
	Via1Decode(des_data2, prepared_key);
1867
	Via1Hash(hashbuffer, hashkey);
1868
	if(memcmp(signature, hashbuffer, 8)) {
1869
		return 6;
1870
	}
1871
	return 0;
1872
}
1873
1874
static int8_t Via26ProcessDw(uint8_t *indata, uint32_t ident, uint8_t desKeyIndex)
1875
{
1876
	uint8_t pv1,pv2, i;
1877
	uint8_t Tmp[8], T1Key[300], P1Key[8], KeyDes1[16], KeyDes2[16], XorKey[8];
1878
	uint32_t ks1[32], ks2[32];
1879
1880
	if(!GetViaKey(T1Key, ident, 'T', 1, 300, 1)) {
1881
		return 2;
1882
	}
1883
	if(!GetViaKey(P1Key, ident, 'P', 1, 8, 1)) {
1884
		return 2;
1885
	}
1886
	if(!GetViaKey(KeyDes1, ident, 'D', 1, 16, 1)) {
1887
		return 2;
1888
	}
1889
	if(!GetViaKey(KeyDes2, ident, '0', desKeyIndex, 16, 1)) {
1890
		return 2;
1891
	}
1892
	if(!GetViaKey(XorKey, ident, 'X', 1, 8, 1)) {
1893
		return 2;
1894
	}
1895
1896
	for (i=0; i<8; i++) {
1897
		pv1 = indata[i];
1898
		Tmp[i] = T1Key[pv1];
1899
	}
1900
	for (i=0; i<8; i++) {
1901
		pv1 = P1Key[i];
1902
		pv2 = Tmp[pv1];
1903
		indata[i]=pv2;
1904
	}
1905
	
1906
	des_set_key(KeyDes1, ks1);
1907
	des(indata, ks1, 1);
1908
	
1909
	for (i=0; i<8; i++) {
1910
		indata[i] ^= XorKey[i];
1911
	}
1912
	
1913
	des_set_key(KeyDes2, ks1);
1914
	des_set_key(KeyDes2+8, ks2);
1915
	des(indata, ks1, 0);
1916
	des(indata, ks2, 1);
1917
	des(indata, ks1, 0);
1918
	
1919
	for (i=0; i<8; i++) {
1920
		indata[i] ^= XorKey[i];
1921
	}
1922
	
1923
	des_set_key(KeyDes1, ks1);
1924
	des(indata, ks1, 0);
1925
1926
	for (i=0; i<8; i++) {
1927
		pv1 = indata[i];
1928
		pv2 = P1Key[i];
1929
		Tmp[pv2] = pv1;
1930
	}
1931
	for (i=0; i<8; i++) {
1932
		pv1 = Tmp[i];
1933
		pv2 = T1Key[pv1];
1934
		indata[i] = pv2;
1935
	}
1936
	return 0;
1937
}
1938
1939
static int8_t Via26Decrypt(uint8_t* source, uint8_t* dw, uint32_t ident, uint8_t desKeyIndex)
1940
{
1941
	uint8_t tmpData[8], C1[8];
1942
	uint8_t *pXorVector;
1943
	int32_t i,j;
1944
1945
	if (ident == 0) {
1946
		return 4;
1947
	}
1948
	if(!GetViaKey(C1, ident, 'C', 1, 8, 1)) {
1949
		return 2;
1950
	}
1951
1952
	for (i=0; i<2; i++) {
1953
		memcpy(tmpData, source+ i*8, 8);
1954
		Via26ProcessDw(tmpData, ident, desKeyIndex);
1955
		if (i!=0) {
1956
			pXorVector = source;
1957
		}
1958
		else {
1959
			pXorVector = &C1[0];
1960
		}
1961
		for (j=0; j<8; j++) {
1962
			dw[i*8+j] = tmpData[j]^pXorVector[j];
1963
		}
1964
	}
1965
	return 0;
1966
}
1967
1968
static void Via3Core(uint8_t *data, uint8_t Off, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key)
1969
{
1970
	uint8_t i;
1971
	uint32_t lR2, lR3, lR4, lR6, lR7;
1972
1973
	switch (ident) {
1974
	case 0x032820: {
1975
		for (i=0; i<4; i++) {
1976
			data[i]^= XorKey[(Off+i) & 0x07];
1977
		}
1978
		lR2 = (data[0]^0xBD)+data[0];
1979
		lR3 = (data[3]^0xEB)+data[3];
1980
		lR2 = (lR2-lR3)^data[2];
1981
		lR3 = ((0x39*data[1])<<2);
1982
		data[4] = (lR2|lR3)+data[2];
1983
		lR3 = ((((data[0]+6)^data[0]) | (data[2]<<1))^0x65)+data[0];
1984
		lR2 = (data[1]^0xED)+data[1];
1985
		lR7 = ((data[3]+0x29)^data[3])*lR2;
1986
		data[5] = lR7+lR3;
1987
		lR2 = ((data[2]^0x33)+data[2]) & 0x0A;
1988
		lR3 = (data[0]+0xAD)^data[0];
1989
		lR3 = lR3+lR2;
1990
		lR2 = data[3]*data[3];
1991
		lR7 = (lR2 | 1) + data[1];
1992
		data[6] = (lR3|lR7)+data[1];
1993
		lR3 = data[1] & 0x07;
1994
		lR2 = (lR3-data[2]) & (data[0] | lR2 |0x01);
1995
		data[7] = lR2+data[3];
1996
		for (i=0; i<4; i++) {
1997
			data[i+4] = T1Key[data[i+4]];
1998
		}
1999
	}
2000
	break;
2001
	case 0x030B00: {
2002
		for (i=0; i<4; i++) {
2003
			data[i]^= XorKey[(Off+i) & 0x07];
2004
		}
2005
		lR6 = (data[3] + 0x6E) ^ data[3];
2006
		lR6 = (lR6*(data[2] << 1)) + 0x17;
2007
		lR3 = (data[1] + 0x77) ^ data[1];
2008
		lR4 = (data[0] + 0xD7) ^ data[0];
2009
		data[4] = ((lR4 & lR3) | lR6) + data[0];
2010
		lR4 = ((data[3] + 0x71) ^ data[3]) ^ 0x90;
2011
		lR6 = (data[1] + 0x1B) ^ data[1];
2012
		lR4 = (lR4*lR6) ^ data[0];
2013
		data[5] = (lR4 ^ (data[2] << 1)) + data[1];
2014
		lR3 = (data[3] * data[3])| 0x01;
2015
		lR4 = (((data[2] ^ 0x35) + data[2]) | lR3) + data[2];
2016
		lR6 = data[1] ^ (data[0] + 0x4A);
2017
		data[6] = lR6 + lR4;
2018
		lR3 = (data[0] * (data[2] << 1)) | data[1];
2019
		lR4 = 0xFE - data[3];
2020
		lR3 = lR4 ^ lR3;
2021
		data[7] = lR3 + data[3];
2022
		for (i=0; i<4; i++) {
2023
			data[4+i] = T1Key[data[4+i]];
2024
		}
2025
	}
2026
	break;
2027
	default:
2028
		break;
2029
	}
2030
}
2031
2032
static void Via3Fct1(uint8_t *data, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key)
2033
{
2034
	uint8_t t;
2035
	Via3Core(data, 0, ident, XorKey, T1Key);
2036
2037
	switch (ident) {
2038
	case 0x032820: {
2039
		t = data[4];
2040
		data[4] = data[7];
2041
		data[7] = t;
2042
	}
2043
	break;
2044
	case 0x030B00: {
2045
		t = data[5];
2046
		data[5] = data[7];
2047
		data[7] = t;
2048
	}
2049
	break;
2050
	default:
2051
		break;
2052
	}
2053
}
2054
2055
static void Via3Fct2(uint8_t *data, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key)
2056
{
2057
	uint8_t t;
2058
	Via3Core(data, 4, ident, XorKey, T1Key);
2059
2060
	switch (ident) {
2061
	case 0x032820: {
2062
		t = data[4];
2063
		data[4] = data[7];
2064
		data[7] = data[5];
2065
		data[5] = data[6];
2066
		data[6] = t;
2067
	}
2068
	break;
2069
	case 0x030B00: {
2070
		t = data[6];
2071
		data[6] = data[7];
2072
		data[7] = t;
2073
	}
2074
	break;
2075
	default:
2076
		break;
2077
	}
2078
}
2079
2080
static int8_t Via3ProcessDw(uint8_t *data, uint32_t ident, uint8_t desKeyIndex)
2081
{
2082
	uint8_t i;
2083
	uint8_t tmp[8], T1Key[300], P1Key[8], KeyDes[16], XorKey[8];
2084
	uint32_t ks1[32], ks2[32];
2085
2086
	if(!GetViaKey(T1Key, ident, 'T', 1, 300, 1)) {
2087
		return 2;
2088
	}
2089
	if(!GetViaKey(P1Key, ident, 'P', 1, 8, 1)) {
2090
		return 2;
2091
	}
2092
	if(!GetViaKey(KeyDes, ident, '0', desKeyIndex, 16, 1)) {
2093
		return 2;
2094
	}
2095
	if(!GetViaKey(XorKey, ident, 'X', 1, 8, 1)) {
2096
		return 2;
2097
	}
2098
2099
	for (i=0; i<4; i++) {
2100
		tmp[i] = data[i+4];
2101
	}
2102
	Via3Fct1(tmp, ident, XorKey, T1Key);
2103
	for (i=0; i<4; i++) {
2104
		tmp[i] = data[i]^tmp[i+4];
2105
	}
2106
	Via3Fct2(tmp, ident, XorKey, T1Key);
2107
	for (i=0; i<4; i++) {
2108
		tmp[i]^= XorKey[i+4];
2109
	}
2110
	for (i=0; i<4; i++) {
2111
		data[i] = data[i+4]^tmp[i+4];
2112
		data[i+4] = tmp[i];
2113
	}
2114
	
2115
	des_set_key(KeyDes, ks1);
2116
	des_set_key(KeyDes+8, ks2);
2117
	
2118
	des(data, ks1, 0);
2119
	des(data, ks2, 1);
2120
	des(data, ks1, 0);
2121
	
2122
	for (i=0; i<4; i++) {
2123
		tmp[i] = data[i+4];
2124
	}
2125
	Via3Fct2(tmp, ident, XorKey, T1Key);
2126
	for (i=0; i<4; i++) {
2127
		tmp[i] = data[i]^tmp[i+4];
2128
	}
2129
	Via3Fct1(tmp, ident, XorKey, T1Key);
2130
	for (i=0; i<4; i++) {
2131
		tmp[i]^= XorKey[i];
2132
	}
2133
	for (i=0; i<4; i++) {
2134
		data[i] = data[i+4]^tmp[i+4];
2135
		data[i+4] = tmp[i];
2136
	}
2137
	return 0;
2138
}
2139
2140
static void Via3FinalMix(uint8_t *dw)
2141
{
2142
	uint8_t tmp[4];
2143
2144
	memcpy(tmp, dw, 4);
2145
	memcpy(dw, dw + 4, 4);
2146
	memcpy(dw + 4, tmp, 4);
2147
2148
	memcpy(tmp, dw + 8, 4);
2149
	memcpy(dw + 8, dw + 12, 4);
2150
	memcpy(dw + 12, tmp, 4);
2151
}
2152
2153
static int8_t Via3Decrypt(uint8_t* source, uint8_t* dw, uint32_t ident, uint8_t desKeyIndex, uint8_t aesKeyIndex, uint8_t aesMode, int8_t doFinalMix)
2154
{
2155
	int8_t aesAfterCore = 0;
2156
	int8_t needsAES = (aesKeyIndex != 0xFF);
2157
	uint8_t tmpData[8], C1[8];
2158
	uint8_t *pXorVector;
2159
	char aesKey[16];
2160
	int32_t i, j;
2161
2162
	if(ident == 0) {
2163
		return 4;
2164
	}
2165
	if(!GetViaKey(C1, ident, 'C', 1, 8, 1)) {
2166
		return 2;
2167
	}
2168
	if(needsAES && !GetViaKey((uint8_t*)aesKey, ident, 'E', aesKeyIndex, 16, 1)) {
2169
		return 2;
2170
	}
2171
	if(aesMode == 0x0D || aesMode == 0x11 || aesMode == 0x15) {
2172
		aesAfterCore = 1;
2173
	}
2174
2175
	if(needsAES && !aesAfterCore) {
2176
		if(aesMode == 0x0F) {
2177
			hdSurEncPhase1_D2_0F_11(source);
2178
			hdSurEncPhase2_D2_0F_11(source);
2179
		}
2180
		else if(aesMode == 0x13) {
2181
			hdSurEncPhase1_D2_13_15(source);
2182
		}
2183
		struct aes_keys aes;
2184
		aes_set_key(&aes, aesKey);
2185
		aes_decrypt(&aes, source, 16);
2186
		if(aesMode == 0x0F) {
2187
			hdSurEncPhase1_D2_0F_11(source);
2188
		}
2189
		else if(aesMode == 0x13) {
2190
			hdSurEncPhase2_D2_13_15(source);
2191
		}
2192
	}
2193
2194
	for(i=0; i<2; i++) {
2195
		memcpy(tmpData, source+i*8, 8);
2196
		Via3ProcessDw(tmpData, ident, desKeyIndex);
2197
		if (i!=0) {
2198
			pXorVector = source;
2199
		}
2200
		else {
2201
			pXorVector = &C1[0];
2202
		}
2203
		for (j=0; j<8; j++) {
2204
			dw[i*8+j] = tmpData[j]^pXorVector[j];
2205
		}
2206
	}
2207
2208
	if(needsAES && aesAfterCore) {
2209
		if(aesMode == 0x11) {
2210
			hdSurEncPhase1_D2_0F_11(dw);
2211
			hdSurEncPhase2_D2_0F_11(dw);
2212
		}
2213
		else if(aesMode == 0x15) {
2214
			hdSurEncPhase1_D2_13_15(dw);
2215
		}
2216
		struct aes_keys aes;
2217
		aes_set_key(&aes, aesKey);
2218
		aes_decrypt(&aes, dw, 16);
2219
		if(aesMode == 0x11) {
2220
			hdSurEncPhase1_D2_0F_11(dw);
2221
		}
2222
		if(aesMode == 0x15) {
2223
			hdSurEncPhase2_D2_13_15(dw);
2224
		}
2225
	}
2226
2227
	if(ident == 0x030B00) {
2228
		if(doFinalMix) {
2229
			Via3FinalMix(dw);
2230
		}
2231
		if(!isValidDCW(dw)) {
2232
			return 6;
2233
		}
2234
	}
2235
	return 0;
2236
}
2237
2238
static int8_t ViaccessECM(uint8_t *ecm, uint8_t *dw)
2239
{
2240
	uint32_t currentIdent = 0;
2241
	uint8_t nanoCmd = 0, nanoLen = 0, version = 0, providerKeyLen = 0, desKeyIndex = 0, aesMode = 0, aesKeyIndex = 0xFF;
2242
	int8_t doFinalMix = 0, result = 1;
2243
	uint16_t i = 0, keySelectPos = 0, ecmLen = GetEcmLen(ecm);
2244
2245
	for (i=4; i+2<ecmLen; ) {
2246
		nanoCmd = ecm[i++];
2247
		nanoLen = ecm[i++];
2248
		if(i+nanoLen > ecmLen) {
2249
			return 1;
2250
		}
2251
2252
		switch (nanoCmd) {
2253
		case 0x40:
2254
			if (nanoLen < 0x03) {
2255
				break;
2256
			}
2257
			version = ecm[i];
2258
			if (nanoLen == 3) {
2259
				currentIdent = ((ecm[i]<<16)|(ecm[i+1]<<8))|(ecm[i+2]&0xF0);
2260
				desKeyIndex  = ecm[i+2]&0x0F;
2261
				keySelectPos = i+3;
2262
			}
2263
			else {
2264
				currentIdent = (ecm[i]<<16)|(ecm[i+1]<<8)|((ecm[i+2]>>4)&0x0F);
2265
				desKeyIndex  = ecm[i+3];
2266
				keySelectPos = i+4;
2267
			}
2268
			providerKeyLen = nanoLen;
2269
			break;
2270
		case 0x90:
2271
			if (nanoLen < 0x03) {
2272
				break;
2273
			}
2274
			version = ecm[i];
2275
			currentIdent = ((ecm[i]<<16)|(ecm[i+1]<<8))|(ecm[i+2]&0xF0);
2276
			desKeyIndex  = ecm[i+2]&0x0F;
2277
			keySelectPos = i+4;
2278
			if((version == 3) && (nanoLen > 3)) {
2279
				desKeyIndex = ecm[i+(nanoLen-4)]&0x0F;
2280
			}
2281
			providerKeyLen = nanoLen;
2282
			break;
2283
		case 0x80:
2284
			nanoLen = 0;
2285
			break;
2286
		case 0xD2:
2287
			if (nanoLen < 0x02) {
2288
				break;
2289
			}
2290
			aesMode = ecm[i];
2291
			aesKeyIndex = ecm[i+1];
2292
			break;
2293
		case 0xDD:
2294
			nanoLen = 0;
2295
			break;
2296
		case 0xEA:
2297
			if (nanoLen < 0x10) {
2298
				break;
2299
			}
2300
2301
			if (version < 2) {
2302
				return Via1Decrypt(ecm, dw, currentIdent, desKeyIndex);
2303
			}
2304
			else if (version == 2) {
2305
				return Via26Decrypt(ecm + i, dw, currentIdent, desKeyIndex);
2306
			}
2307
			else if (version == 3) {
2308
				doFinalMix = 0;
2309
				if (currentIdent == 0x030B00 && providerKeyLen>3) {
2310
					if(keySelectPos+2 >= ecmLen) {
2311
						break;
2312
					}
2313
					if (ecm[keySelectPos] == 0x05 && ecm[keySelectPos+1] == 0x67 && (ecm[keySelectPos+2] == 0x00 || ecm[keySelectPos+2] == 0x01)) {
2314
						if(ecm[keySelectPos+2] == 0x01) {
2315
							doFinalMix = 1;
2316
						}
2317
					}
2318
					else {
2319
						break;
2320
					}
2321
				}
2322
				return Via3Decrypt(ecm + i, dw, currentIdent, desKeyIndex, aesKeyIndex, aesMode, doFinalMix);
2323
			}
2324
			break;
2325
		default:
2326
			break;
2327
		}
2328
		i += nanoLen;
2329
	}
2330
	return result;
2331
}
2332
2333
// Nagra EMU
2334
static int8_t GetNagraKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint8_t isCriticalKey)
2335
{
2336
	char keyStr[EMU_MAX_CHAR_KEYNAME];
2337
	snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
2338
	if(FindKey('N', ident, 0, keyStr, buf, keyName == 'M' ? 64 : 16, isCriticalKey, 0, 0, NULL)) {
2339
		return 1;
2340
	}
2341
2342
	return 0;
2343
}
2344
2345
static int8_t Nagra2Signature(const uint8_t *vkey, const uint8_t *sig, const uint8_t *msg, int32_t len)
2346
{
2347
	uint8_t buff[16];
2348
	uint8_t iv[8];
2349
	int32_t i,j;
2350
2351
	memcpy(buff,vkey,sizeof(buff));
2352
	for(i=0; i+7<len; i+=8) {
2353
		IDEA_KEY_SCHEDULE ek;
2354
		idea_set_encrypt_key(buff, &ek);
2355
		memcpy(buff,buff+8,8);
2356
		memset(iv,0,sizeof(iv));
2357
		idea_cbc_encrypt(msg+i,buff+8,8,&ek,iv,IDEA_ENCRYPT);
2358
		for(j=7; j>=0; j--) {
2359
			buff[j+8]^=msg[i+j];
2360
		}
2361
	}
2362
	buff[8]&=0x7F;
2363
	return (memcmp(sig, buff+8, 8) == 0);
2364
}
2365
2366
static int8_t DecryptNagra2ECM(uint8_t *in, uint8_t *out, const uint8_t *key, int32_t len, const uint8_t *vkey, uint8_t *keyM)
2367
{
2368
	BIGNUM *exp, *mod;
2369
	uint8_t iv[8];
2370
	int32_t i = 0, sign = in[0] & 0x80;
2371
	uint8_t binExp = 3;
2372
	int8_t result = 1;
2373
2374
	exp = BN_new();
2375
	mod = BN_new();
2376
	BN_bin2bn(&binExp, 1, exp);
2377
	BN_bin2bn(keyM, 64, mod);
2378
2379
	if(EmuRSA(out,in+1,64,exp,mod,1)<=0) {
2380
		BN_free(exp);
2381
		BN_free(mod);
2382
		return 0;
2383
	}
2384
	out[63]|=sign;
2385
	if(len>64) {
2386
		memcpy(out+64,in+65,len-64);
2387
	}
2388
2389
	memset(iv,0,sizeof(iv));
2390
	if(in[0]&0x04) {
2391
		uint8_t key1[8], key2[8];
2392
		ReverseMemInOut(key1,&key[0],8);
2393
		ReverseMemInOut(key2,&key[8],8);
2394
2395
		for(i=7; i>=0; i--) {
2396
			ReverseMem(out+8*i,8);
2397
		}
2398
		des_ede2_cbc_decrypt(out, iv, key1, key2, len);
2399
		for(i=7; i>=0; i--) {
2400
			ReverseMem(out+8*i,8);
2401
		}
2402
	}
2403
	else {
2404
		IDEA_KEY_SCHEDULE ek;
2405
		idea_set_encrypt_key(key, &ek);
2406
		idea_cbc_encrypt(out, out, len&~7, &ek, iv, IDEA_DECRYPT);
2407
	}
2408
2409
	ReverseMem(out,64);
2410
	if(result && EmuRSA(out,out,64,exp,mod,0)<=0) {
2411
		result = 0;
2412
	}
2413
	if(result && vkey && !Nagra2Signature(vkey,out,out+8,len-8)) {
2414
		result = 0;
2415
	}
2416
2417
	BN_free(exp);
2418
	BN_free(mod);
2419
	return result;
2420
}
2421
2422
static int8_t Nagra2ECM(uint8_t *ecm, uint8_t *dw)
2423
{
2424
	uint32_t ident, identMask, tmp1, tmp2, tmp3;
2425
	uint8_t cmdLen, ideaKeyNr, *dec, ideaKey[16], vKey[16], m1Key[64], mecmAlgo = 0;
2426
	int8_t useVerifyKey = 0;
2427
	int32_t l=0, s;
2428
	uint16_t i = 0, ecmLen = GetEcmLen(ecm);
2429
2430
	if(ecmLen < 8) {
2431
		return 1;
2432
	}
2433
	cmdLen = ecm[4] - 5;
2434
	ident = (ecm[5] << 8) + ecm[6];
2435
	ideaKeyNr = (ecm[7]&0x10)>>4;
2436
	if(ideaKeyNr) {
2437
		ideaKeyNr = 1;
2438
	}
2439
	if(ident == 1283 || ident == 1285 || ident == 1297) {
2440
		ident = 1281;
2441
	}
2442
	if(cmdLen <= 63 || ecmLen < cmdLen + 10) {
2443
		return 1;
2444
	}
2445
2446
	if(!GetNagraKey(ideaKey, ident, '0', ideaKeyNr, 1)) {
2447
		return 2;
2448
	}
2449
	if(GetNagraKey(vKey, ident, 'V', 0, 0)) {
2450
		useVerifyKey = 1;
2451
	}
2452
	if(!GetNagraKey(m1Key, ident, 'M', 1, 1)) {
2453
		return 2;
2454
	}
2455
	ReverseMem(m1Key, 64);
2456
2457
	dec = (uint8_t*)malloc(sizeof(uint8_t)*cmdLen);
2458
	if(dec == NULL) {
2459
		return 7;
2460
	}
2461
	if(!DecryptNagra2ECM(ecm+9, dec, ideaKey, cmdLen, useVerifyKey?vKey:0, m1Key)) {
2462
		free(dec);
2463
		return 1;
2464
	}
2465
2466
	for(i=(dec[14]&0x10)?16:20; i<cmdLen && l!=3; ) {
2467
		switch(dec[i]) {
2468
		case 0x10:
2469
		case 0x11:
2470
			if(i+10 < cmdLen && dec[i+1] == 0x09) {
2471
				s = (~dec[i])&1;
2472
				mecmAlgo = dec[i+2]&0x60;
2473
				memcpy(dw+(s<<3), &dec[i+3], 8);
2474
				i+=11;
2475
				l|=(s+1);
2476
			}
2477
			else {
2478
				i++;
2479
			}
2480
			break;
2481
		case 0x00:
2482
			i+=2;
2483
			break;
2484
		case 0x30:
2485
		case 0x31:
2486
		case 0x32:
2487
		case 0x33:
2488
		case 0x34:
2489
		case 0x35:
2490
		case 0x36:
2491
		case 0xB0:
2492
			if(i+1 < cmdLen) {
2493
				i+=dec[i+1]+2;
2494
			}
2495
			else {
2496
				i++;
2497
			}
2498
			break;
2499
		default:
2500
			i++;
2501
			continue;
2502
		}
2503
	}
2504
2505
	free(dec);
2506
2507
	if(l!=3) {
2508
		return 1;
2509
	}
2510
	if(mecmAlgo>0) {
2511
		return 1;
2512
	}
2513
2514
	identMask = ident & 0xFF00;
2515
	if (identMask == 0x1100 || identMask == 0x500 || identMask == 0x3100) {
2516
		memcpy(&tmp1, dw, 4);
2517
		memcpy(&tmp2, dw + 4, 4);
2518
		memcpy(&tmp3, dw + 12, 4);
2519
		memcpy(dw, dw + 8, 4);
2520
		memcpy(dw + 4, &tmp3, 4);
2521
		memcpy(dw + 8, &tmp1, 4);
2522
		memcpy(dw + 12, &tmp2, 4);
2523
	}
2524
	return 0;
2525
}
2526
2527
// Irdeto EMU
2528
static int8_t GetIrdetoKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint8_t isCriticalKey, uint32_t *keyRef)
2529
{
2530
	char keyStr[EMU_MAX_CHAR_KEYNAME];
2531
	
2532
	if(*keyRef > 0xFF)
2533
	{
2534
		return 0;
2535
	}
2536
	
2537
	snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
2538
	if(FindKey('I', ident, 0, keyStr, buf, 16, *keyRef > 0 ? 0 : isCriticalKey, *keyRef, 0, NULL)) {
2539
		(*keyRef)++;
2540
		return 1;
2541
	}
2542
2543
	return 0;
2544
}
2545
2546
static void Irdeto2Encrypt(uint8_t *data, const uint8_t *seed, const uint8_t *key, int32_t len)
2547
{
2548
	const uint8_t *tmp = seed;;
2549
	int32_t i;
2550
	uint32_t ks1[32], ks2[32];
2551
2552
	des_set_key(key, ks1);
2553
	des_set_key(key+8, ks2);
2554
	
2555
	len&=~7;
2556
2557
	for(i=0; i+7<len; i+=8) {
2558
		xxor(&data[i],8,&data[i],tmp);
2559
		tmp=&data[i];	
2560
		des(&data[i], ks1, 1);
2561
		des(&data[i], ks2, 0);
2562
		des(&data[i], ks1, 1);
2563
	}
2564
}
2565
2566
static void Irdeto2Decrypt(uint8_t *data, const uint8_t *seed, const uint8_t *key, int32_t len)
2567
{
2568
	uint8_t buf[2][8];
2569
	int32_t i, n=0;
2570
	uint32_t ks1[32], ks2[32];
2571
	
2572
	des_set_key(key, ks1);
2573
	des_set_key(key+8, ks2);
2574
	
2575
	len&=~7;
2576
2577
	memcpy(buf[n],seed,8);
2578
	for(i=0; i+7<len; i+=8,data+=8,n^=1) {
2579
		memcpy(buf[1-n],data,8);
2580
		des(data, ks1, 0);
2581
		des(data, ks2, 1);
2582
		des(data, ks1, 0);
2583
		xxor(data,8,data,buf[n]);
2584
	}
2585
}
2586
2587
static int8_t Irdeto2CalculateHash(const uint8_t *key, const uint8_t *iv, const uint8_t *data, int32_t len)
2588
{
2589
	uint8_t cbuff[8];
2590
	int32_t l, y;
2591
	uint32_t ks1[32], ks2[32];
2592
	
2593
	des_set_key(key, ks1);
2594
	des_set_key(key+8, ks2);
2595
	
2596
	memset(cbuff,0,sizeof(cbuff));
2597
	len-=8;
2598
2599
	for(y=0; y<len; y+=8) {
2600
		if(y<len-8) {
2601
			xxor(cbuff,8,cbuff,&data[y]);
2602
		}
2603
		else {
2604
			l=len-y;
2605
			xxor(cbuff,l,cbuff,&data[y]);
2606
			xxor(cbuff+l,8-l,cbuff+l,iv+8);
2607
		}
2608
		
2609
		des(cbuff, ks1, 1);
2610
		des(cbuff, ks2, 0);
2611
		des(cbuff, ks1, 1);
2612
	}
2613
2614
	return memcmp(cbuff, &data[len], 8) == 0;
2615
}
2616
2617
static int8_t Irdeto2ECM(uint16_t caid, uint8_t *oecm, uint8_t *dw)
2618
{
2619
	uint8_t keyNr=0, length, end, key[16], okeySeed[16], keySeed[16], keyIV[16], tmp[16];
2620
	uint32_t i, l, ident;
2621
	uint32_t key0Ref, keySeedRef, keyIVRef;
2622
	uint8_t ecmCopy[EMU_MAX_ECM_LEN], *ecm = oecm;
2623
	uint16_t ecmLen = GetEcmLen(ecm);
2624
2625
	if(ecmLen < 12) {
2626
		return 1;
2627
	}
2628
2629
	length = ecm[11];
2630
	keyNr = ecm[9];
2631
	ident = ecm[8] | caid << 8;
2632
2633
	if(ecmLen < length+12) {
2634
		return 1;
2635
	}
2636
2637
	key0Ref = 0;
2638
	while(GetIrdetoKey(key, ident, '0', keyNr, 1, &key0Ref)) {
2639
		keySeedRef = 0;
2640
		while(GetIrdetoKey(okeySeed, ident, 'M', 1, 1, &keySeedRef)) {
2641
			keyIVRef = 0;
2642
			while(GetIrdetoKey(keyIV, ident, 'M', 2, 1, &keyIVRef)) {
2643
				
2644
				memcpy(keySeed, okeySeed, 16);
2645
				memcpy(ecmCopy, oecm, ecmLen);
2646
				ecm = ecmCopy;
2647
				
2648
				memset(tmp, 0, 16);
2649
				Irdeto2Encrypt(keySeed, tmp, key, 16);
2650
				ecm+=12;
2651
				Irdeto2Decrypt(ecm, keyIV, keySeed, length);
2652
				i=(ecm[0]&7)+1;
2653
				end = length-8 < 0 ? 0 : length-8;
2654
				
2655
				while(i<end) {
2656
					l = ecm[i+1] ? (ecm[i+1]&0x3F)+2 : 1;
2657
					switch(ecm[i]) {
2658
					case 0x10:
2659
					case 0x50:
2660
						if(l == 0x13 && i <= length-8-l) {
2661
							Irdeto2Decrypt(&ecm[i+3], keyIV, key, 16);
2662
						}
2663
						break;
2664
					case 0x78:
2665
						if(l == 0x14 && i <= length-8-l) {
2666
							Irdeto2Decrypt(&ecm[i+4], keyIV, key, 16);
2667
						}
2668
						break;
2669
					}
2670
					i+=l;
2671
				}
2672
				
2673
				i=(ecm[0]&7)+1;
2674
				if(Irdeto2CalculateHash(keySeed, keyIV, ecm-6, length+6)) {
2675
					while(i<end) {
2676
						l = ecm[i+1] ? (ecm[i+1]&0x3F)+2 : 1;
2677
						switch(ecm[i]) {
2678
						case 0x78:
2679
							if(l == 0x14 && i <= length-8-l) {
2680
								memcpy(dw, &ecm[i+4], 16);
2681
								return 0;
2682
							}
2683
						}
2684
						i+=l;
2685
					}
2686
				}
2687
			}
2688
			if(keyIVRef == 0) {
2689
				return 2;
2690
			}
2691
		}
2692
		if(keySeedRef == 0) {
2693
			return 2;
2694
		}
2695
	}
2696
	if(key0Ref == 0) {
2697
		return 2;
2698
	}
2699
2700
	return 1;
2701
}
2702
2703
// BISS EMU
2704
static void BissUnifyOrbitals(uint32_t *namespace)
2705
{
2706
	// Unify orbitals to produce same namespace among users
2707
	// Set positions according to http://satellites-xml.org
2708
2709
	uint16_t pos = (*namespace & 0x0FFF0000) >> 16;
2710
2711
	switch (pos)
2712
	{
2713
		case 29: // Rascom QAF 1R
2714
		case 31: // Eutelsat 3B
2715
		{
2716
			pos = 30;
2717
			break;
2718
		}
2719
2720
		case 49:
2721
		case 50: // SES 5
2722
		{
2723
			pos = 48; // Astra 4A
2724
			break;
2725
		}
2726
2727
		case 215:
2728
		{
2729
			pos = 216; // Eutelsat 21B
2730
			break;
2731
		}
2732
2733
		case 285: // Astra 2E
2734
		{
2735
			pos = 282; // Astra 2F/2G
2736
			break;
2737
		}
2738
2739
		case 328: // Intelsat 28
2740
		case 329:
2741
		case 331: // Eutelsat 33C
2742
		{
2743
			pos = 330;
2744
			break;
2745
		}
2746
2747
		case 359: // Eutelsat 36B
2748
		case 361: // Express AMU1
2749
		{
2750
			pos = 360;
2751
			break;
2752
		}
2753
2754
		case 451: // Intelsat 904
2755
		{
2756
			pos = 450; // Intelsat 12
2757
			break;
2758
		}
2759
2760
		case 550:
2761
		case 551: // G-Sat 8/16
2762
		{
2763
			pos = 549; // Yamal 402
2764
			break;
2765
		}
2766
2767
		case 748:
2768
		case 749: // ABS 2A
2769
		{
2770
			pos = 750;
2771
			break;
2772
		}
2773
2774
		case 848: // Horizons 2
2775
		case 852: // Intelsat 15
2776
		{
2777
			pos = 850;
2778
			break;
2779
		}
2780
2781
		case 914: // Mesasat 3a
2782
		{
2783
			pos = 915; // Mesasat 3/3b
2784
			break;
2785
		}
2786
2787
		case 934: // G-Sat 17
2788
		case 936: // Insat 4B
2789
		{
2790
			pos = 935; // G-Sat 15
2791
			break;
2792
		}
2793
2794
		case 3600 - 911: // Nimiq 6
2795
		{
2796
			pos = 3600 - 910; // Galaxy 17
2797
		}
2798
2799
		case 3600 - 870: // SES 2
2800
		case 3600 - 872: // TKSat 1
2801
		{
2802
			pos = 3600 - 871;
2803
			break;
2804
		}
2805
2806
		case 3600 - 432: // Sky Brasil 1
2807
		case 3600 - 430: // Intelsat 11
2808
		{
2809
			pos = 3600 - 431;
2810
			break;
2811
		}
2812
2813
		case 3600 - 376: // Telstar 11N
2814
		case 3600 - 374: // NSS 10
2815
		{
2816
			pos = 3600 - 375;
2817
			break;
2818
		}
2819
2820
		case 3600 - 359: // Hispasat 36W-1
2821
		{
2822
			pos = 3600 - 360; // Eutelsat 36 West A
2823
			break;
2824
		}
2825
2826
		case 3600 - 81: // Eutelsat 8 West B
2827
		{
2828
			pos = 3600 - 80;
2829
			break;
2830
		}
2831
2832
		case 3600 - 73: // Eutelsat 7 West A
2833
		case 3600 - 72:
2834
		case 3600 - 71:
2835
		{
2836
			pos = 3600 - 70; // Nilesat 201
2837
			break;
2838
		}
2839
2840
		case 3600 - 10: // Intelsat 10-02
2841
		case 3600 - 9: // Thor 6
2842
		case 3600 - 7: // Thor 7
2843
		case 3600 - 6: // Thor 7
2844
		{
2845
			pos = 3600 - 8; // Thor 5
2846
			break;
2847
		}
2848
	}
2849
2850
	*namespace = (*namespace & 0xF000FFFF) | (pos << 16);
2851
}
2852
2853
static void BissAnnotate(char *buf, uint8_t len, const uint8_t *ecm, uint16_t ecmLen, uint32_t hash, int8_t isNamespaceHash, int8_t datecoded)
2854
{
2855
	// Extract useful information to append to the "Example key ..." message.
2856
	//
2857
	// For feeds, the orbital position & frequency are usually embedded in the namespace.
2858
	// See https://github.com/openatv/enigma2/blob/master/lib/dvb/frontend.cpp#L496
2859
	// hash = (sat.orbital_position << 16);
2860
	// hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15);
2861
	//
2862
	// If the onid & tsid appear to be a unique DVB identifier, enigma2 strips the frequency
2863
	// from our namespace. See https://github.com/openatv/enigma2/blob/master/lib/dvb/scan.cpp#L59
2864
	// In that case, our annotation contains the onid:tsid:sid triplet in lieu of frequency.
2865
	//
2866
	// For the universal case, we print the number of elementary stream pids & pmtpid.
2867
	// The sid and current time are included for all. Examples:
2868
	//
2869
	// F 1A2B3C4D 00000000 XXXXXXXXXXXXXXXX ; 110.5W 12345H sid:0001 added: 2017-10-17 @ 13:14:15 // namespace
2870
	// F 1A2B3C4D 20180123 XXXXXXXXXXXXXXXX ;  33.5E  ABCD:9876:1234 added: 2017-10-17 @ 13:14:15 // stripped namespace
2871
	// F 1A2B3C4D 20180123 XXXXXXXXXXXXXXXX ; av:5 pmt:0134 sid:0001 added: 2017-10-17 @ 13:14:15 // universal
2872
2873
	uint8_t pidcount;
2874
	uint16_t frequency, degrees, pmtpid, srvid, tsid, onid;
2875
	uint32_t ens;
2876
	char compass, polarisation, timeStr1[9], timeStr2[19];
2877
2878
	if (datecoded)
2879
	{
2880
		Date2Str(timeStr1, sizeof(timeStr1), 4, 3);
2881
	}
2882
	else
2883
	{
2884
		snprintf(timeStr1, sizeof(timeStr1), "00000000");
2885
	}
2886
2887
	Date2Str(timeStr2, sizeof(timeStr2), 0, 2);
2888
2889
	if (isNamespaceHash) // Namespace hash
2890
	{
2891
		ens = b2i(4, ecm + ecmLen - 4); // Namespace will be the last 4 bytes of the ecm
2892
		degrees = (ens >> 16) & 0x0FFF; // Remove not-a-pid flag
2893
2894
		if (degrees > 1800)
2895
		{
2896
			degrees = 3600 - degrees;
2897
			compass = 'W';
2898
		}
2899
		else
2900
		{
2901
			compass = 'E';
2902
		}
2903
2904
		if (0 == (ens & 0xFFFF)) // Stripped namespace hash
2905
		{
2906
			srvid = b2i(2, ecm + 3);
2907
			tsid = b2i(2, ecm + ecmLen - 8);
2908
			onid = b2i(2, ecm + ecmLen - 6);
2909
			// Printing degree sign "\u00B0" requires c99 standard
2910
			snprintf(buf, len, "F %08X %s XXXXXXXXXXXXXXXX ; %5.1f%c  %04X:%04X:%04X added: %s",
2911
								hash, timeStr1, degrees / 10.0, compass, onid, tsid, srvid, timeStr2);
2912
		}
2913
		else // Full namespace hash
2914
		{
2915
			srvid = b2i(2, ecm + 3);
2916
			frequency = ens & 0x7FFF; // Remove polarity bit
2917
			polarisation = ens & 0x8000 ? 'V' : 'H';
2918
			// Printing degree sign "\u00B0" requires c99 standard
2919
			snprintf(buf, len, "F %08X %s XXXXXXXXXXXXXXXX ; %5.1f%c %5d%c sid:%04X added: %s",
2920
								hash, timeStr1, degrees / 10.0, compass, frequency, polarisation, srvid, timeStr2);
2921
		}
2922
	}
2923
	else // Universal hash
2924
	{
2925
		srvid = b2i(2, ecm + 3);
2926
		pmtpid = b2i(2, ecm + 5);
2927
		pidcount = (ecmLen - 15) / 2; // video + audio pids count
2928
		snprintf(buf, len, "F %08X %s XXXXXXXXXXXXXXXX ; av:%d pmt:%04X sid:%04X added: %s",
2929
							hash, timeStr1, pidcount, pmtpid, srvid, timeStr2);
2930
	}
2931
}
2932
2933
static int8_t BissIsCommonHash(uint32_t hash)
2934
{
2935
	// Check universal hash against a number of commnon universal
2936
	// hashes in order to warn users about potential key clashes
2937
2938
	switch (hash)
2939
	{
2940
		case 0xBAFCD9FD: // 0001 0020 0200 1010 1020 (most common hash)
2941
			return 1;
2942
		case 0xA6A4FBD4: // 0001 0800 0200 1010 1020
2943
			return 1;
2944
		case 0xEFAB7A4D: // 0001 0800 1010 1020 0200
2945
			return 1;
2946
		case 0x83FA15D1: // 0001 0020 0134 0100 0101
2947
			return 1;
2948
		case 0x58934C38: // 0001 0800 1010 1020 1030 0200
2949
			return 1;
2950
		case 0x2C3CEC17: // 0001 0020 0134 0100
2951
			return 1;
2952
		case 0x73DF7F7E: // 0001 0020 0200 1010 1020 1030
2953
			return 1;
2954
		case 0xAFA85BC8: // 0001 0020 0021 0022 0023
2955
			return 1;
2956
		case 0x8C51F31D: // 0001 0800 0200 1010 1020 1030 1040
2957
			return 1;
2958
		case 0xE2F9BD29: // 0001 0800 0200 1010 1020 1030
2959
			return 1;
2960
		case 0xB9EBE0FF: // 0001 0100 0200 1010 1020 (less common hash)
2961
			return 1;
2962
		default:
2963
			return 0;
2964
	}
2965
}
2966
2967
static int8_t BissIsValidNamespace(uint32_t namespace)
2968
{
2969
	// Note to developers:
2970
	// If we ever have a satellite at 0.0E, edit to allow stripped namespace
2971
	// '0xA0000000' with an additional test on tsid and onid being != 0
2972
2973
	uint16_t orbital, frequency;
2974
2975
	orbital = (namespace >> 16) & 0x0FFF;
2976
	frequency = namespace & 0x7FFF;
2977
2978
	if ((namespace & 0xA0000000) != 0xA0000000) return 0;   // Value isn't flagged as namespace
2979
	if (namespace == 0xA0000000) return 0;                  // Empty namespace
2980
	if (orbital > 3599) return 0;                           // Allow only DVB-S
2981
	if (frequency == 0) return 1;                           // Stripped namespace
2982
	if (frequency >= 3400 && frequency <= 4200) return 1;   // Super extended C band
2983
	if (frequency >= 10700 && frequency <= 12750) return 1; // Ku band Europe
2984
2985
	return 0;
2986
}
2987
2988
static int8_t BissGetKey(uint32_t provider, uint8_t *key, int8_t dateCoded, int8_t printMsg)
2989
{
2990
	// If date-coded keys are enabled in the webif, this function evaluates the expiration date
2991
	// of the keys found. Expired keys are not sent to BissECM(). If date-coded keys are disabled,
2992
	// then all keys found are sent without any evaluation. It takes the "provider" as input and
2993
	// outputs the "key". Returns 0 (Key not found, or expired) or 1 (Key found).
2994
2995
	// printMsg: 0 => No message
2996
	// printMsg: 1 => Print message only if key is found
2997
	// printMsg: 2 => Always print message, regardless if key is found or not
2998
2999
	char keyExpDate[9] = "00000000";
3000
3001
	if (FindKey('F', provider, 0, keyExpDate, key, 8, 0, 0, 0, NULL)) // Key found
3002
	{
3003
		if (dateCoded) // Date-coded keys are enabled, evaluate expiration date
3004
		{
3005
			char currentDate[9];
3006
			Date2Str(currentDate, sizeof(currentDate), 0, 3);
3007
3008
			if (strncmp("00000000", keyExpDate, 9) == 0 || strncmp(currentDate, keyExpDate, 9) < 0) // Evergreen or not expired
3009
			{
3010
				if (printMsg == 1 || printMsg == 2) cs_log("Key found: F %08X %s", provider, keyExpDate);
3011
				return 1;
3012
			}
3013
			else // Key expired
3014
			{
3015
				key = NULL; // Make sure we don't send any expired key
3016
				if (printMsg == 2) cs_log("Key expired: F %08X %s", provider, keyExpDate);
3017
				return 0;
3018
			}
3019
		}
3020
		else // Date-coded keys are disabled, don't evaluate expiration date
3021
		{
3022
			if (printMsg == 1 || printMsg == 2) cs_log("Key found: F %08X %s", provider, keyExpDate);
3023
			return 1;
3024
		}
3025
	}
3026
	else // Key not found
3027
	{
3028
		if (printMsg == 2) cs_log("Key not found: F %08X", provider);
3029
		return 0;
3030
	}
3031
}
3032
3033
static int8_t BissECM(struct s_reader *rdr, const uint8_t *ecm, int16_t ecmDataLen, uint8_t *dw, uint16_t srvid, uint16_t ecmpid)
3034
{
3035
	// Oscam's fake ecm consists of [sid] [pmtpid] [pid1] [pid2] ... [pidx] [tsid] [onid] [namespace]
3036
	//
3037
	// On enigma boxes tsid, onid and namespace should be non zero, while on non-enigma
3038
	// boxes they are usually all zero.
3039
	// The emulator creates a unique channel hash using srvid and enigma namespace or
3040
	// srvid, tsid, onid and namespace (in case of namespace without frequency) and
3041
	// another weaker (not unique) hash based on every pid of the channel. This universal
3042
	// hash should be available on all types of stbs (enigma and non-enigma).
3043
3044
	// Flags inside [namespace]
3045
	//
3046
	// emu r748- : no namespace, no flag
3047
	// emu r749  : 0x80000000 (full namespase), 0xC0000000 (stripped namespace, injected with tsid^onid^ecmpid^0x1FFF)
3048
	// emu r752+ : 0xA0000000 (pure namespace, either full, stripped, or null)
3049
3050
	// Key searches are made in order:
3051
	// Highest priority / tightest test first
3052
	// Lowest priority / loosest test last
3053
	//
3054
	// 1st: namespace hash (only on enigma boxes)
3055
	// 2nd: universal hash (all box types with emu r752+)
3056
	// 3rd: valid tsid, onid combination
3057
	// 4th: faulty ecmpid (other than 0x1FFF)
3058
	// 5th: reverse order pid (audio, video, pmt pids)
3059
	// 6th: standard BISS ecmpid (0x1FFF)
3060
	// 7th: default "All Feeds" key
3061
3062
	// If enabled in the webif, a date based key search can be performed. If the expiration
3063
	// date has passed, the key is not sent from BissGetKey(). This search method is only
3064
	// used in the namespace hash, universal hash and the default "All Feeds" key.
3065
3066
	uint8_t ecmCopy[EMU_MAX_ECM_LEN];
3067
	uint16_t ecmLen = 0, pid = 0;
3068
	uint32_t i, ens = 0, hash = 0;
3069
	char tmpBuffer1[17], tmpBuffer2[90] = "0", tmpBuffer3[90] = "0";
3070
3071
	if (ecmDataLen >= 3)
3072
	{
3073
		ecmLen = GetEcmLen(ecm);
3074
	}
3075
3076
	// First try using the unique namespace hash (enigma only)
3077
	if (ecmLen >= 13 && ecmLen <= ecmDataLen) // ecmLen >= 13, allow patching the ecmLen for r749 ecms
3078
	{
3079
		memcpy(ecmCopy, ecm, ecmLen);
3080
		ens = b2i(4, ecm + ecmLen - 4); // Namespace will be the last 4 bytes
3081
3082
		if (BissIsValidNamespace(ens)) // An r752+ extended ecm with valid namespace
3083
		{
3084
			BissUnifyOrbitals(&ens);
3085
			i2b_buf(4, ens, ecmCopy + ecmLen - 4);
3086
3087
			for (i = 0; i < 5; i++) // Find key matching hash made with frequency modified to: f+0, then f-1, f+1, f-2, lastly f+2
3088
			{
3089
				ecmCopy[ecmLen - 1] = (i & 1) ? ecmCopy[ecmLen - 1] - i : ecmCopy[ecmLen - 1] + i; // frequency +/- 1, 2 MHz
3090
3091
				if (0 != (ens & 0xFFFF)) // Full namespace - Calculate hash with srvid and namespace only
3092
				{
3093
					i2b_buf(2, srvid, ecmCopy + ecmLen - 6); // Put [srvid] right before [namespace]
3094
					hash = crc32(0x2600, ecmCopy + ecmLen - 6, 6);
3095
				}
3096
				else // Namespace without frequency - Calculate hash with srvid, tsid, onid and namespace
3097
				{
3098
					i2b_buf(2, srvid, ecmCopy + ecmLen - 10); // Put [srvid] right before [tsid] [onid] [namespace] sequence
3099
					hash = crc32(0x2600, ecmCopy + ecmLen - 10, 10);
3100
				}
3101
3102
				if (BissGetKey(hash, dw, rdr->emu_datecodedenabled, i == 0 ? 2 : 1)) // Do not print "key not found" for frequency off by 1, 2
3103
				{
3104
					memcpy(dw + 8, dw, 8);
3105
					return 0;
3106
				}
3107
3108
				if (i == 0) // No key found matching our hash: create example SoftCam.Key BISS line for the live log
3109
				{
3110
					BissAnnotate(tmpBuffer2, sizeof(tmpBuffer2), ecmCopy, ecmLen, hash, 1, rdr->emu_datecodedenabled);
3111
				}
3112
3113
				if (0 == (ens & 0xFFFF)) // Namespace without frequency - Do not iterate
3114
				{
3115
					break;
3116
				}
3117
			}
3118
		}
3119
3120
		if ((ens & 0xA0000000) == 0x80000000) // r749 ecms only (exclude r752+ ecms)
3121
		{
3122
			cs_log("Hey! Network buddy, you need to upgrade your OSCam-Emu");
3123
			ecmCopy[ecmLen] = 0xA0; // Patch ecm to look like r752+
3124
			ecmLen += 4;
3125
			ecmDataLen += 4;
3126
		}
3127
	}
3128
3129
	// Try using the universal channel hash (namespace not available)
3130
	if (ecmLen >= 17 && ecmLen <= ecmDataLen) // ecmLen >= 17, length of r749 ecms has been patched to match r752+ ecms
3131
	{
3132
		ens = b2i(4, ecmCopy + ecmLen - 4); // Namespace will be last 4 bytes
3133
3134
		if ((ens & 0xE0000000) == 0xA0000000) // We have an r752+ style ecm which contains pmtpid
3135
		{
3136
			memcpy(ecmCopy, ecm, ecmLen - 8); // Make a new ecmCopy from the original ecm as the old ecmCopy may be altered in namespace hash (skip [tsid] [onid] [namespace])
3137
			hash = crc32(0x2600, ecmCopy + 3, ecmLen - 3 - 8); // ecmCopy doesn't have [tsid] [onid] [namespace] part
3138
3139
			if (BissGetKey(hash, dw, rdr->emu_datecodedenabled, 2)) // Key found
3140
			{
3141
				memcpy(dw + 8, dw, 8);
3142
				return 0;
3143
			}
3144
			
3145
			// No key found matching our hash: create example SoftCam.Key BISS line for the live log
3146
			BissAnnotate(tmpBuffer3, sizeof(tmpBuffer3), ecmCopy, ecmLen, hash, 0, rdr->emu_datecodedenabled);
3147
		}
3148
	}
3149
3150
	// Try using only [tsid][onid] (useful when many channels on a transpoder use the same key)
3151
	if (ecmLen >= 17 && ecmLen <= ecmDataLen) // ecmLen >= 17, length of r749 ecms has been patched to match r752+ ecms
3152
	{
3153
		ens = b2i(4, ecmCopy + ecmLen - 4); // Namespace will be last 4 bytes
3154
3155
		// We have an r752+ style ecm with stripped namespace, thus a valid [tsid][onid] combo to use as provider
3156
		if ((ens & 0xE000FFFF) == 0xA0000000 && BissGetKey(b2i(4, ecm + ecmLen - 8), dw, 0, 2))
3157
		{
3158
			memcpy(dw + 8, dw, 8);
3159
			return 0;
3160
		}
3161
3162
		if ((ens & 0xE0000000) == 0xA0000000) // Strip [tsid] [onid] [namespace] on r752+ ecms
3163
		{
3164
			ecmLen -= 8;
3165
			ecmDataLen -= 8;
3166
		}
3167
	}
3168
3169
	// Try using ecmpid if it seems to be faulty (should be 0x1FFF always for BISS)
3170
	if (ecmpid != 0x1FFF && ecmpid != 0)
3171
	{
3172
		if (BissGetKey((srvid << 16) | ecmpid, dw, 0, 2))
3173
		{
3174
			memcpy(dw + 8, dw, 8);
3175
			return 0;
3176
		}
3177
	}
3178
3179
	// Try to get the pid from oscam's fake ecm (only search [pid1] [pid2] ... [pidx] to be compatible with emu r748-)
3180
	if (ecmLen >= 7 && ecmLen <= ecmDataLen) // Use >= for radio channels with just one (audio) pid
3181
	{
3182
		// Reverse search order: last pid in list first
3183
		// Better identifies channels where they share identical video pid but have variable counts of audio pids
3184
		for (i = ecmLen - 2; i >= 5; i -= 2)
3185
		{
3186
			pid = b2i(2, ecm + i);
3187
3188
			if (BissGetKey((srvid << 16) | pid, dw, 0, 2))
3189
			{
3190
				memcpy(dw + 8, dw, 8);
3191
				return 0;
3192
			}
3193
		}
3194
	}
3195
3196
	// Try using the standard BISS ecm pid
3197
	if (ecmpid == 0x1FFF || ecmpid == 0)
3198
	{
3199
		if (BissGetKey((srvid << 16) | 0x1FFF, dw, 0, 2))
3200
		{
3201
			memcpy(dw + 8, dw, 8);
3202
			return 0;
3203
		}
3204
	}
3205
3206
	// Default BISS key for events with many feeds sharing same key
3207
	if (ecmpid != 0 && BissGetKey(0xA11FEED5, dw, rdr->emu_datecodedenabled, 2)) // Limit to local ecms, block netwotk ecms
3208
	{
3209
		memcpy(dw + 8, dw, 8);
3210
		cs_hexdump(0, dw, 8, tmpBuffer1, sizeof(tmpBuffer1));
3211
		cs_log("No specific match found. Using 'All Feeds' key: %s", tmpBuffer1);
3212
		return 0;
3213
	}
3214
3215
	// Print example key lines for available hash search methods, if no key is found
3216
	if (strncmp(tmpBuffer2, "0", 2)) cs_log("Example key based on namespace hash: %s", tmpBuffer2);
3217
	if (strncmp(tmpBuffer3, "0", 2)) cs_log("Example key based on universal hash: %s", tmpBuffer3);
3218
3219
	// Check if universal hash is common and warn user
3220
	if (BissIsCommonHash(hash)) cs_log("Feed has commonly used pids, universal hash clashes in SoftCam.Key are likely!");
3221
3222
	return 2;
3223
}
3224
3225
// PowerVu Emu
3226
static uint8_t PowervuCrc8Calc(uint8_t *data, int len)
3227
{
3228
	int i;
3229
	uint8_t crc = 0x00;
3230
	uint8_t crcTable[256] = {0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
3231
							 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
3232
							 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
3233
							 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
3234
							 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
3235
							 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
3236
							 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
3237
							 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
3238
							 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
3239
							 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
3240
							 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
3241
							 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
3242
							 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
3243
							 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
3244
							 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
3245
							 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3};
3246
	
3247
	for(i = 0; i < len; i++)
3248
	{
3249
		crc = crcTable[data[i] ^ crc];
3250
	}
3251
	
3252
	return crc;
3253
}
3254
3255
static void PowervuPadData(uint8_t *data, int len, uint8_t *dataPadded)
3256
{
3257
	int i;
3258
	uint8_t pad[] = {0x01, 0x02, 0x22, 0x04, 0x20, 0x2A, 0x1F, 0x03, 0x04, 0x06, 0x02, 0x0C, 0x2B, 0x2B, 0x01, 0x7B};
3259
	
3260
	for(i = 0; i < len; i++)
3261
	{
3262
		dataPadded[i] = data[i];
3263
	}
3264
	
3265
	dataPadded[len] = 0x01;
3266
	
3267
	for(i = len + 1; i < 0x2F; i++)
3268
	{
3269
		dataPadded[i] = 0x00;
3270
	}
3271
	
3272
	dataPadded[0x2F] = len;
3273
	
3274
	for(i = 0; i < 0x10; i++)
3275
	{
3276
		dataPadded[0x30 + i] = pad[i];
3277
	}
3278
}
3279
3280
static void PowervuHashMode01CustomMD5(uint8_t *data, uint8_t *hash)
3281
{
3282
	int i, j, s;
3283
	uint32_t a, b, c, d, f, g;
3284
	
3285
	uint32_t T[] = {0x783E16F6, 0xC267AC13, 0xA2B17F12, 0x6B8A31A4, 0xF910654D, 0xB702DBCB, 0x266CEF60, 0x5145E47C,
3286
					0xB92E00D6, 0xE80A4A64, 0x8A07FA77, 0xBA7D89A9, 0xEBED8022, 0x653AAF2B, 0xF118B03B, 0x6CC16544,
3287
					0x96EB6583, 0xF4E27E35, 0x1ABB119E, 0x068D3EF2, 0xDAEAA8A5, 0x3C312A3D, 0x59538388, 0xA100772F,
3288
					0xAB0165CE, 0x979959E7, 0x5DD8F53D, 0x189662BA, 0xFD021A9C, 0x6BC2D338, 0x1EFF667E, 0x40C66888,
3289
					0x6E9F07FF, 0x0CEF442F, 0x82D20190, 0x4E8CAEAC, 0x0F7CB305, 0x2E73FBE7, 0x1CE884A2, 0x7A60BD52,
3290
					0xC348B30D, 0x081CE3AA, 0xA12220E7, 0x38C7EC79, 0xCBD8DD3A, 0x62B4FBA5, 0xAD2A63DB, 0xE4D0852E,
3291
					0x53DE980F, 0x9C8DDA59, 0xA6B4CEDE, 0xB48A7692, 0x0E2C46A4, 0xEB9367CB, 0x165D72EE, 0x75532B45,
3292
					0xB9CA8E97, 0x08C8837B, 0x966F917B, 0x527515B4, 0xF27A5E5D, 0xB71E6267, 0x7603D7E6, 0x9837DD69}; // CUSTOM T
3293
	
3294
	uint8_t r[] = {0x06, 0x0A, 0x0F, 0x15, 0x05, 0x09, 0x0E, 0x14, 0x04, 0x0B, 0x10, 0x17, 0x07, 0x0C, 0x11, 0x16}; // STANDARD REORDERED
3295
	
3296
	uint8_t tIdxInit[] = {0, 1, 5, 0}; // STANDARD
3297
	uint8_t tIdxIncr[] = {1, 5, 3, 7}; // STANDARD
3298
	
3299
	uint32_t h[] = {0xEAD81D2E, 0xCE4DC6E9, 0xF9B5C301, 0x10325476}; // CUSTOM h0, h1, h2  STANDARD h3
3300
	uint32_t dataLongs[0x10];
3301
	
3302
	for(i = 0; i < 0x10; i++)
3303
	{
3304
		dataLongs[i] = (data[4 * i + 0] << 0) + (data[4 * i + 1] << 8) + (data[4 * i + 2] << 16) + (data[4 * i + 3] << 24);
3305
	}
3306
	
3307
	a = h[0];
3308
	b = h[1];
3309
	c = h[2];
3310
	d = h[3];
3311
	
3312
	for(i = 0; i < 4; i++)
3313
	{
3314
		g = tIdxInit[i];
3315
		
3316
		for(j = 0; j < 16; j++)
3317
		{
3318
			if(i == 0)
3319
			{
3320
				f = (b & c) | (~b & d);
3321
			}
3322
			else if(i == 1)
3323
			{
3324
				f = (b & d) | (~d & c);
3325
			}
3326
			else if(i == 2)
3327
			{
3328
				f = (b ^ c ^ d);
3329
			}
3330
			else if (i == 3)
3331
			{
3332
				f = (~d | b) ^ c;
3333
			}
3334
			
3335
			f = dataLongs[g] + a + T[16 * i + j] + f;
3336
			
3337
			s = r[4 * i + (j & 3)];
3338
			f = (f << s) | (f >> (32 - s));
3339
			
3340
			a = d;
3341
			d = c;
3342
			c = b;
3343
			b += f;
3344
			
3345
			g = (g + tIdxIncr[i]) & 0xF;
3346
		}
3347
	}
3348
	
3349
	h[0] += a;
3350
	h[1] += b;
3351
	h[2] += c;
3352
	h[3] += d;
3353
	
3354
	for(i = 0; i < 4; i++)
3355
	{
3356
		hash[4 * i + 0] = h[i] >> 0;
3357
		hash[4 * i + 1] = h[i] >> 8;
3358
		hash[4 * i + 2] = h[i] >> 16;
3359
		hash[4 * i + 3] = h[i] >> 24;
3360
	}
3361
}
3362
3363
static void PowervuHashMode02(uint8_t *data, uint8_t *hash)
3364
{
3365
	int i;
3366
	uint32_t a, b, c, d, e, f, tmp;
3367
	uint32_t h[] = {0x81887F3A, 0x36CCA480, 0x99056FB1, 0x79705BAE};
3368
	uint32_t dataLongs[0x50];
3369
3370
	for (i = 0; i < 0x10; i++)
3371
	{
3372
		dataLongs[i] = (data[4 * i + 0] << 24) + (data[4 * i + 1] << 16) + (data[4 * i + 2] << 8) + (data[4 * i + 3] << 0);
3373
	}
3374
3375
	for (i = 0; i < 0x40; i++)
3376
	{
3377
		dataLongs[0x10 + i] = dataLongs[0x10 + i - 2];
3378
		dataLongs[0x10 + i] ^= dataLongs[0x10 + i - 7];
3379
		dataLongs[0x10 + i] ^= dataLongs[0x10 + i - 13];
3380
		dataLongs[0x10 + i] ^= dataLongs[0x10 + i - 16];
3381
	}
3382
3383
	a = dataLongs[0];
3384
	b = dataLongs[1];
3385
	c = dataLongs[2];
3386
	d = dataLongs[3];
3387
	e = dataLongs[4];
3388
3389
	for (i = 0; i < 0x50; i++)
3390
	{
3391
		if (i < 0x15) f = (b & c) | (~b & d);
3392
		else if (i < 0x28) f = (b ^ c ^ d);
3393
		else if (i < 0x3D) f = (b & c) | (c & d) | (b & d);
3394
		else if (i < 0x50) f = (b ^ c ^ d);
3395
3396
		tmp = a;
3397
		a = e + f + (a << 5) + (a >> 27) + h[i / 0x14] + dataLongs[i];
3398
		e = d;
3399
		d = c;
3400
		c = (b << 30) + (b >> 2);
3401
		b = tmp;
3402
	}
3403
3404
	dataLongs[0] += a;
3405
	dataLongs[1] += b;
3406
	dataLongs[2] += c;
3407
	dataLongs[3] += d;
3408
3409
	for (i = 0; i < 4; i++)
3410
	{
3411
		hash[4 * i + 0] = dataLongs[i] >> 24;
3412
		hash[4 * i + 1] = dataLongs[i] >> 16;
3413
		hash[4 * i + 2] = dataLongs[i] >> 8;
3414
		hash[4 * i + 3] = dataLongs[i] >> 0;
3415
	}
3416
}
3417
3418
static void PowervuHashMode03(uint8_t *data, uint8_t *hash)
3419
{
3420
	int i, j, k, s, s2, tmp;
3421
	uint32_t a, b, c, d, f, g;
3422
	uint32_t a2, b2, c2, d2, f2, g2;
3423
3424
	uint32_t T[] = { 0xC88F3F2E, 0x967506BA, 0xDA877A7B, 0x0DECCDFE };
3425
	uint32_t T2[] = { 0x01F42668, 0x39C7CDA5, 0xD490E2FE, 0x9965235D };
3426
3427
	uint8_t r[] = { 0x0B, 0x0E, 0x0F, 0x0C, 0x05, 0x08, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x0F, 0x06, 0x07, 0x09, 0x08,
3428
					0x07, 0x06, 0x08, 0x0D, 0x0B, 0x09, 0x07, 0x0F, 0x07, 0x0C, 0x0F, 0x09, 0x0B, 0x07, 0x0D, 0x0C };
3429
3430
	uint8_t tIdxIncr[] = { 0x07, 0x04, 0x0D, 0x01, 0x0A, 0x06, 0x0F, 0x03, 0x0C, 0x00, 0x09, 0x05, 0x02, 0x0E, 0x0B, 0x08,
3431
						   0x05, 0x0D, 0x02, 0x00, 0x04, 0x09, 0x03, 0x08, 0x01, 0x0A, 0x07, 0x0B, 0x06, 0x0F, 0x0C, 0x0E };
3432
3433
	uint32_t h[] = { 0xC8616857, 0x9D3F5B8E, 0x4D7B8F76, 0x97BC8D80 };
3434
3435
	uint32_t dataLongs[0x50];
3436
	uint32_t result[4];
3437
3438
	for (i = 0; i < 0x10; i++)
3439
	{
3440
		dataLongs[i] = (data[4 * i + 0] << 24) + (data[4 * i + 1] << 16) + (data[4 * i + 2] << 8) + (data[4 * i + 3] << 0);
3441
	}
3442
3443
	a = h[0];
3444
	b = h[1];
3445
	c = h[2];
3446
	d = h[3];
3447
3448
	a2 = h[3];
3449
	b2 = h[2];
3450
	c2 = h[1];
3451
	d2 = h[0];
3452
3453
	for (i = 0; i < 4; i++)
3454
	{
3455
		for (j = 0; j < 16; j++)
3456
		{
3457
			tmp = j;
3458
3459
			for (k = 0; k < i; k++)
3460
			{
3461
				tmp = tIdxIncr[tmp];
3462
			}
3463
3464
			g = 0x0F - tmp;
3465
			g2 = tmp;
3466
3467
			if (i == 0) f = (b & d) | (~d & c);
3468
			else if (i == 1) f = (~c | b) ^ d;
3469
			else if (i == 2) f = (~b & d) | (b & c);
3470
			else if (i == 3) f = (b ^ c ^ d);
3471
3472
			if (i == 0) f2 = (b2 ^ c2 ^ d2);
3473
			else if (i == 1) f2 = (~b2 & d2) | (b2 & c2);
3474
			else if (i == 2) f2 = (~c2 | b2) ^ d2;
3475
			else if (i == 3) f2 = (b2 & d2) | (~d2 & c2);
3476
3477
			f = dataLongs[g] + a + T[i] + f;
3478
			s = r[0x0F + (((i & 1) ^ 1) << 4) - j];
3479
			f = (f << s) | (f >> (32 - s));
3480
3481
			f2 = dataLongs[g2] + a2 + T2[i] + f2;
3482
			s2 = r[((i & 1) << 4) + j];
3483
			f2 = (f2 << s2) | (f2 >> (32 - s2));
3484
3485
			a = d;
3486
			d = (c << 10) | (c >> 22);
3487
			c = b;
3488
			b = f;
3489
3490
			a2 = d2;
3491
			d2 = (c2 << 10) | (c2 >> 22);
3492
			c2 = b2;
3493
			b2 = f2;
3494
		}
3495
	}
3496
3497
	result[0] = h[3] + b + a2;
3498
	result[1] = h[2] + c + b2;
3499
	result[2] = h[1] + d + c2;
3500
	result[3] = h[0] + a + d2;
3501
3502
	for (i = 0; i < 4; i++)
3503
	{
3504
		hash[4 * i + 0] = result[i] >> 0;
3505
		hash[4 * i + 1] = result[i] >> 8;
3506
		hash[4 * i + 2] = result[i] >> 16;
3507
		hash[4 * i + 3] = result[i] >> 24;
3508
	}
3509
}
3510
3511
uint8_t table04[] = { 0x02, 0x03, 0x07, 0x0B, 0x0D, 0x08, 0x00, 0x01, 0x2B, 0x2D, 0x28, 0x20, 0x21, 0x0A, 0x0C, 0x0E,
3512
					  0x22, 0x36, 0x23, 0x27, 0x29, 0x24, 0x25, 0x26, 0x2A, 0x3C, 0x3E, 0x3F, 0x0F, 0x2C, 0x2E, 0x2F,
3513
					  0x12, 0x13, 0x17, 0x1B, 0x1C, 0x18, 0x10, 0x11, 0x19, 0x14, 0x15, 0x16, 0x1A, 0x09, 0x04, 0x05,
3514
					  0x32, 0x33, 0x37, 0x3B, 0x06, 0x1C, 0x1E, 0x1F, 0x3D, 0x38, 0x30, 0x31, 0x39, 0x34, 0x35, 0x3A };
3515
3516
uint8_t table05[] = { 0x08, 0x09, 0x0A, 0x03, 0x04, 0x3F, 0x27, 0x28, 0x29, 0x2A, 0x05, 0x0B, 0x1B, 0x1C, 0x1C, 0x1E,
3517
					  0x20, 0x0C, 0x0D, 0x22, 0x23, 0x24, 0x00, 0x01, 0x02, 0x06, 0x07, 0x25, 0x26, 0x0E, 0x0F, 0x21,
3518
					  0x10, 0x11, 0x12, 0x2E, 0x2F, 0x13, 0x14, 0x15, 0x2B, 0x2C, 0x2D, 0x16, 0x17, 0x18, 0x19, 0x1A,
3519
					  0x30, 0x31, 0x37, 0x3B, 0x3C, 0x3D, 0x3E, 0x1F, 0x38, 0x39, 0x32, 0x33, 0x34, 0x35, 0x36, 0x3A };
3520
3521
uint8_t table06[] = { 0x00, 0x01, 0x02, 0x06, 0x07, 0x08, 0x03, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x04, 0x05, 0x09, 0x0D,
3522
					  0x20, 0x21, 0x22, 0x26, 0x27, 0x3A, 0x3B, 0x3C, 0x3E, 0x3F, 0x10, 0x11, 0x12, 0x16, 0x17, 0x28,
3523
					  0x18, 0x13, 0x14, 0x15, 0x19, 0x1C, 0x1A, 0x1B, 0x1C, 0x1E, 0x1F, 0x23, 0x24, 0x25, 0x29, 0x2D,
3524
					  0x30, 0x31, 0x32, 0x36, 0x37, 0x38, 0x33, 0x34, 0x0A, 0x0B, 0x0C, 0x0E, 0x0F, 0x35, 0x39, 0x3D };
3525
3526
uint8_t table09[] = { 0x20, 0x21, 0x24, 0x22, 0x23, 0x2A, 0x2B, 0x33, 0x35, 0x38, 0x39, 0x36, 0x2D, 0x2C, 0x2E, 0x2F,
3527
					  0x00, 0x01, 0x04, 0x02, 0x25, 0x28, 0x08, 0x09, 0x06, 0x07, 0x0A, 0x0B, 0x0D, 0x0C, 0x0E, 0x0F,
3528
					  0x10, 0x11, 0x14, 0x12, 0x13, 0x15, 0x19, 0x16, 0x29, 0x26, 0x03, 0x17, 0x1A, 0x1C, 0x1C, 0x1E,
3529
					  0x30, 0x31, 0x34, 0x32, 0x37, 0x3A, 0x3B, 0x3D, 0x3C, 0x3E, 0x3F, 0x1B, 0x05, 0x18, 0x27, 0x1F };
3530
3531
static void PowervuHashModes04to0ATables(uint8_t *data, uint8_t *hash, uint8_t *table)
3532
{
3533
	int i;
3534
3535
	for (i = 0; i < 0x10; i++)
3536
	{
3537
		hash[i] = table[i];
3538
		hash[i] ^= data[table[i]];
3539
		hash[i] ^= table[0x10 + i];
3540
		hash[i] ^= data[table[0x10 + i]];
3541
		hash[i] ^= table[0x20 + i];
3542
		hash[i] ^= data[table[0x20 + i]];
3543
		hash[i] ^= table[0x30 + i];
3544
		hash[i] ^= data[table[0x30 + i]];
3545
	}
3546
}
3547
3548
static void PowervuCreateHash(uint8_t *data, int len, uint8_t *hash, int mode)
3549
{
3550
	uint8_t dataPadded[0x40];
3551
3552
	PowervuPadData(data, len, dataPadded);
3553
	
3554
	switch(mode)
3555
	{
3556
		case 1:
3557
			PowervuHashMode01CustomMD5(dataPadded, hash);
3558
			break;
3559
3560
		case 2:
3561
			PowervuHashMode02(dataPadded, hash);
3562
			break;
3563
3564
		case 3:
3565
			PowervuHashMode03(dataPadded, hash);
3566
			break;
3567
3568
		case 4:
3569
			PowervuHashModes04to0ATables(dataPadded, hash, table04);
3570
			break;
3571
3572
		case 5:
3573
			PowervuHashModes04to0ATables(dataPadded, hash, table05);
3574
			break;
3575
3576
		case 6:
3577
			PowervuHashModes04to0ATables(dataPadded, hash, table06);
3578
			break;
3579
3580
		case 9:
3581
			PowervuHashModes04to0ATables(dataPadded, hash, table09);
3582
			break;
3583
3584
		default:
3585
			cs_log("A new hash mode [%d] is in use.", mode);
3586
			break;
3587
	}
3588
}
3589
3590
static void PowervuCreateDataEcmEmm(uint8_t *emmEcm, uint8_t *pos, int lenHeader, int len, uint8_t *data)
3591
{
3592
	int i;
3593
	
3594
	for(i = 0; i < len; i++)
3595
	{
3596
		data[i] = emmEcm[lenHeader + pos[i]];
3597
	}
3598
}
3599
3600
static uint8_t PowervuCreateDataCw(uint8_t *seed, uint8_t lenSeed, uint8_t *baseCw, uint8_t val, uint8_t *seedEcmCw, uint8_t *data)
3601
{
3602
	int i;
3603
	
3604
	for(i = 0; i < lenSeed; i++)
3605
	{
3606
		data[i] = seed[i];
3607
	}
3608
	
3609
	for(i = 0; i < 7; i++)
3610
	{
3611
		data[lenSeed + i] = baseCw[i];
3612
	}
3613
	
3614
	data[lenSeed + 7] = val;
3615
	
3616
	for(i = 0; i < 16; i++)
3617
	{
3618
		data[lenSeed + 7 + 1 + i] = seedEcmCw[i];
3619
	}
3620
	
3621
	return lenSeed + 7 + 1 + 0x10;
3622
}
3623
3624
static uint8_t PowervuUnmaskEcm(uint8_t *ecm, uint8_t *seedEcmCw)
3625
{
3626
	int i, l;
3627
	
3628
	uint8_t sourcePos[] = {0x04, 0x05, 0x06, 0x07, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x17, 0x1C, 0x1D, 0x1F, 0x23,
3629
						   0x24, 0x25, 0x26, 0x27, 0x29, 0x2C, 0x2D, 0x2E};
3630
	uint8_t destPos[]   = {0x08, 0x09, 0x11, 0x18, 0x19, 0x1A, 0x1B, 0x1E, 0x20, 0x21, 0x22, 0x28, 0x2A, 0x2B, 0x2F, 0x30};
3631
	uint8_t seedCwPos[] = {0x07, 0x0A, 0x04, 0x0D, 0x05, 0x0E, 0x06, 0x0B, 0x10, 0x0C, 0x0F};
3632
	
3633
	uint8_t data[0x18];
3634
	uint8_t mask[0x10];
3635
	uint8_t hashModeEcm;
3636
	uint8_t hashModeCw;
3637
	uint32_t crc;
3638
	
3639
	// Create seed for CW decryption
3640
	memset(seedEcmCw, 0, 0x10);
3641
	
3642
	int extraBytesLen = ecm[9];
3643
	int startOffset = extraBytesLen + 0x0A;
3644
3645
	for (i = 0; i < 0x0B; i++)
3646
	{
3647
		seedEcmCw[i] = ecm[startOffset + seedCwPos[i]];
3648
	}
3649
	
3650
	// Read hash mode CW
3651
	hashModeCw = ecm[28 + extraBytesLen] ^ PowervuCrc8Calc(seedEcmCw, 0x10);
3652
	
3653
	// Create mask for ECM decryption
3654
	PowervuCreateDataEcmEmm(ecm, sourcePos, startOffset, 0x18, data);
3655
	
3656
	hashModeEcm = ecm[8] ^ PowervuCrc8Calc(data, 0x18);
3657
	
3658
	PowervuCreateHash(data, 0x18, mask, hashModeEcm);
3659
	
3660
	// Fix header
3661
	ecm[3] &= 0x0F;
3662
	ecm[3] |= 0x30;
3663
	ecm[8]  = 0x00;
3664
	ecm[28 + extraBytesLen] = 0x00;
3665
	
3666
	// Unmask body
3667
	for (i = 0; i < 0x10; i++)
3668
	{
3669
		ecm[startOffset + destPos[i]] ^= mask[i & 0x0F];
3670
	}
3671
	
3672
	// Fix CRC (optional)
3673
	l = (((ecm[1] << 8) + ecm[2]) & 0xFFF) + 3 - 4;
3674
	
3675
	crc = fletcher_crc32(ecm, l);
3676
	
3677
	ecm[l + 0] = crc >> 24;
3678
	ecm[l + 1] = crc >> 16;
3679
	ecm[l + 2] = crc >> 8;
3680
	ecm[l + 3] = crc >> 0;
3681
	
3682
	return hashModeCw;
3683
}
3684
3685
static void PowervuCreateCw(uint8_t *seed, uint8_t lenSeed, uint8_t *baseCw, uint8_t val,
3686
								uint8_t *seedEcmCw, uint8_t *cw, int modeDesCsa, int hashMode)
3687
{
3688
	uint8_t tableFixParity[] = {0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0B, 0x0B, 0x0D, 0x0D, 0x0E, 0x0E,
3689
								0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, 0x19, 0x19, 0x1A, 0x1A, 0x1C, 0x1C, 0x1F, 0x1F,
3690
								0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2A, 0x2A, 0x2C, 0x2C, 0x2F, 0x2F,
3691
								0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, 0x38, 0x38, 0x3B, 0x3B, 0x3D, 0x3D, 0x3E, 0x3E,
3692
								0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 0x49, 0x49, 0x4A, 0x4A, 0x4C, 0x4C, 0x4F, 0x4F,
3693
								0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, 0x58, 0x58, 0x5B, 0x5B, 0x5D, 0x5D, 0x5E, 0x5E,
3694
								0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, 0x68, 0x68, 0x6B, 0x6B, 0x6D, 0x6D, 0x6E, 0x6E,
3695
								0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, 0x79, 0x79, 0x7A, 0x7A, 0x7C, 0x7C, 0x7F, 0x7F,
3696
								0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86, 0x89, 0x89, 0x8A, 0x8A, 0x8C, 0x8C, 0x8F, 0x8F,
3697
								0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, 0x98, 0x98, 0x9B, 0x9B, 0x9D, 0x9D, 0x9E, 0x9E,
3698
								0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA4, 0xA7, 0xA7, 0xA8, 0xA8, 0xAB, 0xAB, 0xAD, 0xAD, 0xAE, 0xAE,
3699
								0xB0, 0xB0, 0xB3, 0xB3, 0xB5, 0xB5, 0xB6, 0xB6, 0xB9, 0xB9, 0xBA, 0xBA, 0xBC, 0xBC, 0xBF, 0xBF,
3700
								0xC1, 0xC1, 0xC2, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7, 0xC8, 0xC8, 0xCB, 0xCB, 0xCD, 0xCD, 0xCE, 0xCE,
3701
								0xD0, 0xD0, 0xD3, 0xD3, 0xD5, 0xD5, 0xD6, 0xD6, 0xD9, 0xD9, 0xDA, 0xDA, 0xDC, 0xDC, 0xDF, 0xDF,
3702
								0xE0, 0xE0, 0xE3, 0xE3, 0xE5, 0xE5, 0xE6, 0xE6, 0xE9, 0xE9, 0xEA, 0xEA, 0xEC, 0xEC, 0xEF, 0xEF,
3703
								0xF1, 0xF1, 0xF2, 0xF2, 0xF4, 0xF4, 0xF7, 0xF7, 0xF8, 0xF8, 0xFB, 0xFB, 0xFD, 0xFD, 0xFE, 0xFE};
3704
	
3705
	uint8_t data[0x1C];
3706
	uint8_t hash[0x10];
3707
	uint8_t lenData;
3708
	int i;
3709
	
3710
	lenData = PowervuCreateDataCw(seed, lenSeed, baseCw, val, seedEcmCw, data);
3711
	PowervuCreateHash(data, lenData, hash, hashMode);
3712
	
3713
	for(i = 0; i < 8; i++)
3714
	{
3715
		cw[i] = hash[i];
3716
	}
3717
	
3718
	if(modeDesCsa == 0) // DES - Fix Parity Bits
3719
	{
3720
		for(i = 0; i < 8; i++)
3721
		{
3722
			cw[i] = tableFixParity[cw[i]];
3723
		}
3724
	}
3725
	else if(modeDesCsa == 1) // CSA - Fix Checksums
3726
	{
3727
		cw[3] = cw[0] + cw[1] + cw[2];
3728
		cw[7] = cw[4] + cw[5] + cw[6];
3729
	}
3730
}
3731
3732
static int8_t GetPowervuKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey, uint32_t keyRef)
3733
{
3734
	char keyStr[EMU_MAX_CHAR_KEYNAME];
3735
	
3736
	snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
3737
	if(FindKey('P', ident, 0xFFFF0000, keyStr, buf, keyLength, isCriticalKey, keyRef, 0, NULL)) {
3738
		return 1;
3739
	}
3740
	
3741
	return 0;
3742
}
3743
3744
static int8_t GetPowervuEmmKey(uint8_t *buf, uint32_t ident, char *keyName, uint32_t keyLength, uint8_t isCriticalKey, uint32_t keyRef, uint32_t *getProvider)
3745
{
3746
	if(FindKey('P', ident, 0xFFFFFFFF, keyName, buf, keyLength, isCriticalKey, keyRef, 0, getProvider)) {
3747
		return 1;
3748
	}
3749
3750
	return 0;
3751
}
3752
3753
static const uint8_t PowerVu_A0_S_1[16] = {0x33, 0xA4, 0x44, 0x3C, 0xCA, 0x2E, 0x75, 0x7B, 0xBC, 0xE6, 0xE5, 0x35, 0xA0, 0x55, 0xC9, 0xA2};
3754
static const uint8_t PowerVu_A0_S_2[16] = {0x5A, 0xB0, 0x2C, 0xBC, 0xDA, 0x32, 0xE6, 0x92, 0x40, 0x53, 0x6E, 0xF9, 0x69, 0x11, 0x1E, 0xFB};
3755
static const uint8_t PowerVu_A0_S_3[16] = {0x4E, 0x18, 0x9B, 0x19, 0x79, 0xFB, 0x01, 0xFA, 0xE3, 0xE1, 0x28, 0x3D, 0x32, 0xE4, 0x92, 0xEA};
3756
static const uint8_t PowerVu_A0_S_4[16] = {0x05, 0x6F, 0x37, 0x66, 0x35, 0xE1, 0x58, 0xD0, 0xB4, 0x6A, 0x97, 0xAE, 0xD8, 0x91, 0x27, 0x56};
3757
static const uint8_t PowerVu_A0_S_5[16] = {0x7B, 0x26, 0xAD, 0x34, 0x3D, 0x77, 0x39, 0x51, 0xE0, 0xE0, 0x48, 0x8C, 0x39, 0xF5, 0xE8, 0x47};
3758
static const uint8_t PowerVu_A0_S_6[16] = {0x74, 0xFA, 0x4D, 0x79, 0x42, 0x39, 0xD1, 0xA4, 0x99, 0xA3, 0x97, 0x07, 0xDF, 0x14, 0x3A, 0xC4};
3759
static const uint8_t PowerVu_A0_S_7[16] = {0xC6, 0x1E, 0x3C, 0x24, 0x11, 0x08, 0x5D, 0x6A, 0xEB, 0x97, 0xB9, 0x25, 0xA7, 0xFA, 0xE9, 0x1A};
3760
static const uint8_t PowerVu_A0_S_8[16] = {0x9A, 0xAD, 0x72, 0xD7, 0x7C, 0x68, 0x3B, 0x55, 0x1D, 0x4A, 0xA2, 0xB0, 0x38, 0xB9, 0x56, 0xD0};
3761
static const uint8_t PowerVu_A0_S_9[32] = {0x61, 0xDA, 0x5F, 0xB7, 0xEB, 0xC6, 0x3F, 0x6C, 0x09, 0xF3, 0x64, 0x38, 0x33, 0x08, 0xAA, 0x15,
3762
										   0xCC, 0xEF, 0x22, 0x64, 0x01, 0x2C, 0x12, 0xDE, 0xF4, 0x6E, 0x3C, 0xCD, 0x1A, 0x64, 0x63, 0x7C
3763
										  };
3764
3765
static const uint8_t PowerVu_00_S_1[16] = {0x97, 0x13, 0xEB, 0x6B, 0x04, 0x5E, 0x60, 0x3A, 0xD9, 0xCC, 0x91, 0xC2, 0x5A, 0xFD, 0xBA, 0x0C};
3766
static const uint8_t PowerVu_00_S_2[16] = {0x61, 0x3C, 0x03, 0xB0, 0xB5, 0x6F, 0xF8, 0x01, 0xED, 0xE0, 0xE5, 0xF3, 0x78, 0x0F, 0x0A, 0x73};
3767
static const uint8_t PowerVu_00_S_3[16] = {0xFD, 0xDF, 0xD2, 0x97, 0x06, 0x14, 0x91, 0xB5, 0x36, 0xAD, 0xBC, 0xE1, 0xB3, 0x00, 0x66, 0x41};
3768
static const uint8_t PowerVu_00_S_4[16] = {0x8B, 0xD9, 0x18, 0x0A, 0xED, 0xEE, 0x61, 0x34, 0x1A, 0x79, 0x80, 0x8C, 0x1E, 0x7F, 0xC5, 0x9F};
3769
static const uint8_t PowerVu_00_S_5[16] = {0xB0, 0xA1, 0xF2, 0xB8, 0xEA, 0x72, 0xDD, 0xD3, 0x30, 0x65, 0x2B, 0x1E, 0xE9, 0xE1, 0x45, 0x29};
3770
static const uint8_t PowerVu_00_S_6[16] = {0x5D, 0xCA, 0x53, 0x75, 0xB2, 0x24, 0xCE, 0xAF, 0x21, 0x54, 0x9E, 0xBE, 0x02, 0xA9, 0x4C, 0x5D};
3771
static const uint8_t PowerVu_00_S_7[16] = {0x42, 0x66, 0x72, 0x83, 0x1B, 0x2D, 0x22, 0xC9, 0xF8, 0x4D, 0xBA, 0xCD, 0xBB, 0x20, 0xBD, 0x6B};
3772
static const uint8_t PowerVu_00_S_8[16] = {0xC4, 0x0C, 0x6B, 0xD3, 0x6D, 0x94, 0x7E, 0x53, 0xCE, 0x96, 0xAC, 0x40, 0x2C, 0x7A, 0xD3, 0xA9};
3773
static const uint8_t PowerVu_00_S_9[32] = {0x31, 0x82, 0x4F, 0x9B, 0xCB, 0x6F, 0x9D, 0xB7, 0xAE, 0x68, 0x0B, 0xA0, 0x93, 0x15, 0x32, 0xE2,
3774
										   0xED, 0xE9, 0x47, 0x29, 0xC2, 0xA8, 0x92, 0xEF, 0xBA, 0x27, 0x22, 0x57, 0x76, 0x54, 0xC0, 0x59,
3775
										  };
3776
3777
static uint8_t PowervuSbox(uint8_t *input, uint8_t mode)
3778
{
3779
	uint8_t s_index, bit, last_index, last_bit;
3780
	uint8_t const *Sbox1, *Sbox2, *Sbox3, *Sbox4, *Sbox5, *Sbox6, *Sbox7, *Sbox8, *Sbox9;
3781
	
3782
	if(mode)
3783
	{
3784
		Sbox1 = PowerVu_A0_S_1;
3785
		Sbox2 = PowerVu_A0_S_2;
3786
		Sbox3 = PowerVu_A0_S_3;
3787
		Sbox4 = PowerVu_A0_S_4;
3788
		Sbox5 = PowerVu_A0_S_5;
3789
		Sbox6 = PowerVu_A0_S_6;
3790
		Sbox7 = PowerVu_A0_S_7;
3791
		Sbox8 = PowerVu_A0_S_8;
3792
		Sbox9 = PowerVu_A0_S_9;
3793
	}
3794
	else
3795
	{
3796
		Sbox1 = PowerVu_00_S_1;
3797
		Sbox2 = PowerVu_00_S_2;
3798
		Sbox3 = PowerVu_00_S_3;
3799
		Sbox4 = PowerVu_00_S_4;
3800
		Sbox5 = PowerVu_00_S_5;
3801
		Sbox6 = PowerVu_00_S_6;
3802
		Sbox7 = PowerVu_00_S_7;
3803
		Sbox8 = PowerVu_00_S_8;
3804
		Sbox9 = PowerVu_00_S_9;
3805
	}
3806
	
3807
	bit = (GetBit(input[2],0)<<2) | (GetBit(input[3],4)<<1) | (GetBit(input[5],3));
3808
	s_index = (GetBit(input[0],0)<<3) | (GetBit(input[2],6)<<2) | (GetBit(input[2],4)<<1) | (GetBit(input[5],7));
3809
	last_bit = GetBit(Sbox1[s_index],7-bit);
3810
	
3811
	bit = (GetBit(input[5],0)<<2) | (GetBit(input[4],0)<<1) | (GetBit(input[6],2));
3812
	s_index = (GetBit(input[2],1)<<3) | (GetBit(input[2],2)<<2) | (GetBit(input[5],5)<<1) | (GetBit(input[5],1));
3813
	last_bit = last_bit | (GetBit(Sbox2[s_index],7-bit)<<1);
3814
	
3815
	bit = (GetBit(input[6],0)<<2) | (GetBit(input[1],7)<<1) | (GetBit(input[6],7));
3816
	s_index = (GetBit(input[1],3)<<3) | (GetBit(input[3],7)<<2) | (GetBit(input[1],5)<<1) | (GetBit(input[5],2));
3817
	last_bit = last_bit | (GetBit(Sbox3[s_index], 7-bit)<<2);
3818
	
3819
	bit = (GetBit(input[1],0)<<2) | (GetBit(input[2],7)<<1) | (GetBit(input[2],5));
3820
	s_index = (GetBit(input[6],3)<<3) | (GetBit(input[6],4)<<2) | (GetBit(input[6],6)<<1) | (GetBit(input[3],5));
3821
	last_index = GetBit(Sbox4[s_index], 7-bit);
3822
	
3823
	bit = (GetBit(input[3],3)<<2) | (GetBit(input[4],6)<<1) | (GetBit(input[3],2));
3824
	s_index = (GetBit(input[3],1)<<3) | (GetBit(input[4],5)<<2) | (GetBit(input[3],0)<<1) | (GetBit(input[4],7));
3825
	last_index = last_index | (GetBit(Sbox5[s_index], 7-bit)<<1);
3826
	
3827
	bit = (GetBit(input[5],4)<<2) | (GetBit(input[4],4)<<1) | (GetBit(input[1],2));
3828
	s_index = (GetBit(input[2],3)<<3) | (GetBit(input[6],5)<<2) | (GetBit(input[1],4)<<1) | (GetBit(input[4],1));
3829
	last_index = last_index | (GetBit(Sbox6[s_index], 7-bit)<<2);
3830
	
3831
	bit = (GetBit(input[0],6)<<2) | (GetBit(input[0],7)<<1) | (GetBit(input[0],4));
3832
	s_index = (GetBit(input[0],5)<<3) | (GetBit(input[0],3)<<2) | (GetBit(input[0],1)<<1) | (GetBit(input[0],2));
3833
	last_index = last_index | (GetBit(Sbox7[s_index], 7-bit)<<3);
3834
	
3835
	bit = (GetBit(input[4],2)<<2) | (GetBit(input[4],3)<<1) | (GetBit(input[1],1));
3836
	s_index = (GetBit(input[1],6)<<3) | (GetBit(input[6],1)<<2) | (GetBit(input[5],6)<<1) | (GetBit(input[3],6));
3837
	last_index = last_index | (GetBit(Sbox8[s_index], 7-bit)<<4);
3838
	
3839
	return (GetBit(Sbox9[last_index&0x1f],7-last_bit)&1) ? 1: 0;
3840
}
3841
3842
static void PowervuDecrypt(uint8_t *data, uint32_t length, uint8_t *key, uint8_t sbox)
3843
{
3844
	uint32_t i;
3845
	int32_t j, k;
3846
	uint8_t curByte, tmpBit;
3847
	
3848
	for(i = 0; i < length; i++)
3849
	{
3850
		curByte = data[i];
3851
		
3852
		for(j = 7; j >= 0; j--)
3853
		{
3854
			data[i] = SetBit(data[i], j, (GetBit(curByte, j)^PowervuSbox(key, sbox))^GetBit(key[0], 7));
3855
			
3856
			tmpBit = GetBit(data[i], j)^(GetBit(key[6], 0));
3857
			if (tmpBit)
3858
			{
3859
				key[3] ^= 0x10;
3860
			}
3861
			
3862
			for (k = 6; k > 0; k--)
3863
			{
3864
				key[k] = (key[k]>>1) | (key[k-1]<<7);
3865
			}
3866
			key[0] = (key[0]>>1);
3867
			
3868
			key[0] = SetBit(key[0], 7, tmpBit);
3869
		}
3870
	}
3871
}
3872
3873
#define PVU_CW_VID 0	// VIDeo
3874
#define PVU_CW_HSD 1	// High Speed Data
3875
#define PVU_CW_A1 2	// Audio 1
3876
#define PVU_CW_A2 3	// Audio 2
3877
#define PVU_CW_A3 4	// Audio 3
3878
#define PVU_CW_A4 5	// Audio 4
3879
#define PVU_CW_UTL 6	// UTiLity
3880
#define PVU_CW_VBI 7	// Vertical Blanking Interval
3881
3882
#define PVU_CONVCW_VID_ECM 0x80	// VIDeo
3883
#define PVU_CONVCW_HSD_ECM 0x40	// High Speed Data
3884
#define PVU_CONVCW_A1_ECM 0x20	// Audio 1
3885
#define PVU_CONVCW_A2_ECM 0x10	// Audio 2
3886
#define PVU_CONVCW_A3_ECM 0x08	// Audio 3
3887
#define PVU_CONVCW_A4_ECM 0x04	// Audio 4
3888
#define PVU_CONVCW_UTL_ECM 0x02	// UTiLity
3889
#define PVU_CONVCW_VBI_ECM 0x01	// Vertical Blanking Interval
3890
3891
static uint8_t PowervuGetConvcwIndex(uint8_t ecmTag)
3892
{
3893
	switch(ecmTag)
3894
	{
3895
	case PVU_CONVCW_VID_ECM:
3896
		return PVU_CW_VID;
3897
	
3898
	case PVU_CONVCW_HSD_ECM:
3899
		return PVU_CW_HSD;
3900
	
3901
	case PVU_CONVCW_A1_ECM:
3902
		return PVU_CW_A1;
3903
	
3904
	case PVU_CONVCW_A2_ECM:
3905
		return PVU_CW_A2;
3906
	
3907
	case PVU_CONVCW_A3_ECM:
3908
		return PVU_CW_A3;
3909
	
3910
	case PVU_CONVCW_A4_ECM:
3911
		return PVU_CW_A4;
3912
	
3913
	case PVU_CONVCW_UTL_ECM:
3914
		return PVU_CW_UTL;
3915
	
3916
	case PVU_CONVCW_VBI_ECM:
3917
		return PVU_CW_VBI;
3918
	
3919
	default:
3920
		return PVU_CW_VBI;
3921
	}
3922
}
3923
3924
static uint16_t PowervuGetSeedIV(uint8_t seedType, uint8_t *ecm)
3925
{
3926
	switch(seedType)
3927
	{
3928
	case PVU_CW_VID:
3929
		return ((ecm[0x10] & 0x1F) <<3) | 0;
3930
	case PVU_CW_HSD:
3931
		return ((ecm[0x12] & 0x1F) <<3) | 2;
3932
	case PVU_CW_A1:
3933
		return ((ecm[0x11] & 0x3F) <<3) | 1;
3934
	case PVU_CW_A2:
3935
		return ((ecm[0x13] & 0x3F) <<3) | 1;
3936
	case PVU_CW_A3:
3937
		return ((ecm[0x19] & 0x3F) <<3) | 1;
3938
	case PVU_CW_A4:
3939
		return ((ecm[0x1A] & 0x3F) <<3) | 1;;
3940
	case PVU_CW_UTL:
3941
		return ((ecm[0x14] & 0x0F) <<3) | 4;
3942
	case PVU_CW_VBI:
3943
		return (((ecm[0x15] & 0xF8)>>3)<<3) | 5;
3944
	default:
3945
		return 0;
3946
	}
3947
}
3948
3949
static uint8_t PowervuExpandSeed(uint8_t seedType, uint8_t *seed)
3950
{
3951
	uint8_t seedLength = 0, i;
3952
	
3953
	switch(seedType)
3954
	{
3955
	case PVU_CW_VID:
3956
	case PVU_CW_HSD:
3957
		seedLength = 4;
3958
		break;
3959
	case PVU_CW_A1:
3960
	case PVU_CW_A2:
3961
	case PVU_CW_A3:
3962
	case PVU_CW_A4:
3963
		seedLength = 3;
3964
		break;
3965
	case PVU_CW_UTL:
3966
	case PVU_CW_VBI:
3967
		seedLength = 2;
3968
		break;
3969
	default:
3970
		return seedLength;
3971
	}
3972
	
3973
	for(i=seedLength; i<7; i++)
3974
	{
3975
		seed[i] = seed[i%seedLength];
3976
	}
3977
3978
	return seedLength;
3979
}
3980
3981
static void PowervuCalculateSeed(uint8_t seedType, uint8_t *ecm, uint8_t *seedBase, uint8_t *key, uint8_t *seed, uint8_t sbox)
3982
{
3983
	uint16_t tmpSeed;
3984
3985
	tmpSeed = PowervuGetSeedIV(seedType, ecm+23);
3986
	seed[0] = (tmpSeed >> 2) & 0xFF;
3987
	seed[1] = ((tmpSeed & 0x3) << 6) | (seedBase[0] >> 2);
3988
	seed[2] = (    seedBase[0] << 6) | (seedBase[1] >> 2);
3989
	seed[3] = (    seedBase[1] << 6) | (seedBase[2] >> 2);
3990
	seed[4] = (    seedBase[2] << 6) | (seedBase[3] >> 2);
3991
	seed[5] = (    seedBase[3] << 6);
3992
3993
	PowervuDecrypt(seed, 6, key, sbox);
3994
3995
	seed[0] = (seed[1] << 2) | (seed[2] >> 6);
3996
	seed[1] = (seed[2] << 2) | (seed[3] >> 6);
3997
	seed[2] = (seed[3] << 2) | (seed[4] >> 6);
3998
	seed[3] = (seed[4] << 2) | (seed[5] >> 6);
3999
}
4000
4001
static void PowervuCalculateCw(uint8_t seedType, uint8_t *seed, uint8_t csaUsed, uint8_t *convolvedCw,
4002
								uint8_t *cw, uint8_t *baseCw, uint8_t *seedEcmCw, uint8_t hashModeCw,
4003
								uint8_t needsUnmasking, uint8_t xorMode)
4004
{
4005
	int32_t k;
4006
	uint8_t seedLength, val = 0;
4007
4008
	seedLength = PowervuExpandSeed(seedType, seed);
4009
4010
	if(csaUsed)
4011
	{
4012
		if(!needsUnmasking || (hashModeCw == 0))
4013
		{
4014
			for(k = 0; k < 7; k++)
4015
			{
4016
				seed[k] ^= baseCw[k];
4017
			}
4018
			
4019
			cw[0] = seed[0] ^ convolvedCw[0];
4020
			cw[1] = seed[1] ^ convolvedCw[1];
4021
			cw[2] = seed[2] ^ convolvedCw[2];
4022
			cw[3] = seed[3] ^ convolvedCw[3];
4023
			cw[4] = seed[3] ^ convolvedCw[4];
4024
			cw[5] = seed[4] ^ convolvedCw[5];
4025
			cw[6] = seed[5] ^ convolvedCw[6];
4026
			cw[7] = seed[6] ^ convolvedCw[7];
4027
		}
4028
	}
4029
	else
4030
	{
4031
		if(xorMode == 0)
4032
		{
4033
			for(k = 0; k < 7; k++)
4034
			{
4035
				cw[k] = seed[k] ^ baseCw[k];
4036
			}
4037
		}
4038
		
4039
		if(xorMode == 1)
4040
		{
4041
			for(k = 0; k < 3; k++)
4042
			{
4043
				cw[k] = seed[k] ^ baseCw[k];
4044
			}
4045
			
4046
			for(k = 3; k < 7; k++)
4047
			{
4048
				cw[k] = baseCw[k];
4049
			}
4050
		}
4051
		
4052
		ExpandDesKey(cw);
4053
	}
4054
	
4055
	if(needsUnmasking && (hashModeCw > 0))
4056
	{
4057
		switch(seedType)
4058
		{
4059
			case PVU_CW_VID:
4060
				val = 0;
4061
				break;
4062
			
4063
			case PVU_CW_A1:
4064
			case PVU_CW_A2:
4065
			case PVU_CW_A3:
4066
			case PVU_CW_A4:
4067
				val = 1;
4068
				break;
4069
			
4070
			case PVU_CW_HSD:
4071
				val = 2;
4072
				break;
4073
			
4074
			case PVU_CW_UTL:
4075
				val = 4;
4076
				break;
4077
			
4078
			case PVU_CW_VBI:
4079
				val = 5;
4080
				break;
4081
		}
4082
		PowervuCreateCw(seed, seedLength, baseCw, val, seedEcmCw, cw, csaUsed, hashModeCw);
4083
	}
4084
}
4085
4086
#ifdef WITH_EMU
4087
int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, uint16_t srvid, emu_stream_client_key_data *cdata, EXTENDED_CW* cw_ex)
4088
#else
4089
int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, emu_stream_client_key_data *cdata)
4090
#endif
4091
{
4092
	int8_t ret = 1;
4093
	uint16_t ecmLen = GetEcmLen(ecm);
4094
	uint32_t ecmCrc32;
4095
	uint8_t nanoCmd, nanoChecksum, keyType, fixedKey, oddKey, bid, csaUsed;
4096
	uint16_t nanoLen;
4097
	uint32_t channelId, ecmSrvid, keyIndex;
4098
	uint32_t i, j, k;
4099
	uint8_t convolvedCw[8][8];
4100
	uint8_t ecmKey[7], tmpEcmKey[7], seedBase[4], baseCw[7], seed[8][8], cw[8][8];
4101
	uint8_t decrypt_ok;
4102
	uint8_t ecmPart1[14], ecmPart2[27];
4103
	uint8_t sbox;
4104
	uint32_t keyRef1, keyRef2;
4105
	uint8_t calculateAllCws;
4106
	uint8_t seedEcmCw[0x10];
4107
	uint8_t hashModeCw = 0, needsUnmasking, xorMode;
4108
#ifdef WITH_EMU
4109
	uint8_t *dwp;
4110
	emu_stream_cw_item *cw_item;
4111
	int8_t update_global_key = 0;
4112
	int8_t update_global_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
4113
	
4114
	memset(update_global_keys, 0, sizeof(update_global_keys));
4115
#endif
4116
	
4117
	if(ecmLen < 7)
4118
	{
4119
		return 1;
4120
	}
4121
	
4122
	needsUnmasking = (ecm[3] & 0xF0) == 0x50;
4123
	
4124
	if(needsUnmasking)
4125
	{
4126
		hashModeCw = PowervuUnmaskEcm(ecm, seedEcmCw);
4127
	}
4128
	
4129
	ecmCrc32 = b2i(4, ecm+ecmLen-4);
4130
	
4131
	if(fletcher_crc32(ecm, ecmLen-4) != ecmCrc32)
4132
	{
4133
		return 8;
4134
	}
4135
	ecmLen -= 4;
4136
	
4137
	for(i = 0; i < 8; i++) {
4138
		memset(convolvedCw[i], 0, 8);
4139
	}
4140
	
4141
	for(i = 3; i+3 < ecmLen; ) {
4142
		nanoLen = (((ecm[i] & 0x0f) << 8) | ecm[i+1]);
4143
		i += 2;
4144
		if(nanoLen > 0)
4145
		{
4146
			nanoLen--;
4147
		}
4148
		nanoCmd = ecm[i++];
4149
		if(i+nanoLen > ecmLen) {
4150
			return 1;
4151
		}
4152
		
4153
		switch (nanoCmd) {
4154
		case 0x27:
4155
			if(nanoLen < 15)
4156
			{
4157
				break;
4158
			}
4159
			
4160
			nanoChecksum = 0;
4161
			for(j = 4; j < 15; j++)
4162
			{
4163
				nanoChecksum += ecm[i+j];
4164
			}
4165
			
4166
			if(nanoChecksum != 0)
4167
			{
4168
				break;
4169
			}
4170
			
4171
			keyType = PowervuGetConvcwIndex(ecm[i+4]);
4172
			memcpy(convolvedCw[keyType], &ecm[i+6], 8);
4173
			break;
4174
		
4175
		default:
4176
			break;
4177
		}
4178
		i += nanoLen;
4179
	}
4180
	
4181
	for(i = 3; i+3 < ecmLen; ) {
4182
		nanoLen = (((ecm[i] & 0x0f) << 8) | ecm[i+1]);
4183
		i += 2;
4184
		if(nanoLen > 0)
4185
		{
4186
			nanoLen--;
4187
		}
4188
		nanoCmd = ecm[i++];
4189
		if(i+nanoLen > ecmLen) {
4190
			return 1;
4191
		}
4192
		
4193
		switch (nanoCmd) {
4194
		case 0x20:
4195
			if(nanoLen < 54)
4196
			{
4197
				break;
4198
			}
4199
4200
			i += ecm[i + 3]; // Extra Data Length
4201
4202
			csaUsed = GetBit(ecm[i+7], 7);
4203
			fixedKey = !GetBit(ecm[i+6], 5);
4204
			oddKey = GetBit(ecm[i+6], 4);
4205
			xorMode = GetBit(ecm[i+6], 0);
4206
			bid = (GetBit(ecm[i+7], 1) << 1) | GetBit(ecm[i+7], 0);
4207
			sbox = GetBit(ecm[i+6], 3);
4208
			
4209
			keyIndex = (fixedKey << 3) | (bid << 2) | oddKey;
4210
			channelId = b2i(2, ecm+i+23);
4211
			ecmSrvid = (channelId >> 4) | ((channelId & 0xF) << 12);
4212
			
4213
			decrypt_ok = 0;
4214
			
4215
			memcpy(ecmPart1, ecm+i+8, 14);
4216
			memcpy(ecmPart2, ecm+i+27, 27);
4217
			
4218
			keyRef1 = 0;
4219
			keyRef2 = 0;
4220
			
4221
			do
4222
			{
4223
				if(!GetPowervuKey(ecmKey, ecmSrvid, '0', keyIndex, 7, 0, keyRef1++))
4224
				{
4225
					if(!GetPowervuKey(ecmKey, channelId, '0', keyIndex, 7, 0, keyRef2++))
4226
					{
4227
						cs_log("Key not found: P %04X 0%X", ecmSrvid, keyIndex);
4228
						return 2;
4229
					}
4230
				}
4231
				
4232
				PowervuDecrypt(ecm+i+8, 14, ecmKey, sbox);
4233
				if((ecm[i+6] != ecm[i+6+7]) || (ecm[i+6+8] != ecm[i+6+15]))
4234
				{
4235
					memcpy(ecm+i+8, ecmPart1, 14);
4236
					continue;
4237
				}
4238
				
4239
				memcpy(tmpEcmKey, ecmKey, 7);
4240
				
4241
				PowervuDecrypt(ecm+i+27, 27, ecmKey, sbox);
4242
				if((ecm[i+23] != ecm[i+23+29]) || (ecm[i+23+1] != ecm[i+23+30]))
4243
				{
4244
					memcpy(ecm+i+8, ecmPart1, 14);
4245
					memcpy(ecm+i+27, ecmPart2, 27);
4246
					continue;
4247
				}
4248
				
4249
				decrypt_ok = 1;
4250
			}
4251
			while(!decrypt_ok);
4252
			
4253
			memcpy(seedBase, ecm+i+6+2, 4);
4254
			
4255
#ifdef WITH_EMU	
4256
			if(cdata == NULL)
4257
			{
4258
				SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
4259
				for(j = 0; j < EMU_STREAM_SERVER_MAX_CONNECTIONS; j++)
4260
				{
4261
					if(!stream_server_has_ecm[j] && emu_stream_cur_srvid[j] == srvid)
4262
					{
4263
						update_global_key = 1;
4264
						update_global_keys[j] = 1;
4265
					}	
4266
				}
4267
				SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
4268
			}
4269
			
4270
			if(cdata != NULL || update_global_key || cw_ex != NULL)
4271
#else	
4272
			if(cdata != NULL)
4273
#endif
4274
			{
4275
				// Calculate all seeds
4276
				for(j = 0; j < 8; j++)
4277
				{
4278
					memcpy(ecmKey, tmpEcmKey, 7);
4279
					PowervuCalculateSeed(j, ecm+i, seedBase, ecmKey, seed[j], sbox);
4280
				}
4281
			}
4282
			else
4283
			{
4284
				// Calculate only video seed
4285
				memcpy(ecmKey, tmpEcmKey, 7);
4286
				PowervuCalculateSeed(PVU_CW_VID, ecm+i, seedBase, ecmKey, seed[PVU_CW_VID], sbox);
4287
			}
4288
			
4289
			memcpy(baseCw, ecm+i+6+8, 7);
4290
			
4291
#ifdef WITH_EMU
4292
			calculateAllCws = cdata != NULL || update_global_key || cw_ex != NULL;
4293
#else
4294
			calculateAllCws = cdata != NULL;
4295
#endif
4296
			if(calculateAllCws)
4297
			{
4298
				// Calculate all cws
4299
				for(j = 0; j < 8; j++)
4300
				{
4301
					PowervuCalculateCw(j, seed[j], csaUsed, convolvedCw[j], cw[j], baseCw,
4302
										seedEcmCw, hashModeCw, needsUnmasking, xorMode);
4303
					
4304
					if(csaUsed)
4305
					{
4306
						for(k = 0; k < 8; k += 4) {
4307
							cw[j][k + 3] = ((cw[j][k] + cw[j][k + 1] + cw[j][k + 2]) & 0xff);
4308
						}
4309
					}
4310
				}
4311
				
4312
#ifdef WITH_EMU
4313
				if(update_global_key)
4314
				{
4315
					for(j = 0; j < EMU_STREAM_SERVER_MAX_CONNECTIONS; j++)
4316
					{
4317
						if(update_global_keys[j])
4318
						{
4319
							cw_item = (emu_stream_cw_item*)malloc(sizeof(emu_stream_cw_item));
4320
							if(cw_item != NULL)
4321
							{
4322
								cw_item->csa_used = csaUsed;
4323
								cw_item->is_even = ecm[0] == 0x80 ? 1 : 0;
4324
								cs_ftime(&cw_item->write_time);
4325
								add_ms_to_timeb(&cw_item->write_time, cfg.emu_stream_ecm_delay);
4326
								memcpy(cw_item->cw, cw, sizeof(cw));
4327
								ll_append(ll_emu_stream_delayed_keys[j], cw_item);
4328
							}
4329
						}
4330
					}
4331
				}
4332
				
4333
				if(cdata != NULL) 
4334
				{
4335
#endif
4336
					for(j = 0; j < 8; j++)
4337
					{
4338
						if(csaUsed)
4339
						{	
4340
							if(cdata->pvu_csa_ks[j] == NULL)
4341
								{ cdata->pvu_csa_ks[j] = get_key_struct(); }
4342
								
4343
							if(ecm[0] == 0x80)
4344
								{ set_even_control_word(cdata->pvu_csa_ks[j], cw[j]); }
4345
							else
4346
								{ set_odd_control_word(cdata->pvu_csa_ks[j], cw[j]); }
4347
							
4348
							cdata->pvu_csa_used = 1;
4349
						}
4350
						else
4351
						{
4352
							if(ecm[0] == 0x80)
4353
								{ des_set_key(cw[j], cdata->pvu_des_ks[j][0]); }
4354
							else
4355
								{ des_set_key(cw[j], cdata->pvu_des_ks[j][1]); }
4356
							
4357
							cdata->pvu_csa_used = 0;
4358
						}
4359
					}
4360
#ifdef WITH_EMU
4361
				}
4362
				
4363
				if(cw_ex != NULL)
4364
				{	
4365
					cw_ex->mode = CW_MODE_MULTIPLE_CW;
4366
					
4367
					if(csaUsed)
4368
					{
4369
						cw_ex->algo = CW_ALGO_CSA;
4370
						cw_ex->algo_mode = CW_ALGO_MODE_ECB;
4371
					}
4372
					else
4373
					{
4374
						cw_ex->algo = CW_ALGO_DES;
4375
						cw_ex->algo_mode = CW_ALGO_MODE_ECB;
4376
					}
4377
					
4378
					for(j = 0; j < 4; j++)
4379
					{
4380
						dwp = cw_ex->audio[j];
4381
						
4382
						memset(dwp, 0, 16);
4383
						
4384
						if(ecm[0] == 0x80)
4385
						{
4386
							memcpy(dwp, cw[PVU_CW_A1+j], 8);
4387
							
4388
							if(csaUsed)
4389
							{
4390
								for(k = 0; k < 8; k += 4)
4391
								{
4392
									dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff);
4393
								}
4394
							}
4395
						}
4396
						else
4397
						{
4398
							memcpy(&dwp[8], cw[PVU_CW_A1+j], 8);
4399
							
4400
							if(csaUsed)
4401
							{
4402
								for(k = 8; k < 16; k += 4)
4403
								{
4404
									dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff);
4405
								}
4406
							}
4407
						}
4408
					}
4409
					
4410
					dwp = cw_ex->data;
4411
					
4412
					memset(dwp, 0, 16);
4413
					
4414
					if(ecm[0] == 0x80)
4415
					{
4416
						memcpy(dwp, cw[PVU_CW_HSD], 8);
4417
						
4418
						if(csaUsed)
4419
						{
4420
							for(k = 0; k < 8; k += 4)
4421
							{
4422
								dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff);
4423
							}
4424
						}
4425
					}
4426
					else
4427
					{
4428
						memcpy(&dwp[8], cw[PVU_CW_HSD], 8);
4429
						
4430
						if(csaUsed)
4431
						{
4432
							for(k = 8; k < 16; k += 4)
4433
							{
4434
								dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff);
4435
							}
4436
						}
4437
					}
4438
				}
4439
#endif		
4440
			}
4441
			else
4442
			{
4443
				// Calculate only video cw
4444
				PowervuCalculateCw(PVU_CW_VID, seed[PVU_CW_VID], csaUsed, convolvedCw[PVU_CW_VID], cw[PVU_CW_VID], baseCw,
4445
									seedEcmCw, hashModeCw, needsUnmasking, xorMode);
4446
			}
4447
			
4448
			memset(dw, 0, 16);
4449
			
4450
			if(ecm[0] == 0x80)
4451
			{
4452
				memcpy(dw, cw[PVU_CW_VID], 8);
4453
				
4454
				if(csaUsed)
4455
				{
4456
					for(k = 0; k < 8; k += 4)
4457
					{
4458
						dw[k + 3] = ((dw[k] + dw[k + 1] + dw[k + 2]) & 0xff);
4459
					}
4460
				}
4461
			}
4462
			else
4463
			{
4464
				memcpy(&dw[8], cw[PVU_CW_VID], 8);
4465
				
4466
				if(csaUsed)
4467
				{
4468
					for(k = 8; k < 16; k += 4)
4469
					{
4470
						dw[k + 3] = ((dw[k] + dw[k + 1] + dw[k + 2]) & 0xff);
4471
					}
4472
				}
4473
			}
4474
			
4475
			return 0;
4476
		
4477
		default:
4478
			break;
4479
		}
4480
		i += nanoLen;
4481
	}
4482
4483
	return ret;
4484
}
4485
4486
4487
// Drecrypt EMU
4488
static void DREover(const uint8_t *ECMdata, uint8_t *dw)
4489
{
4490
	uint8_t key[8];
4491
	uint32_t key_schedule[32];
4492
	
4493
	if (ECMdata[2] >= (43 + 4) && ECMdata[40] == 0x3A && ECMdata[41] == 0x4B)
4494
	{
4495
		if (!FindKey('D', ECMdata[42] & 0x0F, 0, "OVER", key, 8, 1, 0, 0, NULL))
4496
		{
4497
			return;
4498
		}
4499
4500
		des_set_key(key, key_schedule);
4501
4502
		des(dw, key_schedule, 0); // even dw post-process
4503
		des(dw + 8, key_schedule, 0); // odd dw post-process
4504
	}
4505
}
4506
4507
static uint32_t DreGostDec(uint32_t inData)
4508
{
4509
	static uint8_t Sbox[128] =
4510
	{
4511
		0x0E,0x04,0x0D,0x01,0x02,0x0F,0x0B,0x08,0x03,0x0A,0x06,0x0C,0x05,0x09,0x00,0x07,
4512
		0x0F,0x01,0x08,0x0E,0x06,0x0B,0x03,0x04,0x09,0x07,0x02,0x0D,0x0C,0x00,0x05,0x0A,
4513
		0x0A,0x00,0x09,0x0E,0x06,0x03,0x0F,0x05,0x01,0x0D,0x0C,0x07,0x0B,0x04,0x02,0x08,
4514
		0x07,0x0D,0x0E,0x03,0x00,0x06,0x09,0x0A,0x01,0x02,0x08,0x05,0x0B,0x0C,0x04,0x0F,
4515
		0x02,0x0C,0x04,0x01,0x07,0x0A,0x0B,0x06,0x08,0x05,0x03,0x0F,0x0D,0x00,0x0E,0x09,
4516
		0x0C,0x01,0x0A,0x0F,0x09,0x02,0x06,0x08,0x00,0x0D,0x03,0x04,0x0E,0x07,0x05,0x0B,
4517
		0x04,0x0B,0x02,0x0E,0x0F,0x00,0x08,0x0D,0x03,0x0C,0x09,0x07,0x05,0x0A,0x06,0x01,
4518
		0x0D,0x02,0x08,0x04,0x06,0x0F,0x0B,0x01,0x0A,0x09,0x03,0x0E,0x05,0x00,0x0C,0x07
4519
	};
4520
	uint8_t i, j;
4521
	
4522
	for(i = 0; i < 8; i++)
4523
	{
4524
		j = (inData >> 28) & 0x0F;
4525
		inData = (inData << 4) | (Sbox[i * 16 + j] & 0x0F);
4526
	}
4527
	
4528
	inData = (inData << 11) | (inData >> 21);
4529
	
4530
	return (inData);
4531
}
4532
4533
static void DrecryptDecrypt(uint8_t *Data, uint8_t *Key) // DRE GOST 28147-89 CORE
4534
{
4535
	int i, j;
4536
	uint32_t L_part = 0, R_part = 0, temp = 0;
4537
4538
	for(i = 0; i < 4; i++) L_part = (L_part << 8) | (Data[i] & 0xFF), R_part = (R_part << 8) | (Data[i + 4] & 0xFF);
4539
4540
	for(i = 0; i < 4; i++)
4541
	{
4542
		temp = ((Key[i*8+0] & 0xFF) << 24) | ((Key[i*8+1] & 0xFF) << 16) | ((Key[i*8+2] & 0xFF) << 8) | (Key[i*8+3] & 0xFF);
4543
		R_part ^= DreGostDec(temp + L_part);
4544
		temp = ((Key[i*8+4] & 0xFF) << 24) | ((Key[i*8+5] & 0xFF) << 16) | ((Key[i*8+6] & 0xFF) << 8) | (Key[i*8+7] & 0xFF);
4545
		L_part ^= DreGostDec(temp + R_part);
4546
	}
4547
4548
	for(j = 0; j < 3; j++)
4549
	{
4550
		for(i = 3; i >= 0; i--)
4551
		{
4552
			temp = ((Key[i*8+4] & 0xFF) << 24) | ((Key[i*8+5] & 0xFF) << 16) | ((Key[i*8+6] & 0xFF) << 8) | (Key[i*8+7] & 0xFF);
4553
			R_part ^= DreGostDec(temp + L_part);
4554
			temp = ((Key[i*8+0] & 0xFF) << 24) | ((Key[i*8+1] & 0xFF) << 16) | ((Key[i*8+2] & 0xFF) << 8) | (Key[i*8+3] & 0xFF);
4555
			L_part ^= DreGostDec(temp + R_part);
4556
		}
4557
	}
4558
4559
	for(i = 0; i < 4; i++) Data[i] = (R_part >> i*8) & 0xFF, Data[i+4] = (L_part >> i*8) & 0xFF;
4560
}
4561
4562
static void DrecryptPostCw(uint8_t* ccw)
4563
{
4564
	uint32_t i, j;
4565
	uint8_t tmp[4];
4566
	
4567
	for(i = 0; i < 4; i++)
4568
	{
4569
		for(j = 0; j < 4; j++)
4570
		{
4571
			tmp[j] = ccw[3 - j];
4572
		}
4573
		
4574
		for(j = 0; j < 4; j++)
4575
		{
4576
			ccw[j] = tmp[j];
4577
		}
4578
		
4579
		ccw += 4;
4580
	}
4581
}
4582
4583
static void DrecryptSwap(uint8_t* ccw)
4584
{
4585
	uint32_t tmp1, tmp2;
4586
4587
	memcpy(&tmp1, ccw, 4);
4588
	memcpy(&tmp2, ccw + 4, 4);
4589
4590
	memcpy(ccw, ccw + 8, 8);
4591
4592
	memcpy(ccw + 8 , &tmp1, 4);
4593
	memcpy(ccw + 8 + 4, &tmp2, 4);
4594
}
4595
4596
static int8_t Drecrypt2ECM(uint32_t provId, uint8_t *ecm, uint8_t *dw)
4597
{
4598
	uint8_t ecmDataLen, ccw[16], key[32];
4599
	uint16_t ecmLen, overcryptId;
4600
	char keyName[EMU_MAX_CHAR_KEYNAME];
4601
4602
	ecmLen = GetEcmLen(ecm);
4603
4604
	if (ecmLen < 3)
4605
	{
4606
		return 1; // Not supported
4607
	}
4608
4609
	ecmDataLen = ecm[2];
4610
4611
	if (ecmLen < ecmDataLen + 3)
4612
	{
4613
		return 4; // Corrupt data
4614
	}
4615
4616
	switch (provId & 0xFF)
4617
	{
4618
		case 0x11:
4619
		{
4620
			if (ecm[3] == 0x56)
4621
			{
4622
				snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X%02X", ecm[6], ecm[5]);
4623
4624
				if (!FindKey('D', 0x4AE111, 0, keyName, key, 32, 1, 0, 0, NULL))
4625
				{
4626
					return 2;
4627
				}
4628
			}
4629
			else
4630
			{
4631
				snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X%02X", ecm[6], ecm[3]);
4632
4633
				if (!FindKey('D', 0x4AE111, 0, keyName, key, 32, 1, 0, 0, NULL))
4634
				{
4635
					return 2;
4636
				}
4637
			}
4638
4639
			break;
4640
		}
4641
4642
		case 0x14:
4643
		{
4644
			snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X%02X", ecm[6], ecm[5]);
4645
4646
			if (!FindKey('D', 0x4AE114, 0, keyName, key, 32, 1, 0, 0, NULL))
4647
			{
4648
				return 2;
4649
			}
4650
4651
			break;
4652
		}
4653
4654
		default:
4655
			return 1;
4656
	}
4657
4658
	memcpy(ccw, ecm + 13, 16);
4659
4660
	DrecryptPostCw(key);
4661
	DrecryptPostCw(key + 16);
4662
4663
	DrecryptDecrypt(ccw, key);
4664
	DrecryptDecrypt(ccw + 8, key);
4665
4666
	if (ecm[2] >= 46 && ecm[43] == 1 && provId == 0x11)
4667
	{
4668
		DrecryptSwap(ccw);
4669
		overcryptId = b2i(2, &ecm[44]);
4670
4671
		Drecrypt2OverCW(overcryptId, ccw);
4672
4673
		if (isValidDCW(ccw))
4674
		{
4675
			memcpy(dw, ccw, 16);
4676
			return 0;
4677
		}
4678
4679
		return 9; // ICG error
4680
	}
4681
4682
	DREover(ecm, ccw);
4683
4684
	if (isValidDCW(ccw))
4685
	{
4686
		DrecryptSwap(ccw);
4687
		memcpy(dw, ccw, 16);
4688
		return 0;
4689
	}
4690
4691
	return 1;
4692
}
4693
4694
// Tandberg EMU
4695
static uint16_t TandbergChecksum(uint8_t *data, uint8_t length)
4696
{
4697
	// ECM and EMM checksum calculation
4698
	// 1. Combine data in 2 byte groups
4699
	// 2. Add them together
4700
	// 3. Multiply result by itself (power of 7)
4701
	// 4. XOR with fixed value 0x17E3
4702
	
4703
	uint8_t i;
4704
	uint16_t checksum = 0;
4705
	
4706
	for(i = 0; i < length; i += 2)
4707
	{
4708
		checksum += (data[i] << 8) | data[i + 1];
4709
	}
4710
	
4711
	checksum =  checksum * checksum * checksum * checksum * checksum * checksum * checksum;
4712
	checksum ^= 0x17E3;
4713
	
4714
	return checksum;
4715
}
4716
4717
static int8_t GetTandbergKey(uint32_t keyIndex, char *keyName, uint8_t *key, uint32_t keyLength)
4718
{
4719
	// keyIndex: ecm keys --> entitlementId
4720
	//			 emm keys --> aeskeyIndex
4721
	//			 aes keys --> keyIndex
4722
4723
	// keyName: ecm keys --> "01"
4724
	//			emm keys --> "MK" or "MK01"
4725
	//			aes keys --> "AES"
4726
4727
	return FindKey('T', keyIndex, 0, keyName, key, keyLength, 1, 0, 0, NULL);
4728
}
4729
4730
static int8_t TandbergECM(uint8_t *ecm, uint8_t *dw)
4731
{
4732
	uint8_t nanoType, nanoLength;
4733
	uint8_t* nanoData;
4734
	uint32_t pos = 3;
4735
	uint32_t entitlementId;
4736
	uint32_t ks[32];
4737
	uint8_t ecmKey[8];
4738
	uint16_t ecmLen = GetEcmLen(ecm);
4739
	
4740
	if(ecmLen < 5)
4741
	{
4742
		return 1;
4743
	}
4744
	
4745
	do
4746
	{
4747
		nanoType = ecm[pos];
4748
		nanoLength = ecm[pos+1];
4749
		
4750
		if(pos + 2 + nanoLength > ecmLen)
4751
		{
4752
			break;
4753
		}
4754
		
4755
		nanoData = ecm + pos + 2;
4756
		
4757
		// ECM validation
4758
		uint16_t payloadChecksum = (nanoData[nanoLength - 2] << 8) | nanoData[nanoLength - 1];
4759
		uint16_t calculatedChecksum = TandbergChecksum(nanoData, nanoLength - 2);
4760
		
4761
		if(calculatedChecksum != payloadChecksum)
4762
		{
4763
			cs_log("ECM checksum error (%.4X instead of %.4X)", calculatedChecksum, payloadChecksum);
4764
			return 8;
4765
		}
4766
		// End of ECM validation
4767
		
4768
		switch(nanoType)
4769
		{
4770
			case 0xEC: // Director v6 (September 2017)
4771
			{
4772
				if(nanoLength != 0x28)
4773
				{
4774
					cs_log("WARNING: nanoType EC length (%d) != %d", nanoLength, 0x28);
4775
					break;
4776
				}
4777
				
4778
				entitlementId = b2i(4, nanoData);
4779
				
4780
				if(!GetTandbergKey(entitlementId, "01", ecmKey, 8))
4781
				{
4782
					return 2;
4783
				}
4784
				
4785
				cs_log("Active entitlement %.4X", entitlementId);
4786
				
4787
				// Step 1 - Decrypt DES CBC with ecmKey and iv = { 0 } (equal to nanoED)
4788
				uint8_t encryptedData[32] = { 0 };
4789
				memcpy(encryptedData, nanoData + 6, 32);
4790
				
4791
				uint8_t iv[8] = { 0 };
4792
				des_cbc_decrypt(encryptedData, iv, ecmKey, 32);
4793
				
4794
				uint8_t nanoMode = nanoData[5];
4795
4796
				if ((nanoMode & 0x20) == 0) // Old algo
4797
				{
4798
					// Step 2 - Create CW (equal to nano ED)
4799
					dw[0] = encryptedData[0x05];
4800
					dw[1] = encryptedData[0x19];
4801
					dw[2] = encryptedData[0x1D];
4802
4803
					dw[4] = encryptedData[0x0B];
4804
					dw[5] = encryptedData[0x12];
4805
					dw[6] = encryptedData[0x1A];
4806
4807
					dw[8] = encryptedData[0x16];
4808
					dw[9] = encryptedData[0x03];
4809
					dw[10] = encryptedData[0x11];
4810
4811
					dw[12] = encryptedData[0x18];
4812
					dw[13] = encryptedData[0x10];
4813
					dw[14] = encryptedData[0x0E];
4814
4815
					return 0;
4816
				}
4817
				else // New algo (overencryption with AES)
4818
				{
4819
					// Step 2 - Prepare data for AES (it is like the creation of CW in nanoED but swapped each 8 bytes)
4820
					uint8_t dataEC[16] = { 0 };
4821
4822
					dataEC[0] = encryptedData[0x02];
4823
					dataEC[1] = encryptedData[0x0E];
4824
					dataEC[2] = encryptedData[0x10];
4825
					dataEC[3] = encryptedData[0x18];
4826
					dataEC[4] = encryptedData[0x09];
4827
					dataEC[5] = encryptedData[0x11];
4828
					dataEC[6] = encryptedData[0x03];
4829
					dataEC[7] = encryptedData[0x16];
4830
4831
					dataEC[8] = encryptedData[0x13];
4832
					dataEC[9] = encryptedData[0x1A];
4833
					dataEC[10] = encryptedData[0x12];
4834
					dataEC[11] = encryptedData[0x0B];
4835
					dataEC[12] = encryptedData[0x04];
4836
					dataEC[13] = encryptedData[0x1D];
4837
					dataEC[14] = encryptedData[0x19];
4838
					dataEC[15] = encryptedData[0x05];
4839
4840
					// Step 3 - Decrypt AES CBC with new aesKey and iv 2EBD816A5E749A708AE45ADDD84333DE
4841
					uint8_t aesKeyIndex = nanoMode & 0x1F; // 32 possible AES keys
4842
					uint8_t aesKey[16] = { 0 };
4843
4844
					if(!GetTandbergKey(aesKeyIndex, "AES", aesKey, 16))
4845
					{
4846
						return 2;
4847
					}
4848
4849
					struct aes_keys aes;
4850
					aes_set_key(&aes, (char *)aesKey);
4851
4852
					uint8_t ivAes[16] = { 0x2E, 0xBD, 0x81, 0x6A, 0x5E, 0x74, 0x9A, 0x70, 0x8A, 0xE4, 0x5A, 0xDD, 0xD8, 0x43, 0x33, 0xDE };
4853
					aes_cbc_decrypt(&aes, dataEC, 16, ivAes);
4854
4855
					// Step 4 - Create CW (a simple swap)
4856
					uint8_t offset;
4857
					for (offset = 0; offset < 16; offset++)
4858
					{
4859
						dw[offset] = dataEC[15 - offset];
4860
					}
4861
4862
					return 0;
4863
				}
4864
			}
4865
4866
			case 0xED: // ECM_TAG_CW_DESCRIPTOR
4867
			{
4868
				if(nanoLength != 0x26)
4869
				{
4870
					cs_log("WARNING: nanoType ED length (%d) != %d", nanoLength, 0x26);
4871
					break;
4872
				}
4873
				
4874
				entitlementId = b2i(4, nanoData);
4875
				
4876
				if(!GetTandbergKey(entitlementId, "01", ecmKey, 8))
4877
				{
4878
					return 2;
4879
				}
4880
				
4881
				cs_log("Active entitlement %.4X", entitlementId);
4882
				
4883
				uint8_t encryptedData[32] = { 0 };
4884
				memcpy(encryptedData, nanoData + 4, 32);
4885
				
4886
				uint8_t iv[8] = { 0 };
4887
				des_cbc_decrypt(encryptedData, iv, ecmKey, 32);
4888
				
4889
				dw[0] = encryptedData[0x05];
4890
				dw[1] = encryptedData[0x19];
4891
				dw[2] = encryptedData[0x1D];
4892
				dw[4] = encryptedData[0x0B];
4893
				dw[5] = encryptedData[0x12];
4894
				dw[6] = encryptedData[0x1A];
4895
				dw[8] = encryptedData[0x16];
4896
				dw[9] = encryptedData[0x03];
4897
				dw[10] = encryptedData[0x11];
4898
				dw[12] = encryptedData[0x18];
4899
				dw[13] = encryptedData[0x10];
4900
				dw[14] = encryptedData[0x0E];
4901
				
4902
				return 0;
4903
			}
4904
			
4905
			case 0xEE: // ECM_TAG_CW_DESCRIPTOR
4906
			{
4907
				if(nanoLength != 0x16)
4908
				{
4909
					cs_log("WARNING: nanoType EE length (%d) != %d", nanoLength, 0x16);
4910
					break;
4911
				}
4912
				
4913
				entitlementId = b2i(4, nanoData);
4914
				
4915
				if(!GetTandbergKey(entitlementId, "01", ecmKey, 8))
4916
				{
4917
					return 2;
4918
				}
4919
				
4920
				cs_log("Active entitlement %.4X", entitlementId);
4921
				
4922
				memcpy(dw, nanoData + 4 + 8, 8); // even
4923
				memcpy(dw + 8, nanoData + 4, 8); // odd
4924
				
4925
				des_set_key(ecmKey, ks);
4926
				
4927
				des(dw, ks, 0);
4928
				des(dw + 8, ks, 0);
4929
				
4930
				return 0;
4931
			}
4932
			
4933
			default:
4934
				cs_log("WARNING: nanoType %.2X not supported", nanoType);
4935
			break;
4936
		}
4937
		
4938
		pos += 2 + nanoLength;
4939
		
4940
	} while (pos < ecmLen);
4941
	
4942
	return 1;
4943
}
4944
4945
const char* GetProcessECMErrorReason(int8_t result)
4946
{
4947
	switch(result) {
4948
	case 0:
4949
		return "No error";
4950
	case 1:
4951
		return "ECM not supported";
4952
	case 2:
4953
		return "Key not found";
4954
	case 3:
4955
		return "Nano80 problem";
4956
	case 4:
4957
		return "Corrupt data";
4958
	case 5:
4959
		return "CW not found";
4960
	case 6:
4961
		return "CW checksum error";
4962
	case 7:
4963
		return "Out of memory";
4964
	case 8:
4965
		return "ECM checksum error";
4966
	case 9:
4967
		return "ICG error";
4968
	default:
4969
		return "Unknown";
4970
	}
4971
}
4972
4973
/* Error codes
4974
0  OK
4975
1  ECM not supported
4976
2  Key not found
4977
3  Nano80 problem
4978
4  Corrupt data
4979
5  CW not found
4980
6  CW checksum error
4981
7  Out of memory
4982
8  ECM checksum error
4983
9  ICG error
4984
*/
4985
#ifdef WITH_EMU
4986
int8_t ProcessECM(struct s_reader *rdr, int16_t ecmDataLen, uint16_t caid, uint32_t provider, const uint8_t *ecm,
4987
				  uint8_t *dw, uint16_t srvid, uint16_t ecmpid, EXTENDED_CW* cw_ex)
4988
#else
4989
int8_t ProcessECM(struct s_reader *rdr, int16_t ecmDataLen, uint16_t caid, uint32_t provider, const uint8_t *ecm,
4990
				  uint8_t *dw, uint16_t srvid, uint16_t ecmpid)
4991
#endif
4992
{
4993
	int8_t result = 1, i;
4994
	uint8_t ecmCopy[EMU_MAX_ECM_LEN];
4995
	uint16_t ecmLen = 0;
4996
4997
	if(ecmDataLen < 3) {
4998
		// accept requests without ecm only for biss
4999
		if((caid>>8) != 0x26 && caid != 0xFFFF) {
5000
			return 1;
5001
		}
5002
	}
5003
	else {
5004
		ecmLen = GetEcmLen(ecm);
5005
	}
5006
5007
	if(ecmLen > ecmDataLen) {
5008
		return 1;
5009
	}
5010
5011
	if(ecmLen > EMU_MAX_ECM_LEN) {
5012
		return 1;
5013
	}
5014
	memcpy(ecmCopy, ecm, ecmLen);
5015
5016
	if((caid >> 8) == 0x0D) {
5017
		result = CryptoworksECM(caid, ecmCopy, dw);
5018
	}
5019
	else if((caid >> 8) == 0x09) {
5020
		result = SoftNDSECM(caid, ecmCopy, dw);
5021
	}
5022
	else if(caid == 0x0500) {
5023
		result = ViaccessECM(ecmCopy, dw);
5024
	}
5025
	else if((caid >> 8) == 0x18) {
5026
		result = Nagra2ECM(ecmCopy, dw);
5027
	}
5028
	else if((caid >> 8) == 0x06) {
5029
		result = Irdeto2ECM(caid, ecmCopy, dw);
5030
	}
5031
	else if((caid >> 8) == 0x26 || caid == 0xFFFF) {
5032
		result = BissECM(rdr, ecm, ecmDataLen, dw, srvid, ecmpid);
5033
	}
5034
	else if((caid >> 8) == 0x0E) {
5035
#ifdef WITH_EMU
5036
		result = PowervuECM(ecmCopy, dw, srvid, NULL, cw_ex);
5037
#else
5038
		result = PowervuECM(ecmCopy, dw, NULL);
5039
#endif
5040
	}
5041
	else if(caid == 0x4AE1) {
5042
		result = Drecrypt2ECM(provider, ecmCopy, dw);
5043
	}
5044
	else if((caid >> 8) == 0x10) {
5045
		result = TandbergECM(ecmCopy, dw);
5046
	}
5047
5048
	// fix dcw checksum
5049
	if(result == 0 && !((caid >> 8) == 0x0E)) {
5050
		for(i = 0; i < 16; i += 4) {
5051
			dw[i + 3] = ((dw[i] + dw[i + 1] + dw[i + 2]) & 0xff);
5052
		}
5053
	}
5054
5055
	if(result != 0) {
5056
		cs_log("ECM failed: %s", GetProcessECMErrorReason(result));
5057
	}
5058
5059
	return result;
5060
}
5061
5062
// Viaccess EMM EMU
5063
static int8_t ViaccessEMM(uint8_t *emm, uint32_t *keysAdded)
5064
{
5065
	uint8_t nanoCmd = 0, subNanoCmd = 0, *tmp;
5066
	uint16_t i = 0, j = 0, k = 0, emmLen = GetEcmLen(emm);
5067
	uint8_t ecmKeys[6][16], keyD0[2], emmKey[16], emmXorKey[16], provName[17];
5068
	uint8_t ecmKeyCount = 0, emmKeyIndex = 0, aesMode = 0x0D;
5069
	uint8_t nanoLen = 0, subNanoLen = 0, haveEmmXorKey = 0, haveNewD0 = 0;
5070
	uint32_t ui1, ui2, ui3, ecmKeyIndex[6], provider = 0, ecmProvider = 0;
5071
	char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36];
5072
	struct aes_keys aes;
5073
5074
	memset(keyD0, 0, 2);
5075
	memset(ecmKeyIndex, 0, sizeof(uint32_t)*6);
5076
5077
	for(i=3; i+2<emmLen; ) {
5078
		nanoCmd = emm[i++];
5079
		nanoLen = emm[i++];
5080
		if(i+nanoLen > emmLen) {
5081
			return 1;
5082
		}
5083
5084
		switch(nanoCmd) {
5085
		case 0x90: {
5086
			if(nanoLen < 3) {
5087
				break;
5088
			}
5089
			ui1 = emm[i+2];
5090
			ui2 = emm[i+1];
5091
			ui3 = emm[i];
5092
			provider = (ui1 | (ui2 << 8) | (ui3 << 16));
5093
			if(provider == 0x00D00040) {
5094
				ecmProvider = 0x030B00;
5095
			}
5096
			else {
5097
				return 1;
5098
			}
5099
			break;
5100
		}
5101
		case 0xD2: {
5102
			if(nanoLen < 2) {
5103
				break;
5104
			}
5105
			emmKeyIndex = emm[i+1];
5106
			break;
5107
		}
5108
		case 0x41: {
5109
			if(nanoLen < 1) {
5110
				break;
5111
			}
5112
			if(!GetViaKey(emmKey, provider, 'M', emmKeyIndex, 16, 1)) {
5113
				return 2;
5114
			}
5115
			memset(provName, 0, 17);
5116
			memset(emmXorKey, 0, 16);
5117
			k = nanoLen < 16 ? nanoLen : 16;
5118
			memcpy(provName, &emm[i], k);
5119
			aes_set_key(&aes, (char*)emmKey);
5120
			aes_decrypt(&aes, emmXorKey, 16);
5121
			for(j=0; j<16; j++) {
5122
				provName[j] ^= emmXorKey[j];
5123
			}
5124
			provName[k] = 0;
5125
5126
			if(strcmp((char*)provName, "TNTSAT") != 0 && strcmp((char*)provName, "TNTSATPRO") != 0
5127
					&&strcmp((char*)provName, "CSAT V") != 0) {
5128
				return 1;
5129
			}
5130
			break;
5131
		}
5132
		case 0xBA: {
5133
			if(nanoLen < 2) {
5134
				break;
5135
			}
5136
			GetViaKey(keyD0, ecmProvider, 'D', 0, 2, 0);
5137
			ui1 = (emm[i] << 8) | emm[i+1];
5138
			if( (uint32_t)((keyD0[0] << 8) | keyD0[1]) < ui1 || (keyD0[0] == 0x00 && keyD0[1] == 0x00)) {
5139
				keyD0[0] = emm[i];
5140
				keyD0[1] = emm[i+1];
5141
				haveNewD0 = 1;
5142
				break;
5143
			}
5144
			return 0;
5145
		}
5146
		case 0xBC: {
5147
			break;
5148
		}
5149
		case 0x43: {
5150
			if(nanoLen < 16) {
5151
				break;
5152
			}
5153
			memcpy(emmXorKey, &emm[i], 16);
5154
			haveEmmXorKey = 1;
5155
			break;
5156
		}
5157
		case 0x44: {
5158
			if(nanoLen < 3) {
5159
				break;
5160
			}
5161
			if (!haveEmmXorKey) {
5162
				memset(emmXorKey, 0, 16);
5163
			}
5164
			tmp = (uint8_t*)malloc(((nanoLen/16)+1)*16*sizeof(uint8_t));
5165
			if(tmp == NULL) {
5166
				return 7;
5167
			}
5168
			memcpy(tmp, &emm[i], nanoLen);
5169
			aes_set_key(&aes, (char*)emmKey);
5170
			for(j=0; j<nanoLen; j+=16) {
5171
				aes_decrypt(&aes, emmXorKey, 16);
5172
				for(k=0; k<16; k++) {
5173
					tmp[j+k] ^= emmXorKey[k];
5174
				}
5175
			}
5176
			memcpy(&emm[i-2], tmp, nanoLen);
5177
			free(tmp);
5178
			nanoLen = 0;
5179
			i -= 2;
5180
			break;
5181
		}
5182
		case 0x68: {
5183
			if(ecmKeyCount > 5) {
5184
				break;
5185
			}
5186
			for(j=i; j+2<i+nanoLen; ) {
5187
				subNanoCmd = emm[j++];
5188
				subNanoLen = emm[j++];
5189
				if(j+subNanoLen > i+nanoLen) {
5190
					break;
5191
				}
5192
				switch(subNanoCmd) {
5193
				case 0xD2: {
5194
					if(nanoLen < 2) {
5195
						break;
5196
					}
5197
					aesMode = emm[j];
5198
					emmKeyIndex = emm[j+1];
5199
					break;
5200
				}
5201
				case 0x01: {
5202
					if(nanoLen < 17) {
5203
						break;
5204
					}
5205
					ecmKeyIndex[ecmKeyCount] = emm[j];
5206
					memcpy(&ecmKeys[ecmKeyCount], &emm[j+1], 16);
5207
					if(!GetViaKey(emmKey, provider, 'M', emmKeyIndex, 16, 1)) {
5208
						break;
5209
					}
5210
5211
					if(aesMode == 0x0F || aesMode == 0x11) {
5212
						hdSurEncPhase1_D2_0F_11(ecmKeys[ecmKeyCount]);
5213
						hdSurEncPhase2_D2_0F_11(ecmKeys[ecmKeyCount]);
5214
					}
5215
					else if(aesMode == 0x13 || aesMode == 0x15) {
5216
						hdSurEncPhase1_D2_13_15(ecmKeys[ecmKeyCount]);
5217
					}
5218
					aes_set_key(&aes, (char*)emmKey);
5219
					aes_decrypt(&aes, ecmKeys[ecmKeyCount], 16);
5220
					if(aesMode == 0x0F || aesMode == 0x11) {
5221
						hdSurEncPhase1_D2_0F_11(ecmKeys[ecmKeyCount]);
5222
					}
5223
					else if(aesMode == 0x13 || aesMode == 0x15) {
5224
						hdSurEncPhase2_D2_13_15(ecmKeys[ecmKeyCount]);
5225
					}
5226
5227
					ecmKeyCount++;
5228
					break;
5229
				}
5230
				default:
5231
					break;
5232
				}
5233
				j += subNanoLen;
5234
			}
5235
			break;
5236
		}
5237
		case 0xF0: {
5238
			if(nanoLen != 4) {
5239
				break;
5240
			}
5241
			ui1 = ((emm[i+2] << 8) | (emm[i+1] << 16) | (emm[i] << 24) | emm[i+3]);
5242
			if(fletcher_crc32(emm + 3, emmLen - 11) != ui1) {
5243
				return 4;
5244
			}
5245
5246
			if(haveNewD0) {
5247
				
5248
				SetKey('V', ecmProvider, "D0", keyD0, 2, 1, NULL, NULL);
5249
				
5250
				for(j=0; j<ecmKeyCount; j++) {
5251
					
5252
					snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "E%X", ecmKeyIndex[j]);
5253
					SetKey('V', ecmProvider, keyName, ecmKeys[j], 16, 1, NULL, NULL);
5254
					
5255
					(*keysAdded)++;
5256
					cs_hexdump(0, ecmKeys[j], 16, keyValue, sizeof(keyValue));
5257
					cs_log("Key found in EMM: V %06X %s %s", ecmProvider, keyName, keyValue);
5258
				}
5259
			}
5260
			break;
5261
		}
5262
		default:
5263
			break;
5264
		}
5265
		i += nanoLen;
5266
	}
5267
	return 0;
5268
}
5269
5270
// Irdeto2 EMM EMU
5271
static int8_t Irdeto2DoEMMTypeOP(uint32_t ident, uint8_t *emm, uint8_t *keySeed, uint8_t *keyIV, uint8_t *keyPMK,
5272
								 uint16_t emmLen, uint8_t startOffset, uint8_t length, uint32_t *keysAdded)
5273
{
5274
	uint32_t end, i, l;
5275
	uint8_t tmp[16];
5276
	char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36];
5277
5278
	memset(tmp, 0, 16);
5279
	Irdeto2Encrypt(keySeed, tmp, keyPMK, 16);
5280
	Irdeto2Decrypt(&emm[startOffset], keyIV, keySeed, length);
5281
5282
	i = 16;
5283
	end = startOffset + (length-8 < 0 ? 0 : length-8);
5284
5285
	while(i<end) {
5286
		l = emm[i+1] ? (emm[i+1]&0x3F)+2 : 1;
5287
		switch(emm[i]) {
5288
		case 0x10:
5289
		case 0x50:
5290
			if(l==0x13 && i<=startOffset+length-8-l) {
5291
				Irdeto2Decrypt(&emm[i+3], keyIV, keyPMK, 16);
5292
			}
5293
			break;
5294
		case 0x78:
5295
			if(l==0x14 && i<=startOffset+length-8-l) {
5296
				Irdeto2Decrypt(&emm[i+4], keyIV, keyPMK, 16);
5297
			}
5298
			break;
5299
		}
5300
		i+=l;
5301
	}
5302
5303
	memmove(emm+6, emm+7, emmLen-7);
5304
5305
	i = 15;
5306
	end = startOffset + (length-9 < 0 ? 0 : length-9);
5307
5308
	if(Irdeto2CalculateHash(keySeed, keyIV, emm+3, emmLen-4)) {
5309
		while(i<end) {
5310
			l = emm[i+1] ? (emm[i+1]&0x3F)+2 : 1;
5311
			switch(emm[i]) {
5312
			case 0x10:
5313
			case 0x50:
5314
				if(l==0x13 && i<=startOffset+length-9-l) {
5315
					
5316
					snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X", emm[i+2]>>2);
5317
					SetKey('I', ident, keyName, &emm[i+3], 16, 1, NULL, NULL);
5318
					
5319
					(*keysAdded)++;
5320
					cs_hexdump(0, &emm[i+3], 16, keyValue, sizeof(keyValue));
5321
					cs_log("Key found in EMM: I %06X %s %s", ident, keyName, keyValue);
5322
				}
5323
			}
5324
			i+=l;
5325
		}
5326
5327
		if(*keysAdded > 0) {
5328
			return 0;
5329
		}
5330
	}
5331
5332
	return 1;
5333
}
5334
5335
static int8_t Irdeto2DoEMMTypePMK(uint32_t ident, uint8_t *emm, uint8_t *keySeed, uint8_t *keyIV, uint8_t *keyPMK,
5336
								  uint16_t emmLen, uint8_t startOffset, uint8_t length, uint32_t *keysAdded)
5337
{
5338
	uint32_t end, i, l, j;
5339
	char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36];
5340
5341
	Irdeto2Decrypt(&emm[startOffset], keyIV, keySeed, length);
5342
5343
	i = 13;
5344
	end = startOffset + (length-8 < 0 ? 0 : length-8);
5345
5346
	while(i<end) {
5347
		l = emm[i+1] ? (emm[i+1]&0x3F)+2 : 1;
5348
		switch(emm[i]) {
5349
		case 0x10:
5350
		case 0x50:
5351
			if(l==0x13 && i<=startOffset+length-8-l) {
5352
				Irdeto2Decrypt(&emm[i+3], keyIV, keyPMK, 16);
5353
			}
5354
			break;
5355
		case 0x78:
5356
			if(l==0x14 && i<=startOffset+length-8-l) {
5357
				Irdeto2Decrypt(&emm[i+4], keyIV, keyPMK, 16);
5358
			}
5359
			break;
5360
		case 0x68:
5361
			if(l==0x26 && i<=startOffset+length-8-l) {
5362
				Irdeto2Decrypt(&emm[i+3], keyIV, keyPMK, 16*2);
5363
			}
5364
			break;
5365
		}
5366
		i+=l;
5367
	}
5368
5369
	memmove(emm+7, emm+9, emmLen-9);
5370
5371
	i = 11;
5372
	end = startOffset + (length-10 < 0 ? 0 : length-10);
5373
5374
	if(Irdeto2CalculateHash(keySeed, keyIV, emm+3, emmLen-5)) {
5375
		while(i<end) {
5376
			l = emm[i+1] ? (emm[i+1]&0x3F)+2 : 1;
5377
			switch(emm[i]) {
5378
			case 0x68:
5379
				if(l==0x26 && i<=startOffset+length-10-l) {
5380
					for(j=0; j<2; j++) {
5381
						
5382
						snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "M%01X", 3+j);
5383
						SetKey('I', ident, keyName, &emm[i+3+j*16], 16, 1, NULL, NULL);
5384
						
5385
						(*keysAdded)++;
5386
						cs_hexdump(0, &emm[i+3+j*16], 16, keyValue, sizeof(keyValue));
5387
						cs_log("Key found in EMM: I %06X %s %s", ident, keyName, keyValue);
5388
					}
5389
				}
5390
			}
5391
			i+=l;
5392
		}
5393
5394
		if(*keysAdded > 0) {
5395
			return 0;
5396
		}
5397
	}
5398
5399
	return 1;
5400
}
5401
5402
static const uint8_t fausto_xor[16] = { 0x22, 0x58, 0xBD, 0x85, 0x2E, 0x8E, 0x52, 0x80, 0xA3, 0x79, 0x98, 0x69, 0x68, 0xE2, 0xD8, 0x4D };
5403
5404
static int8_t Irdeto2EMM(uint16_t caid, uint8_t *oemm, uint32_t *keysAdded)
5405
{
5406
	uint8_t length, okeySeed[16], keySeed[16], keyIV[16], keyPMK[16], startOffset, emmType;
5407
	uint32_t ident;
5408
	uint32_t keySeedRef, keyIVRef, keyPMK0Ref, keyPMK1Ref, keyPMK0ERef, keyPMK1ERef;
5409
	uint8_t emmCopy[EMU_MAX_EMM_LEN], *emm = oemm;
5410
	uint16_t emmLen = GetEcmLen(emm);
5411
5412
	if(emmLen < 11) {
5413
		return 1;
5414
	}
5415
5416
	if(emm[3] == 0xC3 || emm[3] == 0xCB) {
5417
		emmType = 2;
5418
		startOffset = 11;
5419
	}
5420
	else {
5421
		emmType = 1;
5422
		startOffset = 10;
5423
	}
5424
5425
	ident = emm[startOffset-2] | caid << 8;
5426
	length = emm[startOffset-1];
5427
5428
5429
	if(emmLen < length+startOffset) {
5430
		return 1;
5431
	}
5432
5433
	keySeedRef = 0;
5434
	while(GetIrdetoKey(okeySeed, ident, 'M', emmType == 1 ? 0 : 0xA, 1, &keySeedRef)) {
5435
		keyIVRef = 0;
5436
		while(GetIrdetoKey(keyIV, ident, 'M', 2, 1, &keyIVRef)) {
5437
5438
			keyPMK0Ref = 0;
5439
			keyPMK1Ref = 0;
5440
			keyPMK0ERef = 0;
5441
			keyPMK1ERef = 0;
5442
5443
			while(GetIrdetoKey(keyPMK, ident, 'M', emmType == 1 ? 3 : 0xB, 1, &keyPMK0Ref)) {
5444
				memcpy(keySeed, okeySeed, 16);
5445
				memcpy(emmCopy, oemm, emmLen);
5446
				emm = emmCopy;
5447
				if(emmType == 1) {
5448
					if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
5449
						return 0;
5450
					}
5451
				}
5452
				else {
5453
					if(Irdeto2DoEMMTypePMK(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
5454
						return 0;
5455
					}
5456
				}
5457
			}
5458
5459
			if(emmType == 1) {
5460
				while(GetIrdetoKey(keyPMK, ident, 'M', 4, 1, &keyPMK1Ref)) {
5461
					memcpy(keySeed, okeySeed, 16);
5462
					memcpy(emmCopy, oemm, emmLen);
5463
					emm = emmCopy;
5464
					if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
5465
						return 0;
5466
					}
5467
				}
5468
5469
				while(GetIrdetoKey(keyPMK, ident, 'M', 5, 1, &keyPMK0ERef)) {
5470
					xxor(keyPMK, 16, keyPMK, fausto_xor);
5471
					memcpy(keySeed, okeySeed, 16);
5472
					memcpy(emmCopy, oemm, emmLen);
5473
					emm = emmCopy;
5474
					if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
5475
						return 0;
5476
					}
5477
				}
5478
5479
				while(GetIrdetoKey(keyPMK, ident, 'M', 6, 1, &keyPMK1ERef)) {
5480
					xxor(keyPMK, 16, keyPMK, fausto_xor);
5481
					memcpy(keySeed, okeySeed, 16);
5482
					memcpy(emmCopy, oemm, emmLen);
5483
					emm = emmCopy;
5484
					if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
5485
						return 0;
5486
					}
5487
				}
5488
			}
5489
5490
			if(keyPMK0Ref == 0 && keyPMK1Ref == 0 && keyPMK0ERef == 0 && keyPMK1ERef == 0) {
5491
				return 2;
5492
			}
5493
		}
5494
		if(keyIVRef == 0) {
5495
			return 2;
5496
		}
5497
	}
5498
	if(keySeedRef == 0) {
5499
		return 2;
5500
	}
5501
5502
	return 1;
5503
}
5504
5505
int32_t GetIrdeto2Hexserial(uint16_t caid, uint8_t *hexserial)
5506
{
5507
	uint32_t i, len;
5508
	KeyDataContainer *KeyDB;
5509
	KeyData *tmpKeyData;
5510
5511
	KeyDB = GetKeyContainer('I');
5512
	if(KeyDB == NULL) {
5513
		return 0;
5514
	}
5515
5516
	for(i=0; i<KeyDB->keyCount; i++) {
5517
5518
		if(KeyDB->EmuKeys[i].provider>>8 != caid) {
5519
			continue;
5520
		}
5521
		if(strcmp(KeyDB->EmuKeys[i].keyName, "MC")) {
5522
			continue;
5523
		}
5524
5525
		tmpKeyData = &KeyDB->EmuKeys[i];
5526
		
5527
		len = tmpKeyData->keyLength;
5528
		if(len > 3)
5529
			{ len = 3; }
5530
		
5531
		memcpy(hexserial+(3-len), tmpKeyData->key, len);
5532
		return 1;
5533
	}
5534
5535
	return 0;
5536
}
5537
5538
5539
// PowerVu EMM EMU
5540
static void PowervuUnmaskEmm(uint8_t *emm)
5541
{
5542
	int i, l;
5543
	
5544
	uint8_t sourcePos[] = {0x03, 0x0C, 0x0D, 0x11, 0x15, 0x18, 0x1D, 0x1F, 0x25, 0x2A, 0x32, 0x35, 0x3A, 0x3B, 0x3E,
5545
						   0x42, 0x47, 0x48, 0x53, 0x58, 0x5C, 0x61, 0x66, 0x69, 0x71, 0x72, 0x78, 0x7B, 0x81, 0x84};
5546
	
5547
	uint8_t destPos[] = {0x02, 0x08, 0x0B, 0x0E, 0x13, 0x16, 0x1E, 0x23, 0x28, 0x2B, 0x2F, 0x33, 0x38, 0x3C, 0x40,
5548
						 0x44, 0x4A, 0x4D, 0x54, 0x57, 0x5A, 0x63, 0x68, 0x6A, 0x70, 0x75, 0x76, 0x7D, 0x82, 0x85};
5549
	
5550
	uint8_t data[0x1E];
5551
	uint8_t hashModeEmm;
5552
	uint8_t mask[0x10];
5553
	uint32_t crc;
5554
	
5555
	// Create Mask for ECM decryption
5556
	PowervuCreateDataEcmEmm(emm, sourcePos, 0x13, 0x1E, data);
5557
	
5558
	hashModeEmm = emm[8] ^ PowervuCrc8Calc(data, 0x1E);
5559
	
5560
	PowervuCreateHash(data, 0x1E, mask, hashModeEmm);
5561
	
5562
	// Fix Header
5563
	emm[3] &= 0x0F;
5564
	emm[3] |= 0x10;
5565
	emm[8]  = 0x00;
5566
	
5567
	// Unmask Body
5568
	for(i = 0; i < 0x1E; i++)
5569
	{
5570
		emm[0x13 + destPos[i]] ^= mask[i & 0x0F];
5571
	}
5572
	
5573
	// Fix CRC (optional)
5574
	l = (((emm[1] << 8) + emm[2]) & 0xFFF) + 3 - 4;
5575
	crc = fletcher_crc32(emm, l);
5576
	
5577
	emm[l + 0] = crc >> 24;
5578
	emm[l + 1] = crc >> 16;
5579
	emm[l + 2] = crc >> 8;
5580
	emm[l + 3] = crc >> 0;
5581
}
5582
5583
static int8_t PowervuEMM(uint8_t *emm, uint32_t *keysAdded)
5584
{
5585
	uint8_t emmInfo, emmType, decryptOk = 0;
5586
	uint16_t emmLen = GetEcmLen(emm);
5587
	uint32_t i, uniqueAddress, groupId, keyRef = 0;
5588
	//uint32_t emmCrc32;
5589
	uint8_t emmKey[7], tmpEmmKey[7], tmp[26];
5590
	char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[16];
5591
	char uaInfo[4+8+1];
5592
5593
	if(emmLen < 50)
5594
	{
5595
		return 1;
5596
	}
5597
	
5598
	// Check if unmasking is needed
5599
	if((emm[3] & 0xF0) == 0x50)
5600
	{
5601
		PowervuUnmaskEmm(emm);
5602
	}
5603
	
5604
	// looks like checksum does not work for all EMMs
5605
	//emmCrc32 = b2i(4, emm+emmLen-4);
5606
	//
5607
	//if(fletcher_crc32(emm, emmLen-4) != emmCrc32)
5608
	//{
5609
	//	return 8;
5610
	//}
5611
	emmLen -= 4;
5612
5613
	uniqueAddress = b2i(4, emm+12);
5614
	snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.8X", uniqueAddress);
5615
	
5616
	do
5617
	{
5618
		if(!GetPowervuEmmKey(emmKey, 0, keyName, 7, 0, keyRef++, &groupId))
5619
		{
5620
			cs_log_dbg(D_EMM, "EMM error: AU key for UA %s is missing", keyName);
5621
			return 2;
5622
		}
5623
		
5624
		for(i=19; i+27<=emmLen; i+=27) {
5625
			emmInfo = emm[i];
5626
			
5627
			if(!GetBit(emmInfo, 7))
5628
			{
5629
				continue;
5630
			}
5631
			
5632
			//keyNb = emm[i] & 0x0F;
5633
			
5634
			memcpy(tmp, emm+i+1, 26);
5635
			memcpy(tmpEmmKey, emmKey, 7);
5636
			PowervuDecrypt(emm+i+1, 26, tmpEmmKey, 0);
5637
			
5638
			if((emm[13] != emm[i+24]) || (emm[14] != emm[i+25]) || (emm[15] != emm[i+26]))
5639
			{
5640
				memcpy(emm+i+1, tmp, 26);
5641
				memcpy(tmpEmmKey, emmKey, 7);
5642
				PowervuDecrypt(emm+i+1, 26, tmpEmmKey, 1);
5643
				
5644
				if((emm[13] != emm[i+24]) || (emm[14] != emm[i+25]) || (emm[15] != emm[i+26]))
5645
				{
5646
					memcpy(emm+i+1, tmp, 26);
5647
					memcpy(tmpEmmKey, emmKey, 7);
5648
					continue;
5649
				}
5650
			}
5651
			
5652
			decryptOk = 1;
5653
			
5654
			emmType = emm[i+2] & 0x7F;
5655
			if(emmType > 1)
5656
			{
5657
				continue;
5658
			}
5659
			
5660
			snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.2X", emmType);
5661
			snprintf(uaInfo, sizeof(uaInfo), "UA: %08X", uniqueAddress);
5662
			
5663
			if(emm[i+3] == 0 && emm[i+4] == 0)
5664
			{
5665
				cs_hexdump(0, &emm[i+3], 7, keyValue, sizeof(keyValue));
5666
				cs_log("Key found in EMM: P %.4X**** %s %s -> REJECTED (looks invalid) UA: %.8X", groupId, keyName, keyValue, uniqueAddress);
5667
				continue;	
5668
			}
5669
			
5670
			UpdateKeysByProviderMask('P', groupId<<16, 0x0000FFFF, keyName, &emm[i+3], 7, uaInfo);
5671
			
5672
			(*keysAdded)++;
5673
			cs_hexdump(0, &emm[i+3], 7, keyValue, sizeof(keyValue));
5674
			cs_log("Key found in EMM: P %.4X**** %s %s ; UA: %.8X", groupId, keyName, keyValue, uniqueAddress);
5675
		}
5676
		
5677
	} while(!decryptOk);
5678
	
5679
	return 0;
5680
}
5681
5682
int32_t GetPowervuHexserials(uint16_t srvid, uint8_t hexserials[][4], int32_t length, int32_t* count)
5683
{
5684
	//srvid == 0xFFFF -> get all
5685
	
5686
	uint32_t i, j;
5687
	uint32_t groupid;
5688
	int32_t len, k;
5689
	KeyDataContainer *KeyDB;
5690
	uint8_t tmp[4];
5691
	int8_t alreadyAdded;
5692
5693
	KeyDB = GetKeyContainer('P');
5694
	if(KeyDB == NULL)
5695
		{ return 0; }
5696
	
5697
	(*count) = 0;
5698
5699
	for(i=0; i<KeyDB->keyCount && (*count)<length ; i++) {
5700
		
5701
		if(KeyDB->EmuKeys[i].provider <= 0x0000FFFF) // skip au keys
5702
			{ continue; }
5703
5704
		if(srvid != 0xFFFF && (KeyDB->EmuKeys[i].provider & 0x0000FFFF) != srvid)
5705
			{ continue; }
5706
		
5707
		groupid = KeyDB->EmuKeys[i].provider>>16;
5708
5709
		for(j=0; j<KeyDB->keyCount && (*count)<length ; j++) {
5710
5711
			if(KeyDB->EmuKeys[j].provider != groupid) // search au key with groupip
5712
				{ continue; }
5713
			
5714
			len = strlen(KeyDB->EmuKeys[j].keyName);
5715
			
5716
			if(len < 3)
5717
				{ continue;}
5718
			
5719
			if(len > 8)
5720
				{ len = 8; }
5721
			
5722
			memset(tmp, 0, 4);
5723
			CharToBin(tmp+(4-(len/2)), KeyDB->EmuKeys[j].keyName, len);
5724
			
5725
			for(k=0, alreadyAdded=0; k<*count; k++)
5726
			{
5727
				if(!memcmp(hexserials[k], tmp, 4))
5728
				{
5729
					alreadyAdded = 1;
5730
					break;
5731
				}
5732
			}
5733
			
5734
			if(!alreadyAdded)
5735
			{
5736
				memcpy(hexserials[*count], tmp, 4);
5737
				(*count)++;
5738
			}
5739
		}
5740
		
5741
	}
5742
5743
	return 1;
5744
}
5745
5746
// Drecrypt EMM EMU
5747
static int8_t DrecryptGetEmmKey(uint8_t *buf, uint32_t keyIdent, uint16_t keyName, uint8_t isCriticalKey)
5748
{
5749
	char keyStr[EMU_MAX_CHAR_KEYNAME];
5750
	snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "MK%04X", keyName);
5751
	return FindKey('D', keyIdent, 0, keyStr, buf, 32, isCriticalKey, 0, 0, NULL);
5752
}
5753
5754
static void DrecryptWriteEebin(const char *path, const char *name)
5755
{
5756
	char tmp[256];
5757
	FILE *file = NULL;
5758
	uint8_t i, buffer[64][32];
5759
	uint32_t prvid;
5760
5761
	// Set path
5762
	if (path != NULL)
5763
	{
5764
		snprintf(tmp, 256, "%s%s", path, name);
5765
	}
5766
	else // No path set, use SoftCam.Keys's path
5767
	{
5768
		snprintf(tmp, 256, "%s%s", emu_keyfile_path, name);
5769
	}
5770
5771
	if ((file = fopen(tmp, "wb")) != NULL)
5772
	{
5773
		cs_log("Writing key file: %s", tmp);
5774
	}
5775
	else
5776
	{
5777
		cs_log("Error writing key file: %s", tmp);
5778
		return;
5779
	}
5780
5781
	// Load keys from db to buffer
5782
	prvid = (strncmp(name, "ee36.bin", 9) == 0) ? 0x4AE111 : 0x4AE114;
5783
5784
	for (i = 0; i < 32; i++) // Load "3B" type keys
5785
	{
5786
		snprintf(tmp, 5, "3B%02X", i);
5787
		if (!FindKey('D', prvid, 0, tmp, buffer[i], 32, 0, 0, 0, NULL))
5788
		{
5789
			memset(buffer[i], 0xFF, 32);
5790
		}
5791
	}
5792
5793
	for (i = 0; i < 32; i++) // Load "56" type keys
5794
	{
5795
		snprintf(tmp, 5, "56%02X", i);
5796
		if (!FindKey('D', prvid, 0, tmp, buffer[32 + i], 32, 0, 0, 0, NULL))
5797
		{
5798
			memset(buffer[32 + i], 0xFF, 32);
5799
		}
5800
	}
5801
5802
	// Write buffer to ee.bin file
5803
	fwrite(buffer, 1, sizeof(buffer), file);
5804
	fclose(file);
5805
}
5806
5807
static int8_t DrecryptProcessEMM(struct s_reader *rdr, uint32_t provId, uint8_t *emm, uint32_t *keysAdded)
5808
{
5809
	uint16_t emmLen, emmDataLen;
5810
	uint32_t i, keyIdent;
5811
	uint16_t keyName;
5812
	uint8_t emmKey[32];
5813
	uint8_t *curECMkey3B = NULL, *curECMkey56 = NULL;
5814
	uint8_t keynum =0, keyidx = 0, keyclass = 0, key1offset, key2offset;
5815
	char newKeyName[EMU_MAX_CHAR_KEYNAME], curKeyName[EMU_MAX_CHAR_KEYNAME], keyValue[100];
5816
	
5817
	emmDataLen = GetEcmLen(emm);
5818
	emmLen = ((emm[1] & 0xF) << 8) | emm[2];
5819
5820
	if (emmDataLen < emmLen + 3)
5821
	{
5822
		return 4; // Corrupt data
5823
	}
5824
5825
	if (emm[0] == 0x91)
5826
	{
5827
		Drecrypt2OverEMM(emm);
5828
		return 0;
5829
	}
5830
	else if (emm[0] == 0x82)
5831
	{
5832
		ReasmEMM82(emm);
5833
		return 0;
5834
	}
5835
	else if (emm[0] != 0x86)
5836
	{
5837
		return 1; // Not supported
5838
	}
5839
5840
	// Emm type 0x86 only
5841
	switch (emm[4])
5842
	{
5843
		case 0x02:
5844
			keynum = 0x2C;
5845
			keyidx = 0x30;
5846
			keyclass = 0x26;
5847
			key1offset = 0x35;
5848
			key2offset = 0x6D;
5849
			break;
5850
5851
		case 0x4D:
5852
			keynum = 0x61;
5853
			keyidx = 0x60;
5854
			keyclass = 0x05;
5855
			key1offset = 0x62;
5856
			key2offset = 0x8B;
5857
			break;
5858
5859
		default:
5860
			return 1; // Not supported
5861
	}
5862
	
5863
	switch (provId & 0xFF)
5864
	{
5865
		case 0x11:
5866
		{
5867
			snprintf(curKeyName, EMU_MAX_CHAR_KEYNAME, "3B%02X", emm[keyclass]);
5868
			FindKey('D', 0x4AE111, 0, curKeyName, curECMkey3B, 32, 0, 0, 0, NULL);
5869
5870
			snprintf(curKeyName, EMU_MAX_CHAR_KEYNAME, "56%02X", emm[keyclass]);
5871
			FindKey('D', 0x4AE111, 0, curKeyName, curECMkey56, 32, 0, 0, 0, NULL);
5872
5873
			break;
5874
		}
5875
5876
		case 0x14:
5877
		{
5878
			snprintf(curKeyName, EMU_MAX_CHAR_KEYNAME, "3B%02X", emm[keyclass]);
5879
			FindKey('D', 0x4AE114, 0, curKeyName, curECMkey3B, 32, 0, 0, 0, NULL);
5880
5881
			snprintf(curKeyName, EMU_MAX_CHAR_KEYNAME, "56%02X", emm[keyclass]);
5882
			FindKey('D', 0x4AE114, 0, curKeyName, curECMkey56, 32, 0, 0, 0, NULL);
5883
5884
			break;
5885
		}
5886
5887
		default:
5888
			return 9; // Wrong provider
5889
	}
5890
	
5891
	keyIdent = (0x4AE1 << 8) | provId;
5892
	keyName = (emm[3] << 8) | emm[keynum];
5893
5894
	if (!DrecryptGetEmmKey(emmKey, keyIdent, keyName, 1))
5895
	{
5896
		return 2;
5897
	}
5898
	
5899
	// Key #1
5900
	for (i = 0; i < 4; i++)
5901
	{
5902
		DrecryptDecrypt(&emm[key1offset + (i * 8)], emmKey);
5903
	}
5904
5905
	// Key #2
5906
	for (i = 0; i < 4; i++)
5907
	{
5908
		DrecryptDecrypt(&emm[key2offset + (i * 8)], emmKey);
5909
	}
5910
5911
	// Key #1
5912
	keyName = emm[keyidx] << 8 | emm[keyclass];
5913
	snprintf(newKeyName, EMU_MAX_CHAR_KEYNAME, "%.4X", keyName);
5914
5915
	if (memcmp(&emm[key1offset], emm[keyidx] == 0x3b ? curECMkey3B : curECMkey56, 32) != 0)
5916
	{
5917
		memcpy(emm[keyidx] == 0x3b ? curECMkey3B : curECMkey56, &emm[key1offset], 32);
5918
		SetKey('D', keyIdent, newKeyName, &emm[key1offset], 32, 0, NULL, NULL);
5919
		(*keysAdded)++;
5920
5921
		cs_hexdump(0, &emm[key1offset], 32, keyValue, sizeof(keyValue));
5922
		cs_log("Key found in EMM: D %.6X %s %s class %02X", keyIdent, newKeyName, keyValue, emm[keyclass]);
5923
	}
5924
	else
5925
	{
5926
		cs_log("Key %.6X %s already exists", keyIdent, newKeyName);
5927
	}
5928
5929
	// Key #2
5930
	keyName = (emm[keyidx] == 0x56 ? 0x3B00 : 0x5600) | emm[keyclass];
5931
	snprintf(newKeyName, EMU_MAX_CHAR_KEYNAME, "%.4X", keyName);
5932
5933
	if (memcmp(&emm[key2offset], emm[keyidx] == 0x3b ? curECMkey56 : curECMkey3B, 32) != 0)
5934
	{
5935
		memcpy(emm[keyidx] == 0x3b ? curECMkey56 : curECMkey3B, &emm[key2offset], 32);
5936
		SetKey('D', keyIdent, newKeyName, &emm[key2offset], 32, 0, NULL, NULL);
5937
		(*keysAdded)++;
5938
5939
		cs_hexdump(0, &emm[key2offset], 32, keyValue, sizeof(keyValue));
5940
		cs_log("Key found in EMM: D %.6X %s %s class %02X", keyIdent, newKeyName, keyValue, emm[keyclass]);
5941
	}
5942
	else
5943
	{
5944
		cs_log("Key %.6X %s already exists", keyIdent, newKeyName);
5945
	}
5946
5947
	if (*keysAdded > 0) // Write new ecm keys to ee.bin file
5948
	{
5949
		switch (provId & 0xFF)
5950
		{
5951
			case 0x11:
5952
				DrecryptWriteEebin(rdr->extee36, "ee36.bin");
5953
				break;
5954
5955
			case 0x14:
5956
				DrecryptWriteEebin(rdr->extee56, "ee56.bin");
5957
				break;
5958
5959
			default:
5960
				cs_log("Provider %02X doesn't have a matching ee.bin file", provId & 0xFF);
5961
				break;
5962
		}
5963
	}
5964
5965
	return 0;
5966
}
5967
5968
static int8_t Drecrypt2EMM(struct s_reader *rdr, uint32_t provId, uint8_t *emm, uint32_t *keysAdded)
5969
{
5970
	int8_t result = DrecryptProcessEMM(rdr, provId, emm, keysAdded);
5971
5972
	if (result == 2)
5973
	{
5974
		uint8_t keynum = 0, emmkey;
5975
		uint32_t i;
5976
		KeyDataContainer *KeyDB = GetKeyContainer('D');
5977
5978
		if (KeyDB == NULL)
5979
		{
5980
			return result;
5981
		}
5982
5983
		for (i = 0; i < KeyDB->keyCount; i++)
5984
		{
5985
			if (KeyDB->EmuKeys[i].provider != ((0x4AE1 << 8) | provId))
5986
			{
5987
				continue;
5988
			}
5989
5990
			if (strlen(KeyDB->EmuKeys[i].keyName) < 6)
5991
			{
5992
				continue;
5993
			}
5994
5995
			if (memcmp(KeyDB->EmuKeys[i].keyName, "MK", 2))
5996
			{
5997
				continue;
5998
			}
5999
6000
			CharToBin(&keynum, KeyDB->EmuKeys[i].keyName + 4, 2);
6001
			emmkey = (emm[4] == 0x4D) ? emm[0x61] : emm[0x2C];
6002
6003
			if (keynum == emmkey)
6004
			{
6005
				if (provId == 0x11)
6006
				{
6007
					CharToBin(&rdr->dre36_force_group, KeyDB->EmuKeys[i].keyName + 2, 2);
6008
				}
6009
				else
6010
				{
6011
					CharToBin(&rdr->dre56_force_group, KeyDB->EmuKeys[i].keyName + 2, 2);
6012
				}
6013
6014
				break;
6015
			}
6016
		}
6017
	}
6018
6019
	return result;
6020
}
6021
6022
int32_t GetDrecryptHexserials(uint16_t caid, uint32_t provid, uint8_t *hexserials, int32_t length, int32_t *count)
6023
{
6024
	uint32_t i;
6025
	KeyDataContainer *KeyDB = GetKeyContainer('D');
6026
6027
	if (KeyDB == NULL)
6028
	{
6029
		return 0;
6030
	}
6031
6032
	(*count) = 0;
6033
6034
	for (i = 0; i < KeyDB->keyCount && (*count) < length; i++)
6035
	{
6036
6037
		if (KeyDB->EmuKeys[i].provider != ((caid << 8) | provid))
6038
		{
6039
			continue;
6040
		}
6041
6042
		if (strlen(KeyDB->EmuKeys[i].keyName) < 6)
6043
		{
6044
			continue;
6045
		}
6046
6047
		if (memcmp(KeyDB->EmuKeys[i].keyName, "MK", 2))
6048
		{
6049
			continue;
6050
		}
6051
6052
		CharToBin(&hexserials[(*count)], KeyDB->EmuKeys[i].keyName + 2, 2);
6053
6054
		(*count)++;
6055
	}
6056
6057
	return 1;
6058
}
6059
6060
// Tandberg EMM EMU
6061
static uint8_t MixTable[] =
6062
{
6063
	0x12,0x78,0x4B,0x19,0x13,0x80,0x2F,0x84,
6064
	0x86,0x4C,0x09,0x53,0x15,0x79,0x6B,0x49,
6065
	0x10,0x4D,0x33,0x43,0x18,0x37,0x83,0x38,
6066
	0x82,0x1B,0x6E,0x24,0x2A,0x85,0x3C,0x3D,
6067
	0x5A,0x58,0x55,0x5D,0x20,0x41,0x65,0x51,
6068
	0x0C,0x45,0x63,0x7F,0x0F,0x46,0x21,0x7C,
6069
	0x2C,0x61,0x7E,0x0A,0x42,0x57,0x35,0x16,
6070
	0x87,0x3B,0x4F,0x40,0x34,0x22,0x26,0x74,
6071
	0x32,0x69,0x44,0x7A,0x6A,0x6D,0x0D,0x56,
6072
	0x23,0x2B,0x5C,0x72,0x76,0x36,0x28,0x25,
6073
	0x2E,0x52,0x5B,0x6C,0x7D,0x30,0x0B,0x5E,
6074
	0x47,0x1F,0x7B,0x31,0x3E,0x11,0x77,0x1E,
6075
	0x60,0x75,0x54,0x27,0x50,0x17,0x70,0x59,
6076
	0x1A,0x2D,0x4A,0x67,0x3A,0x5F,0x68,0x08,
6077
	0x4E,0x3F,0x29,0x6F,0x81,0x71,0x39,0x64,
6078
	0x48,0x66,0x73,0x14,0x0E,0x1D,0x62,0x1C
6079
};
6080
6081
void TandbergRotateBytes(unsigned char *in, int n)
6082
{
6083
	if(n > 1)
6084
	{
6085
		unsigned char *e = in + n - 1;
6086
		do
6087
		{
6088
			unsigned char temp = *in;
6089
			*in++ = *e;
6090
			*e-- = temp;
6091
		}
6092
		while (in < e);
6093
	}
6094
}
6095
6096
static void TandbergECMKeyDecrypt(uint8_t* emmKey, uint8_t* tagData, uint8_t* ecmKey)
6097
{
6098
	TandbergRotateBytes(emmKey, 8);
6099
	uint8_t iv[8] = { 0 };
6100
	uint8_t* payLoad = tagData + 4 + 5;
6101
	des_cbc_decrypt(payLoad, iv, emmKey, 16);
6102
6103
	ecmKey[0] = payLoad[0x0F];
6104
	ecmKey[1] = payLoad[0x01];
6105
	ecmKey[2] = payLoad[0x0B];
6106
	ecmKey[3] = payLoad[0x03];
6107
	ecmKey[4] = payLoad[0x0E];
6108
	ecmKey[5] = payLoad[0x04];
6109
	ecmKey[6] = payLoad[0x0A];
6110
	ecmKey[7] = payLoad[0x08];
6111
}
6112
6113
static int8_t TandbergParseEMMNanoTags(uint8_t* data, uint32_t length, uint8_t keyIndex, uint32_t *keysAdded)
6114
{
6115
	uint8_t tagType, tagLength, blockIndex;
6116
	uint32_t pos = 0, entitlementId;
6117
	int32_t i, k;
6118
	uint32_t ks[32];
6119
	uint8_t* tagData;
6120
	uint8_t emmKey[8];
6121
	char keyValue[17];
6122
	uint8_t tagDataDecrypted[0x10][8];
6123
	
6124
	if(length < 2)
6125
	{
6126
		return 1;
6127
	}
6128
	
6129
	while(pos < length)
6130
	{
6131
		tagType = data[pos];
6132
		tagLength = data[pos+1];
6133
		
6134
		if(pos + 2 + tagLength > length)
6135
		{
6136
			return 1;
6137
		}
6138
			
6139
		tagData = data + pos + 2;
6140
	
6141
		switch(tagType)
6142
		{
6143
			case 0xE4: // EMM_TAG_SECURITY_TABLE_DESCRIPTOR (ram emm keys)
6144
			{
6145
				uint8_t tagMode = data[pos + 2];
6146
				
6147
				switch(tagMode)
6148
				{
6149
					case 0x01: // keySet 01 (MK01)
6150
					{
6151
						if(tagLength != 0x8A)
6152
						{
6153
							cs_log("WARNING: nanoTag E4 length (%d) != %d", tagLength, 0x8A);
6154
							break;
6155
						}
6156
						
6157
						if(!GetTandbergKey(keyIndex, "MK01", emmKey, 8))
6158
						{
6159
							break;
6160
						}
6161
						
6162
						uint8_t iv[8] = { 0 };
6163
						uint8_t* tagPayload = tagData + 2;
6164
						des_cbc_decrypt(tagPayload, iv, emmKey, 136);
6165
					
6166
						for (k = 0; k < 0x10; k++) // loop 0x10 keys
6167
						{
6168
							for (i = 0; i < 8; i++) // loop 8 bytes of key
6169
							{
6170
								tagDataDecrypted[k][i] = tagPayload[MixTable[8*k + i]];
6171
							}
6172
						}
6173
						
6174
						blockIndex = tagData[1] & 0x03;
6175
						
6176
						for(i = 0; i < 0x10; i++)
6177
						{
6178
							SetKey('T', (blockIndex << 4) + i, "MK01", tagDataDecrypted[i], 8, 0, NULL, NULL);
6179
						}
6180
					}
6181
					break;
6182
					
6183
					case 0xFF: // keySet FF (MK)
6184
					{
6185
						if(tagLength != 0x82)
6186
						{
6187
							cs_log("WARNING: nanoTag E4 length (%d) != %d", tagLength, 0x82);
6188
							break;
6189
						}
6190
						
6191
						blockIndex = tagData[1] & 0x03;
6192
						
6193
						if(!GetTandbergKey(keyIndex, "MK", emmKey, 8))
6194
						{
6195
							break;
6196
						}
6197
						
6198
						des_set_key(emmKey, ks);
6199
						
6200
						for(i = 0; i < 0x10; i++)
6201
						{
6202
							des(tagData + 2 + (i*8), ks, 0);
6203
						}
6204
						
6205
						for(i = 0; i < 0x10; i++)
6206
						{
6207
							SetKey('T', (blockIndex << 4) + i, "MK", tagData + 2 + (i*8), 8, 0, NULL, NULL);
6208
						}
6209
					}
6210
					break;
6211
					
6212
					default:
6213
						cs_log("WARNING: nanoTag E4 mode %.2X not supported", tagMode);
6214
					break;
6215
				}
6216
				break;
6217
			}
6218
			
6219
			case 0xE1: // EMM_TAG_EVENT_ENTITLEMENT_DESCRIPTOR (ecm keys)
6220
			{
6221
				uint8_t tagMode = data[pos + 2 + 4];
6222
				
6223
				switch(tagMode)
6224
				{
6225
					case 0x00: // ecm keys from mode FF
6226
					{
6227
						if(tagLength != 0x12)
6228
						{
6229
							cs_log("WARNING: nanoTag E1 length (%d) != %d", tagLength, 0x12);
6230
							break;
6231
						}
6232
						
6233
						entitlementId = b2i(4, tagData);
6234
						
6235
						if(!GetTandbergKey(keyIndex, "MK", emmKey, 8))
6236
						{
6237
							break;
6238
						}
6239
						
6240
						des_set_key(emmKey, ks);
6241
						des(tagData + 4 + 5, ks, 0);
6242
						
6243
						if((tagData + 4 + 5 + 7) != 0x00) // check if key looks valid (last byte 0x00)
6244
						{
6245
							break;
6246
						}
6247
						
6248
						if(UpdateKey('T', entitlementId, "01", tagData + 4 + 5, 8, 1, NULL))
6249
						{
6250
							(*keysAdded)++;
6251
							cs_hexdump(0, tagData + 4 + 5, 8, keyValue, sizeof(keyValue));
6252
							cs_log("Key found in EMM: T %.8X 01 %s", entitlementId, keyValue);
6253
						}
6254
					}
6255
					break;
6256
					
6257
					case 0x01: // ecm keys from mode 01
6258
					{
6259
						if(tagLength != 0x1A)
6260
						{
6261
							cs_log("WARNING: nanoTag E1 length (%d) != %d", tagLength, 0x1A);
6262
							break;
6263
						}
6264
						
6265
						entitlementId = b2i(4, tagData);
6266
						
6267
						if(!GetTandbergKey(keyIndex, "MK01", emmKey, 8))
6268
						{
6269
							break;
6270
						}
6271
						
6272
						uint8_t ecmKey[8] = { 0 };
6273
						TandbergECMKeyDecrypt(emmKey, tagData, ecmKey);
6274
						
6275
						if(ecmKey[7] != 0x00) // check if key looks valid (last byte 0x00)
6276
						{
6277
							break;
6278
						}
6279
						
6280
						if(UpdateKey('T', entitlementId, "01", ecmKey, 8, 1, NULL))
6281
						{
6282
							(*keysAdded)++;
6283
							cs_hexdump(0, ecmKey, 8, keyValue, sizeof(keyValue));
6284
							cs_log("Key found in EMM: T %.8X 01 %s", entitlementId, keyValue);
6285
						}
6286
					}
6287
					break;
6288
					
6289
					default:
6290
						cs_log("WARNING: nanoTag E1 mode %.2X not supported", tagMode);
6291
					break;
6292
				}
6293
				break;
6294
			}
6295
			
6296
			default:
6297
				cs_log("WARNING: nanoTag %.2X not supported", tagType);
6298
			break;
6299
		}
6300
		
6301
		pos += 2 + tagLength;
6302
	}
6303
	
6304
	return 0;
6305
}
6306
6307
static int8_t TandbergParseEMMNanoData(uint8_t* data, uint32_t* nanoLength, uint32_t maxLength, uint8_t keyIndex, uint32_t *keysAdded)
6308
{
6309
	uint32_t pos = 0;
6310
	uint16_t sectionLength;
6311
	int8_t ret = 0;
6312
	
6313
	if(maxLength < 2)
6314
	{
6315
		(*nanoLength) = 0;
6316
		return 1;
6317
	}
6318
	
6319
	sectionLength = ((data[pos]<<8) | data[pos+1]) & 0x0FFF;
6320
	
6321
	if(pos + 2 + sectionLength > maxLength)
6322
	{
6323
		(*nanoLength) = pos;
6324
		return 1;
6325
	}
6326
		
6327
	ret = TandbergParseEMMNanoTags(data + pos + 2, sectionLength, keyIndex, keysAdded);
6328
		
6329
	pos += 2 + sectionLength;	
6330
	
6331
	(*nanoLength) = pos;
6332
	return ret;
6333
}
6334
6335
static int8_t TandbergEMM(uint8_t *emm, uint32_t *keysAdded)
6336
{
6337
	uint8_t keyIndex, ret = 0;
6338
	uint16_t emmLen = GetEcmLen(emm);
6339
	uint32_t pos = 3;
6340
	uint32_t permissionDataType;
6341
	uint32_t nanoLength = 0;
6342
	
6343
	while (pos < emmLen && !ret)
6344
	{
6345
		permissionDataType = emm[pos];
6346
	
6347
		switch(permissionDataType)
6348
		{
6349
			case 0x00:
6350
			{
6351
				break;
6352
			}
6353
			
6354
			case 0x01:
6355
			{
6356
				pos += 0x0A;
6357
				break;
6358
			}
6359
			
6360
			case 0x02:
6361
			{
6362
				pos += 0x26;
6363
				break;
6364
			}
6365
			
6366
			default:
6367
				cs_log("ERROR: unknown permissionDataType %.2X (pos: %d)", permissionDataType, pos);
6368
				return 1;
6369
		}
6370
		
6371
		if(pos+6 >= emmLen)
6372
		{
6373
			break;
6374
		}
6375
		
6376
		keyIndex = emm[pos+1];
6377
		
6378
		// EMM validation
6379
		// Copy payload checksum bytes and then set them to zero,
6380
		// so they do not affect the calculated checksum.
6381
		uint16_t payloadChecksum = (emm[pos + 2] << 8) | emm[pos + 3];
6382
		memset(emm + pos + 2, 0, 2);
6383
		uint16_t calculatedChecksum = TandbergChecksum(emm + 3, emmLen - 3);
6384
		
6385
		if(calculatedChecksum != payloadChecksum)
6386
		{
6387
			cs_log("EMM checksum error (%.4X instead of %.4X)", calculatedChecksum, payloadChecksum);
6388
			return 8;
6389
		}
6390
		// End of EMM validation
6391
		
6392
		pos += 0x04;
6393
		ret = TandbergParseEMMNanoData(emm + pos, &nanoLength, emmLen - pos, keyIndex, keysAdded);
6394
		pos += nanoLength;
6395
	}
6396
	
6397
	return ret;
6398
}
6399
6400
const char* GetProcessEMMErrorReason(int8_t result)
6401
{
6402
	switch(result) {
6403
	case 0:
6404
		return "No error";
6405
	case 1:
6406
		return "EMM not supported";
6407
	case 2:
6408
		return "Key not found";
6409
	case 3:
6410
		return "Nano80 problem";
6411
	case 4:
6412
		return "Corrupt data";
6413
	case 5:
6414
		return "Unknown";
6415
	case 6:
6416
		return "Checksum error";
6417
	case 7:
6418
		return "Out of memory";
6419
	case 8:
6420
		return "EMM checksum error";
6421
	case 9:
6422
		return "Wrong provider";
6423
	default:
6424
		return "Unknown";
6425
	}
6426
}
6427
6428
int8_t ProcessEMM(struct s_reader *rdr, uint16_t caid, uint32_t provider, const uint8_t *emm, uint32_t *keysAdded)
6429
{
6430
	int8_t result = 1;
6431
	uint8_t emmCopy[EMU_MAX_EMM_LEN];
6432
	uint16_t emmLen = GetEcmLen(emm);
6433
6434
	if(emmLen > EMU_MAX_EMM_LEN) {
6435
		return 1;
6436
	}
6437
	memcpy(emmCopy, emm, emmLen);
6438
	*keysAdded = 0;
6439
6440
	if(caid==0x0500) {
6441
		result = ViaccessEMM(emmCopy, keysAdded);
6442
	}
6443
	else if((caid>>8)==0x06) {
6444
		result = Irdeto2EMM(caid, emmCopy, keysAdded);
6445
	}
6446
	else if((caid>>8)==0x0E) {
6447
		result = PowervuEMM(emmCopy, keysAdded);
6448
	}
6449
	else if(caid==0x4AE1) {
6450
		result = Drecrypt2EMM(rdr, provider, emmCopy, keysAdded);
6451
	}
6452
	else if((caid>>8)==0x10) {
6453
		result = TandbergEMM(emmCopy, keysAdded);
6454
	}
6455
	
6456
	if(result != 0) {
6457
		cs_log_dbg(D_EMM,"EMM failed: %s", GetProcessEMMErrorReason(result));
6458
	}
6459
6460
	return result;
6461
}
(-)module-emulator-osemu.h (+127 lines)
Line 0 Link Here
1
#include "globals.h"
2
#include "module-emulator-stream.h"
3
4
#ifndef EMULATOR_H_
5
#define EMULATOR_H_
6
7
#define EMU_MAX_CHAR_KEYNAME 12
8
#define EMU_KEY_FILENAME "SoftCam.Key"
9
#define EMU_KEY_FILENAME_MAX_LEN 31
10
#define EMU_MAX_ECM_LEN MAX_ECM_SIZE
11
#define EMU_MAX_EMM_LEN MAX_EMM_SIZE
12
13
typedef struct KeyData KeyData;
14
15
struct KeyData
16
{
17
	char identifier;
18
	uint32_t provider;
19
	char keyName[EMU_MAX_CHAR_KEYNAME];
20
	uint8_t *key;
21
	uint32_t keyLength;
22
	KeyData *nextKey;
23
};
24
25
typedef struct
26
{
27
	KeyData *EmuKeys;
28
	uint32_t keyCount;
29
	uint32_t keyMax;
30
} KeyDataContainer;
31
32
extern KeyDataContainer CwKeys;
33
extern KeyDataContainer ViKeys;
34
extern KeyDataContainer NagraKeys;
35
extern KeyDataContainer IrdetoKeys;
36
extern KeyDataContainer NDSKeys;
37
extern KeyDataContainer BissKeys;
38
extern KeyDataContainer PowervuKeys;
39
extern KeyDataContainer DreKeys;
40
extern KeyDataContainer TandbergKeys;
41
extern uint8_t viasat_const[];
42
43
uint32_t GetOSemuVersion(void);
44
45
void set_emu_keyfile_path(const char *path);
46
void clear_emu_keydata(void);
47
uint8_t read_emu_keyfile(struct s_reader *rdr, const char *path);
48
49
#if !defined(__APPLE__) && !defined(__ANDROID__)
50
void read_emu_keymemory(struct s_reader *rdr);
51
#endif
52
53
void read_emu_eebin(const char *path, const char *name);
54
void read_emu_deskey(uint8_t *dreOverKey, uint8_t len);
55
56
int32_t CharToBin(uint8_t *out, const char *in, uint32_t inLen);
57
58
/* Error codes
59
0  OK
60
1  ECM not supported
61
2  Key not found
62
3  Nano80 problem
63
4  Corrupt data
64
5  CW not found
65
6  CW checksum error
66
7  Out of memory
67
8  ECM checksum error
68
9  ICG error
69
*/
70
#ifdef WITH_EMU
71
int8_t ProcessECM(struct s_reader *rdr, int16_t ecmDataLen, uint16_t caid, uint32_t provider,
72
				  const uint8_t *ecm, uint8_t *dw, uint16_t srvid, uint16_t ecmpid, EXTENDED_CW* cw_ex);
73
#else
74
int8_t ProcessECM(struct s_reader *rdr, int16_t ecmDataLen, uint16_t caid, uint32_t provider,
75
				  const uint8_t *ecm, uint8_t *dw, uint16_t srvid, uint16_t ecmpid);
76
#endif
77
78
const char* GetProcessECMErrorReason(int8_t result);
79
80
/* Error codes
81
0  OK
82
1  EMM not supported
83
2  Key not found
84
3  Nano80 problem
85
4  Corrupt data
86
5
87
6  Checksum error
88
7  Out of memory
89
*/
90
int8_t ProcessEMM(struct s_reader *rdr, uint16_t caid, uint32_t provider, const uint8_t *emm, uint32_t *keysAdded);
91
92
const char* GetProcessEMMErrorReason(int8_t result);
93
94
// hexserial must be of type "uint8_t hexserial[3]"
95
// returns 0 on error, 1 on success
96
int32_t GetIrdeto2Hexserial(uint16_t caid, uint8_t* hexserial);
97
98
// hexserials must be of type "uint8_t hexserials[length][4]"
99
// if srvid == 0xFFFF all serials are returned (no srvid filtering)
100
// returns 0 on error, 1 on success
101
int32_t GetPowervuHexserials(uint16_t srvid, uint8_t hexserials[][4], int32_t length, int32_t* count);
102
103
// hexserials must be of type "uint8_t hexserials[length]"
104
// returns 0 on error, 1 on success
105
int32_t GetDrecryptHexserials(uint16_t caid, uint32_t provid, uint8_t *hexserials, int32_t length, int32_t* count);
106
107
#define PVU_CW_VID 0    // VIDeo
108
#define PVU_CW_HSD 1    // High Speed Data
109
#define PVU_CW_A1  2    // Audio 1
110
#define PVU_CW_A2  3    // Audio 2
111
#define PVU_CW_A3  4    // Audio 3
112
#define PVU_CW_A4  5    // Audio 4
113
#define PVU_CW_UTL 6    // UTiLity
114
#define PVU_CW_VBI 7    // Vertical Blanking Interval
115
116
#ifdef WITH_EMU
117
int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, uint16_t srvid, emu_stream_client_key_data *cdata, EXTENDED_CW* cw_ex);
118
#else
119
int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, emu_stream_client_key_data *cdata);
120
#endif
121
122
#ifdef WITH_EMU
123
int32_t FindKey(char identifier, uint32_t provider, uint32_t providerIgnoreMask, char *keyName, uint8_t *key,
124
				uint32_t maxKeyLength, uint8_t isCriticalKey, uint32_t keyRef, uint8_t matchLength, uint32_t *getProvider);
125
#endif
126
127
#endif
(-)module-emulator-stream.c (+1105 lines)
Line 0 Link Here
1
#define MODULE_LOG_PREFIX "emu"
2
3
#include "globals.h"
4
#include "cscrypt/des.h"
5
6
#ifdef WITH_EMU
7
#include "oscam-string.h"
8
#include "oscam-config.h"
9
#include "oscam-time.h"
10
#include "oscam-net.h"
11
12
extern int32_t exit_oscam;
13
#endif
14
15
#include "ffdecsa/ffdecsa.h"
16
#include "module-emulator-osemu.h"
17
#include "module-emulator-stream.h"
18
19
typedef struct
20
{
21
	int32_t connfd;
22
	int32_t connid;	
23
} emu_stream_client_conn_data;
24
25
int8_t stream_server_thread_init = 0;
26
char emu_stream_source_host[256] = {"127.0.0.1"};
27
int32_t emu_stream_source_port = 8001;
28
char *emu_stream_source_auth = NULL;
29
int32_t emu_stream_relay_port = 17999;
30
int8_t emu_stream_emm_enabled = 0;
31
uint32_t cluster_size = 50;
32
33
static uint8_t emu_stream_server_mutex_init = 0;
34
static pthread_mutex_t emu_stream_server_mutex;
35
static int32_t glistenfd, gconncount = 0, gconnfd[EMU_STREAM_SERVER_MAX_CONNECTIONS];
36
37
#ifdef WITH_EMU
38
pthread_mutex_t emu_fixed_key_srvid_mutex;
39
uint16_t emu_stream_cur_srvid[EMU_STREAM_SERVER_MAX_CONNECTIONS];
40
int8_t stream_server_has_ecm[EMU_STREAM_SERVER_MAX_CONNECTIONS];
41
42
pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
43
emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS];
44
LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
45
#endif
46
47
static void SearchTsPackets(uint8_t *buf, uint32_t bufLength, uint16_t *packetSize, uint16_t *startOffset)
48
{
49
	uint32_t i;
50
	
51
	(*packetSize) = 0;
52
	(*startOffset) = 0;
53
54
	for(i=0; i<bufLength; i++) {
55
		if(buf[i] == 0x47) {
56
			if((buf[i+188] == 0x47) & (buf[i+376] == 0x47)) { // if three packets align, probably safe to assume correct size.
57
				(*packetSize) = 188;
58
				(*startOffset) = i;
59
				return;
60
			}
61
			else if((buf[i+204] == 0x47) & (buf[i+408] == 0x47)) {
62
				(*packetSize) = 204;
63
				(*startOffset) = i;
64
				return;
65
			}
66
			else if((buf[i+208] == 0x47) & (buf[i+416] == 0x47)) {
67
				(*packetSize) = 208;
68
				(*startOffset) = i;
69
				return;
70
			}
71
		}
72
	}
73
}
74
75
typedef void (*ts_data_callback)(emu_stream_client_data *cdata);
76
77
static void ParseTSData(uint8_t table_id, uint8_t table_mask, uint8_t min_table_length, int8_t* flag, uint8_t* data,
78
							uint16_t data_length, uint16_t* data_pos, int8_t payloadStart, uint8_t* buf, int32_t len,
79
							ts_data_callback func, emu_stream_client_data *cdata)
80
{
81
	uint16_t section_length;
82
	int32_t i;
83
	int8_t found_start = 0;
84
	uint16_t offset = 0;
85
	int32_t free_data_length;
86
	int32_t copySize;
87
	
88
	if(len < 1)
89
		{ return; }
90
	
91
	if(*flag == 0 && !payloadStart)
92
		{ return; }
93
94
	if(*flag == 0)
95
	{
96
		*data_pos = 0;
97
		 offset = 1 + buf[0];
98
	}
99
	else if(payloadStart)
100
	{
101
		offset = 1;
102
	}
103
	
104
	if(len-offset < 1)
105
		{ return; }
106
	
107
	free_data_length = data_length - *data_pos;
108
	copySize = (len-offset) > free_data_length ? free_data_length : (len-offset);
109
	
110
	memcpy(data+(*data_pos), buf+offset, copySize);
111
	(*data_pos) += copySize;
112
113
	found_start = 0;
114
	for(i=0; i < *data_pos; i++)
115
	{
116
		if((data[i] & table_mask) == table_id)
117
		{
118
			if(i != 0)
119
			{
120
				if((*data_pos)-i > i)
121
					{ memmove(data, &data[i], (*data_pos)-i); }
122
				else
123
					{ memcpy(data, &data[i], (*data_pos)-i); }
124
				
125
				*data_pos -= i;
126
			}
127
			found_start = 1;
128
			break;
129
		}
130
	}
131
	if(!found_start)
132
		{ *flag = 0; return; }
133
134
	*flag = 2;
135
136
	if(*data_pos < 3)
137
		{ return; }
138
139
	section_length = SCT_LEN(data);
140
141
	if(section_length > data_length || section_length < min_table_length)
142
		{ *flag = 0; return; }
143
	
144
	if((*data_pos) < section_length)
145
		{ return; }
146
147
	func(cdata);
148
	
149
	found_start = 0;
150
	for(i=section_length; i < *data_pos; i++)
151
	{
152
		if((data[i] & table_mask) == table_id)
153
		{
154
			if((*data_pos)-i > i)
155
				{ memmove(data, &data[i], (*data_pos)-i); }
156
			else
157
				{ memcpy(data, &data[i], (*data_pos)-i); }
158
			
159
			*data_pos -= i;
160
			found_start = 1;
161
			break;
162
		}	
163
	}	
164
	if(!found_start)
165
		{ *data_pos = 0; }
166
	
167
	*flag = 1;
168
}
169
170
static void ParsePATData(emu_stream_client_data *cdata)
171
{
172
	uint8_t* data = cdata->pat_data;
173
	uint16_t section_length = SCT_LEN(data);
174
	uint16_t srvid;
175
	int32_t i;
176
177
	for(i=8; i+7<section_length; i+=4)
178
	{
179
		srvid = b2i(2, data+i);
180
		
181
		if(srvid == 0)
182
			{ continue; }
183
		
184
		if(cdata->srvid == srvid)
185
		{
186
			cdata->pmt_pid = b2i(2, data+i+2) & 0x1FFF;
187
			cs_log_dbg(D_READER, "Stream %i found pmt pid: 0x%04X (%i)",cdata->connid, cdata->pmt_pid, cdata->pmt_pid);
188
			break;
189
		}
190
	}
191
}
192
193
static void ParsePMTData(emu_stream_client_data *cdata)
194
{
195
	uint8_t* data = cdata->pmt_data;
196
	
197
	uint16_t section_length = SCT_LEN(data);
198
	int32_t i;
199
	uint16_t program_info_length = 0, es_info_length = 0;
200
	uint8_t descriptor_tag = 0, descriptor_length = 0;
201
	uint8_t stream_type;
202
	uint16_t stream_pid, caid;
203
204
	cdata->pcr_pid = b2i(2, data+8) &0x1FFF;
205
	if(cdata->pcr_pid != 0x1FFF)
206
	{
207
		cs_log_dbg(D_READER, "Stream %i found pcr pid: 0x%04X (%i)",cdata->connid, cdata->pcr_pid, cdata->pcr_pid);
208
	}
209
	
210
	program_info_length = b2i(2, data+10) &0xFFF;
211
	
212
	if(12+program_info_length >= section_length)
213
		{ return; }
214
	
215
	for(i=12; i+1 < 12+program_info_length; i+=descriptor_length+2)
216
	{
217
		descriptor_tag = data[i];
218
		descriptor_length = data[i+1];
219
		
220
		if(descriptor_length < 1)
221
			{ break; }
222
			
223
		if(i+1+descriptor_length >= 12+program_info_length)
224
			{ break; }
225
		
226
		if(descriptor_tag == 0x09 && descriptor_length >= 4)
227
		{
228
			caid = b2i(2, data+i+2);
229
			
230
			if(caid>>8 == 0x0E)
231
			{
232
				cdata->ecm_pid = b2i(2, data+i+4) &0x1FFF;
233
				cs_log_dbg(D_READER, "Stream %i found ecm pid: 0x%04X (%i)", cdata->connid, cdata->ecm_pid, cdata->ecm_pid);
234
				break;
235
			}
236
		}
237
	}
238
	
239
	for(i=12+program_info_length; i+4<section_length; i+=5+es_info_length)
240
	{
241
		stream_type = data[i];
242
		stream_pid = b2i(2, data+i+1) &0x1FFF;
243
		es_info_length = b2i(2, data+i+3) &0xFFF;
244
		
245
		if(stream_type == 0x01 || stream_type == 0x02 || stream_type == 0x10 || stream_type == 0x1B 
246
			|| stream_type == 0x24 || stream_type == 0x42 || stream_type == 0x80 || stream_type == 0xD1 
247
			|| stream_type == 0xEA)
248
		{
249
			cdata->video_pid = stream_pid;
250
			cs_log_dbg(D_READER, "Stream %i found video pid: 0x%04X (%i)",cdata->connid, stream_pid, stream_pid);
251
		}
252
		
253
		else if(stream_type == 0x03 || stream_type == 0x04 || stream_type == 0x05 || stream_type == 0x06 ||
254
				stream_type == 0x0F || stream_type == 0x11 || (stream_type >= 0x81 && stream_type <= 0x87) || stream_type == 0x8A)
255
		{
256
			if(cdata->audio_pid_count >= EMU_STREAM_MAX_AUDIO_SUB_TRACKS)
257
				{ continue; }
258
			
259
			cdata->audio_pids[cdata->audio_pid_count] = stream_pid;
260
			cdata->audio_pid_count++;
261
			cs_log_dbg(D_READER, "Stream %i found audio pid: 0x%04X (%i)", cdata->connid, stream_pid, stream_pid);
262
		}
263
	}
264
}
265
266
static void ParseCATData(emu_stream_client_data *cdata)
267
{
268
	uint8_t* data = cdata->cat_data;
269
	uint32_t i;
270
	
271
	for(i = 8; i < (b2i(2, data + 1)&0xFFF) - 1; i += data[i + 1] + 2)
272
	{
273
		if(data[i] != 0x09) { continue; }
274
		
275
		uint16_t caid = b2i(2, data + i + 2);
276
		uint16_t emm_pid = b2i(2, data + i +4)&0x1FFF;
277
		
278
		if(caid>>8 == 0x0E)
279
		{
280
			cdata->emm_pid = emm_pid;
281
			cs_log_dbg(D_READER, "Stream %i found audio pid: 0x%04X (%i)", cdata->connid, emm_pid, emm_pid);
282
			break;
283
		}
284
	}
285
}
286
287
static void ParseEMMData(emu_stream_client_data *cdata)
288
{
289
	uint8_t* data = cdata->emm_data;
290
	uint32_t keysAdded = 0;
291
	
292
	ProcessEMM(NULL, 0x0E00, 0, data, &keysAdded);
293
	
294
	if(keysAdded)
295
	{
296
		cs_log("Stream %i found %i keys", cdata->connid, keysAdded);
297
	}
298
}
299
300
static void ParseECMData(emu_stream_client_data *cdata)
301
{
302
	uint8_t* data = cdata->ecm_data;
303
	uint16_t section_length = SCT_LEN(data);
304
	uint8_t dcw[16];
305
	
306
	if(section_length < 0xb)
307
		{ return; }
308
309
	if(data[0xb] > cdata->ecm_nb || (cdata->ecm_nb == 255 && data[0xb] == 0)
310
		|| ((cdata->ecm_nb - data[0xb]) > 5))
311
	{
312
		cdata->ecm_nb = data[0xb];
313
#ifdef WITH_EMU
314
		PowervuECM(data, dcw, cdata->srvid, &cdata->key, NULL);
315
#else
316
		PowervuECM(data, dcw, &cdata->key);
317
#endif
318
	}
319
}
320
321
static void ParseTSPackets(emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
322
{
323
	uint32_t i, j, k;
324
	uint32_t tsHeader;
325
	uint16_t pid, offset;
326
	uint8_t scramblingControl, payloadStart, oddeven;
327
	int8_t oddKeyUsed;
328
	uint32_t *deskey;
329
	uint8_t *pdata;
330
	uint8_t *packetClusterA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS][64]; // separate cluster arrays for video and each audio track
331
	uint8_t *packetClusterV[256];
332
	void *csakeyA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0};
333
	void *csakeyV = 0;
334
	emu_stream_client_key_data *keydata;
335
	uint32_t scrambled_packets = 0;
336
	uint32_t scrambled_packetsA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0};
337
	packetClusterV[0] = NULL;
338
	uint32_t cs =0; // video cluster start
339
	uint32_t ce =1; // video cluster end
340
	uint32_t csa[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0}; // cluster index for audio tracks
341
	
342
	for(i=0; i<bufLength; i+=packetSize)
343
	{
344
		tsHeader = b2i(4, stream_buf+i);
345
		pid = (tsHeader & 0x1fff00) >> 8;
346
		scramblingControl = tsHeader & 0xc0;
347
		payloadStart = (tsHeader & 0x400000) >> 22;
348
		
349
		if(tsHeader & 0x20)
350
			{ offset = 4 + stream_buf[i+4] + 1; }
351
		else
352
			{ offset = 4; }
353
		
354
		if(packetSize-offset < 1)
355
			{ continue; }
356
		
357
		if(pid == 1)
358
		{
359
			// set to null pid
360
			stream_buf[i+1] |= 0x1f;
361
			stream_buf[i+2]  = 0xff;
362
			
363
			if(emu_stream_emm_enabled && !data->emm_pid)
364
			{
365
				ParseTSData(0x01, 0xFF, 8, &data->have_cat_data, data->cat_data, sizeof(data->cat_data), &data->cat_data_pos, payloadStart, 
366
											stream_buf+i+offset, packetSize-offset, ParseCATData, data);
367
				continue;
368
			}
369
		}
370
		
371
		if(emu_stream_emm_enabled && data->emm_pid && pid == data->emm_pid)
372
		{	
373
			// set to null pid
374
			stream_buf[i+1] |= 0x1f;
375
			stream_buf[i+2]  = 0xff;
376
			
377
			ParseTSData(0x80, 0xF0, 3, &data->have_emm_data, data->emm_data, sizeof(data->emm_data), &data->emm_data_pos, payloadStart, 
378
										stream_buf+i+offset, packetSize-offset, ParseEMMData, data);
379
			continue;
380
		}
381
		
382
		if(pid == 0 && !data->pmt_pid)
383
		{
384
			ParseTSData(0x00, 0xFF, 16, &data->have_pat_data, data->pat_data, sizeof(data->pat_data), &data->pat_data_pos, payloadStart, 
385
										stream_buf+i+offset, packetSize-offset, ParsePATData, data);		
386
			continue;
387
		}
388
		
389
		if(!data->ecm_pid && pid == data->pmt_pid)
390
		{
391
			ParseTSData(0x02, 0xFF, 21, &data->have_pmt_data, data->pmt_data, sizeof(data->pmt_data), &data->pmt_data_pos, payloadStart, 
392
										stream_buf+i+offset, packetSize-offset, ParsePMTData, data);	
393
			continue;
394
		}
395
		
396
		if(data->ecm_pid && pid == data->ecm_pid)
397
		{
398
#ifdef WITH_EMU
399
			stream_server_has_ecm[data->connid] = 1;
400
#endif
401
			
402
			// set to null pid
403
			stream_buf[i+1] |= 0x1f; 
404
			stream_buf[i+2]  = 0xff;
405
			
406
			ParseTSData(0x80, 0xFE, 3, &data->have_ecm_data, data->ecm_data, sizeof(data->ecm_data), &data->ecm_data_pos, payloadStart, 
407
										stream_buf+i+offset, packetSize-offset, ParseECMData, data);
408
			continue;
409
		}
410
		
411
		if(scramblingControl == 0)
412
			{ continue; }
413
		
414
		if(!(stream_buf[i+3] & 0x10))
415
		{
416
			stream_buf[i+3] &= 0x3F;
417
			continue;
418
		}
419
		
420
		oddKeyUsed = scramblingControl == 0xC0 ? 1 : 0;
421
		
422
#ifdef WITH_EMU
423
		if(!stream_server_has_ecm[data->connid])
424
		{
425
			keydata = &emu_fixed_key_data[data->connid];
426
			SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[data->connid]);
427
			data->key.pvu_csa_used = keydata->pvu_csa_used;
428
		}
429
		else
430
		{
431
#endif
432
			keydata = &data->key;
433
#ifdef WITH_EMU
434
		}
435
#endif
436
		
437
		if(keydata->pvu_csa_used)
438
		{
439
			oddeven = scramblingControl; // for detecting odd/even switch
440
			
441
			if(pid == data->video_pid) // start with video pid, since it is most dominant
442
			{
443
				csakeyV = keydata->pvu_csa_ks[PVU_CW_VID];
444
				
445
				if(csakeyV !=NULL)
446
				{
447
					cs=0;
448
					ce=1;
449
					packetClusterV[cs] = stream_buf+i; // set first cluster start
450
					packetClusterV[ce] = stream_buf+i+packetSize-1;
451
					scrambled_packets=1;
452
					
453
					for(j = i+packetSize; j < bufLength; j += packetSize) // Now iterate through the rest of the packets and create clusters for batch decryption
454
					{
455
						tsHeader = b2i(4, stream_buf+j);
456
						pid = (tsHeader & 0x1fff00) >> 8;
457
						if(pid == data->video_pid)
458
						{
459
							if(oddeven != (tsHeader & 0xc0)) // changed key so stop adding clusters
460
							{
461
								break;
462
							}
463
							if(cs > ce) // First video packet for each cluster
464
							{
465
								packetClusterV[cs] = stream_buf+j;
466
								ce = cs+1;
467
							}
468
							
469
							scrambled_packets++;
470
						}
471
						else
472
						{
473
							if(cs < ce) // First non-video packet - need to set end of video cluster
474
							{
475
								packetClusterV[ce] = stream_buf+j-1;
476
								cs = ce+1;
477
							}
478
							
479
							if((tsHeader & 0xc0) == 0) {
480
								continue;
481
							}
482
							
483
							if(oddeven != (tsHeader & 0xc0)) // changed key so stop adding clusters
484
							{
485
								j = bufLength; // to break out of outer loop also
486
								break;
487
							}
488
							
489
							for(k = 0; k < data->audio_pid_count; k++) // Check for audio tracks and create single packet clusters
490
							{
491
								if(pid == data->audio_pids[k])
492
								{
493
									packetClusterA[k][csa[k]] = stream_buf+j;
494
									csa[k]++;
495
									packetClusterA[k][csa[k]] = stream_buf+j+packetSize-1;
496
									csa[k]++;
497
									scrambled_packetsA[k]++;
498
								}
499
							}
500
						}
501
					}
502
					
503
					if( cs > ce ) // last packet was not a video packet, so set null for end of all clusters
504
						{ packetClusterV[cs] = NULL; }
505
					else 
506
					{
507
						if(scrambled_packets > 1) // last packet was a video packet, so set end of cluster to end of last packet
508
						{
509
							packetClusterV[ce] = stream_buf+j-1;
510
						}
511
						packetClusterV[ce+1] = NULL; // add null to end of cluster list
512
					}
513
					
514
					while( j >= cluster_size )
515
						{ j = decrypt_packets(csakeyV, packetClusterV); }
516
					
517
					for(k = 0; k < data->audio_pid_count; k++)
518
					{
519
						if(scrambled_packetsA[k]) // if audio track has scrambled packets, set null to mark end and decrypt
520
						{
521
							csakeyA[k] = keydata->pvu_csa_ks[PVU_CW_A1+k];
522
							packetClusterA[k][csa[k]] = NULL;
523
							decrypt_packets(csakeyA[k], packetClusterA[k]);
524
							csa[k]=0;
525
							scrambled_packetsA[k] = 0;
526
						}
527
					}
528
				}
529
			}
530
			else
531
			{
532
				for(j = 0; j < data->audio_pid_count; j++)
533
					if(pid == data->audio_pids[j])
534
						{ csakeyA[0] = keydata->pvu_csa_ks[PVU_CW_A1+j]; }
535
				
536
				if(csakeyA[0] != NULL)
537
				{
538
					packetClusterA[0][0] = stream_buf+i;
539
					packetClusterA[0][1] = stream_buf+i+packetSize -1;
540
					packetClusterA[0][2] = NULL;
541
					decrypt_packets(csakeyA[0], packetClusterA[0]);
542
				}
543
			}
544
		}
545
		else
546
		{
547
			deskey = NULL;
548
			
549
			if(pid == data->video_pid)
550
				{ deskey = keydata->pvu_des_ks[PVU_CW_VID][oddKeyUsed]; }
551
			else
552
			{
553
				for(j = 0; j < data->audio_pid_count; j++)
554
					if(pid == data->audio_pids[j])
555
						{ deskey = keydata->pvu_des_ks[PVU_CW_A1+j][oddKeyUsed]; }
556
			}
557
			
558
			if(deskey == NULL)
559
			{
560
				deskey = keydata->pvu_des_ks[PVU_CW_HSD][oddKeyUsed];
561
			}
562
			
563
			for(j = offset; j+7 < 188; j += 8)
564
			{
565
				pdata = stream_buf+i+j;
566
				des(pdata, deskey, 0);
567
			}
568
			
569
			stream_buf[i+3] &= 0x3F;
570
		}
571
		
572
#ifdef WITH_EMU
573
		if(!stream_server_has_ecm[data->connid])
574
		{
575
			SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[data->connid]);
576
		}
577
#endif
578
	}
579
}
580
581
static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *stream_path)
582
{
583
	struct sockaddr_in cservaddr;
584
	IN_ADDR_T in_addr;
585
	
586
	int32_t streamfd = socket(AF_INET, SOCK_STREAM, 0);
587
	if(streamfd == -1)
588
		{ return -1; }
589
590
	struct timeval tv;
591
	tv.tv_sec = 2;
592
	tv.tv_usec = 0;
593
	if(setsockopt(streamfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv))
594
	{
595
		cs_log("ERROR: setsockopt() failed for SO_RCVTIMEO");
596
		return -1;
597
	}
598
599
	bzero(&cservaddr, sizeof(cservaddr));
600
	cservaddr.sin_family = AF_INET;
601
	cs_resolve(emu_stream_source_host, &in_addr, NULL, NULL);
602
	SIN_GET_ADDR(cservaddr) = in_addr;
603
	cservaddr.sin_port = htons(emu_stream_source_port);
604
	
605
	if(connect(streamfd, (struct sockaddr *)&cservaddr, sizeof(cservaddr)) == -1)
606
		{ return -1; }
607
	if(emu_stream_source_auth)
608
	{
609
		snprintf(http_buf, http_buf_len, "GET %s HTTP/1.1\nHost: %s:%u\n"
610
				"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n"
611
				"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
612
				"Accept-Language: en-US\n"
613
				"Authorization: Basic %s\n"
614
				"Connection: keep-alive\n\n", stream_path, emu_stream_source_host, emu_stream_source_port, emu_stream_source_auth);
615
	}
616
	else
617
	{
618
		snprintf(http_buf, http_buf_len, "GET %s HTTP/1.1\nHost: %s:%u\n"
619
				"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n"
620
				"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
621
				"Accept-Language: en-US\n"
622
				"Connection: keep-alive\n\n", stream_path, emu_stream_source_host, emu_stream_source_port);
623
	}
624
625
	if(send(streamfd, http_buf, strlen(http_buf), 0) == -1)
626
		{ return -1; }
627
	
628
	return streamfd;
629
}
630
631
static void stream_client_disconnect(emu_stream_client_conn_data *conndata)
632
{
633
	int32_t i;
634
	
635
#ifdef WITH_EMU
636
	SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
637
	emu_stream_cur_srvid[conndata->connid] = NO_SRVID_VALUE;
638
	stream_server_has_ecm[conndata->connid] = 0;
639
	SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
640
#endif
641
	
642
	SAFE_MUTEX_LOCK(&emu_stream_server_mutex);
643
	for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
644
	{
645
		if(gconnfd[i] == conndata->connfd)
646
		{
647
			gconnfd[i] = -1;
648
			gconncount--;
649
		}
650
	}
651
	SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex);
652
	
653
	shutdown(conndata->connfd, 2);
654
	close(conndata->connfd);
655
	
656
	cs_log("Stream client %i disconnected",conndata->connid);
657
	
658
	NULLFREE(conndata);
659
}
660
661
static void *stream_client_handler(void *arg)
662
{
663
#define EMU_DVB_MAX_TS_PACKETS 278
664
#define EMU_DVB_BUFFER_SIZE_CSA 188*EMU_DVB_MAX_TS_PACKETS
665
#define EMU_DVB_BUFFER_WAIT_CSA 188*(EMU_DVB_MAX_TS_PACKETS-128)
666
#define EMU_DVB_BUFFER_SIZE_DES 188*32
667
#define EMU_DVB_BUFFER_WAIT_DES 188*29
668
#define EMU_DVB_BUFFER_SIZE EMU_DVB_BUFFER_SIZE_CSA
669
670
	emu_stream_client_conn_data *conndata = (emu_stream_client_conn_data *)arg;
671
	char *http_buf, stream_path[255], stream_path_copy[255];
672
	int32_t streamfd;
673
	int32_t clientStatus, streamStatus;
674
	uint8_t *stream_buf;
675
	uint16_t packetCount = 0, packetSize = 0, startOffset = 0;
676
	uint32_t remainingDataPos, remainingDataLength;
677
	int32_t cur_dvb_buffer_size, cur_dvb_buffer_wait;
678
	int32_t bytesRead = 0;
679
	emu_stream_client_data *data;
680
	int8_t streamConnectErrorCount = 0;
681
	int8_t streamDataErrorCount = 0;
682
	int32_t i, srvidtmp;
683
	char *saveptr, *token;
684
	char http_version[4];
685
	int32_t http_status_code = 0;
686
687
	cs_log("Stream client %i connected", conndata->connid);
688
	
689
	if(!cs_malloc(&http_buf, 1024))
690
	{
691
		stream_client_disconnect(conndata);
692
		return NULL;
693
	}
694
	
695
	if(!cs_malloc(&stream_buf, EMU_DVB_BUFFER_SIZE))
696
	{
697
		NULLFREE(http_buf);
698
		stream_client_disconnect(conndata);
699
		return NULL;
700
	}
701
	
702
	if(!cs_malloc(&data, sizeof(emu_stream_client_data)))
703
	{
704
		NULLFREE(http_buf);
705
		NULLFREE(stream_buf);
706
		stream_client_disconnect(conndata);
707
		return NULL;
708
	}
709
	
710
	clientStatus = recv(conndata->connfd, http_buf, 1024, 0);
711
	if(clientStatus < 1)
712
	{
713
		NULLFREE(http_buf);
714
		NULLFREE(stream_buf);
715
		NULLFREE(data);
716
		stream_client_disconnect(conndata);
717
		return NULL;
718
	}
719
	
720
	http_buf[1023] = '\0';
721
	if(sscanf(http_buf, "GET %254s ", stream_path) < 1)
722
	{
723
		NULLFREE(http_buf);
724
		NULLFREE(stream_buf);
725
		NULLFREE(data);
726
		stream_client_disconnect(conndata);
727
		return NULL;
728
	}
729
	
730
	cs_strncpy(stream_path_copy, stream_path, sizeof(stream_path));
731
	
732
	token = strtok_r(stream_path_copy, ":", &saveptr);
733
734
	for(i=0; token != NULL && i<3; i++)
735
	{
736
		token = strtok_r(NULL, ":", &saveptr);
737
		if(token == NULL)
738
			{ break; }
739
	}
740
	if(token != NULL)
741
	{
742
		if(sscanf(token, "%x", &srvidtmp) < 1)
743
		{
744
			token = NULL;
745
		}
746
		else
747
		{
748
			data->srvid = srvidtmp & 0xFFFF;
749
		}
750
	}
751
752
	if(token == NULL)
753
	{
754
		NULLFREE(http_buf);
755
		NULLFREE(stream_buf);
756
		NULLFREE(data);
757
		stream_client_disconnect(conndata);
758
		return NULL;
759
	}
760
761
#ifdef WITH_EMU
762
	SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
763
	emu_stream_cur_srvid[conndata->connid] = data->srvid;
764
	stream_server_has_ecm[conndata->connid] = 0;
765
	SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
766
#endif
767
768
	cs_log("Stream client %i request %s", conndata->connid, stream_path);
769
770
	snprintf(http_buf, 1024, "HTTP/1.0 200 OK\nConnection: Close\nContent-Type: video/mpeg\nServer: stream_enigma2\n\n");
771
	clientStatus = send(conndata->connfd, http_buf, strlen(http_buf), 0);
772
773
	data->connid = conndata->connid;
774
775
	while(!exit_oscam && clientStatus != -1 && streamConnectErrorCount < 3 && streamDataErrorCount < 15)
776
	{
777
		streamfd = connect_to_stream(http_buf, 1024, stream_path);
778
		if(streamfd == -1)
779
		{
780
			cs_log("WARNING: stream client %i cannot connect to stream source", conndata->connid);
781
			streamConnectErrorCount++;
782
			cs_sleepms(500);
783
			continue;
784
		}
785
		
786
		streamStatus = 0;
787
		bytesRead = 0;
788
		
789
		while(!exit_oscam && clientStatus != -1 && streamStatus != -1 && streamConnectErrorCount < 3 && streamDataErrorCount < 15)
790
		{
791
			if(data->key.pvu_csa_used)
792
			{
793
				cur_dvb_buffer_size = EMU_DVB_BUFFER_SIZE_CSA;
794
				cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_CSA;
795
			}
796
			else
797
			{
798
				cur_dvb_buffer_size = EMU_DVB_BUFFER_SIZE_DES;
799
				cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_DES;
800
			}
801
			
802
			streamStatus = recv(streamfd, stream_buf+bytesRead, cur_dvb_buffer_size-bytesRead, MSG_WAITALL);
803
			if(streamStatus == 0) // socket closed
804
			{
805
				cs_log("WARNING: stream client %i - stream source closed connection", conndata->connid);
806
				streamConnectErrorCount++;
807
				cs_sleepms(100);
808
				break;
809
			}
810
			
811
			if(streamStatus < 0) // error
812
			{
813
				if ((errno == EWOULDBLOCK) | (errno == EAGAIN)) {
814
					cs_log("WARNING: stream client %i no data from stream source", conndata->connid);
815
					streamDataErrorCount++; // 2 sec timeout * 15 = 30 seconds no data -> close
816
					cs_sleepms(100);
817
					continue;
818
				}
819
				
820
				cs_log("WARNING: stream client %i error receiving data from stream source", conndata->connid);
821
				streamConnectErrorCount++;
822
				cs_sleepms(100);
823
				break;
824
			}
825
			
826
			if(streamStatus < cur_dvb_buffer_size-bytesRead) // probably just received header but no stream
827
			{
828
				if(!bytesRead && streamStatus > 13 &&
829
					sscanf((const char*)stream_buf, "HTTP/%3s %d ", http_version , &http_status_code) == 2 &&
830
					http_status_code != 200)
831
				{
832
					cs_log("ERROR: stream client %i got %d response from stream source", conndata->connid, http_status_code);
833
					streamConnectErrorCount++;
834
					cs_sleepms(100);
835
					break;
836
				}
837
				else
838
				{
839
					cs_log_dbg(0, "WARNING: stream client %i non-full buffer from stream source", conndata->connid);
840
					streamDataErrorCount++;
841
					cs_sleepms(100);
842
				}
843
			}
844
			else
845
			{
846
				streamDataErrorCount = 0;
847
			}
848
			
849
			streamConnectErrorCount = 0;
850
			bytesRead += streamStatus;
851
			
852
			if(bytesRead >= cur_dvb_buffer_wait)
853
			{	
854
				startOffset = 0;
855
				if(stream_buf[0] != 0x47 || packetSize == 0) // only search if not starting on ts packet or unknown packet size
856
				{
857
					SearchTsPackets(stream_buf, bytesRead, &packetSize, &startOffset);
858
				}
859
				if(packetSize == 0)
860
				{
861
					bytesRead = 0;
862
				}
863
				else
864
				{
865
					packetCount = ((bytesRead-startOffset) / packetSize);
866
					
867
					ParseTSPackets(data, stream_buf+startOffset, packetCount*packetSize, packetSize);
868
					
869
					clientStatus = send(conndata->connfd, stream_buf+startOffset, packetCount*packetSize, 0);
870
						 
871
					remainingDataPos = startOffset+(packetCount*packetSize);
872
					remainingDataLength = bytesRead-remainingDataPos;
873
					
874
					if(remainingDataPos < remainingDataLength)
875
						{ memmove(stream_buf, stream_buf+remainingDataPos, remainingDataLength); }
876
					else
877
						{ memcpy(stream_buf, stream_buf+remainingDataPos, remainingDataLength); }
878
					
879
					bytesRead = remainingDataLength;
880
				}
881
			}
882
		}
883
		
884
		close(streamfd);
885
	}
886
	
887
	NULLFREE(http_buf);
888
	NULLFREE(stream_buf);
889
	for(i=0; i<8; i++)
890
	{
891
		if(data->key.pvu_csa_ks[i])
892
			{ free_key_struct(data->key.pvu_csa_ks[i]); }
893
	}
894
	NULLFREE(data);
895
896
	stream_client_disconnect(conndata);
897
	return NULL;
898
}
899
900
void *stream_server(void *UNUSED(a))
901
{
902
	struct sockaddr_in servaddr, cliaddr;
903
	socklen_t clilen;
904
	int32_t connfd, reuse = 1, i;
905
	int8_t connaccepted;
906
	emu_stream_client_conn_data *conndata;
907
908
	cluster_size = get_internal_parallelism();
909
	cs_log("INFO: FFDecsa parallel mode = %d", cluster_size);
910
911
	if(!emu_stream_server_mutex_init)
912
	{
913
		SAFE_MUTEX_INIT(&emu_stream_server_mutex, NULL);
914
		emu_stream_server_mutex_init = 1;
915
	}
916
	
917
#ifdef WITH_EMU
918
	SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
919
	for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
920
	{
921
		emu_stream_cur_srvid[i] = NO_SRVID_VALUE;
922
		stream_server_has_ecm[i] = 0;
923
	}
924
	SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
925
#endif
926
	
927
	for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
928
	{
929
		gconnfd[i] = -1;
930
	}
931
	
932
	glistenfd = socket(AF_INET, SOCK_STREAM, 0);
933
	if(glistenfd == -1)
934
	{
935
		cs_log("ERROR: cannot create stream server socket");
936
		return NULL;
937
	}
938
939
	bzero(&servaddr,sizeof(servaddr));
940
	servaddr.sin_family = AF_INET;
941
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
942
	servaddr.sin_port = htons(emu_stream_relay_port);
943
	setsockopt(glistenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
944
	
945
	if(bind(glistenfd,(struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
946
	{
947
		cs_log("ERROR: cannot bind to stream server socket");
948
		close(glistenfd);
949
		return NULL;
950
	}
951
	
952
	if(listen(glistenfd, 3) == -1)
953
	{
954
		cs_log("ERROR: cannot listen to stream server socket");
955
		close(glistenfd);
956
		return NULL;
957
	}
958
	
959
	while(!exit_oscam)
960
	{
961
		clilen = sizeof(cliaddr);
962
		connfd = accept(glistenfd,(struct sockaddr *)&cliaddr, &clilen);
963
		
964
		if(connfd == -1)
965
		{
966
			cs_log("ERROR: accept() failed");
967
			break;
968
		}
969
		
970
		connaccepted = 0;
971
		
972
		if(cs_malloc(&conndata, sizeof(emu_stream_client_conn_data)))
973
		{		
974
			SAFE_MUTEX_LOCK(&emu_stream_server_mutex);
975
			if(gconncount < EMU_STREAM_SERVER_MAX_CONNECTIONS)
976
			{
977
				for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
978
				{
979
					if(gconnfd[i] == -1)
980
					{
981
						gconnfd[i] = connfd;
982
						gconncount++;
983
						connaccepted = 1;
984
						
985
						conndata->connfd = connfd;
986
						conndata->connid = i;
987
						
988
						break;
989
					}
990
				}
991
			}
992
			SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex);
993
		}
994
	
995
		if(connaccepted)
996
		{
997
			int on = 1;
998
			if(setsockopt(connfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
999
			{
1000
				cs_log("ERROR: stream client %i setsockopt() failed for TCP_NODELAY", conndata->connid);
1001
			}
1002
			
1003
			start_thread("emu stream client", stream_client_handler, (void*)conndata, NULL, 1, 0);
1004
		}
1005
		else
1006
		{
1007
			shutdown(connfd, 2);
1008
			close(connfd);
1009
			cs_log("ERROR: stream server client dropped because of too many connections (%i)", EMU_STREAM_SERVER_MAX_CONNECTIONS);
1010
		}
1011
		
1012
		cs_sleepms(20);
1013
	}
1014
	
1015
	close(glistenfd);
1016
	
1017
	return NULL;
1018
}
1019
1020
#ifdef WITH_EMU
1021
void *stream_key_delayer(void *UNUSED(arg))
1022
{
1023
	int32_t i, j;
1024
	emu_stream_client_key_data* cdata;
1025
	LL_ITER it;
1026
	emu_stream_cw_item *item;
1027
	struct timeb t_now;
1028
	
1029
	while(!exit_oscam)
1030
	{
1031
		cs_ftime(&t_now);
1032
		
1033
		for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
1034
		{
1035
			it = ll_iter_create(ll_emu_stream_delayed_keys[i]);
1036
			while((item = ll_iter_next(&it)))
1037
			{
1038
				if(comp_timeb(&t_now, &item->write_time) < 0)
1039
				{
1040
					break;
1041
				}
1042
				
1043
				SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[i]);
1044
				
1045
				cdata = &emu_fixed_key_data[i];
1046
				
1047
				for(j=0; j<8; j++)
1048
				{
1049
					if(item->csa_used)
1050
					{	
1051
						if(cdata->pvu_csa_ks[j] == NULL)
1052
							{ cdata->pvu_csa_ks[j] = get_key_struct(); }
1053
							
1054
						if(item->is_even)
1055
							{ set_even_control_word(cdata->pvu_csa_ks[j], item->cw[j]); }
1056
						else
1057
							{ set_odd_control_word(cdata->pvu_csa_ks[j], item->cw[j]); }
1058
						
1059
						cdata->pvu_csa_used = 1;
1060
					}
1061
					else
1062
					{
1063
						if(item->is_even)
1064
							{ des_set_key(item->cw[j], cdata->pvu_des_ks[j][0]); }
1065
						else
1066
							{ des_set_key(item->cw[j], cdata->pvu_des_ks[j][1]); }
1067
							
1068
						cdata->pvu_csa_used = 0;
1069
					}
1070
				}
1071
				
1072
				SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[i]);
1073
				
1074
				ll_iter_remove_data(&it);
1075
			}
1076
		}
1077
		
1078
		cs_sleepms(25);
1079
	}
1080
	
1081
	return NULL;
1082
}
1083
#endif
1084
1085
void stop_stream_server(void)
1086
{
1087
	int32_t i;
1088
	
1089
	SAFE_MUTEX_LOCK(&emu_stream_server_mutex);
1090
	for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
1091
	{
1092
		if(gconnfd[i] != -1)
1093
		{
1094
			shutdown(gconnfd[i], 2);
1095
			close(gconnfd[i]);
1096
			gconnfd[i] = -1;
1097
		}
1098
	}
1099
	
1100
	gconncount = 0;
1101
	SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex);
1102
	
1103
	shutdown(glistenfd, 2);
1104
	close(glistenfd);
1105
}
(-)module-emulator-stream.h (+75 lines)
Line 0 Link Here
1
#ifndef EMU_STREAM_SERVER_H_
2
#define EMU_STREAM_SERVER_H_
3
4
#define EMU_STREAM_SERVER_MAX_CONNECTIONS 8
5
#define EMU_STREAM_MAX_AUDIO_SUB_TRACKS 16
6
7
typedef struct
8
{
9
	uint32_t pvu_des_ks[8][2][32];
10
	int8_t pvu_csa_used;
11
	void* pvu_csa_ks[8];
12
} emu_stream_client_key_data;
13
14
typedef struct
15
{
16
	int32_t connid;
17
	int8_t have_cat_data;
18
	int8_t have_pat_data;
19
	int8_t have_pmt_data;
20
	int8_t have_ecm_data;
21
	int8_t have_emm_data;
22
	uint8_t cat_data[1024+208];
23
	uint8_t pat_data[1024+208];
24
	uint8_t pmt_data[1024+208];
25
	uint8_t ecm_data[1024+208];
26
	uint8_t emm_data[1024+208];
27
	uint16_t cat_data_pos;
28
	uint16_t pat_data_pos;
29
	uint16_t pmt_data_pos;
30
	uint16_t ecm_data_pos;
31
	uint16_t emm_data_pos;
32
	uint16_t srvid;
33
	uint16_t pmt_pid;
34
	uint16_t ecm_pid;
35
	uint16_t emm_pid;
36
	uint16_t video_pid;
37
	uint16_t pcr_pid;
38
	uint16_t audio_pids[EMU_STREAM_MAX_AUDIO_SUB_TRACKS];
39
	uint8_t audio_pid_count;
40
	int16_t ecm_nb;
41
	emu_stream_client_key_data key;
42
} emu_stream_client_data;
43
44
extern char emu_stream_source_host[256];
45
extern int32_t emu_stream_source_port;
46
extern char *emu_stream_source_auth;
47
extern int32_t emu_stream_relay_port;
48
extern int8_t emu_stream_emm_enabled;
49
50
extern int8_t stream_server_thread_init;
51
52
void *stream_server(void *a);
53
void stop_stream_server(void);
54
55
#ifdef WITH_EMU
56
typedef struct
57
{
58
	struct timeb write_time;
59
	int8_t csa_used;
60
	int8_t is_even;
61
	uint8_t cw[8][8];
62
} emu_stream_cw_item;
63
64
extern pthread_mutex_t emu_fixed_key_srvid_mutex;
65
extern uint16_t emu_stream_cur_srvid[EMU_STREAM_SERVER_MAX_CONNECTIONS];
66
extern int8_t stream_server_has_ecm[EMU_STREAM_SERVER_MAX_CONNECTIONS];
67
68
extern pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
69
extern emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS];
70
extern LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
71
72
void *stream_key_delayer(void *arg);
73
#endif
74
75
#endif
(-)module-emulator.c (+904 lines)
Line 0 Link Here
1
#define MODULE_LOG_PREFIX "emu"
2
3
#include "globals.h"
4
#include "oscam-string.h"
5
#include "oscam-config.h"
6
#include "oscam-conf-chk.h"
7
#include "oscam-time.h"
8
#include "oscam-reader.h"
9
#include "module-emulator-osemu.h"
10
#include "module-emulator-stream.h"
11
12
/*
13
 * Readers in OSCam consist of 2 basic parts.
14
 * The hardware or the device part. This is where physical smart cards are inserted
15
 * and made available to OSCam.
16
 * The software or the emulation part. This is where the actual card reading is done,
17
 * including ecm and emm processing (i.e emulation of the various cryptosystems).
18
 * In the Emu reader, the device part has no meaning, but we have to create it in
19
 * order to be compatible with OSCam's reader structure.
20
*/
21
22
/*
23
 * Create the Emu "emulation" part. This is of type s_cardsystem.
24
 * Similar structures are found in the main sources folder (files reader-xxxxxx.c)
25
 * for every cryptosystem supported by OSCam.
26
 * Here we read keys from our virtual card (aka the SoftCam.Key file) and we inform
27
 * OSCam about them. This is done with the emu_card_info() function. Keep in mind
28
 * that Emu holds all its keys to separate structures for faster access.
29
 * In addition, ECM and EMM requests are processed here, with the emu_do_ecm() and
30
 * emu_do_emm() functions.
31
*/
32
33
#define CS_OK     1
34
#define CS_ERROR  0
35
36
static uint8_t oneByte = 0x01;
37
extern char cs_confdir[128];
38
39
static void set_hexserial_to_version(struct s_reader *rdr)
40
{
41
	char cVersion[32];
42
	uint32_t version = GetOSemuVersion();
43
	uint8_t hversion[2];
44
	memset(hversion, 0, 2);
45
	snprintf(cVersion, sizeof(cVersion), "%04d", version);
46
	CharToBin(hversion, cVersion, 4);
47
	rdr->hexserial[3] = hversion[0];
48
	rdr->hexserial[4] = hversion[1];
49
}
50
51
static void set_prids(struct s_reader *rdr)
52
{
53
	int32_t i, j;
54
55
	rdr->nprov = 0;
56
57
	for (i = 0; (i < rdr->emu_auproviders.nfilts) && (rdr->nprov < CS_MAXPROV); i++)
58
	{
59
		for (j = 0; (j < rdr->emu_auproviders.filts[i].nprids) && (rdr->nprov < CS_MAXPROV); j++)
60
		{
61
			i2b_buf(4, rdr->emu_auproviders.filts[i].prids[j], rdr->prid[i]);
62
			rdr->nprov++;
63
		}
64
	}
65
}
66
67
static void emu_add_entitlement(struct s_reader *rdr, uint16_t caid, uint32_t provid, uint8_t *key, char *keyName, uint32_t keyLength, uint8_t isData)
68
{
69
	if (!rdr->ll_entitlements)
70
	{
71
		rdr->ll_entitlements = ll_create("ll_entitlements");
72
	}
73
74
	S_ENTITLEMENT *item;
75
	if (cs_malloc(&item, sizeof(S_ENTITLEMENT)))
76
	{
77
		// fill item
78
		item->caid = caid;
79
		item->provid = provid;
80
		item->id = 0;
81
		item->class = 0;
82
		item->start = 0;
83
		item->end = 2147472000;
84
		item->type = 0;
85
		item->isKey = 1;
86
		memcpy(item->name, keyName, 8);
87
		item->key = key;
88
		item->keyLength = keyLength;
89
		item->isData = isData;
90
91
		// add item
92
		ll_append(rdr->ll_entitlements, item);
93
	}
94
}
95
96
static void refresh_entitlements(struct s_reader *rdr)
97
{
98
	uint32_t i;
99
	KeyData *tmpKeyData;
100
101
	cs_clear_entitlement(rdr);
102
103
	for (i = 0; i < CwKeys.keyCount; i++)
104
	{
105
		emu_add_entitlement(rdr, CwKeys.EmuKeys[i].provider >> 8, CwKeys.EmuKeys[i].provider & 0xFF,
106
							CwKeys.EmuKeys[i].key, CwKeys.EmuKeys[i].keyName, CwKeys.EmuKeys[i].keyLength, 0);
107
	}
108
109
	for (i = 0; i < ViKeys.keyCount; i++)
110
	{
111
		emu_add_entitlement(rdr, 0x500, ViKeys.EmuKeys[i].provider, ViKeys.EmuKeys[i].key,
112
							ViKeys.EmuKeys[i].keyName, ViKeys.EmuKeys[i].keyLength, 0);
113
	}
114
115
	for (i = 0; i < NagraKeys.keyCount; i++)
116
	{
117
		emu_add_entitlement(rdr, 0x1801, NagraKeys.EmuKeys[i].provider, NagraKeys.EmuKeys[i].key,
118
							NagraKeys.EmuKeys[i].keyName, NagraKeys.EmuKeys[i].keyLength, 0);
119
	}
120
121
	for (i = 0; i < IrdetoKeys.keyCount; i++)
122
	{
123
		tmpKeyData = &IrdetoKeys.EmuKeys[i];
124
		do
125
		{
126
			emu_add_entitlement(rdr, tmpKeyData->provider >> 8, tmpKeyData->provider & 0xFF,
127
								tmpKeyData->key, tmpKeyData->keyName, tmpKeyData->keyLength, 0);
128
129
			tmpKeyData = tmpKeyData->nextKey;
130
		}
131
		while (tmpKeyData != NULL);
132
	}
133
134
	for (i = 0; i < NDSKeys.keyCount; i++)
135
	{
136
		emu_add_entitlement(rdr, NDSKeys.EmuKeys[i].provider, 0, NDSKeys.EmuKeys[i].key,
137
							NDSKeys.EmuKeys[i].keyName, NDSKeys.EmuKeys[i].keyLength, 0);
138
	}
139
140
	emu_add_entitlement(rdr, 0x090F, 0, viasat_const, "00", 64, 1);
141
	emu_add_entitlement(rdr, 0x093E, 0, viasat_const, "00", 64, 1);
142
143
	for (i = 0; i < BissKeys.keyCount; i++)
144
	{
145
		emu_add_entitlement(rdr, 0x2600, BissKeys.EmuKeys[i].provider, BissKeys.EmuKeys[i].key,
146
							BissKeys.EmuKeys[i].keyName, BissKeys.EmuKeys[i].keyLength, 0);
147
	}
148
149
	emu_add_entitlement(rdr, 0xFFFF, 0, &oneByte, "00", 1, 1);
150
	
151
	for (i = 0; i < PowervuKeys.keyCount; i++)
152
	{
153
		emu_add_entitlement(rdr, 0x0E00, PowervuKeys.EmuKeys[i].provider, PowervuKeys.EmuKeys[i].key,
154
							PowervuKeys.EmuKeys[i].keyName, PowervuKeys.EmuKeys[i].keyLength, 0);
155
	}
156
157
	for (i = 0; i < DreKeys.keyCount; i++)
158
	{
159
		emu_add_entitlement(rdr, 0x4AE1, DreKeys.EmuKeys[i].provider, DreKeys.EmuKeys[i].key,
160
							DreKeys.EmuKeys[i].keyName, DreKeys.EmuKeys[i].keyLength, 0);
161
	}
162
163
	for (i = 0; i < TandbergKeys.keyCount; i++)
164
	{
165
		emu_add_entitlement(rdr, 0x1010, TandbergKeys.EmuKeys[i].provider, TandbergKeys.EmuKeys[i].key,
166
							TandbergKeys.EmuKeys[i].keyName, TandbergKeys.EmuKeys[i].keyLength, 0);
167
	}
168
}
169
170
static int32_t emu_do_ecm(struct s_reader *rdr, const struct ecm_request_t *er, struct s_ecm_answer *ea)
171
{
172
173
	if (!ProcessECM(rdr, er->ecmlen, er->caid, er->prid, er->ecm, ea->cw, er->srvid, er->pid, &ea->cw_ex))
174
	{
175
		return CS_OK;
176
	}
177
178
	return CS_ERROR;
179
}
180
181
static int32_t emu_do_emm(struct s_reader *rdr, struct emm_packet_t *emm)
182
{
183
	uint32_t keysAdded = 0;
184
185
	if (emm->emmlen < 3)
186
	{
187
		return CS_ERROR;
188
	}
189
190
	if (SCT_LEN(emm->emm) > emm->emmlen)
191
	{
192
		return CS_ERROR;
193
	}
194
195
	if (!ProcessEMM(rdr, b2i(2, emm->caid), b2i(4, emm->provid), emm->emm, &keysAdded))
196
	{
197
		if (keysAdded > 0)
198
		{
199
			refresh_entitlements(rdr);
200
		}
201
202
		return CS_OK;
203
	}
204
205
	return CS_ERROR;
206
}
207
208
static int32_t emu_card_info(struct s_reader *rdr)
209
{
210
	// Delete keys from Emu's memory
211
	clear_emu_keydata();
212
213
	// Read keys built in the OSCam-Emu binary
214
#if !defined(__APPLE__) && !defined(__ANDROID__)
215
	read_emu_keymemory(rdr);
216
#endif
217
218
	// Read keys from SoftCam.Key file
219
	set_emu_keyfile_path(cs_confdir);
220
221
	if (!read_emu_keyfile(rdr, cs_confdir))
222
	{
223
		if (read_emu_keyfile(rdr, "/var/keys/"))
224
		{
225
			set_emu_keyfile_path("/var/keys/");
226
		}
227
	}
228
229
	// Load keys from external files (set via the webif or the reader config directly)
230
	read_emu_eebin(rdr->extee36, "ee36.bin");           // Read "ee36.bin"
231
	read_emu_eebin(rdr->extee56, "ee56.bin");           // Read "ee56.bin"
232
	read_emu_deskey(rdr->des_key, rdr->des_key_length); // Read overcrypt keys for DreCrypt ADEC
233
234
	cs_log("Total keys in memory: W:%d V:%d N:%d I:%d S:%d F:%d P:%d D:%d T:%d", \
235
					CwKeys.keyCount, ViKeys.keyCount, NagraKeys.keyCount, \
236
					IrdetoKeys.keyCount, NDSKeys.keyCount, BissKeys.keyCount, \
237
					PowervuKeys.keyCount, DreKeys.keyCount, TandbergKeys.keyCount);
238
239
	// Inform OSCam about all available keys.
240
	// This is used for listing the "entitlements" in the webif's reader page.
241
	refresh_entitlements(rdr);
242
243
	set_prids(rdr);
244
245
	set_hexserial_to_version(rdr);
246
247
	return CS_OK;
248
}
249
250
/*
251
static int32_t emu_card_init(struct s_reader *UNUSED(rdr), struct s_ATR *UNUSED(atr))
252
{
253
	return CS_ERROR;
254
}
255
*/
256
257
int32_t emu_get_via3_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
258
{
259
	uint32_t provid = 0;
260
261
	if(ep->emm[3] == 0x90 && ep->emm[4] == 0x03)
262
	{
263
		provid = b2i(3, ep->emm+5);
264
		provid &=0xFFFFF0; 
265
		i2b_buf(4, provid, ep->provid);
266
	}
267
268
	switch(ep->emm[0])
269
	{
270
	case 0x88:
271
		ep->type = UNIQUE;
272
		memset(ep->hexserial, 0, 8);
273
		memcpy(ep->hexserial, ep->emm + 4, 4);
274
		rdr_log_dbg(rdr, D_EMM, "UNIQUE");
275
		return 1;
276
277
	case 0x8A:
278
	case 0x8B:
279
		ep->type = GLOBAL;
280
		rdr_log_dbg(rdr, D_EMM, "GLOBAL");
281
		return 1;
282
283
	case 0x8C:
284
	case 0x8D:
285
		ep->type = SHARED;
286
		rdr_log_dbg(rdr, D_EMM, "SHARED (part)");
287
		// We need those packets to pass otherwise we would never
288
		// be able to complete EMM reassembly
289
		return 1;
290
291
	case 0x8E:
292
		ep->type = SHARED;
293
		rdr_log_dbg(rdr, D_EMM, "SHARED");
294
		memset(ep->hexserial, 0, 8);
295
		memcpy(ep->hexserial, ep->emm + 3, 3);
296
		return 1;
297
298
	default:
299
		ep->type = UNKNOWN;
300
		rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
301
		return 1;
302
	}
303
}
304
305
int32_t emu_get_ird2_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
306
{
307
	int32_t l = (ep->emm[3] & 0x07);
308
	int32_t base = (ep->emm[3] >> 3);
309
	char dumprdrserial[l * 3], dumpemmserial[l * 3];
310
311
	switch(l)
312
	{
313
314
	case 0:
315
		// global emm, 0 bytes addressed
316
		ep->type = GLOBAL;
317
		rdr_log_dbg(rdr, D_EMM, "GLOBAL base = %02x", base);
318
		return 1;
319
320
	case 2:
321
		// shared emm, 2 bytes addressed
322
		ep->type = SHARED;
323
		memset(ep->hexserial, 0, 8);
324
		memcpy(ep->hexserial, ep->emm + 4, l);
325
		cs_hexdump(1, rdr->hexserial, l, dumprdrserial, sizeof(dumprdrserial));
326
		cs_hexdump(1, ep->hexserial, l, dumpemmserial, sizeof(dumpemmserial));
327
		rdr_log_dbg_sensitive(rdr, D_EMM, "SHARED l = %d ep = {%s} rdr = {%s} base = %02x", l,
328
								 dumpemmserial, dumprdrserial, base);
329
		return 1;
330
331
	case 3:
332
		// unique emm, 3 bytes addressed
333
		ep->type = UNIQUE;
334
		memset(ep->hexserial, 0, 8);
335
		memcpy(ep->hexserial, ep->emm + 4, l);
336
		cs_hexdump(1, rdr->hexserial, l, dumprdrserial, sizeof(dumprdrserial));
337
		cs_hexdump(1, ep->hexserial, l, dumpemmserial, sizeof(dumpemmserial));
338
		rdr_log_dbg_sensitive(rdr, D_EMM, "UNIQUE l = %d ep = {%s} rdr = {%s} base = %02x", l,
339
								 dumpemmserial, dumprdrserial, base);
340
		return 1;
341
342
	default:
343
		ep->type = UNKNOWN;
344
		rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
345
		return 1;
346
	}
347
}
348
349
int32_t emu_get_pvu_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
350
{
351
	if(ep->emm[0] == 0x82)
352
	{
353
		ep->type = UNIQUE;
354
		memset(ep->hexserial, 0, 8);
355
		memcpy(ep->hexserial, ep->emm + 12, 4);
356
	}
357
	else
358
	{
359
		ep->type = UNKNOWN;
360
		rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
361
	}
362
	return 1;	
363
}
364
365
int32_t emu_get_dre2_emm_type(EMM_PACKET *ep, struct s_reader *UNUSED(rdr))
366
{
367
	switch (ep->emm[0])
368
	{
369
		case 0x82:
370
			ep->type = GLOBAL;
371
			return 1;
372
373
		case 0x86:
374
			ep->type = SHARED;
375
			memset(ep->hexserial, 0, 8);
376
			ep->hexserial[0] = ep->emm[3];
377
			return 1;
378
379
		//case 0x87:
380
		//	ep->type = UNIQUE;
381
		//	return 1; //FIXME: no filling of ep->hexserial
382
383
		case 0x88:
384
			ep->type = UNIQUE;
385
			return 1; //FIXME: no filling of ep->hexserial
386
387
		case 0x91:
388
			ep->type = GLOBAL;
389
			return 1;
390
391
		default:
392
			ep->type = UNKNOWN;
393
			return 1;
394
	}
395
}
396
397
int32_t emu_get_tan_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
398
{
399
	if(ep->emm[0] == 0x82 || ep->emm[0] == 0x83)
400
	{
401
		ep->type = GLOBAL;
402
	}
403
	else
404
	{
405
		ep->type = UNKNOWN;
406
		rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
407
	}
408
	return 1;
409
}
410
411
static int32_t emu_get_emm_type(struct emm_packet_t *ep, struct s_reader *rdr)
412
{
413
	switch(b2i(2, ep->caid)>>8)
414
	{
415
		case 0x05:
416
			return emu_get_via3_emm_type(ep, rdr);
417
		
418
		case 0x06:
419
			return emu_get_ird2_emm_type(ep, rdr);
420
		
421
		case 0x0E:
422
			return emu_get_pvu_emm_type(ep, rdr);
423
		
424
		case 0x4A:
425
			return emu_get_dre2_emm_type(ep, rdr);
426
		
427
		case 0x10:
428
			return emu_get_tan_emm_type(ep, rdr);
429
		
430
		default:
431
			break;
432
	}
433
	
434
	return CS_ERROR;
435
}
436
437
FILTER* get_emu_prids_for_caid(struct s_reader *rdr, uint16_t caid)
438
{
439
	int32_t i;
440
	
441
	for(i = 0; i < rdr->emu_auproviders.nfilts; i++)
442
	{
443
		if(caid == rdr->emu_auproviders.filts[i].caid)
444
		{
445
			return &rdr->emu_auproviders.filts[i];
446
		}
447
	}
448
	
449
	return NULL;
450
}
451
452
static int32_t emu_get_via3_emm_filter(struct s_reader *UNUSED(rdr), struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t UNUSED(caid), uint32_t UNUSED(provid))
453
{
454
	if(*emm_filters == NULL)
455
	{
456
		const unsigned int max_filter_count = 1;
457
		
458
		if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
459
			{ return CS_ERROR; }
460
		
461
		struct s_csystem_emm_filter *filters = *emm_filters;
462
		*filter_count = 0;
463
		
464
		int32_t idx = 0;
465
		
466
		filters[idx].type = EMM_GLOBAL;
467
		filters[idx].enabled   = 1;
468
		filters[idx].filter[0] = 0x8A;
469
		filters[idx].mask[0]   = 0xFE;
470
		filters[idx].filter[3] = 0x80;
471
		filters[idx].mask[3]   = 0x80;
472
		idx++;
473
		
474
		*filter_count = idx;
475
	}
476
	
477
	return CS_OK;
478
}
479
480
static int32_t emu_get_ird2_emm_filter(struct s_reader* rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t caid, uint32_t UNUSED(provid))
481
{
482
	uint8_t hexserial[3], prid[4];
483
	FILTER* emu_provids;
484
	int8_t have_provid = 0, have_serial = 0;
485
	int32_t i;
486
	
487
	if(GetIrdeto2Hexserial(caid, hexserial))
488
		{ have_serial = 1; }
489
490
	emu_provids = get_emu_prids_for_caid(rdr, caid);
491
	if(emu_provids != NULL && emu_provids->nprids > 0)
492
		{ have_provid = 1; }
493
494
	if(*emm_filters == NULL)
495
	{
496
		const unsigned int max_filter_count = have_serial + (2*(have_provid ? emu_provids->nprids : 0));
497
		if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
498
			{ return CS_ERROR; }
499
500
		struct s_csystem_emm_filter *filters = *emm_filters;
501
		*filter_count = 0;
502
503
		unsigned int idx = 0;
504
505
		if(have_serial)
506
		{
507
			filters[idx].type = EMM_UNIQUE;
508
			filters[idx].enabled   = 1;
509
			filters[idx].filter[0] = 0x82;
510
			filters[idx].mask[0]   = 0xFF;
511
			filters[idx].filter[1] = 0xFB;
512
			filters[idx].mask[1]   = 0x07;
513
			memcpy(&filters[idx].filter[2], hexserial, 3);
514
			memset(&filters[idx].mask[2], 0xFF, 3);
515
			idx++;
516
		}
517
		
518
		for(i=0; have_provid && i<emu_provids->nprids; i++)
519
		{
520
			i2b_buf(4, emu_provids->prids[i], prid);
521
			
522
			filters[idx].type = EMM_UNIQUE;
523
			filters[idx].enabled   = 1;
524
			filters[idx].filter[0] = 0x82;
525
			filters[idx].mask[0]   = 0xFF;
526
			filters[idx].filter[1] = 0xFB;
527
			filters[idx].mask[1]   = 0x07;
528
			memcpy(&filters[idx].filter[2], &prid[1], 3);
529
			memset(&filters[idx].mask[2], 0xFF, 3);
530
			idx++;
531
			
532
			filters[idx].type = EMM_SHARED;
533
			filters[idx].enabled   = 1;
534
			filters[idx].filter[0] = 0x82;
535
			filters[idx].mask[0]   = 0xFF;
536
			filters[idx].filter[1] = 0xFA;
537
			filters[idx].mask[1]   = 0x07;
538
			memcpy(&filters[idx].filter[2], &prid[1], 2);
539
			memset(&filters[idx].mask[2], 0xFF, 2);
540
			idx++;
541
		}
542
		
543
		*filter_count = idx;
544
	}
545
	
546
	return CS_OK;
547
}
548
549
static int32_t emu_get_pvu_emm_filter(struct s_reader *UNUSED(rdr), struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t UNUSED(caid), uint32_t UNUSED(provid), uint16_t srvid)
550
{
551
	uint8_t hexserials[16][4];
552
	int32_t i, count = 0;
553
	
554
	if(!GetPowervuHexserials(srvid, hexserials, 16, &count))
555
		{ return CS_ERROR; }
556
	
557
	if(*emm_filters == NULL)
558
	{
559
		const unsigned int max_filter_count = count;
560
		if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
561
			{ return CS_ERROR; }
562
		
563
		struct s_csystem_emm_filter *filters = *emm_filters;
564
		*filter_count = 0;
565
		
566
		int32_t idx = 0;
567
		
568
		for(i=0; i<count; i++)
569
		{
570
			filters[idx].type = EMM_UNIQUE;
571
			filters[idx].enabled    = 1;
572
			filters[idx].filter[0]  = 0x82;
573
			filters[idx].filter[10] = hexserials[i][0];
574
			filters[idx].filter[11] = hexserials[i][1];
575
			filters[idx].filter[12] = hexserials[i][2];
576
			filters[idx].filter[13] = hexserials[i][3];
577
			filters[idx].mask[0]    = 0xFF;
578
			filters[idx].mask[10]   = 0xFF;
579
			filters[idx].mask[11]   = 0xFF;
580
			filters[idx].mask[12]   = 0xFF;
581
			filters[idx].mask[13]   = 0xFF;
582
			idx++;
583
		}
584
		
585
		*filter_count = idx;
586
	}
587
588
	return CS_OK;
589
}
590
591
static int32_t emu_get_dre2_emm_filter(struct s_reader *UNUSED(rdr), struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t caid, uint32_t provid)
592
{
593
	uint8_t hexserials[16];
594
	int32_t i, count = 0;
595
	
596
	if(!GetDrecryptHexserials(caid, provid, hexserials, 16, &count))
597
		{ count = 0; }
598
	
599
	if(*emm_filters == NULL)
600
	{
601
		const unsigned int max_filter_count = 1 + count + 1;
602
		if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
603
			{ return CS_ERROR; }
604
		
605
		struct s_csystem_emm_filter *filters = *emm_filters;
606
		*filter_count = 0;
607
		
608
		int32_t idx = 0;
609
		
610
		if(provid == 0xFE)
611
		{
612
			filters[idx].type = EMM_GLOBAL;
613
			filters[idx].enabled   = 1;
614
			filters[idx].filter[0] = 0x91;
615
			filters[idx].mask[0]   = 0xFF;
616
			idx++;
617
		}
618
		
619
		for(i=0; i<count; i++)
620
		{
621
			filters[idx].type = EMM_SHARED;
622
			filters[idx].enabled   = 1;
623
			filters[idx].filter[0] = 0x86;
624
			filters[idx].filter[1] = hexserials[i];
625
			filters[idx].mask[0]   = 0xFF;
626
			filters[idx].mask[1]   = 0xFF;
627
			idx++;
628
		}
629
		
630
		//filters[idx].type = EMM_UNIQUE;
631
		//filters[idx].enabled   = 1;
632
		//filters[idx].filter[0] = 0x87;
633
		//filters[idx].mask[0]   = 0xFF;
634
		//idx++;
635
		
636
		filters[idx].type = EMM_UNIQUE;
637
		filters[idx].enabled   = 1;
638
		filters[idx].filter[0] = 0x88;
639
		filters[idx].mask[0]   = 0xFF;
640
		idx++;
641
		
642
		*filter_count = idx;
643
	}
644
	
645
	return CS_OK;
646
}
647
648
static int32_t emu_get_tan_emm_filter(struct s_reader *UNUSED(rdr), struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t UNUSED(caid), uint32_t UNUSED(provid))
649
{
650
	if(*emm_filters == NULL)
651
	{
652
		const unsigned int max_filter_count = 2;
653
		uint8_t buf[8];
654
		
655
		if(!FindKey('T', 0x40, 0, "MK", buf, 8, 0, 0, 0, NULL) && !FindKey('T', 0x40, 0, "MK01", buf, 8, 0, 0, 0, NULL))
656
			{ return CS_ERROR; }
657
		
658
		if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
659
			{ return CS_ERROR; }
660
		
661
		struct s_csystem_emm_filter *filters = *emm_filters;
662
		*filter_count = 0;
663
		
664
		int32_t idx = 0;
665
		
666
		filters[idx].type = EMM_GLOBAL;
667
		filters[idx].enabled   = 1;
668
		filters[idx].filter[0] = 0x82;
669
		filters[idx].mask[0]   = 0xFF;
670
		idx++;
671
		
672
		filters[idx].type = EMM_GLOBAL;
673
		filters[idx].enabled   = 1;
674
		filters[idx].filter[0] = 0x83;
675
		filters[idx].mask[0]   = 0xFF;
676
		idx++;
677
		
678
		*filter_count = idx;
679
	}	
680
	
681
	return CS_OK;
682
}
683
684
static int32_t emu_get_emm_filter(struct s_reader *UNUSED(rdr), struct s_csystem_emm_filter **UNUSED(emm_filters), unsigned int *UNUSED(filter_count))
685
{
686
	return CS_ERROR;
687
}
688
689
static int32_t emu_get_emm_filter_adv(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t caid, uint32_t provid, uint16_t srvid)
690
{
691
	switch(caid>>8)
692
	{
693
		case 0x05:
694
			return emu_get_via3_emm_filter(rdr, emm_filters, filter_count, caid, provid);
695
		
696
		case 0x06:
697
			return emu_get_ird2_emm_filter(rdr, emm_filters, filter_count, caid, provid);
698
		
699
		case 0x0E:
700
			return emu_get_pvu_emm_filter(rdr, emm_filters, filter_count, caid, provid, srvid);
701
		
702
		case 0x4A:
703
			return emu_get_dre2_emm_filter(rdr, emm_filters, filter_count, caid, provid);
704
		
705
		case 0x10:
706
			return emu_get_tan_emm_filter(rdr, emm_filters, filter_count, caid, provid);
707
		
708
		default:
709
			break;
710
	}
711
	
712
	return CS_ERROR;
713
}
714
715
const struct s_cardsystem reader_emu =
716
{
717
	.desc = "emu",
718
	.caids = (uint16_t[]){ 0x0D, 0x09, 0x0500, 0x18, 0x06, 0x26, 0xFFFF, 0x0E, 0x4A, 0x10, 0 },
719
	.do_ecm = emu_do_ecm,
720
	.do_emm = emu_do_emm,
721
	.card_info = emu_card_info,
722
	//.card_init = emu_card_init, // apparently this is not needed at all
723
	.get_emm_type = emu_get_emm_type,
724
	.get_emm_filter = emu_get_emm_filter, // needed to pass checks
725
	.get_emm_filter_adv = emu_get_emm_filter_adv,
726
};
727
728
/*
729
 * Create the Emu virtual "device" part. This is of type s_cardreader.
730
 * Similar structures are found in the csctapi (Card System Card Terminal API)
731
 * folder for every IFD (InterFace Device), aka smart card reader.
732
 * Since we have no hardware to initialize, we start our Stream Relay server
733
 * with the emu_reader_init() function.
734
 * At Emu shutdown, we remove keys from memory with the emu_close() function.
735
*/
736
737
#define CR_OK     0
738
#define CR_ERROR  1
739
740
static int32_t emu_reader_init(struct s_reader *UNUSED(reader))
741
{
742
	int32_t i;
743
	char authtmp[128];
744
745
	if (cfg.emu_stream_relay_enabled && (stream_server_thread_init == 0))
746
	{
747
		stream_server_thread_init = 1;
748
		SAFE_MUTEX_INIT(&emu_fixed_key_srvid_mutex, NULL);
749
750
		for (i = 0; i < EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
751
		{
752
			SAFE_MUTEX_INIT(&emu_fixed_key_data_mutex[i], NULL);
753
			ll_emu_stream_delayed_keys[i] = ll_create("ll_emu_stream_delayed_keys");
754
			memset(&emu_fixed_key_data[i], 0, sizeof(emu_stream_client_key_data));
755
		}
756
757
		start_thread("stream_key_delayer", stream_key_delayer, NULL, NULL, 1, 1);
758
		cs_log("Stream key delayer initialized");
759
760
		cs_strncpy(emu_stream_source_host, cfg.emu_stream_source_host, sizeof(emu_stream_source_host));
761
		emu_stream_source_port = cfg.emu_stream_source_port;
762
		emu_stream_relay_port = cfg.emu_stream_relay_port;
763
		emu_stream_emm_enabled = cfg.emu_stream_emm_enabled;
764
765
		if (cfg.emu_stream_source_auth_user && cfg.emu_stream_source_auth_password)
766
		{
767
			snprintf(authtmp, sizeof(authtmp), "%s:%s", cfg.emu_stream_source_auth_user, cfg.emu_stream_source_auth_password);
768
			b64encode(authtmp, strlen(authtmp), &emu_stream_source_auth);
769
		}
770
		else
771
		{
772
			NULLFREE(emu_stream_source_auth);
773
		}
774
775
		start_thread("stream_server", stream_server, NULL, NULL, 1, 1);
776
		cs_log("Stream relay server initialized");
777
	}
778
779
	return CR_OK;
780
}
781
782
static int32_t emu_close(struct s_reader *UNUSED(reader))
783
{
784
	cs_log("Reader is shutting down");
785
786
	// Delete keys from Emu's memory
787
	clear_emu_keydata();
788
789
	return CR_OK;
790
}
791
792
static int32_t emu_get_status(struct s_reader *UNUSED(reader), int32_t *in) { *in = 1; return CR_OK; }
793
static int32_t emu_activate(struct s_reader *UNUSED(reader), struct s_ATR *UNUSED(atr)) { return CR_OK; }
794
static int32_t emu_transmit(struct s_reader *UNUSED(reader), uint8_t *UNUSED(buffer), uint32_t UNUSED(size), uint32_t UNUSED(expectedlen), uint32_t UNUSED(delay), uint32_t UNUSED(timeout)) { return CR_OK; }
795
static int32_t emu_receive(struct s_reader *UNUSED(reader), uint8_t *UNUSED(buffer), uint32_t UNUSED(size), uint32_t UNUSED(delay), uint32_t UNUSED(timeout)) { return CR_OK; }
796
static int32_t emu_write_settings(struct s_reader *UNUSED(reader), struct s_cardreader_settings *UNUSED(s)) { return CR_OK; }
797
static int32_t emu_card_write(struct s_reader *UNUSED(pcsc_reader),const uchar *UNUSED(buf) ,uint8_t *UNUSED(cta_res), uint16_t *UNUSED(cta_lr),int32_t UNUSED(l)) { return CR_OK; }
798
static int32_t emu_set_protocol(struct s_reader *UNUSED(rdr),uint8_t *UNUSED(params),uint32_t *UNUSED(length), uint32_t UNUSED(len_request)) { return CR_OK; }
799
800
const struct s_cardreader cardreader_emu =
801
{
802
	.desc                   = "emu",
803
	.typ                    = R_EMU,
804
	.skip_extra_atr_parsing = 1,
805
	.reader_init            = emu_reader_init,
806
	.get_status             = emu_get_status,
807
	.activate               = emu_activate,
808
	.transmit               = emu_transmit,
809
	.receive                = emu_receive,
810
	.close                  = emu_close,
811
	.write_settings         = emu_write_settings,
812
	.card_write             = emu_card_write,
813
	.set_protocol           = emu_set_protocol,
814
};
815
816
void add_emu_reader(void)
817
{
818
	// This function is called inside oscam.c and creates an emu [reader] with default
819
	// settings in oscam.server file. If an emu [reader] already exists, it uses that.
820
821
	LL_ITER itr;
822
	struct s_reader *rdr;
823
	int8_t haveEmuReader = 0;
824
	char *emuName = "emulator";
825
	char *ctab, *ftab, *emu_auproviders;
826
827
	// Check if emu [reader] entry already exists in oscam.server file and get it
828
	itr = ll_iter_create(configured_readers);
829
	while ((rdr = ll_iter_next(&itr)))
830
	{
831
		if (rdr->typ == R_EMU)
832
		{
833
			haveEmuReader = 1;
834
			break;
835
		}
836
	}
837
838
	rdr = NULL;
839
840
	// If there's no emu [reader] in oscam.server, create one with default settings
841
	if (!haveEmuReader)
842
	{
843
		if (!cs_malloc(&rdr, sizeof(struct s_reader)))
844
		{
845
			return;
846
		}
847
848
		reader_set_defaults(rdr);
849
850
		rdr->enable = 1;
851
		rdr->typ = R_EMU;
852
		strncpy(rdr->label, emuName, strlen(emuName));
853
		strncpy(rdr->device, emuName, strlen(emuName));
854
855
		// CAIDs
856
		ctab = strdup("090F,0500,1801,0604,2600,FFFF,0E00,4AE1,1010");
857
		chk_caidtab(ctab, &rdr->ctab);
858
		NULLFREE(ctab);
859
860
		// Idents
861
		ftab = strdup("090F:000000;"
862
					  "0500:000000,023800,021110,007400,007800;"
863
					  "1801:000000,007301,001101,002111;"
864
					  "0604:000000;"
865
					  "2600:000000;"
866
					  "FFFF:000000;"
867
					  "0E00:000000;"
868
					  "4AE1:000011,000014,0000FE;"
869
					  "1010:000000;"
870
					 );
871
		chk_ftab(ftab, &rdr->ftab);
872
		NULLFREE(ftab);
873
874
		// AU providers
875
		emu_auproviders = strdup("0604:010200;0E00:000000;4AE1:000011,000014,0000FE;1010:000000;");
876
		chk_ftab(emu_auproviders, &rdr->emu_auproviders);
877
		NULLFREE(emu_auproviders);
878
879
		// EMM cache
880
		rdr->cachemm = 2;
881
		rdr->rewritemm = 1;
882
		rdr->logemm = 2;
883
		rdr->deviceemm = 1;
884
885
		// User group
886
		rdr->grp = 0x1ULL;
887
888
		// Add the "device" part to our emu reader
889
		rdr->crdr = &cardreader_emu;
890
891
		reader_fixups_fn(rdr);
892
		ll_append(configured_readers, rdr);
893
	}
894
895
	// Set DVB Api delayer option
896
#ifdef HAVE_DVBAPI
897
	if (cfg.dvbapi_enabled && cfg.dvbapi_delayer < 60)
898
	{
899
		cfg.dvbapi_delayer = 60;
900
	}
901
#endif
902
903
	cs_log("OSCam-Emu version %d", GetOSemuVersion());
904
}
(-)module-newcamd-des.c (-4 / +1 lines)
Lines 5-14 Link Here
5
#define DES_IP              1
5
#define DES_IP              1
6
#define DES_IP_1            2
6
#define DES_IP_1            2
7
#define DES_RIGHT           4
7
#define DES_RIGHT           4
8
#define DES_HASH            8
9
8
10
#define DES_ECM_CRYPT       0
11
#define DES_ECM_HASH        DES_HASH
12
#define DES_ECS2_DECRYPT    (DES_IP | DES_IP_1 | DES_RIGHT)
9
#define DES_ECS2_DECRYPT    (DES_IP | DES_IP_1 | DES_RIGHT)
13
#define DES_ECS2_CRYPT      (DES_IP | DES_IP_1)
10
#define DES_ECS2_CRYPT      (DES_IP | DES_IP_1)
14
11
Lines 356-362 Link Here
356
	swap(data - 4, data);
353
	swap(data - 4, data);
357
}
354
}
358
355
359
static void nc_des(unsigned char key[], unsigned char mode, unsigned char data[])
356
void nc_des(unsigned char key[], unsigned char mode, unsigned char data[])
360
{
357
{
361
	unsigned char i;
358
	unsigned char i;
362
	unsigned char left[8];
359
	unsigned char left[8];
(-)module-newcamd-des.h (+7 lines)
Lines 1-8 Link Here
1
#ifndef MODULE_NEWCAMD_DES_H_
1
#ifndef MODULE_NEWCAMD_DES_H_
2
#define MODULE_NEWCAMD_DES_H_
2
#define MODULE_NEWCAMD_DES_H_
3
3
4
#define DES_HASH            8
5
6
#define DES_ECM_CRYPT       0
7
#define DES_ECM_HASH        DES_HASH
8
4
	int nc_des_encrypt(unsigned char *buffer, int len, unsigned char *deskey);
9
	int nc_des_encrypt(unsigned char *buffer, int len, unsigned char *deskey);
5
	int nc_des_decrypt(unsigned char *buffer, int len, unsigned char *deskey);
10
	int nc_des_decrypt(unsigned char *buffer, int len, unsigned char *deskey);
6
	unsigned char *nc_des_login_key_get(unsigned char *key1, unsigned char *key2, int len, unsigned char *des16);
11
	unsigned char *nc_des_login_key_get(unsigned char *key1, unsigned char *key2, int len, unsigned char *des16);
7
12
13
	void nc_des(unsigned char key[], unsigned char mode, unsigned char data[]);
14
8
#endif
15
#endif
(-)module-newcamd.c (-1 / +41 lines)
Lines 919-924 Link Here
919
			// set userfilter for au enabled clients
919
			// set userfilter for au enabled clients
920
			if(aureader)
920
			if(aureader)
921
			{
921
			{
922
#ifdef WITH_EMU
923
				if(aureader->typ == R_EMU)
924
				{
925
					usr_filter = * get_emu_prids_for_caid(aureader, cfg.ncd_ptab.ports[cl->port_idx].ncd->ncd_ftab.filts[0].caid);
926
				}
927
				else
928
#endif
922
				mk_user_au_ftab(aureader, &usr_filter);
929
				mk_user_au_ftab(aureader, &usr_filter);
923
			}
930
			}
924
			
931
			
Lines 948-953 Link Here
948
			else
955
			else
949
				{ memset(&mbuf[8], 0, 6); } //mbuf[8] - mbuf[13]
956
				{ memset(&mbuf[8], 0, 6); } //mbuf[8] - mbuf[13]
950
957
958
#ifdef WITH_EMU
959
			if(aureader && aureader->typ == R_EMU && caid_is_dre(pufilt->caid))
960
			{
961
				mbuf[10] = aureader->dre36_force_group;
962
			}
963
#endif
964
951
			mbuf[14] = pufilt->nprids;
965
			mbuf[14] = pufilt->nprids;
952
			for(j = 0; j < pufilt->nprids; j++)
966
			for(j = 0; j < pufilt->nprids; j++)
953
			{
967
			{
Lines 973-979 Link Here
973
					int32_t k, found;
987
					int32_t k, found;
974
					uint32_t rprid;
988
					uint32_t rprid;
975
					found = 0;
989
					found = 0;
976
					if(pufilt->caid == aureader->caid)
990
					if(pufilt->caid == aureader->caid && aureader->typ != R_EMU)
977
					{
991
					{
978
						for(k = 0; (k < aureader->nprov); k++)
992
						for(k = 0; (k < aureader->nprov); k++)
979
						{
993
						{
Lines 999-1004 Link Here
999
							}
1013
							}
1000
						}
1014
						}
1001
					}
1015
					}
1016
#ifdef WITH_EMU
1017
					else if(aureader->typ == R_EMU)
1018
					{
1019
						if(caid_is_dre(pufilt->caid))
1020
						{
1021
							found = 1;
1022
							memset(&mbuf[22 + 11 * j] ,0 ,4);
1023
							switch((uchar)(pufilt->prids[j]))
1024
							{
1025
								case 0x11:
1026
									mbuf[22 + 11 * j] = aureader->dre36_force_group;
1027
									break;
1028
								case 0x14:
1029
									mbuf[22 + 11 * j] = aureader->dre56_force_group;
1030
									break;
1031
								case 0xfe:
1032
									mbuf[22 + 11 * j] = 0xED;
1033
									mbuf[25 + 11 * j] = 0x02;
1034
									break;
1035
								default:
1036
									found = 0;
1037
							}
1038
						}
1039
					}
1040
#endif
1041
					
1002
					if(!found)
1042
					if(!found)
1003
					{
1043
					{
1004
						mbuf[22 + 11 * j] = 0x00;
1044
						mbuf[22 + 11 * j] = 0x00;
(-)module-stat.c (-2 / +2 lines)
Lines 903-909 Link Here
903
903
904
uint16_t get_rdr_caid(struct s_reader *rdr)
904
uint16_t get_rdr_caid(struct s_reader *rdr)
905
{
905
{
906
	if(is_network_reader(rdr))
906
	if(is_network_reader(rdr) || rdr->typ == R_EMU)
907
	{
907
	{
908
		return 0; //reader caid is not real caid
908
		return 0; //reader caid is not real caid
909
	}
909
	}
Lines 1301-1307 Link Here
1301
		for(ea = er->matching_rdr; ea; ea = ea->next)
1301
		for(ea = er->matching_rdr; ea; ea = ea->next)
1302
		{
1302
		{
1303
			rdr = ea->reader;
1303
			rdr = ea->reader;
1304
			if(is_network_reader(rdr))    //reader caid is not real caid
1304
			if(is_network_reader(rdr) || rdr->typ == R_EMU)    //reader caid is not real caid
1305
			{
1305
			{
1306
				prv = ea;
1306
				prv = ea;
1307
				continue; // proxy can convert or reject
1307
				continue; // proxy can convert or reject
(-)module-webif-tpl.c (+1 lines)
Lines 457-462 Link Here
457
											check_conf(WITH_SSL, ptr2);
457
											check_conf(WITH_SSL, ptr2);
458
											check_conf(WITH_STAPI, ptr2);
458
											check_conf(WITH_STAPI, ptr2);
459
											check_conf(WITH_STAPI5, ptr2);
459
											check_conf(WITH_STAPI5, ptr2);
460
											check_conf(WITH_EMU, ptr2);
460
										} // for
461
										} // for
461
										if(ok == 0)
462
										if(ok == 0)
462
										{
463
										{
(-)module-webif.c (-5 / +105 lines)
Lines 101-106 Link Here
101
#define MNU_CFG_LCD			14
101
#define MNU_CFG_LCD			14
102
#define MNU_CFG_MONITOR		15
102
#define MNU_CFG_MONITOR		15
103
#define MNU_CFG_WEBIF		16
103
#define MNU_CFG_WEBIF		16
104
#define MNU_CFG_STREAMRELAY	17
104
105
105
/* constants for files.html submenuactivating */
106
/* constants for files.html submenuactivating */
106
#define MNU_CFG_FVERSION	0
107
#define MNU_CFG_FVERSION	0
Lines 134-141 Link Here
134
#define MNU_GBX_FSTAINF     	27
135
#define MNU_GBX_FSTAINF     	27
135
#define MNU_GBX_FEXPINF     	28
136
#define MNU_GBX_FEXPINF     	28
136
#define MNU_GBX_INFOLOG     	29
137
#define MNU_GBX_INFOLOG     	29
138
#define MNU_CFG_FSOFTCAMKEY	30
137
139
138
#define MNU_CFG_TOTAL_ITEMS 	30 // sum of items above. Use it for "All inactive" in function calls too.
140
#define MNU_CFG_TOTAL_ITEMS 	31 // sum of config or files items above. Use it for "All inactive" in function calls too.
139
141
140
static void set_status_info_var(struct templatevars *vars, char *varname, int no_data, char *fmt, double value) {
142
static void set_status_info_var(struct templatevars *vars, char *varname, int no_data, char *fmt, double value) {
141
	if (no_data)
143
	if (no_data)
Lines 1216-1221 Link Here
1216
}
1218
}
1217
#endif
1219
#endif
1218
1220
1221
#ifdef WITH_EMU
1222
#include "module-emulator-stream.h"
1223
1224
static char *send_oscam_config_streamrelay(struct templatevars *vars, struct uriparams *params)
1225
{
1226
	setActiveSubMenu(vars, MNU_CFG_STREAMRELAY);
1227
1228
	webif_save_config("streamrelay", vars, params);
1229
1230
	tpl_printf(vars, TPLADD, "STREAM_SOURCE_HOST", "%s", cfg.emu_stream_source_host);
1231
	tpl_printf(vars, TPLADD, "STREAM_SOURCE_PORT", "%d", cfg.emu_stream_source_port);
1232
	if(cfg.emu_stream_source_auth_user)
1233
		{ tpl_printf(vars, TPLADD, "STREAM_SOURCE_AUTH_USER", "%s", cfg.emu_stream_source_auth_user); }
1234
	if(cfg.emu_stream_source_auth_password)
1235
		{ tpl_printf(vars, TPLADD, "STREAM_SOURCE_AUTH_PASSWORD", "%s", cfg.emu_stream_source_auth_password); }
1236
	tpl_printf(vars, TPLADD, "STREAM_RELAY_PORT", "%d", cfg.emu_stream_relay_port);
1237
	tpl_printf(vars, TPLADD, "STREAM_ECM_DELAY", "%d", cfg.emu_stream_ecm_delay);
1238
	
1239
	tpl_printf(vars, TPLADD, "TMP", "STREAMRELAYENABLEDSELECTED%d", cfg.emu_stream_relay_enabled);
1240
	tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1241
1242
	tpl_printf(vars, TPLADD, "TMP", "STREAMEMMENABLEDSELECTED%d", cfg.emu_stream_emm_enabled);
1243
	tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1244
1245
	return tpl_getTpl(vars, "CONFIGSTREAMRELAY");
1246
}
1247
#endif
1248
1219
#ifdef MODULE_CCCAM
1249
#ifdef MODULE_CCCAM
1220
static char *send_oscam_config_cccam(struct templatevars *vars, struct uriparams *params)
1250
static char *send_oscam_config_cccam(struct templatevars *vars, struct uriparams *params)
1221
{
1251
{
Lines 1554-1559 Link Here
1554
	tpl_printf(vars, TPLADD, "TMP", "EXTENDEDCWAPISELECTED%d", cfg.dvbapi_extended_cw_api);
1584
	tpl_printf(vars, TPLADD, "TMP", "EXTENDEDCWAPISELECTED%d", cfg.dvbapi_extended_cw_api);
1555
	tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1585
	tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1556
1586
1587
	//extended_cw_pids (pid limiter)
1588
	tpl_printf(vars, TPLADD, "TMP", "EXTENDEDCWPIDSSELECTED%d", cfg.dvbapi_extended_cw_pids);
1589
	tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1590
1557
	//write_sdt_prov
1591
	//write_sdt_prov
1558
	if(cfg.dvbapi_write_sdt_prov > 0)
1592
	if(cfg.dvbapi_write_sdt_prov > 0)
1559
		{ tpl_addVar(vars, TPLADD, "WRITESDTPROVCHECKED", "checked"); } 
1593
		{ tpl_addVar(vars, TPLADD, "WRITESDTPROVCHECKED", "checked"); } 
Lines 1631-1636 Link Here
1631
#ifdef MODULE_SCAM
1665
#ifdef MODULE_SCAM
1632
	else if(!strcmp(part, "scam")) { return send_oscam_config_scam(vars, params); }
1666
	else if(!strcmp(part, "scam")) { return send_oscam_config_scam(vars, params); }
1633
#endif
1667
#endif
1668
#ifdef WITH_EMU
1669
	else if(!strcmp(part, "streamrelay")) { return send_oscam_config_streamrelay(vars, params); }
1670
#endif
1634
#ifdef MODULE_CCCAM
1671
#ifdef MODULE_CCCAM
1635
	else if(!strcmp(part, "cccam")) { return send_oscam_config_cccam(vars, params); }
1672
	else if(!strcmp(part, "cccam")) { return send_oscam_config_cccam(vars, params); }
1636
#endif
1673
#endif
Lines 2093-2099 Link Here
2093
		chk_reader("services", servicelabels, rdr);
2130
		chk_reader("services", servicelabels, rdr);
2094
		chk_reader("lb_whitelist_services", servicelabelslb, rdr);
2131
		chk_reader("lb_whitelist_services", servicelabelslb, rdr);
2095
2132
2096
		if(is_network_reader(rdr))    //physical readers make trouble if re-started
2133
		if(is_network_reader(rdr) || rdr->typ == R_EMU)    //physical readers make trouble if re-started
2097
		{
2134
		{
2098
			restart_cardreader(rdr, 1);
2135
			restart_cardreader(rdr, 1);
2099
		}
2136
		}
Lines 2671-2676 Link Here
2671
	tpl_addVar(vars, TPLADD, "USERSCRIPT", rdr->userscript);
2708
	tpl_addVar(vars, TPLADD, "USERSCRIPT", rdr->userscript);
2672
#endif
2709
#endif
2673
2710
2711
#ifdef WITH_EMU
2712
	//emu_auproviders
2713
	value = mk_t_ftab(&rdr->emu_auproviders);
2714
	tpl_addVar(vars, TPLADD, "EMUAUPROVIDERS", value);
2715
	free_mk_t(value);
2716
2717
	// Date-coded BISS keys
2718
	if(!apicall)
2719
	{
2720
		tpl_addVar(vars, TPLADD, "EMUDATECODEDENABLED", (rdr->emu_datecodedenabled == 1) ? "checked" : "");
2721
	}
2722
	else
2723
	{
2724
		tpl_addVar(vars, TPLADD, "EMUDATECODEDENABLED", (rdr->emu_datecodedenabled == 1) ? "1" : "0");
2725
	}
2726
2727
	//extee
2728
	tpl_addVar(vars, TPLADD, "EXTEE36", rdr->extee36);
2729
	tpl_addVar(vars, TPLADD, "EXTEE56", rdr->extee56);
2730
2731
	//dre force group
2732
	tpl_printf(vars, TPLADD, "DRE36FORCEGROUP","%02X", rdr->dre36_force_group);
2733
	tpl_printf(vars, TPLADD, "DRE56FORCEGROUP","%02X", rdr->dre56_force_group);
2734
#endif
2735
2674
	tpl_addVar(vars, TPLADD, "PROTOCOL", reader_get_type_desc(rdr, 0));
2736
	tpl_addVar(vars, TPLADD, "PROTOCOL", reader_get_type_desc(rdr, 0));
2675
2737
2676
	// Show only parameters which needed for the reader
2738
	// Show only parameters which needed for the reader
Lines 2692-2697 Link Here
2692
	case R_CAMD35 :
2754
	case R_CAMD35 :
2693
		tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCAMD35BIT"));
2755
		tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCAMD35BIT"));
2694
		break;
2756
		break;
2757
	case R_EMU :
2758
		tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGEMUBIT"));
2759
		break;
2695
	case R_CS378X :
2760
	case R_CS378X :
2696
		tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCS378XBIT"));
2761
		tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCS378XBIT"));
2697
		break;
2762
		break;
Lines 4414-4422 Link Here
4414
4479
4415
					tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", "<BR><BR>New Structure:<BR>");
4480
					tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", "<BR><BR>New Structure:<BR>");
4416
					char tbuffer[83];
4481
					char tbuffer[83];
4482
#ifdef WITH_EMU
4483
					char keyBuffer[1024];
4484
#endif
4417
					int jsondelimiter = 0;
4485
					int jsondelimiter = 0;
4418
					while((item = ll_iter_next(&itr)))
4486
					while((item = ll_iter_next(&itr)))
4419
					{
4487
					{
4488
#ifdef WITH_EMU
4489
						if(item->isKey) {
4490
							tpl_addVar(vars, TPLADD, "ENTSTARTDATE", "");
4491
							tpl_addVar(vars, TPLADD, "ENTENDDATE", "");
4492
							cs_hexdump(0, item->key, item->keyLength, keyBuffer, sizeof(keyBuffer));
4493
							tpl_addVar(vars, TPLADD, "ENTEXPIERED", "e_valid");
4494
							tpl_printf(vars, TPLADD, "ENTCAID", "%04X", item->caid);
4495
							if(item->caid == 0x2600) {
4496
								tpl_printf(vars, TPLADD, "ENTPROVID", "%08X", item->provid);
4497
							}
4498
							else {
4499
								tpl_printf(vars, TPLADD, "ENTPROVID", "%06X", item->provid);
4500
							}
4501
							tpl_addVar(vars, TPLADD, "ENTID", item->name);
4502
							tpl_addVar(vars, TPLADD, "ENTCLASS", keyBuffer);
4503
							if(item->isData) { tpl_addVar(vars, TPLADD, "ENTTYPE", "data"); }
4504
							else { tpl_addVar(vars, TPLADD, "ENTTYPE", "key"); }
4505
							tpl_addVar(vars, TPLADD, "ENTRESNAME", "");
4506
							
4507
							if((strcmp(getParam(params, "hideexpired"), "1") != 0) || (item->end > now))
4508
								{ tpl_addVar(vars, TPLAPPEND, "READERENTENTRY", tpl_getTpl(vars, "ENTITLEMENTITEMBIT")); }
4509
							
4510
							continue;
4511
						}
4512
#endif
4513
4420
						localtime_r(&item->start, &start_t);
4514
						localtime_r(&item->start, &start_t);
4421
						localtime_r(&item->end, &end_t);
4515
						localtime_r(&item->end, &end_t);
4422
4516
Lines 4892-4897 Link Here
4892
#else
4986
#else
4893
						filtered = (type == cl->typ);
4987
						filtered = (type == cl->typ);
4894
#endif
4988
#endif
4989
#ifdef WITH_EMU
4990
                        if(type == 'e' && cl->typ == 'r' && cl->reader->typ == R_EMU) filtered = 1;
4991
#endif
4895
					}
4992
					}
4896
				}
4993
				}
4897
4994
Lines 6336-6341 Link Here
6336
		{ "expired.info",    MNU_GBX_FEXPINF,   FTYPE_GBOX },     // id 28
6433
		{ "expired.info",    MNU_GBX_FEXPINF,   FTYPE_GBOX },     // id 28
6337
		{ "info.log",        MNU_GBX_INFOLOG,   FTYPE_GBOX },     // id 29
6434
		{ "info.log",        MNU_GBX_INFOLOG,   FTYPE_GBOX },     // id 29
6338
#endif
6435
#endif
6436
#ifdef WITH_EMU
6437
		{ "SoftCam.Key",     MNU_CFG_FSOFTCAMKEY,FTYPE_CONFIG },  // id 30
6438
#endif
6339
		{ NULL, 0, 0 },
6439
		{ NULL, 0, 0 },
6340
	};
6440
	};
6341
6441
Lines 6806-6812 Link Here
6806
		else if(!proxy && rdr->csystem_active)     // local active reader
6906
		else if(!proxy && rdr->csystem_active)     // local active reader
6807
		{
6907
		{
6808
			csystem = rdr->csystem;
6908
			csystem = rdr->csystem;
6809
			caid = rdr->caid;
6909
			if(rdr->typ != R_EMU) caid = rdr->caid;
6810
		}
6910
		}
6811
6911
6812
		if(csystem)
6912
		if(csystem)
Lines 7813-7820 Link Here
7813
		memcpy(*result + bufsize, buf2, n);
7913
		memcpy(*result + bufsize, buf2, n);
7814
		bufsize += n;
7914
		bufsize += n;
7815
7915
7816
		//max request size 100kb
7916
		//max request size 200kb
7817
		if(bufsize > 102400)
7917
		if(bufsize > 204800)
7818
		{
7918
		{
7819
			cs_log("error: too much data received from %s", cs_inet_ntoa(in));
7919
			cs_log("error: too much data received from %s", cs_inet_ntoa(in));
7820
			NULLFREE(*result);
7920
			NULLFREE(*result);
(-)oscam-aes.c (+10 lines)
Lines 37-42 Link Here
37
	}
37
	}
38
}
38
}
39
39
40
void aes_cbc_encrypt(struct aes_keys *aes, uchar *buf, int32_t n, uchar *iv)
41
{
42
	AES_cbc_encrypt(buf, buf, n, &aes->aeskey_encrypt, iv, AES_ENCRYPT);
43
}
44
45
void aes_cbc_decrypt(struct aes_keys *aes, uchar *buf, int32_t n, uchar *iv)
46
{
47
	AES_cbc_encrypt(buf, buf, n, &aes->aeskey_decrypt, iv, AES_DECRYPT);
48
}
49
40
/* Creates an AES_ENTRY and adds it to the given linked list. */
50
/* Creates an AES_ENTRY and adds it to the given linked list. */
41
void add_aes_entry(AES_ENTRY **list, uint16_t caid, uint32_t ident, int32_t keyid, uchar *aesKey)
51
void add_aes_entry(AES_ENTRY **list, uint16_t caid, uint32_t ident, int32_t keyid, uchar *aesKey)
42
{
52
{
(-)oscam-aes.h (+2 lines)
Lines 5-10 Link Here
5
bool aes_set_key_alloc(struct aes_keys **aes, char *key);
5
bool aes_set_key_alloc(struct aes_keys **aes, char *key);
6
void aes_decrypt(struct aes_keys *aes, uchar *buf, int32_t n);
6
void aes_decrypt(struct aes_keys *aes, uchar *buf, int32_t n);
7
void aes_encrypt_idx(struct aes_keys *aes, uchar *buf, int32_t n);
7
void aes_encrypt_idx(struct aes_keys *aes, uchar *buf, int32_t n);
8
void aes_cbc_encrypt(struct aes_keys *aes, uchar *buf, int32_t n, uchar *iv);
9
void aes_cbc_decrypt(struct aes_keys *aes, uchar *buf, int32_t n, uchar *iv);
8
10
9
void add_aes_entry(AES_ENTRY **list, uint16_t caid, uint32_t ident, int32_t keyid, uchar *aesKey);
11
void add_aes_entry(AES_ENTRY **list, uint16_t caid, uint32_t ident, int32_t keyid, uchar *aesKey);
10
void parse_aes_entry(AES_ENTRY **list, char *label, char *value);
12
void parse_aes_entry(AES_ENTRY **list, char *label, char *value);
(-)oscam-chk.c (-4 / +4 lines)
Lines 758-764 Link Here
758
		return 0;
758
		return 0;
759
	}
759
	}
760
760
761
	if(!is_network_reader(rdr) && ((rdr->caid >> 8) != ((er->caid >> 8) & 0xFF) && (rdr->caid >> 8) != ((er->ocaid >> 8) & 0xFF)))
761
	if(!(rdr->typ == R_EMU) && !is_network_reader(rdr) && ((rdr->caid >> 8) != ((er->caid >> 8) & 0xFF) && (rdr->caid >> 8) != ((er->ocaid >> 8) & 0xFF)))
762
	{
762
	{
763
		if (!rdr->csystem)
763
		if (!rdr->csystem)
764
			return 0;
764
			return 0;
Lines 794-800 Link Here
794
	}
794
	}
795
795
796
	//Checking ident:
796
	//Checking ident:
797
	if(!chk_rfilter(er, rdr))
797
	if(!(rdr->typ == R_EMU && (er->caid>>8 == 0x26 || er->caid == 0xFFFF)) && !chk_rfilter(er, rdr))
798
	{
798
	{
799
		cs_log_dbg(D_TRACE, "r-filter reader %s", rdr->label);
799
		cs_log_dbg(D_TRACE, "r-filter reader %s", rdr->label);
800
		return (0);
800
		return (0);
Lines 853-859 Link Here
853
	}
853
	}
854
854
855
	//Checking entitlements:
855
	//Checking entitlements:
856
	if(ll_count(rdr->ll_entitlements) > 0)
856
	if(ll_count(rdr->ll_entitlements) > 0 && !(rdr->typ == R_EMU))
857
	{
857
	{
858
		LL_ITER itr = ll_iter_create(rdr->ll_entitlements);
858
		LL_ITER itr = ll_iter_create(rdr->ll_entitlements);
859
		S_ENTITLEMENT *item;
859
		S_ENTITLEMENT *item;
Lines 1024-1030 Link Here
1024
1024
1025
int32_t chk_caid_rdr(struct s_reader *rdr, uint16_t caid)
1025
int32_t chk_caid_rdr(struct s_reader *rdr, uint16_t caid)
1026
{
1026
{
1027
	if(is_network_reader(rdr))
1027
	if(is_network_reader(rdr) || rdr->typ == R_EMU)
1028
	{
1028
	{
1029
		return 1; //reader caid is not real caid
1029
		return 1; //reader caid is not real caid
1030
	}
1030
	}
(-)oscam-config-global.c (+26 lines)
Lines 854-859 Link Here
854
#else
854
#else
855
static const struct config_list scam_opts[] = { DEF_LAST_OPT };
855
static const struct config_list scam_opts[] = { DEF_LAST_OPT };
856
#endif
856
#endif
857
858
#ifdef WITH_EMU
859
static bool streamrelay_should_save_fn(void *UNUSED(var))
860
{
861
	return 1;
862
}
863
static const struct config_list streamrelay_opts[] =
864
{
865
	DEF_OPT_SAVE_FUNC(streamrelay_should_save_fn),
866
	DEF_OPT_STR("stream_source_host"          , OFS(emu_stream_source_host),          "127.0.0.1"),
867
	DEF_OPT_INT32("stream_source_port"        , OFS(emu_stream_source_port),          8001),
868
	DEF_OPT_STR("stream_source_auth_user"     , OFS(emu_stream_source_auth_user),     NULL),
869
	DEF_OPT_STR("stream_source_auth_password" , OFS(emu_stream_source_auth_password), NULL),
870
	DEF_OPT_INT32("stream_relay_port"         , OFS(emu_stream_relay_port),           17999),
871
	DEF_OPT_UINT32("stream_ecm_delay"         , OFS(emu_stream_ecm_delay),            600),
872
	DEF_OPT_INT8("stream_relay_enabled"       , OFS(emu_stream_relay_enabled),        1),
873
	DEF_OPT_INT8("stream_emm_enabled"         , OFS(emu_stream_emm_enabled),          1),
874
	DEF_LAST_OPT
875
};
876
#else
877
static const struct config_list streamrelay_opts[] = { DEF_LAST_OPT };
878
#endif
879
880
857
#ifdef MODULE_RADEGAST
881
#ifdef MODULE_RADEGAST
858
static bool radegast_should_save_fn(void *UNUSED(var))
882
static bool radegast_should_save_fn(void *UNUSED(var))
859
{
883
{
Lines 1236-1241 Link Here
1236
	DEF_OPT_INT8("read_sdt"		, OFS(dvbapi_read_sdt),	0),
1260
	DEF_OPT_INT8("read_sdt"		, OFS(dvbapi_read_sdt),	0),
1237
	DEF_OPT_INT8("write_sdt_prov", OFS(dvbapi_write_sdt_prov),	0),
1261
	DEF_OPT_INT8("write_sdt_prov", OFS(dvbapi_write_sdt_prov),	0),
1238
	DEF_OPT_INT8("extended_cw_api", OFS(dvbapi_extended_cw_api),	0),
1262
	DEF_OPT_INT8("extended_cw_api", OFS(dvbapi_extended_cw_api),	0),
1263
	DEF_OPT_INT8("extended_cw_pids", OFS(dvbapi_extended_cw_pids),	64), // pid limiter
1239
	DEF_OPT_FUNC("boxtype"		, OFS(dvbapi_boxtype),		dvbapi_boxtype_fn),
1264
	DEF_OPT_FUNC("boxtype"		, OFS(dvbapi_boxtype),		dvbapi_boxtype_fn),
1240
	DEF_OPT_FUNC("services"		, OFS(dvbapi_sidtabs.ok),	dvbapi_services_fn),
1265
	DEF_OPT_FUNC("services"		, OFS(dvbapi_sidtabs.ok),	dvbapi_services_fn),
1241
	// OBSOLETE OPTIONS
1266
	// OBSOLETE OPTIONS
Lines 1289-1294 Link Here
1289
	{ "cccam",	cccam_opts },
1314
	{ "cccam",	cccam_opts },
1290
	{ "pandora",	pandora_opts },
1315
	{ "pandora",	pandora_opts },
1291
	{ "scam",	scam_opts },
1316
	{ "scam",	scam_opts },
1317
	{ "streamrelay",	streamrelay_opts },
1292
	{ "dvbapi",	dvbapi_opts },
1318
	{ "dvbapi",	dvbapi_opts },
1293
	{ "monitor",	monitor_opts },
1319
	{ "monitor",	monitor_opts },
1294
	{ "webif",	webif_opts },
1320
	{ "webif",	webif_opts },
(-)oscam-config-reader.c (-1 / +13 lines)
Lines 109-114 Link Here
109
			{ "newcamd525", R_NEWCAMD },
109
			{ "newcamd525", R_NEWCAMD },
110
			{ "newcamd524", R_NEWCAMD },
110
			{ "newcamd524", R_NEWCAMD },
111
			{ "drecas",		R_DRECAS },
111
			{ "drecas",		R_DRECAS },
112
			{ "emu",        R_EMU },
112
			{ NULL        , 0 }
113
			{ NULL        , 0 }
113
		}, *p;
114
		}, *p;
114
		int i;
115
		int i;
Lines 448-453 Link Here
448
		if(ftab_type & FTAB_FBPCAID)     { rdr = container_of(setting, struct s_reader, fallback_percaid); }
449
		if(ftab_type & FTAB_FBPCAID)     { rdr = container_of(setting, struct s_reader, fallback_percaid); }
449
		if(ftab_type & FTAB_LOCALCARDS)  { rdr = container_of(setting, struct s_reader, localcards); }
450
		if(ftab_type & FTAB_LOCALCARDS)  { rdr = container_of(setting, struct s_reader, localcards); }
450
		if(ftab_type & FTAB_IGNCHKSMCAID){ rdr = container_of(setting, struct s_reader, disablecrccws_only_for); }
451
		if(ftab_type & FTAB_IGNCHKSMCAID){ rdr = container_of(setting, struct s_reader, disablecrccws_only_for); }
452
#ifdef WITH_EMU
453
		if(ftab_type & FTAB_EMUAU)       { rdr = container_of(setting, struct s_reader, emu_auproviders); }
454
#endif
451
		if(rdr)
455
		if(rdr)
452
			{ rdr->changes_since_shareupdate = 1; }
456
			{ rdr->changes_since_shareupdate = 1; }
453
	}
457
	}
Lines 779-785 Link Here
779
}
783
}
780
784
781
785
782
static void reader_fixups_fn(void *var)
786
void reader_fixups_fn(void *var)
783
{
787
{
784
	struct s_reader *rdr = var;
788
	struct s_reader *rdr = var;
785
#ifdef WITH_LB
789
#ifdef WITH_LB
Lines 923-928 Link Here
923
#ifdef READER_DRECAS
927
#ifdef READER_DRECAS
924
	DEF_OPT_STR("stmkeys"               , OFS(stmkeys),                 NULL),
928
	DEF_OPT_STR("stmkeys"               , OFS(stmkeys),                 NULL),
925
#endif
929
#endif
930
#ifdef WITH_EMU
931
	DEF_OPT_FUNC_X("emu_auproviders"    , OFS(emu_auproviders),         ftab_fn, FTAB_READER | FTAB_EMUAU),
932
	DEF_OPT_INT8("emu_datecodedenabled" , OFS(emu_datecodedenabled),    0),
933
	DEF_OPT_STR("extee36"               , OFS(extee36),                 NULL),
934
	DEF_OPT_STR("extee56"               , OFS(extee56),                 NULL),
935
	DEF_OPT_HEX("dre36_force_group"     , OFS(dre36_force_group),       1),
936
	DEF_OPT_HEX("dre56_force_group"     , OFS(dre56_force_group),       1),
937
#endif
926
	DEF_OPT_INT8("deprecated"           , OFS(deprecated),              0),
938
	DEF_OPT_INT8("deprecated"           , OFS(deprecated),              0),
927
	DEF_OPT_INT8("audisabled"           , OFS(audisabled),              0),
939
	DEF_OPT_INT8("audisabled"           , OFS(audisabled),              0),
928
	DEF_OPT_FUNC("auprovid"             , 0,                            auprovid_fn),
940
	DEF_OPT_FUNC("auprovid"             , 0,                            auprovid_fn),
(-)oscam-config.h (-1 / +3 lines)
Lines 22-27 Link Here
22
int32_t free_readerdb(void);
22
int32_t free_readerdb(void);
23
int32_t write_server(void);
23
int32_t write_server(void);
24
void    reload_readerdb(void);
24
void    reload_readerdb(void);
25
void    reader_fixups_fn(void *var);
25
26
26
void    chk_sidtab(char *token, char *value, struct s_sidtab *sidtab);
27
void    chk_sidtab(char *token, char *value, struct s_sidtab *sidtab);
27
int32_t init_sidtab(void);
28
int32_t init_sidtab(void);
Lines 63-69 Link Here
63
	FTAB_FBPCAID				= 0x10,
64
	FTAB_FBPCAID				= 0x10,
64
	FTAB_LOCALCARDS				= 0x20,
65
	FTAB_LOCALCARDS				= 0x20,
65
	FTAB_IGNCHKSMCAID			= 0x40,
66
	FTAB_IGNCHKSMCAID			= 0x40,
66
	FTAB_IGNCRCCEX4USERONLYFOR	= 0x80
67
	FTAB_IGNCRCCEX4USERONLYFOR	= 0x80,
68
	FTAB_EMUAU					= 0x100
67
};
69
};
68
70
69
void ftab_fn(const char *token, char *value, void *setting, long ftab_type, FILE *f);
71
void ftab_fn(const char *token, char *value, void *setting, long ftab_type, FILE *f);
(-)oscam-ecm.c (-1 / +1 lines)
Lines 1584-1590 Link Here
1584
1584
1585
	if(reader && cw && rc < E_NOTFOUND)
1585
	if(reader && cw && rc < E_NOTFOUND)
1586
	{
1586
	{
1587
		if(cfg.disablecrccws == 0 && reader->disablecrccws == 0)
1587
		if(cfg.disablecrccws == 0 && reader->disablecrccws == 0 && ((er->caid >> 8) != 0x0E))
1588
		{
1588
		{
1589
			uint8_t selectedForIgnChecksum = chk_if_ignore_checksum(er, cfg.disablecrccws, &cfg.disablecrccws_only_for)
1589
			uint8_t selectedForIgnChecksum = chk_if_ignore_checksum(er, cfg.disablecrccws, &cfg.disablecrccws_only_for)
1590
					+ chk_if_ignore_checksum(er, reader->disablecrccws, &reader->disablecrccws_only_for);
1590
					+ chk_if_ignore_checksum(er, reader->disablecrccws, &reader->disablecrccws_only_for);
(-)oscam-emm.c (-1 / +26 lines)
Lines 50-56 Link Here
50
	unsigned int j, filter_count = 0;
50
	unsigned int j, filter_count = 0;
51
51
52
	// Call cardsystems emm filter
52
	// Call cardsystems emm filter
53
	csystem->get_emm_filter(rdr, &dmx_filter, &filter_count);
53
	if(rdr->typ == R_EMU)
54
	{
55
		return 1; //valid emm
56
	}
57
	else
58
	{
59
		csystem->get_emm_filter(rdr, &dmx_filter, &filter_count);
60
	}
54
61
55
	// Only check matching emmtypes:
62
	// Only check matching emmtypes:
56
	uint8_t org_emmtype;
63
	uint8_t org_emmtype;
Lines 209-214 Link Here
209
		rdr_log_dbg(reader, D_EMM, "reader auprovid = %06X fixup to %06X (ignoring last digit)", reader->auprovid, prid); 
216
		rdr_log_dbg(reader, D_EMM, "reader auprovid = %06X fixup to %06X (ignoring last digit)", reader->auprovid, prid); 
210
	}
217
	}
211
	
218
	
219
#ifdef WITH_EMU
220
	if(reader->typ == R_EMU)
221
	{
222
		FILTER* emu_provids = get_emu_prids_for_caid(reader, caid);
223
		if(emu_provids != NULL)
224
		{
225
			for(i = 0; i < emu_provids->nprids; i++)
226
			{
227
				if(provid == emu_provids->prids[i])
228
				{
229
					return 1;
230
				}
231
			}
232
		}
233
		return 0;
234
	}
235
#endif
236
	
212
	if(prid == provid)
237
	if(prid == provid)
213
	{
238
	{
214
		rdr_log_dbg(reader, D_EMM, "reader auprovid = %06X matching with emm provid = %06X -> SEND!", prid, provid);
239
		rdr_log_dbg(reader, D_EMM, "reader auprovid = %06X matching with emm provid = %06X -> SEND!", prid, provid);
(-)oscam-string.c (+56 lines)
Lines 510-515 Link Here
510
	return crc ^ 0xffffffffL;
510
	return crc ^ 0xffffffffL;
511
}
511
}
512
512
513
static uint32_t fletcher_crc_table[256] = {
514
	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
515
	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
516
	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
517
	0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
518
	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
519
	0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
520
	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
521
	0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
522
	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
523
	0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
524
	0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
525
	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
526
	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
527
	0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
528
	0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
529
	0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
530
	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
531
	0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
532
	0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
533
	0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
534
	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
535
	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
536
	0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
537
	0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
538
	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
539
	0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
540
	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
541
	0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
542
	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
543
	0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
544
	0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
545
	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
546
	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
547
	0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
548
	0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
549
	0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
550
	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
551
	0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
552
	0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
553
	0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
554
	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
555
	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
556
	0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
557
558
uint32_t fletcher_crc32(uint8_t *data, uint32_t len)
559
{
560
	uint32_t i;
561
	uint32_t crc = 0xffffffff;
562
563
	for (i=0; i<len; i++)
564
		crc = (crc << 8) ^ fletcher_crc_table[((crc >> 24) ^ *data++) & 0xff];
565
566
	return crc;
567
}
568
513
static uint16_t ccitt_crc_table [256] =
569
static uint16_t ccitt_crc_table [256] =
514
{
570
{
515
	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5,
571
	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5,
(-)oscam-string.h (+1 lines)
Lines 37-42 Link Here
37
void get_random_bytes(uint8_t *dst, uint32_t dst_len);
37
void get_random_bytes(uint8_t *dst, uint32_t dst_len);
38
38
39
uint32_t crc32(uint32_t crc, const uint8_t *buf, uint32_t len);
39
uint32_t crc32(uint32_t crc, const uint8_t *buf, uint32_t len);
40
uint32_t fletcher_crc32(uint8_t *data, uint32_t len);
40
uint16_t ccitt_crc(uint8_t *data, size_t length, uint16_t seed, uint16_t final);
41
uint16_t ccitt_crc(uint8_t *data, size_t length, uint16_t seed, uint16_t final);
41
uint32_t jhash(const char *key, size_t len);
42
uint32_t jhash(const char *key, size_t len);
42
43
(-)oscam.c (+15 lines)
Lines 41-46 Link Here
41
#include "reader-common.h"
41
#include "reader-common.h"
42
#include "module-gbox.h"
42
#include "module-gbox.h"
43
43
44
#ifdef WITH_EMU
45
	void add_emu_reader(void);
46
	void stop_stream_server(void);
47
#endif
48
44
#ifdef WITH_SSL
49
#ifdef WITH_SSL
45
#include <openssl/crypto.h>
50
#include <openssl/crypto.h>
46
#include <openssl/ssl.h>
51
#include <openssl/ssl.h>
Lines 421-426 Link Here
421
	write_conf(CW_CYCLE_CHECK, "CW Cycle Check support");
426
	write_conf(CW_CYCLE_CHECK, "CW Cycle Check support");
422
	write_conf(LCDSUPPORT, "LCD support");
427
	write_conf(LCDSUPPORT, "LCD support");
423
	write_conf(LEDSUPPORT, "LED support");
428
	write_conf(LEDSUPPORT, "LED support");
429
	write_conf(WITH_EMU, "Emulator support");
424
	switch (cs_getclocktype()) {
430
	switch (cs_getclocktype()) {
425
		case CLOCK_TYPE_UNKNOWN  : write_conf(CLOCKFIX, "Clockfix with UNKNOWN clock"); break;
431
		case CLOCK_TYPE_UNKNOWN  : write_conf(CLOCKFIX, "Clockfix with UNKNOWN clock"); break;
426
		case CLOCK_TYPE_REALTIME : write_conf(CLOCKFIX, "Clockfix with realtime clock"); break;
432
		case CLOCK_TYPE_REALTIME : write_conf(CLOCKFIX, "Clockfix with realtime clock"); break;
Lines 1639-1644 Link Here
1639
#ifdef CARDREADER_STINGER
1645
#ifdef CARDREADER_STINGER
1640
	&cardreader_stinger,
1646
	&cardreader_stinger,
1641
#endif
1647
#endif
1648
#ifdef WITH_EMU
1649
	&cardreader_emu,
1650
#endif
1642
	NULL
1651
	NULL
1643
};
1652
};
1644
1653
Lines 1810-1815 Link Here
1810
1819
1811
	init_sidtab();
1820
	init_sidtab();
1812
	init_readerdb();
1821
	init_readerdb();
1822
#ifdef WITH_EMU
1823
	add_emu_reader();
1824
#endif
1813
	cfg.account = init_userdb();
1825
	cfg.account = init_userdb();
1814
	init_signal();
1826
	init_signal();
1815
	init_provid();
1827
	init_provid();
Lines 1897-1902 Link Here
1897
 if(!cfg.gsms_dis)
1909
 if(!cfg.gsms_dis)
1898
	{ stop_sms_sender(); }
1910
	{ stop_sms_sender(); }
1899
#endif
1911
#endif
1912
#ifdef WITH_EMU
1913
	stop_stream_server();
1914
#endif
1900
	webif_close();
1915
	webif_close();
1901
	azbox_close();
1916
	azbox_close();
1902
	coolapi_close_all();
1917
	coolapi_close_all();
(-)reader-common.c (+14 lines)
Lines 15-20 Link Here
15
#include "reader-common.h"
15
#include "reader-common.h"
16
//#include "csctapi/atr.h"
16
//#include "csctapi/atr.h"
17
#include "csctapi/icc_async.h"
17
#include "csctapi/icc_async.h"
18
#include "readers.h"
18
19
19
extern const struct s_cardsystem *cardsystems[];
20
extern const struct s_cardsystem *cardsystems[];
20
extern char *RDR_CD_TXT[];
21
extern char *RDR_CD_TXT[];
Lines 142-147 Link Here
142
static int32_t reader_get_cardsystem(struct s_reader *reader, ATR *atr)
143
static int32_t reader_get_cardsystem(struct s_reader *reader, ATR *atr)
143
{
144
{
144
	int32_t i;
145
	int32_t i;
146
	
147
#ifdef WITH_EMU
148
	if(reader->typ == R_EMU)
149
	{
150
		NULLFREE(reader->csystem_data);
151
		rdr_log(reader, "found card system %s", reader_emu.desc);
152
		reader->csystem = &reader_emu;
153
		reader->csystem_active = true;
154
		led_status_found_cardsystem();
155
		return (reader->csystem_active);
156
	}
157
#endif
158
	
145
	for(i = 0; cardsystems[i]; i++)
159
	for(i = 0; cardsystems[i]; i++)
146
	{
160
	{
147
		NULLFREE(reader->csystem_data);
161
		NULLFREE(reader->csystem_data);
(-)readers.h (+1 lines)
Lines 16-20 Link Here
16
extern const struct s_cardsystem reader_bulcrypt;
16
extern const struct s_cardsystem reader_bulcrypt;
17
extern const struct s_cardsystem reader_griffin;
17
extern const struct s_cardsystem reader_griffin;
18
extern const struct s_cardsystem reader_dgcrypt;
18
extern const struct s_cardsystem reader_dgcrypt;
19
extern const struct s_cardsystem reader_emu;
19
20
20
#endif
21
#endif
(-)webif/config/dvbapi.html (-2 / +17 lines)
Lines 53-59 Link Here
53
			</TD>
53
			</TD>
54
		</TR>
54
		</TR>
55
		<TR><TD><A>Write detected prov name to srvid:</A></TD><TD><input name="write_sdt_prov" type="checkbox" value="1" ##WRITESDTPROVCHECKED##><label></label>
55
		<TR><TD><A>Write detected prov name to srvid:</A></TD><TD><input name="write_sdt_prov" type="checkbox" value="1" ##WRITESDTPROVCHECKED##><label></label>
56
		<!-- <TR><TD><A>API for extended CWs</A></TD>
56
		<TR><TD><A>API for extended CWs</A></TD>
57
			<TD>
57
			<TD>
58
				<select name="extended_cw_api">
58
				<select name="extended_cw_api">
59
					<option value="0" ##EXTENDEDCWAPISELECTED0##>0 - none (disabled)</option>
59
					<option value="0" ##EXTENDEDCWAPISELECTED0##>0 - none (disabled)</option>
Lines 61-64 Link Here
61
					<option value="2" ##EXTENDEDCWAPISELECTED2##>2 - OE2.0</option>
61
					<option value="2" ##EXTENDEDCWAPISELECTED2##>2 - OE2.0</option>
62
				</select>
62
				</select>
63
			</TD>
63
			</TD>
64
		</TR> -->			
64
		</TR>
65
		</TR>
66
		<TR><TD><A>Max pids for extended CWs</A></TD>
67
			<TD>
68
				<select name="extended_cw_pids">
69
					<option value="2" ##EXTENDEDCWPIDSSELECTED2##>2</option>
70
					<option value="3" ##EXTENDEDCWPIDSSELECTED3##>3</option>
71
					<option value="4" ##EXTENDEDCWPIDSSELECTED4##>4</option>
72
					<option value="5" ##EXTENDEDCWPIDSSELECTED5##>5</option>
73
					<option value="6" ##EXTENDEDCWPIDSSELECTED6##>6</option>
74
					<option value="7" ##EXTENDEDCWPIDSSELECTED7##>7</option>
75
					<option value="8" ##EXTENDEDCWPIDSSELECTED8##>8</option>
76
					<option value="64" ##EXTENDEDCWPIDSSELECTED64##>64</option>
77
				</select>
78
			</TD>
79
		</TR>
(-)webif/config/menu.html (+1 lines)
Lines 16-21 Link Here
16
##TPLCONFIGMENUDVBAPI##		<!-- CMENUACTIVE13 -->
16
##TPLCONFIGMENUDVBAPI##		<!-- CMENUACTIVE13 -->
17
##TPLCONFIGMENULCD##		<!-- CMENUACTIVE14 -->
17
##TPLCONFIGMENULCD##		<!-- CMENUACTIVE14 -->
18
##TPLCONFIGMENUMONITOR##	<!-- CMENUACTIVE15 -->
18
##TPLCONFIGMENUMONITOR##	<!-- CMENUACTIVE15 -->
19
##TPLCONFIGMENUSTREAMRELAY##	<!-- CMENUACTIVE17 -->
19
			<LI CLASS="##CMENUACTIVE16##"><A HREF="config.html?part=webif">WebIf</A></LI>
20
			<LI CLASS="##CMENUACTIVE16##"><A HREF="config.html?part=webif">WebIf</A></LI>
20
	</UL>
21
	</UL>
21
</DIV>
22
</DIV>
(-)webif/config/menu_streamrelay.html (+1 lines)
Line 0 Link Here
1
			<LI CLASS="##CMENUACTIVE17##"><A HREF="config.html?part=streamrelay">Stream Relay</A></LI>
(-)webif/config/streamrelay.html (+25 lines)
Line 0 Link Here
1
		<input name="part" type="hidden" value="streamrelay">
2
		<TABLE CLASS="config">
3
			<TR><TH COLSPAN="2">Edit Stream Relay Config</TH></TR>
4
			<TR><TD><A>Mode (requires OSCam restart)</A></TD>
5
				<TD>
6
					<select name="stream_relay_enabled">
7
						<option value="0" ##STREAMRELAYENABLEDSELECTED0##>0 - disabled (use direct DVBAPI decryption)</option>
8
						<option value="1" ##STREAMRELAYENABLEDSELECTED1##>1 - enabled (use Stream Relay)</option>
9
					</select>
10
				</TD>
11
			</TR>
12
			<TR><TD><A>Source Stream Host:</A></TD><TD><input name="stream_source_host" type="text" maxlength="15" value="##STREAM_SOURCE_HOST##"></TD></TR>
13
			<TR><TD><A>Source Stream Port:</A></TD><TD><input name="stream_source_port" class="short" type="text" maxlength="5" value="##STREAM_SOURCE_PORT##"></TD></TR>
14
			<TR><TD><A>Source Stream User:</A></TD><TD><input name="stream_source_auth_user" type="text" value="##STREAM_SOURCE_AUTH_USER##"></TD></TR>
15
			<TR><TD><A>Source Stream Password:</A></TD><TD><input name="stream_source_auth_password" type="text" value="##STREAM_SOURCE_AUTH_PASSWORD##"></TD></TR>
16
			<TR><TD><A>Relay Port:</A></TD><TD><input name="stream_relay_port" class="short" type="text" maxlength="5" value="##STREAM_RELAY_PORT##"></TD></TR>
17
			<TR><TD><A>ECM fix delay:</A></TD><TD><input name="stream_ecm_delay" class="short" type="text" maxlength="5" value="##STREAM_ECM_DELAY##"></TD></TR>
18
			<TR><TD><A>Process EMM from stream:</A></TD>
19
				<TD>
20
					<select name="stream_emm_enabled">
21
						<option value="0" ##STREAMEMMENABLEDSELECTED0##>0 - disabled </option>
22
						<option value="1" ##STREAMEMMENABLEDSELECTED1##>1 - enabled </option>
23
					</select>
24
				</TD>
25
			</TR>
(-)webif/files/menu.html (-1 / +2 lines)
Lines 10-16 Link Here
10
		<LI CLASS="##CMENUACTIVE7##"><A HREF="files.html?file=logfile">logfile</A></LI>
10
		<LI CLASS="##CMENUACTIVE7##"><A HREF="files.html?file=logfile">logfile</A></LI>
11
		<LI CLASS="##CMENUACTIVE8##"><A HREF="files.html?file=userfile">userfile</A></LI>
11
		<LI CLASS="##CMENUACTIVE8##"><A HREF="files.html?file=userfile">userfile</A></LI>
12
##TPLFILEMENUGBOX##		<!-- CMENUACTIVE19-29 -->
12
##TPLFILEMENUGBOX##		<!-- CMENUACTIVE19-29 -->
13
		<LI CLASS="##CMENUACTIVE9## ##CMENUACTIVE10## ##CMENUACTIVE11## ##CMENUACTIVE12## ##CMENUACTIVE13## ##CMENUACTIVE14## ##CMENUACTIVE15## ##CMENUACTIVE16## ##CMENUACTIVE17## ##CMENUACTIVE18##"><A HREF="#"  class="drop">other files<b class="subcaret"></b></A>
13
		<LI CLASS="##CMENUACTIVE9## ##CMENUACTIVE10## ##CMENUACTIVE11## ##CMENUACTIVE12## ##CMENUACTIVE13## ##CMENUACTIVE14## ##CMENUACTIVE15## ##CMENUACTIVE16## ##CMENUACTIVE17## ##CMENUACTIVE18## ##CMENUACTIVE30##"><A HREF="#"  class="drop">other files<b class="subcaret"></b></A>
14
			<UL CLASS="dropdown_nav">
14
			<UL CLASS="dropdown_nav">
15
				<LI CLASS="##CMENUACTIVE9##"><A HREF="files.html?file=oscam.services">oscam.services</A></LI>
15
				<LI CLASS="##CMENUACTIVE9##"><A HREF="files.html?file=oscam.services">oscam.services</A></LI>
16
				<LI CLASS="##CMENUACTIVE10##"><A HREF="files.html?file=oscam.provid">oscam.provid</A></LI>
16
				<LI CLASS="##CMENUACTIVE10##"><A HREF="files.html?file=oscam.provid">oscam.provid</A></LI>
Lines 22-27 Link Here
22
##VIEW_FILEMENUCSS##		<!-- CMENUACTIVE16 -->
22
##VIEW_FILEMENUCSS##		<!-- CMENUACTIVE16 -->
23
##TPLFILEMENUTWIN##		<!-- CMENUACTIVE17 -->
23
##TPLFILEMENUTWIN##		<!-- CMENUACTIVE17 -->
24
##TPLFILEMENUCONSTCW##  	<!-- CMENUACTIVE18 -->
24
##TPLFILEMENUCONSTCW##  	<!-- CMENUACTIVE18 -->
25
##TPLFILEMENUSOFTCAMKEY##		<!-- CMENUACTIVE30 -->
25
			</UL>
26
			</UL>
26
		</LI>
27
		</LI>
27
	</UL>
28
	</UL>
(-)webif/files/menu_softcamkey.html (+1 lines)
Line 0 Link Here
1
			<LI CLASS="##CMENUACTIVE30##"><A HREF="files.html?file=SoftCam.Key">SoftCam.Key</A></LI>
(-)webif/pages_index.txt (+4 lines)
Lines 80-90 Link Here
80
CONFIGMENUNEWCAMD             config/menu_newcamd.html                                    MODULE_NEWCAMD
80
CONFIGMENUNEWCAMD             config/menu_newcamd.html                                    MODULE_NEWCAMD
81
CONFIGMENURADEGAST            config/menu_radegast.html                                   MODULE_RADEGAST
81
CONFIGMENURADEGAST            config/menu_radegast.html                                   MODULE_RADEGAST
82
CONFIGMENUSCAM                config/menu_scam.html                                       MODULE_SCAM
82
CONFIGMENUSCAM                config/menu_scam.html                                       MODULE_SCAM
83
CONFIGMENUSTREAMRELAY         config/menu_streamrelay.html                                WITH_EMU
83
CONFIGMENUSERIAL              config/menu_serial.html                                     MODULE_SERIAL
84
CONFIGMENUSERIAL              config/menu_serial.html                                     MODULE_SERIAL
84
CONFIGMONITOR                 config/monitor.html                                         MODULE_MONITOR
85
CONFIGMONITOR                 config/monitor.html                                         MODULE_MONITOR
85
CONFIGNEWCAMD                 config/newcamd.html                                         MODULE_NEWCAMD
86
CONFIGNEWCAMD                 config/newcamd.html                                         MODULE_NEWCAMD
86
CONFIGRADEGAST                config/radegast.html                                        MODULE_RADEGAST
87
CONFIGRADEGAST                config/radegast.html                                        MODULE_RADEGAST
87
CONFIGSCAM                    config/scam.html                                            MODULE_SCAM
88
CONFIGSCAM                    config/scam.html                                            MODULE_SCAM
89
CONFIGSTREAMRELAY             config/streamrelay.html                                     WITH_EMU
88
CONFIGSERIAL                  config/serial.html                                          MODULE_SERIAL
90
CONFIGSERIAL                  config/serial.html                                          MODULE_SERIAL
89
CONFIGSERIALDEVICEBIT         config/serial_devices.html                                  MODULE_SERIAL
91
CONFIGSERIALDEVICEBIT         config/serial_devices.html                                  MODULE_SERIAL
90
CONFIGWEBIF                   config/webif.html
92
CONFIGWEBIF                   config/webif.html
Lines 118-123 Link Here
118
FILEMENUFAKECWS               files/menu_fakecws.html                                     CS_CACHEEX
120
FILEMENUFAKECWS               files/menu_fakecws.html                                     CS_CACHEEX
119
FILEMENUGBOX                  files/menu_gbox.html	                                  MODULE_GBOX
121
FILEMENUGBOX                  files/menu_gbox.html	                                  MODULE_GBOX
120
FILEMENUTWIN                  files/menu_twin.html                                        MODULE_SERIAL
122
FILEMENUTWIN                  files/menu_twin.html                                        MODULE_SERIAL
123
FILEMENUSOFTCAMKEY            files/menu_softcamkey.html                                  WITH_EMU
121
124
122
AUTOCONF                      ghttp/autoconf.html                                         MODULE_GHTTP
125
AUTOCONF                      ghttp/autoconf.html                                         MODULE_GHTTP
123
PREAUTOCONF                   ghttp/pre_autoconf.html                                     MODULE_GHTTP
126
PREAUTOCONF                   ghttp/pre_autoconf.html                                     MODULE_GHTTP
Lines 182-187 Link Here
182
READEREDITCACHEEXBIT          readerconfig/readerconfig_cacheexbit.html                   CS_CACHEEX
185
READEREDITCACHEEXBIT          readerconfig/readerconfig_cacheexbit.html                   CS_CACHEEX
183
READERCONFIGCAMD35BIT         readerconfig/readerconfig_camd35bit.html                    MODULE_CAMD35
186
READERCONFIGCAMD35BIT         readerconfig/readerconfig_camd35bit.html                    MODULE_CAMD35
184
READERCONFIGCCCAMBIT          readerconfig/readerconfig_cccambit.html                     MODULE_CCCAM
187
READERCONFIGCCCAMBIT          readerconfig/readerconfig_cccambit.html                     MODULE_CCCAM
188
READERCONFIGEMUBIT            readerconfig/readerconfig_emubit.html                       WITH_EMU
185
READERCONFIGCS378XBIT         readerconfig/readerconfig_cs378xbit.html                    MODULE_CAMD35_TCP
189
READERCONFIGCS378XBIT         readerconfig/readerconfig_cs378xbit.html                    MODULE_CAMD35_TCP
186
READERCONFIGGBOXBIT           readerconfig/readerconfig_gboxbit.html                      MODULE_GBOX
190
READERCONFIGGBOXBIT           readerconfig/readerconfig_gboxbit.html                      MODULE_GBOX
187
READERCONFIGGHTTPBIT          readerconfig/readerconfig_ghttpbit.html                     MODULE_GHTTP
191
READERCONFIGGHTTPBIT          readerconfig/readerconfig_ghttpbit.html                     MODULE_GHTTP
(-)webif/readerconfig/readerconfig_emubit.html (+6 lines)
Line 0 Link Here
1
			<TR><TD><A>AU providers:</A></TD><TD><textarea name="emu_auproviders" rows="3" class="bt">##EMUAUPROVIDERS##</textarea></TD></TR>
2
			<TR><TD><A>[BISS] Enable date-coded keys:</A></TD><TD><input name="emu_datecodedenabled" type="hidden" value="0"><input name="emu_datecodedenabled" type="checkbox" value="1" ##EMUDATECODEDENABLED##><label></label></TD></TR>
3
			<TR><TD><A>[Drecrypt] Path to ee36.bin:</A></TD><TD><input name="extee36" type="text" maxlength="150" value="##EXTEE36##"></TD></TR>
4
			<TR><TD><A>[Drecrypt] Path to ee56.bin:</A></TD><TD><input name="extee56" type="text" maxlength="150" value="##EXTEE56##"></TD></TR>
5
			<TR><TD><A>[Drecrypt] Center force group:</A></TD><TD><input name="dre36_force_group" class="medium" type="text" maxlength="2" value="##DRE36FORCEGROUP##"></TD></TR>
6
			<TR><TD><A>[Drecrypt] Siberia force group:</A></TD><TD><input name="dre56_force_group" class="medium" type="text" maxlength="2" value="##DRE56FORCEGROUP##"></TD></TR>

Return to bug 426518