Advertisement
Guest User

Untitled

a guest
Jan 24th, 2016
734
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 364.23 KB | None | 0 0
  1. Index: CMakeLists.txt
  2. ===================================================================
  3. --- CMakeLists.txt (revision 11209)
  4. +++ CMakeLists.txt (working copy)
  5. @@ -99,6 +99,7 @@
  6. ${CMAKE_CURRENT_SOURCE_DIR}/csctapi
  7. ${CMAKE_CURRENT_SOURCE_DIR}/cscrypt
  8. ${CMAKE_CURRENT_SOURCE_DIR}/minilzo
  9. + ${CMAKE_CURRENT_SOURCE_DIR}/ffdecsa
  10. ${CMAKE_CURRENT_SOURCE_DIR}/extapi/cygwin
  11. /usr/include/w32api
  12. ${OPTIONAL_INCLUDE_DIR}
  13. @@ -108,6 +109,7 @@
  14. ${CMAKE_CURRENT_SOURCE_DIR}/csctapi
  15. ${CMAKE_CURRENT_SOURCE_DIR}/cscrypt
  16. ${CMAKE_CURRENT_SOURCE_DIR}/minilzo
  17. + ${CMAKE_CURRENT_SOURCE_DIR}/ffdecsa
  18. ${OPTIONAL_INCLUDE_DIR}
  19. )
  20. endif (OSCamOperatingSystem MATCHES "Windows/Cygwin")
  21. @@ -415,6 +417,13 @@
  22. # Manage config.h based on command line parameters
  23. # Manipulate config file based on given parameters and read unset parameters
  24.  
  25. +execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --enabled WITH_EMU OUTPUT_VARIABLE CONFIG_WITH_EMU OUTPUT_STRIP_TRAILING_WHITESPACE)
  26. +if (CONFIG_WITH_EMU MATCHES "Y" AND NOT WITH_EMU EQUAL 1)
  27. + add_definitions ("-DWITH_EMU")
  28. + set (WITH_EMU "1")
  29. + message(STATUS " EMU is added by config compiling with EMU")
  30. +endif(CONFIG_WITH_EMU MATCHES "Y" AND NOT WITH_EMU EQUAL 1)
  31. +
  32. execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --show-valid OUTPUT_VARIABLE config_vars_string OUTPUT_STRIP_TRAILING_WHITESPACE)
  33. string(REGEX MATCHALL "[A-Z0-9_]+" config_vars ${config_vars_string})
  34.  
  35. @@ -444,6 +453,7 @@
  36. add_subdirectory (csctapi)
  37. add_subdirectory (minilzo)
  38. add_subdirectory (cscrypt)
  39. +add_subdirectory (ffdecsa)
  40.  
  41. #----------------------- file groups ------------------------------
  42. execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --enabled MODULE_CAMD33 OUTPUT_VARIABLE CAMD33 OUTPUT_STRIP_TRAILING_WHITESPACE)
  43. @@ -493,7 +503,7 @@
  44.  
  45. set (exe_name "oscam")
  46. add_executable (${exe_name} ${exe_srcs} ${exe_hdrs})
  47. -target_link_libraries (${exe_name} ${csoscam} ${csmodules} ${csreaders} csctapi cscrypt minilzo)
  48. +target_link_libraries (${exe_name} ${csoscam} ${csmodules} ${csreaders} csctapi cscrypt minilzo ffdecsa)
  49. if(HAVE_LIBRT AND HAVE_LIBUSB)
  50. if (LIBUSBDIR)
  51. set (libusb_link "imp_libusb")
  52. @@ -642,6 +652,11 @@
  53. execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine COMMAND tr -d '\n' OUTPUT_VARIABLE CS_TARGET)
  54. add_definitions ("-D'CS_TARGET=\"${CS_TARGET}\"'")
  55. #----------------------- global compile and link options ------------------------------
  56. +#enable sse2 on x86
  57. +if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
  58. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3")
  59. +endif (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
  60. +
  61. # disable warning about unused but set variables in gcc 4.6+
  62. if (CMAKE_COMPILER_IS_GNUCC)
  63. execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
  64. @@ -726,6 +741,22 @@
  65.  
  66. #--------------------------------------------------------------------------------
  67.  
  68. +if (NOT OSCamOperatingSystem MATCHES "Mac OS X")
  69. +if (NOT DEFINED ENV{ANDROID_NDK})
  70. +if (NOT DEFINED ENV{ANDROID_STANDALONE_TOOLCHAIN})
  71. + if(WITH_EMU)
  72. + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key)
  73. + execute_process(COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key ${CMAKE_CURRENT_BINARY_DIR}/SoftCam.Key)
  74. + else(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key)
  75. + execute_process(COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/SoftCam.Key)
  76. + endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key)
  77. + execute_process(COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/utils/SoftCam.Key)
  78. + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--format=binary -Wl,SoftCam.Key -Wl,--format=default" )
  79. + endif(WITH_EMU)
  80. +endif (NOT DEFINED ENV{ANDROID_STANDALONE_TOOLCHAIN})
  81. +endif (NOT DEFINED ENV{ANDROID_NDK})
  82. +endif (NOT OSCamOperatingSystem MATCHES "Mac OS X")
  83. +
  84. #----------------------- installation -----------------------------
  85.  
  86. file (GLOB config_files "${CMAKE_CURRENT_SOURCE_DIR}/Distribution/oscam.*")
  87. @@ -814,4 +845,8 @@
  88. endif(STATICLIBUSB AND NOT LIBUSBDIR)
  89. endif (HAVE_LIBUSB)
  90.  
  91. +if (WITH_EMU)
  92. + message(STATUS " Compile with EMU support")
  93. +endif (WITH_EMU)
  94. +
  95. message (STATUS "")
  96. Index: Makefile
  97. ===================================================================
  98. --- Makefile (revision 11209)
  99. +++ Makefile (working copy)
  100. @@ -65,6 +65,13 @@
  101.  
  102. LDFLAGS = -Wl,--gc-sections
  103.  
  104. +TARGETHELP := $(shell $(CC) --target-help)
  105. +ifneq (,$(findstring sse2,$(TARGETHELP)))
  106. +override CFLAGS += -fexpensive-optimizations -mmmx -msse -msse2 -msse3
  107. +else
  108. +override CFLAGS += -fexpensive-optimizations
  109. +endif
  110. +
  111. # The linker for powerpc have bug that prevents --gc-sections from working
  112. # Check for the linker version and if it matches disable --gc-sections
  113. # For more information about the bug see:
  114. @@ -267,6 +274,23 @@
  115. SRC-$(CONFIG_MODULE_CCCAM) += module-cccam.c
  116. SRC-$(CONFIG_MODULE_CCCSHARE) += module-cccshare.c
  117. SRC-$(CONFIG_MODULE_CONSTCW) += module-constcw.c
  118. +SRC-$(CONFIG_WITH_EMU) += module-emulator.c
  119. +SRC-$(CONFIG_WITH_EMU) += module-emulator-osemu.c
  120. +SRC-$(CONFIG_WITH_EMU) += module-emulator-stream.c
  121. +SRC-$(CONFIG_WITH_EMU) += module-emulator-st20.c
  122. +SRC-$(CONFIG_WITH_EMU) += module-emulator-dre2overcrypt.c
  123. +SRC-$(CONFIG_WITH_EMU) += ffdecsa/ffdecsa.c
  124. +UNAME := $(shell uname -s)
  125. +ifneq ($(UNAME),Darwin)
  126. +ifndef ANDROID_NDK
  127. +ifndef ANDROID_STANDALONE_TOOLCHAIN
  128. +ifeq "$(CONFIG_WITH_EMU)" "y"
  129. +TOUCH_SK := $(shell touch SoftCam.Key)
  130. +override LDFLAGS += -Wl,--format=binary -Wl,SoftCam.Key -Wl,--format=default
  131. +endif
  132. +endif
  133. +endif
  134. +endif
  135. SRC-$(CONFIG_CS_CACHEEX) += module-csp.c
  136. SRC-$(CONFIG_CW_CYCLE_CHECK) += module-cw-cycle-check.c
  137. SRC-$(CONFIG_WITH_AZBOX) += module-dvbapi-azbox.c
  138. @@ -359,7 +383,7 @@
  139. # starts the compilation.
  140. all:
  141. @./config.sh --use-flags "$(USE_FLAGS)" --objdir "$(OBJDIR)" --make-config.mak
  142. - @-mkdir -p $(OBJDIR)/cscrypt $(OBJDIR)/csctapi $(OBJDIR)/minilzo $(OBJDIR)/webif
  143. + @-mkdir -p $(OBJDIR)/cscrypt $(OBJDIR)/csctapi $(OBJDIR)/minilzo $(OBJDIR)/ffdecsa $(OBJDIR)/webif
  144. @-printf "\
  145. +-------------------------------------------------------------------------------\n\
  146. | OSCam ver: $(VER) rev: $(SVN_REV) target: $(TARGET)\n\
  147. Index: config.h
  148. ===================================================================
  149. --- config.h (revision 11209)
  150. +++ config.h (working copy)
  151. @@ -1,6 +1,7 @@
  152. #ifndef CONFIG_H_
  153. #define CONFIG_H_
  154.  
  155. +#define WITH_EMU 1
  156. #define WEBIF 1
  157. #define WEBIF_LIVELOG 1
  158. #define WEBIF_JQUERY 1
  159. Index: config.sh
  160. ===================================================================
  161. --- config.sh (revision 11209)
  162. +++ config.sh (working copy)
  163. @@ -1,6 +1,6 @@
  164. #!/bin/sh
  165.  
  166. -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"
  167. +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"
  168. 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"
  169. 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"
  170. card_readers="CARDREADER_PHOENIX CARDREADER_INTERNAL CARDREADER_SC8IN1 CARDREADER_MP35 CARDREADER_SMARGO CARDREADER_DB2COM CARDREADER_STAPI CARDREADER_STAPI5 CARDREADER_STINGER"
  171. @@ -24,6 +24,7 @@
  172. # CONFIG_LEDSUPPORT=n
  173. CONFIG_CLOCKFIX=y
  174. # CONFIG_IPV6SUPPORT=n
  175. +CONFIG_WITH_EMU=y
  176. # CONFIG_MODULE_CAMD33=n
  177. CONFIG_MODULE_CAMD35=y
  178. CONFIG_MODULE_CAMD35_TCP=y
  179. @@ -288,12 +289,14 @@
  180.  
  181. update_deps() {
  182. # Calculate dependencies
  183. - enabled_any $(get_opts readers) $(get_opts card_readers) && enable_opt WITH_CARDREADER >/dev/null
  184. - disabled_all $(get_opts readers) $(get_opts card_readers) && disable_opt WITH_CARDREADER >/dev/null
  185. + enabled_any $(get_opts readers) $(get_opts card_readers) WITH_EMU && enable_opt WITH_CARDREADER >/dev/null
  186. + disabled_all $(get_opts readers) $(get_opts card_readers) WITH_EMU && disable_opt WITH_CARDREADER >/dev/null
  187. disabled WEBIF && disable_opt WEBIF_LIVELOG >/dev/null
  188. disabled WEBIF && disable_opt WEBIF_JQUERY >/dev/null
  189. enabled MODULE_CCCSHARE && enable_opt MODULE_CCCAM >/dev/null
  190. enabled_any CARDREADER_DB2COM CARDREADER_MP35 CARDREADER_SC8IN1 CARDREADER_STINGER && enable_opt CARDREADER_PHOENIX >/dev/null
  191. + enabled WITH_EMU && enable_opt READER_VIACCESS >/dev/null
  192. + enabled WITH_EMU && enable_opt MODULE_NEWCAMD >/dev/null
  193. }
  194.  
  195. list_config() {
  196. @@ -343,9 +346,9 @@
  197. not_have_flag USE_LIBCRYPTO && echo "CONFIG_LIB_AES=y" || echo "# CONFIG_LIB_AES=n"
  198. enabled MODULE_CCCAM && echo "CONFIG_LIB_RC6=y" || echo "# CONFIG_LIB_RC6=n"
  199. not_have_flag USE_LIBCRYPTO && enabled MODULE_CCCAM && echo "CONFIG_LIB_SHA1=y" || echo "# CONFIG_LIB_SHA1=n"
  200. - enabled_any READER_DRE MODULE_SCAM READER_VIACCESS && echo "CONFIG_LIB_DES=y" || echo "# CONFIG_LIB_DES=n"
  201. - enabled_any MODULE_CCCAM READER_NAGRA READER_SECA && echo "CONFIG_LIB_IDEA=y" || echo "# CONFIG_LIB_IDEA=n"
  202. - not_have_flag USE_LIBCRYPTO && enabled_any READER_CONAX READER_CRYPTOWORKS READER_NAGRA && echo "CONFIG_LIB_BIGNUM=y" || echo "# CONFIG_LIB_BIGNUM=n"
  203. + enabled_any READER_DRE MODULE_SCAM READER_VIACCESS WITH_EMU && echo "CONFIG_LIB_DES=y" || echo "# CONFIG_LIB_DES=n"
  204. + enabled_any MODULE_CCCAM READER_NAGRA READER_SECA WITH_EMU && echo "CONFIG_LIB_IDEA=y" || echo "# CONFIG_LIB_IDEA=n"
  205. + 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"
  206. }
  207.  
  208. make_config_c() {
  209. @@ -456,6 +459,7 @@
  210. LEDSUPPORT "LED support" $(check_test "LEDSUPPORT") \
  211. CLOCKFIX "Clockfix (disable on old systems!)" $(check_test "CLOCKFIX") \
  212. IPV6SUPPORT "IPv6 support (experimental)" $(check_test "IPV6SUPPORT") \
  213. + WITH_EMU "Emulator support" $(check_test "WITH_EMU") \
  214. 2> ${tempfile}
  215.  
  216. opt=${?}
  217. Index: cscrypt/md5.c
  218. ===================================================================
  219. --- cscrypt/md5.c (revision 11209)
  220. +++ cscrypt/md5.c (working copy)
  221. @@ -25,13 +25,6 @@
  222.  
  223. #if !defined(WITH_SSL) && !defined(WITH_LIBCRYPTO)
  224.  
  225. -typedef struct MD5Context
  226. -{
  227. - uint32_t buf[4];
  228. - uint32_t bits[2];
  229. - uint32_t in[16];
  230. -} MD5_CTX;
  231. -
  232. #ifdef __i386__
  233. #define byteReverse(a, b)
  234. #else
  235. @@ -155,7 +148,7 @@
  236. * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
  237. * initialization constants.
  238. */
  239. -static void MD5_Init(MD5_CTX *ctx)
  240. +void MD5_Init(MD5_CTX *ctx)
  241. {
  242. ctx->buf[0] = 0x67452301;
  243. ctx->buf[1] = 0xefcdab89;
  244. @@ -170,7 +163,7 @@
  245. * Update context to reflect the concatenation of another buffer full
  246. * of bytes.
  247. */
  248. -static void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len)
  249. +void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len)
  250. {
  251. uint32_t t;
  252.  
  253. @@ -219,7 +212,7 @@
  254. * Final wrapup - pad to 64-byte boundary with the bit pattern
  255. * 1 0* (64-bit count of bits processed, MSB-first)
  256. */
  257. -static void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
  258. +void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
  259. {
  260. unsigned count;
  261. unsigned char *p;
  262. Index: cscrypt/md5.h
  263. ===================================================================
  264. --- cscrypt/md5.h (revision 11209)
  265. +++ cscrypt/md5.h (working copy)
  266. @@ -7,8 +7,16 @@
  267. #define MD5_DIGEST_LENGTH 16
  268.  
  269. unsigned char *MD5(const unsigned char *input, unsigned long len, unsigned char *output_hash);
  270. -#endif
  271.  
  272. -char *__md5_crypt(const char *text_pass, const char *salt, char *crypted_passwd);
  273. +typedef struct MD5Context {
  274. + uint32_t buf[4];
  275. + uint32_t bits[2];
  276. + uint32_t in[16];
  277. +} MD5_CTX;
  278.  
  279. +void MD5_Init(MD5_CTX *ctx);
  280. +void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len);
  281. +void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx);
  282. #endif
  283. +char *__md5_crypt(const char *text_pass, const char *salt, char *crypted_passwd);
  284. +#endif
  285. Index: csctapi/cardreaders.h
  286. ===================================================================
  287. --- csctapi/cardreaders.h (revision 11209)
  288. +++ csctapi/cardreaders.h (working copy)
  289. @@ -13,5 +13,6 @@
  290. extern const struct s_cardreader cardreader_smartreader;
  291. extern const struct s_cardreader cardreader_stapi;
  292. extern const struct s_cardreader cardreader_stinger;
  293. +extern const struct s_cardreader cardreader_emu;
  294.  
  295. #endif
  296. Index: ffdecsa/CMakeLists.txt
  297. ===================================================================
  298. --- ffdecsa/CMakeLists.txt (revision 0)
  299. +++ ffdecsa/CMakeLists.txt (working copy)
  300. @@ -0,0 +1,8 @@
  301. +project (ffdecsa)
  302. +
  303. +file (GLOB ffdecsa_srcs "ffdecsa.c")
  304. +file (GLOB ffdecsa_hdrs "*.h")
  305. +
  306. +set (lib_name "ffdecsa")
  307. +
  308. +add_library (${lib_name} STATIC ${ffdecsa_srcs} ${ffdecsa_hdrs})
  309. Index: ffdecsa/COPYING
  310. ===================================================================
  311. --- ffdecsa/COPYING (revision 0)
  312. +++ ffdecsa/COPYING (working copy)
  313. @@ -0,0 +1,339 @@
  314. + GNU GENERAL PUBLIC LICENSE
  315. + Version 2, June 1991
  316. +
  317. + Copyright (C) 1989, 1991 Free Software Foundation, Inc.
  318. + 675 Mass Ave, Cambridge, MA 02139, USA
  319. + Everyone is permitted to copy and distribute verbatim copies
  320. + of this license document, but changing it is not allowed.
  321. +
  322. + Preamble
  323. +
  324. + The licenses for most software are designed to take away your
  325. +freedom to share and change it. By contrast, the GNU General Public
  326. +License is intended to guarantee your freedom to share and change free
  327. +software--to make sure the software is free for all its users. This
  328. +General Public License applies to most of the Free Software
  329. +Foundation's software and to any other program whose authors commit to
  330. +using it. (Some other Free Software Foundation software is covered by
  331. +the GNU Library General Public License instead.) You can apply it to
  332. +your programs, too.
  333. +
  334. + When we speak of free software, we are referring to freedom, not
  335. +price. Our General Public Licenses are designed to make sure that you
  336. +have the freedom to distribute copies of free software (and charge for
  337. +this service if you wish), that you receive source code or can get it
  338. +if you want it, that you can change the software or use pieces of it
  339. +in new free programs; and that you know you can do these things.
  340. +
  341. + To protect your rights, we need to make restrictions that forbid
  342. +anyone to deny you these rights or to ask you to surrender the rights.
  343. +These restrictions translate to certain responsibilities for you if you
  344. +distribute copies of the software, or if you modify it.
  345. +
  346. + For example, if you distribute copies of such a program, whether
  347. +gratis or for a fee, you must give the recipients all the rights that
  348. +you have. You must make sure that they, too, receive or can get the
  349. +source code. And you must show them these terms so they know their
  350. +rights.
  351. +
  352. + We protect your rights with two steps: (1) copyright the software, and
  353. +(2) offer you this license which gives you legal permission to copy,
  354. +distribute and/or modify the software.
  355. +
  356. + Also, for each author's protection and ours, we want to make certain
  357. +that everyone understands that there is no warranty for this free
  358. +software. If the software is modified by someone else and passed on, we
  359. +want its recipients to know that what they have is not the original, so
  360. +that any problems introduced by others will not reflect on the original
  361. +authors' reputations.
  362. +
  363. + Finally, any free program is threatened constantly by software
  364. +patents. We wish to avoid the danger that redistributors of a free
  365. +program will individually obtain patent licenses, in effect making the
  366. +program proprietary. To prevent this, we have made it clear that any
  367. +patent must be licensed for everyone's free use or not licensed at all.
  368. +
  369. + The precise terms and conditions for copying, distribution and
  370. +modification follow.
  371. +
  372. + GNU GENERAL PUBLIC LICENSE
  373. + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  374. +
  375. + 0. This License applies to any program or other work which contains
  376. +a notice placed by the copyright holder saying it may be distributed
  377. +under the terms of this General Public License. The "Program", below,
  378. +refers to any such program or work, and a "work based on the Program"
  379. +means either the Program or any derivative work under copyright law:
  380. +that is to say, a work containing the Program or a portion of it,
  381. +either verbatim or with modifications and/or translated into another
  382. +language. (Hereinafter, translation is included without limitation in
  383. +the term "modification".) Each licensee is addressed as "you".
  384. +
  385. +Activities other than copying, distribution and modification are not
  386. +covered by this License; they are outside its scope. The act of
  387. +running the Program is not restricted, and the output from the Program
  388. +is covered only if its contents constitute a work based on the
  389. +Program (independent of having been made by running the Program).
  390. +Whether that is true depends on what the Program does.
  391. +
  392. + 1. You may copy and distribute verbatim copies of the Program's
  393. +source code as you receive it, in any medium, provided that you
  394. +conspicuously and appropriately publish on each copy an appropriate
  395. +copyright notice and disclaimer of warranty; keep intact all the
  396. +notices that refer to this License and to the absence of any warranty;
  397. +and give any other recipients of the Program a copy of this License
  398. +along with the Program.
  399. +
  400. +You may charge a fee for the physical act of transferring a copy, and
  401. +you may at your option offer warranty protection in exchange for a fee.
  402. +
  403. + 2. You may modify your copy or copies of the Program or any portion
  404. +of it, thus forming a work based on the Program, and copy and
  405. +distribute such modifications or work under the terms of Section 1
  406. +above, provided that you also meet all of these conditions:
  407. +
  408. + a) You must cause the modified files to carry prominent notices
  409. + stating that you changed the files and the date of any change.
  410. +
  411. + b) You must cause any work that you distribute or publish, that in
  412. + whole or in part contains or is derived from the Program or any
  413. + part thereof, to be licensed as a whole at no charge to all third
  414. + parties under the terms of this License.
  415. +
  416. + c) If the modified program normally reads commands interactively
  417. + when run, you must cause it, when started running for such
  418. + interactive use in the most ordinary way, to print or display an
  419. + announcement including an appropriate copyright notice and a
  420. + notice that there is no warranty (or else, saying that you provide
  421. + a warranty) and that users may redistribute the program under
  422. + these conditions, and telling the user how to view a copy of this
  423. + License. (Exception: if the Program itself is interactive but
  424. + does not normally print such an announcement, your work based on
  425. + the Program is not required to print an announcement.)
  426. +
  427. +These requirements apply to the modified work as a whole. If
  428. +identifiable sections of that work are not derived from the Program,
  429. +and can be reasonably considered independent and separate works in
  430. +themselves, then this License, and its terms, do not apply to those
  431. +sections when you distribute them as separate works. But when you
  432. +distribute the same sections as part of a whole which is a work based
  433. +on the Program, the distribution of the whole must be on the terms of
  434. +this License, whose permissions for other licensees extend to the
  435. +entire whole, and thus to each and every part regardless of who wrote it.
  436. +
  437. +Thus, it is not the intent of this section to claim rights or contest
  438. +your rights to work written entirely by you; rather, the intent is to
  439. +exercise the right to control the distribution of derivative or
  440. +collective works based on the Program.
  441. +
  442. +In addition, mere aggregation of another work not based on the Program
  443. +with the Program (or with a work based on the Program) on a volume of
  444. +a storage or distribution medium does not bring the other work under
  445. +the scope of this License.
  446. +
  447. + 3. You may copy and distribute the Program (or a work based on it,
  448. +under Section 2) in object code or executable form under the terms of
  449. +Sections 1 and 2 above provided that you also do one of the following:
  450. +
  451. + a) Accompany it with the complete corresponding machine-readable
  452. + source code, which must be distributed under the terms of Sections
  453. + 1 and 2 above on a medium customarily used for software interchange; or,
  454. +
  455. + b) Accompany it with a written offer, valid for at least three
  456. + years, to give any third party, for a charge no more than your
  457. + cost of physically performing source distribution, a complete
  458. + machine-readable copy of the corresponding source code, to be
  459. + distributed under the terms of Sections 1 and 2 above on a medium
  460. + customarily used for software interchange; or,
  461. +
  462. + c) Accompany it with the information you received as to the offer
  463. + to distribute corresponding source code. (This alternative is
  464. + allowed only for noncommercial distribution and only if you
  465. + received the program in object code or executable form with such
  466. + an offer, in accord with Subsection b above.)
  467. +
  468. +The source code for a work means the preferred form of the work for
  469. +making modifications to it. For an executable work, complete source
  470. +code means all the source code for all modules it contains, plus any
  471. +associated interface definition files, plus the scripts used to
  472. +control compilation and installation of the executable. However, as a
  473. +special exception, the source code distributed need not include
  474. +anything that is normally distributed (in either source or binary
  475. +form) with the major components (compiler, kernel, and so on) of the
  476. +operating system on which the executable runs, unless that component
  477. +itself accompanies the executable.
  478. +
  479. +If distribution of executable or object code is made by offering
  480. +access to copy from a designated place, then offering equivalent
  481. +access to copy the source code from the same place counts as
  482. +distribution of the source code, even though third parties are not
  483. +compelled to copy the source along with the object code.
  484. +
  485. + 4. You may not copy, modify, sublicense, or distribute the Program
  486. +except as expressly provided under this License. Any attempt
  487. +otherwise to copy, modify, sublicense or distribute the Program is
  488. +void, and will automatically terminate your rights under this License.
  489. +However, parties who have received copies, or rights, from you under
  490. +this License will not have their licenses terminated so long as such
  491. +parties remain in full compliance.
  492. +
  493. + 5. You are not required to accept this License, since you have not
  494. +signed it. However, nothing else grants you permission to modify or
  495. +distribute the Program or its derivative works. These actions are
  496. +prohibited by law if you do not accept this License. Therefore, by
  497. +modifying or distributing the Program (or any work based on the
  498. +Program), you indicate your acceptance of this License to do so, and
  499. +all its terms and conditions for copying, distributing or modifying
  500. +the Program or works based on it.
  501. +
  502. + 6. Each time you redistribute the Program (or any work based on the
  503. +Program), the recipient automatically receives a license from the
  504. +original licensor to copy, distribute or modify the Program subject to
  505. +these terms and conditions. You may not impose any further
  506. +restrictions on the recipients' exercise of the rights granted herein.
  507. +You are not responsible for enforcing compliance by third parties to
  508. +this License.
  509. +
  510. + 7. If, as a consequence of a court judgment or allegation of patent
  511. +infringement or for any other reason (not limited to patent issues),
  512. +conditions are imposed on you (whether by court order, agreement or
  513. +otherwise) that contradict the conditions of this License, they do not
  514. +excuse you from the conditions of this License. If you cannot
  515. +distribute so as to satisfy simultaneously your obligations under this
  516. +License and any other pertinent obligations, then as a consequence you
  517. +may not distribute the Program at all. For example, if a patent
  518. +license would not permit royalty-free redistribution of the Program by
  519. +all those who receive copies directly or indirectly through you, then
  520. +the only way you could satisfy both it and this License would be to
  521. +refrain entirely from distribution of the Program.
  522. +
  523. +If any portion of this section is held invalid or unenforceable under
  524. +any particular circumstance, the balance of the section is intended to
  525. +apply and the section as a whole is intended to apply in other
  526. +circumstances.
  527. +
  528. +It is not the purpose of this section to induce you to infringe any
  529. +patents or other property right claims or to contest validity of any
  530. +such claims; this section has the sole purpose of protecting the
  531. +integrity of the free software distribution system, which is
  532. +implemented by public license practices. Many people have made
  533. +generous contributions to the wide range of software distributed
  534. +through that system in reliance on consistent application of that
  535. +system; it is up to the author/donor to decide if he or she is willing
  536. +to distribute software through any other system and a licensee cannot
  537. +impose that choice.
  538. +
  539. +This section is intended to make thoroughly clear what is believed to
  540. +be a consequence of the rest of this License.
  541. +
  542. + 8. If the distribution and/or use of the Program is restricted in
  543. +certain countries either by patents or by copyrighted interfaces, the
  544. +original copyright holder who places the Program under this License
  545. +may add an explicit geographical distribution limitation excluding
  546. +those countries, so that distribution is permitted only in or among
  547. +countries not thus excluded. In such case, this License incorporates
  548. +the limitation as if written in the body of this License.
  549. +
  550. + 9. The Free Software Foundation may publish revised and/or new versions
  551. +of the General Public License from time to time. Such new versions will
  552. +be similar in spirit to the present version, but may differ in detail to
  553. +address new problems or concerns.
  554. +
  555. +Each version is given a distinguishing version number. If the Program
  556. +specifies a version number of this License which applies to it and "any
  557. +later version", you have the option of following the terms and conditions
  558. +either of that version or of any later version published by the Free
  559. +Software Foundation. If the Program does not specify a version number of
  560. +this License, you may choose any version ever published by the Free Software
  561. +Foundation.
  562. +
  563. + 10. If you wish to incorporate parts of the Program into other free
  564. +programs whose distribution conditions are different, write to the author
  565. +to ask for permission. For software which is copyrighted by the Free
  566. +Software Foundation, write to the Free Software Foundation; we sometimes
  567. +make exceptions for this. Our decision will be guided by the two goals
  568. +of preserving the free status of all derivatives of our free software and
  569. +of promoting the sharing and reuse of software generally.
  570. +
  571. + NO WARRANTY
  572. +
  573. + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
  574. +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
  575. +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
  576. +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
  577. +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  578. +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
  579. +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
  580. +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
  581. +REPAIR OR CORRECTION.
  582. +
  583. + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  584. +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
  585. +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  586. +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
  587. +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
  588. +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
  589. +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
  590. +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
  591. +POSSIBILITY OF SUCH DAMAGES.
  592. +
  593. + END OF TERMS AND CONDITIONS
  594. +
  595. + Appendix: How to Apply These Terms to Your New Programs
  596. +
  597. + If you develop a new program, and you want it to be of the greatest
  598. +possible use to the public, the best way to achieve this is to make it
  599. +free software which everyone can redistribute and change under these terms.
  600. +
  601. + To do so, attach the following notices to the program. It is safest
  602. +to attach them to the start of each source file to most effectively
  603. +convey the exclusion of warranty; and each file should have at least
  604. +the "copyright" line and a pointer to where the full notice is found.
  605. +
  606. + <one line to give the program's name and a brief idea of what it does.>
  607. + Copyright (C) 19yy <name of author>
  608. +
  609. + This program is free software; you can redistribute it and/or modify
  610. + it under the terms of the GNU General Public License as published by
  611. + the Free Software Foundation; either version 2 of the License, or
  612. + (at your option) any later version.
  613. +
  614. + This program is distributed in the hope that it will be useful,
  615. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  616. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  617. + GNU General Public License for more details.
  618. +
  619. + You should have received a copy of the GNU General Public License
  620. + along with this program; if not, write to the Free Software
  621. + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  622. +
  623. +Also add information on how to contact you by electronic and paper mail.
  624. +
  625. +If the program is interactive, make it output a short notice like this
  626. +when it starts in an interactive mode:
  627. +
  628. + Gnomovision version 69, Copyright (C) 19yy name of author
  629. + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
  630. + This is free software, and you are welcome to redistribute it
  631. + under certain conditions; type `show c' for details.
  632. +
  633. +The hypothetical commands `show w' and `show c' should show the appropriate
  634. +parts of the General Public License. Of course, the commands you use may
  635. +be called something other than `show w' and `show c'; they could even be
  636. +mouse-clicks or menu items--whatever suits your program.
  637. +
  638. +You should also get your employer (if you work as a programmer) or your
  639. +school, if any, to sign a "copyright disclaimer" for the program, if
  640. +necessary. Here is a sample; alter the names:
  641. +
  642. + Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  643. + `Gnomovision' (which makes passes at compilers) written by James Hacker.
  644. +
  645. + <signature of Ty Coon>, 1 April 1989
  646. + Ty Coon, President of Vice
  647. +
  648. +This General Public License does not permit incorporating your program into
  649. +proprietary programs. If your program is a subroutine library, you may
  650. +consider it more useful to permit linking proprietary applications with the
  651. +library. If this is what you want to do, use the GNU Library General
  652. +Public License instead of this License.
  653. Index: ffdecsa/Makefile
  654. ===================================================================
  655. --- ffdecsa/Makefile (revision 0)
  656. +++ ffdecsa/Makefile (working copy)
  657. @@ -0,0 +1,2 @@
  658. +parent:
  659. + @$(MAKE) --no-print-directory -C ..
  660. Index: ffdecsa/ffdecsa.c
  661. ===================================================================
  662. --- ffdecsa/ffdecsa.c (revision 0)
  663. +++ ffdecsa/ffdecsa.c (working copy)
  664. @@ -0,0 +1,926 @@
  665. +/* FFdecsa -- fast decsa algorithm
  666. + *
  667. + * Copyright (C) 2003-2004 fatih89r
  668. + *
  669. + * This program is free software; you can redistribute it and/or modify
  670. + * it under the terms of the GNU General Public License as published by
  671. + * the Free Software Foundation; either version 2 of the License, or
  672. + * (at your option) any later version.
  673. + *
  674. + * This program is distributed in the hope that it will be useful,
  675. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  676. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  677. + * GNU General Public License for more details.
  678. + *
  679. + * You should have received a copy of the GNU General Public License
  680. + * along with this program; if not, write to the Free Software
  681. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  682. + */
  683. +
  684. +
  685. +#include <sys/types.h>
  686. +#include <string.h>
  687. +#include <stdio.h>
  688. +#include <stdlib.h>
  689. +
  690. +#include "ffdecsa.h"
  691. +
  692. +#ifndef NULL
  693. +#define NULL 0
  694. +#endif
  695. +
  696. +//#define DEBUG
  697. +#ifdef DEBUG
  698. +#define DBG(a) a
  699. +#else
  700. +#define DBG(a)
  701. +#endif
  702. +
  703. +//// parallelization stuff, large speed differences are possible
  704. +// possible choices
  705. +#define PARALLEL_32_4CHAR 320
  706. +#define PARALLEL_32_4CHARA 321
  707. +#define PARALLEL_32_INT 322
  708. +#define PARALLEL_64_8CHAR 640
  709. +#define PARALLEL_64_8CHARA 641
  710. +#define PARALLEL_64_2INT 642
  711. +#define PARALLEL_64_LONG 643
  712. +#define PARALLEL_64_MMX 644
  713. +#define PARALLEL_128_16CHAR 1280
  714. +#define PARALLEL_128_16CHARA 1281
  715. +#define PARALLEL_128_4INT 1282
  716. +#define PARALLEL_128_2LONG 1283
  717. +#define PARALLEL_128_2MMX 1284
  718. +#define PARALLEL_128_SSE 1285
  719. +#define PARALLEL_128_SSE2 1286
  720. +
  721. +//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice ////////
  722. +#ifndef PARALLEL_MODE
  723. +
  724. +#if defined(__x86_64__) || defined(_M_X64)
  725. +#define PARALLEL_MODE PARALLEL_128_SSE2
  726. +
  727. +#elif defined(__mips__) || defined(__mips) || defined(__MIPS__)
  728. +#define PARALLEL_MODE PARALLEL_64_LONG
  729. +
  730. +#elif defined(__sh__) || defined(__SH4__)
  731. +#define PARALLEL_MODE PARALLEL_32_INT
  732. +#define COPY_UNALIGNED_PKT
  733. +#define MEMALIGN_VAL 4
  734. +
  735. +#else
  736. +#define PARALLEL_MODE PARALLEL_32_INT
  737. +#endif
  738. +
  739. +#endif
  740. +//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice ////////
  741. +
  742. +#include "parallel_generic.h"
  743. +//// conditionals
  744. +#if PARALLEL_MODE==PARALLEL_32_4CHAR
  745. +#include "parallel_032_4char.h"
  746. +#elif PARALLEL_MODE==PARALLEL_32_4CHARA
  747. +#include "parallel_032_4charA.h"
  748. +#elif PARALLEL_MODE==PARALLEL_32_INT
  749. +#include "parallel_032_int.h"
  750. +#elif PARALLEL_MODE==PARALLEL_64_8CHAR
  751. +#include "parallel_064_8char.h"
  752. +#elif PARALLEL_MODE==PARALLEL_64_8CHARA
  753. +#include "parallel_064_8charA.h"
  754. +#elif PARALLEL_MODE==PARALLEL_64_2INT
  755. +#include "parallel_064_2int.h"
  756. +#elif PARALLEL_MODE==PARALLEL_64_LONG
  757. +#include "parallel_064_long.h"
  758. +#elif PARALLEL_MODE==PARALLEL_64_MMX
  759. +#include "parallel_064_mmx.h"
  760. +#elif PARALLEL_MODE==PARALLEL_128_16CHAR
  761. +#include "parallel_128_16char.h"
  762. +#elif PARALLEL_MODE==PARALLEL_128_16CHARA
  763. +#include "parallel_128_16charA.h"
  764. +#elif PARALLEL_MODE==PARALLEL_128_4INT
  765. +#include "parallel_128_4int.h"
  766. +#elif PARALLEL_MODE==PARALLEL_128_2LONG
  767. +#include "parallel_128_2long.h"
  768. +#elif PARALLEL_MODE==PARALLEL_128_2MMX
  769. +#include "parallel_128_2mmx.h"
  770. +#elif PARALLEL_MODE==PARALLEL_128_SSE
  771. +#include "parallel_128_sse.h"
  772. +#elif PARALLEL_MODE==PARALLEL_128_SSE2
  773. +#include "parallel_128_sse2.h"
  774. +#else
  775. +#error "unknown/undefined parallel mode"
  776. +#endif
  777. +
  778. +// stuff depending on conditionals
  779. +
  780. +#define BYTES_PER_GROUP (GROUP_PARALLELISM/8)
  781. +#define BYPG BYTES_PER_GROUP
  782. +#define BITS_PER_GROUP GROUP_PARALLELISM
  783. +#define BIPG BITS_PER_GROUP
  784. +
  785. +// platform specific
  786. +
  787. +#ifdef __arm__
  788. +#if !defined(MEMALIGN_VAL) || MEMALIGN_VAL<4
  789. +#undef MEMALIGN_VAL
  790. +#define MEMALIGN_VAL 4
  791. +#endif
  792. +#define COPY_UNALIGNED_PKT
  793. +#endif
  794. +
  795. +//
  796. +
  797. +#ifndef MALLOC
  798. +#define MALLOC(X) malloc(X)
  799. +#endif
  800. +#ifndef FREE
  801. +#define FREE(X) free(X)
  802. +#endif
  803. +#ifdef MEMALIGN_VAL
  804. +#define MEMALIGN __attribute__((aligned(MEMALIGN_VAL)))
  805. +#else
  806. +#define MEMALIGN
  807. +#endif
  808. +
  809. +//// debug tool
  810. +
  811. +#ifdef DEBUG
  812. +static void dump_mem(const char *string, const unsigned char *p, int len, int linelen){
  813. + int i;
  814. + for(i=0;i<len;i++){
  815. + if(i%linelen==0&&i) fprintf(stderr,"\n");
  816. + if(i%linelen==0) fprintf(stderr,"%s %08x:",string,i);
  817. + else{
  818. + if(i%8==0) fprintf(stderr," ");
  819. + if(i%4==0) fprintf(stderr," ");
  820. + }
  821. + fprintf(stderr," %02x",p[i]);
  822. + }
  823. + if(i%linelen==0) fprintf(stderr,"\n");
  824. +}
  825. +#endif
  826. +
  827. +//////////////////////////////////////////////////////////////////////////////////
  828. +
  829. +struct csa_key_t{
  830. + unsigned char ck[8];
  831. +// used by stream
  832. + int iA[8]; // iA[0] is for A1, iA[7] is for A8
  833. + int iB[8]; // iB[0] is for B1, iB[7] is for B8
  834. +// used by stream (group)
  835. + MEMALIGN group ck_g[8][8]; // [byte][bit:0=LSB,7=MSB]
  836. + MEMALIGN group iA_g[8][4]; // [0 for A1][0 for LSB]
  837. + MEMALIGN group iB_g[8][4]; // [0 for B1][0 for LSB]
  838. +// used by block
  839. + unsigned char kk[56];
  840. +// used by block (group)
  841. + MEMALIGN batch kkmulti[56]; // many times the same byte in every batch
  842. +};
  843. +
  844. +struct csa_keys_t{
  845. + struct csa_key_t even;
  846. + struct csa_key_t odd;
  847. +};
  848. +
  849. +//-----stream cypher
  850. +
  851. +//-----key schedule for stream decypher
  852. +static void key_schedule_stream(
  853. + unsigned char *ck, // [In] ck[0]-ck[7] 8 bytes | Key.
  854. + int *iA, // [Out] iA[0]-iA[7] 8 nibbles | Key schedule.
  855. + int *iB) // [Out] iB[0]-iB[7] 8 nibbles | Key schedule.
  856. +{
  857. + iA[0]=(ck[0]>>4)&0xf;
  858. + iA[1]=(ck[0] )&0xf;
  859. + iA[2]=(ck[1]>>4)&0xf;
  860. + iA[3]=(ck[1] )&0xf;
  861. + iA[4]=(ck[2]>>4)&0xf;
  862. + iA[5]=(ck[2] )&0xf;
  863. + iA[6]=(ck[3]>>4)&0xf;
  864. + iA[7]=(ck[3] )&0xf;
  865. + iB[0]=(ck[4]>>4)&0xf;
  866. + iB[1]=(ck[4] )&0xf;
  867. + iB[2]=(ck[5]>>4)&0xf;
  868. + iB[3]=(ck[5] )&0xf;
  869. + iB[4]=(ck[6]>>4)&0xf;
  870. + iB[5]=(ck[6] )&0xf;
  871. + iB[6]=(ck[7]>>4)&0xf;
  872. + iB[7]=(ck[7] )&0xf;
  873. +}
  874. +
  875. +//----- stream main function
  876. +
  877. +#define STREAM_INIT
  878. +#include "stream.c"
  879. +#undef STREAM_INIT
  880. +
  881. +#define STREAM_NORMAL
  882. +#include "stream.c"
  883. +#undef STREAM_NORMAL
  884. +
  885. +
  886. +//-----block decypher
  887. +
  888. +//-----key schedule for block decypher
  889. +
  890. +static void key_schedule_block(
  891. + unsigned char *ck, // [In] ck[0]-ck[7] 8 bytes | Key.
  892. + unsigned char *kk) // [Out] kk[0]-kk[55] 56 bytes | Key schedule.
  893. +{
  894. + static const unsigned char key_perm[0x40] = {
  895. + 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15, 0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
  896. + 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01, 0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
  897. + 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A, 0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
  898. + 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C, 0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
  899. + };
  900. +
  901. + int i,j,k;
  902. + int bit[64];
  903. + int newbit[64];
  904. + int kb[7][8];
  905. +
  906. + // 56 steps
  907. + // 56 key bytes kk(55)..kk(0) by key schedule from ck
  908. +
  909. + // kb(6,0) .. kb(6,7) = ck(0) .. ck(7)
  910. + kb[6][0] = ck[0];
  911. + kb[6][1] = ck[1];
  912. + kb[6][2] = ck[2];
  913. + kb[6][3] = ck[3];
  914. + kb[6][4] = ck[4];
  915. + kb[6][5] = ck[5];
  916. + kb[6][6] = ck[6];
  917. + kb[6][7] = ck[7];
  918. +
  919. + // calculate kb[5] .. kb[0]
  920. + for(i=5; i>=0; i--){
  921. + // 64 bit perm on kb
  922. + for(j=0; j<8; j++){
  923. + for(k=0; k<8; k++){
  924. + bit[j*8+k] = (kb[i+1][j] >> (7-k)) & 1;
  925. + newbit[key_perm[j*8+k]-1] = bit[j*8+k];
  926. + }
  927. + }
  928. + for(j=0; j<8; j++){
  929. + kb[i][j] = 0;
  930. + for(k=0; k<8; k++){
  931. + kb[i][j] |= newbit[j*8+k] << (7-k);
  932. + }
  933. + }
  934. + }
  935. +
  936. + // xor to give kk
  937. + for(i=0; i<7; i++){
  938. + for(j=0; j<8; j++){
  939. + kk[i*8+j] = kb[i][j] ^ i;
  940. + }
  941. + }
  942. +
  943. +}
  944. +
  945. +//-----block utils
  946. +
  947. +static inline __attribute__((always_inline)) void trasp_N_8 (unsigned char *in,unsigned char* out,int count){
  948. + int *ri=(int *)in;
  949. + int *ibi=(int *)out;
  950. + int j,i,k,g;
  951. + // copy and first step
  952. + for(g=0;g<count;g++){
  953. + ri[g]=ibi[2*g];
  954. + ri[GROUP_PARALLELISM+g]=ibi[2*g+1];
  955. + }
  956. +//dump_mem("NE1 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
  957. +// now 01230123
  958. +#define INTS_PER_ROW (GROUP_PARALLELISM/8*2)
  959. + for(j=0;j<8;j+=4){
  960. + for(i=0;i<2;i++){
  961. + for(k=0;k<INTS_PER_ROW;k++){
  962. + unsigned int t,b;
  963. + t=ri[INTS_PER_ROW*(j+i)+k];
  964. + b=ri[INTS_PER_ROW*(j+i+2)+k];
  965. + ri[INTS_PER_ROW*(j+i)+k]= (t&0x0000ffff) | ((b )<<16);
  966. + ri[INTS_PER_ROW*(j+i+2)+k]= ((t )>>16) | (b&0xffff0000) ;
  967. + }
  968. + }
  969. + }
  970. +//dump_mem("NE2 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
  971. +// now 01010101
  972. + for(j=0;j<8;j+=2){
  973. + for(i=0;i<1;i++){
  974. + for(k=0;k<INTS_PER_ROW;k++){
  975. + unsigned int t,b;
  976. + t=ri[INTS_PER_ROW*(j+i)+k];
  977. + b=ri[INTS_PER_ROW*(j+i+1)+k];
  978. + ri[INTS_PER_ROW*(j+i)+k]= (t&0x00ff00ff) | ((b&0x00ff00ff)<<8);
  979. + ri[INTS_PER_ROW*(j+i+1)+k]= ((t&0xff00ff00)>>8) | (b&0xff00ff00);
  980. + }
  981. + }
  982. + }
  983. +//dump_mem("NE3 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
  984. +// now 00000000
  985. +}
  986. +
  987. +static inline __attribute__((always_inline)) void trasp_8_N (unsigned char *in,unsigned char* out,int count){
  988. + int *ri=(int *)in;
  989. + int *bdi=(int *)out;
  990. + int j,i,k,g;
  991. +#define INTS_PER_ROW (GROUP_PARALLELISM/8*2)
  992. +//dump_mem("NE1 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
  993. +// now 00000000
  994. + for(j=0;j<8;j+=2){
  995. + for(i=0;i<1;i++){
  996. + for(k=0;k<INTS_PER_ROW;k++){
  997. + unsigned int t,b;
  998. + t=ri[INTS_PER_ROW*(j+i)+k];
  999. + b=ri[INTS_PER_ROW*(j+i+1)+k];
  1000. + ri[INTS_PER_ROW*(j+i)+k]= (t&0x00ff00ff) | ((b&0x00ff00ff)<<8);
  1001. + ri[INTS_PER_ROW*(j+i+1)+k]= ((t&0xff00ff00)>>8) | (b&0xff00ff00);
  1002. + }
  1003. + }
  1004. + }
  1005. +//dump_mem("NE2 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
  1006. +// now 01010101
  1007. + for(j=0;j<8;j+=4){
  1008. + for(i=0;i<2;i++){
  1009. + for(k=0;k<INTS_PER_ROW;k++){
  1010. + unsigned int t,b;
  1011. + t=ri[INTS_PER_ROW*(j+i)+k];
  1012. + b=ri[INTS_PER_ROW*(j+i+2)+k];
  1013. + ri[INTS_PER_ROW*(j+i)+k]= (t&0x0000ffff) | ((b )<<16);
  1014. + ri[INTS_PER_ROW*(j+i+2)+k]= ((t )>>16) | (b&0xffff0000) ;
  1015. + }
  1016. + }
  1017. + }
  1018. +//dump_mem("NE3 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
  1019. +// now 01230123
  1020. + for(g=0;g<count;g++){
  1021. + bdi[2*g]=ri[g];
  1022. + bdi[2*g+1]=ri[GROUP_PARALLELISM+g];
  1023. + }
  1024. +}
  1025. +
  1026. +//-----block main function
  1027. +
  1028. +// block group
  1029. +static void block_decypher_group(
  1030. + batch *kkmulti, // [In] kkmulti[0]-kkmulti[55] 56 batches | Key schedule (each batch has repeated equal bytes).
  1031. + unsigned char *ib, // [In] (ib0,ib1,...ib7)...x32 32*8 bytes | Initialization vector.
  1032. + unsigned char *bd, // [Out] (bd0,bd1,...bd7)...x32 32*8 bytes | Block decipher.
  1033. + int count)
  1034. +{
  1035. + // int is faster than unsigned char. apparently not
  1036. + static const unsigned char block_sbox[0x100] = {
  1037. + 0x3A,0xEA,0x68,0xFE,0x33,0xE9,0x88,0x1A, 0x83,0xCF,0xE1,0x7F,0xBA,0xE2,0x38,0x12,
  1038. + 0xE8,0x27,0x61,0x95,0x0C,0x36,0xE5,0x70, 0xA2,0x06,0x82,0x7C,0x17,0xA3,0x26,0x49,
  1039. + 0xBE,0x7A,0x6D,0x47,0xC1,0x51,0x8F,0xF3, 0xCC,0x5B,0x67,0xBD,0xCD,0x18,0x08,0xC9,
  1040. + 0xFF,0x69,0xEF,0x03,0x4E,0x48,0x4A,0x84, 0x3F,0xB4,0x10,0x04,0xDC,0xF5,0x5C,0xC6,
  1041. + 0x16,0xAB,0xAC,0x4C,0xF1,0x6A,0x2F,0x3C, 0x3B,0xD4,0xD5,0x94,0xD0,0xC4,0x63,0x62,
  1042. + 0x71,0xA1,0xF9,0x4F,0x2E,0xAA,0xC5,0x56, 0xE3,0x39,0x93,0xCE,0x65,0x64,0xE4,0x58,
  1043. + 0x6C,0x19,0x42,0x79,0xDD,0xEE,0x96,0xF6, 0x8A,0xEC,0x1E,0x85,0x53,0x45,0xDE,0xBB,
  1044. + 0x7E,0x0A,0x9A,0x13,0x2A,0x9D,0xC2,0x5E, 0x5A,0x1F,0x32,0x35,0x9C,0xA8,0x73,0x30,
  1045. +
  1046. + 0x29,0x3D,0xE7,0x92,0x87,0x1B,0x2B,0x4B, 0xA5,0x57,0x97,0x40,0x15,0xE6,0xBC,0x0E,
  1047. + 0xEB,0xC3,0x34,0x2D,0xB8,0x44,0x25,0xA4, 0x1C,0xC7,0x23,0xED,0x90,0x6E,0x50,0x00,
  1048. + 0x99,0x9E,0x4D,0xD9,0xDA,0x8D,0x6F,0x5F, 0x3E,0xD7,0x21,0x74,0x86,0xDF,0x6B,0x05,
  1049. + 0x8E,0x5D,0x37,0x11,0xD2,0x28,0x75,0xD6, 0xA7,0x77,0x24,0xBF,0xF0,0xB0,0x02,0xB7,
  1050. + 0xF8,0xFC,0x81,0x09,0xB1,0x01,0x76,0x91, 0x7D,0x0F,0xC8,0xA0,0xF2,0xCB,0x78,0x60,
  1051. + 0xD1,0xF7,0xE0,0xB5,0x98,0x22,0xB3,0x20, 0x1D,0xA6,0xDB,0x7B,0x59,0x9F,0xAE,0x31,
  1052. + 0xFB,0xD3,0xB6,0xCA,0x43,0x72,0x07,0xF4, 0xD8,0x41,0x14,0x55,0x0D,0x54,0x8B,0xB9,
  1053. + 0xAD,0x46,0x0B,0xAF,0x80,0x52,0x2C,0xFA, 0x8C,0x89,0x66,0xFD,0xB2,0xA9,0x9B,0xC0,
  1054. + };
  1055. + MEMALIGN unsigned char r[GROUP_PARALLELISM*(8+56)]; /* 56 because we will move back in memory while looping */
  1056. + MEMALIGN unsigned char sbox_in[GROUP_PARALLELISM],sbox_out[GROUP_PARALLELISM],perm_out[GROUP_PARALLELISM];
  1057. + int roff;
  1058. + int i,g,count_all=GROUP_PARALLELISM;
  1059. +
  1060. + roff=GROUP_PARALLELISM*56;
  1061. +
  1062. +#define FASTTRASP1
  1063. +#ifndef FASTTRASP1
  1064. + for(g=0;g<count;g++){
  1065. + // Init registers
  1066. + int j;
  1067. + for(j=0;j<8;j++){
  1068. + r[roff+GROUP_PARALLELISM*j+g]=ib[8*g+j];
  1069. + }
  1070. + }
  1071. +#else
  1072. + trasp_N_8((unsigned char *)&r[roff],(unsigned char *)ib,count);
  1073. +#endif
  1074. +//dump_mem("OLD r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM);
  1075. +
  1076. + // loop over kk[55]..kk[0]
  1077. + for(i=55;i>=0;i--){
  1078. + {
  1079. + MEMALIGN batch tkkmulti=kkmulti[i];
  1080. + batch *si=(batch *)sbox_in;
  1081. + batch *r6_N=(batch *)(r+roff+GROUP_PARALLELISM*6);
  1082. + for(g=0;g<count_all/BYTES_PER_BATCH;g++){
  1083. + si[g]=B_FFXOR(tkkmulti,r6_N[g]); //FIXME: introduce FASTBATCH?
  1084. + }
  1085. + }
  1086. +
  1087. + // table lookup, this works on only one byte at a time
  1088. + // most difficult part of all
  1089. + // - can't be parallelized
  1090. + // - can't be synthetized through boolean terms (8 input bits are too many)
  1091. + for(g=0;g<count_all;g++){
  1092. + sbox_out[g]=block_sbox[sbox_in[g]];
  1093. + }
  1094. +
  1095. + // bit permutation
  1096. + {
  1097. + unsigned char *po=(unsigned char *)perm_out;
  1098. + unsigned char *so=(unsigned char *)sbox_out;
  1099. +//dump_mem("pre perm ",(unsigned char *)so,GROUP_PARALLELISM,GROUP_PARALLELISM);
  1100. + for(g=0;g<count_all;g+=BYTES_PER_BATCH){
  1101. + MEMALIGN batch in,out;
  1102. + in=*(batch *)&so[g];
  1103. +
  1104. + out=B_FFOR(
  1105. + B_FFOR(
  1106. + B_FFOR(
  1107. + B_FFOR(
  1108. + B_FFOR(
  1109. + B_FFSH8L(B_FFAND(in,B_FFN_ALL_29()),1),
  1110. + B_FFSH8L(B_FFAND(in,B_FFN_ALL_02()),6)),
  1111. + B_FFSH8L(B_FFAND(in,B_FFN_ALL_04()),3)),
  1112. + B_FFSH8R(B_FFAND(in,B_FFN_ALL_10()),2)),
  1113. + B_FFSH8R(B_FFAND(in,B_FFN_ALL_40()),6)),
  1114. + B_FFSH8R(B_FFAND(in,B_FFN_ALL_80()),4));
  1115. +
  1116. + *(batch *)&po[g]=out;
  1117. + }
  1118. +//dump_mem("post perm",(unsigned char *)po,GROUP_PARALLELISM,GROUP_PARALLELISM);
  1119. + }
  1120. +
  1121. + roff-=GROUP_PARALLELISM; /* virtual shift of registers */
  1122. +
  1123. +#if 0
  1124. +/* one by one */
  1125. + for(g=0;g<count_all;g++){
  1126. + r[roff+GROUP_PARALLELISM*0+g]=r[roff+GROUP_PARALLELISM*8+g]^sbox_out[g];
  1127. + r[roff+GROUP_PARALLELISM*6+g]^=perm_out[g];
  1128. + r[roff+GROUP_PARALLELISM*4+g]^=r[roff+GROUP_PARALLELISM*0+g];
  1129. + r[roff+GROUP_PARALLELISM*3+g]^=r[roff+GROUP_PARALLELISM*0+g];
  1130. + r[roff+GROUP_PARALLELISM*2+g]^=r[roff+GROUP_PARALLELISM*0+g];
  1131. + }
  1132. +#else
  1133. + for(g=0;g<count_all;g+=BEST_SPAN){
  1134. + XOR_BEST_BY(&r[roff+GROUP_PARALLELISM*0+g],&r[roff+GROUP_PARALLELISM*8+g],&sbox_out[g]);
  1135. + XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*6+g],&perm_out[g]);
  1136. + XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*4+g],&r[roff+GROUP_PARALLELISM*0+g]);
  1137. + XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*3+g],&r[roff+GROUP_PARALLELISM*0+g]);
  1138. + XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*2+g],&r[roff+GROUP_PARALLELISM*0+g]);
  1139. + }
  1140. +#endif
  1141. + }
  1142. +
  1143. +#define FASTTRASP2
  1144. +#ifndef FASTTRASP2
  1145. + for(g=0;g<count;g++){
  1146. + // Copy results
  1147. + int j;
  1148. + for(j=0;j<8;j++){
  1149. + bd[8*g+j]=r[roff+GROUP_PARALLELISM*j+g];
  1150. + }
  1151. + }
  1152. +#else
  1153. + trasp_8_N((unsigned char *)&r[roff],(unsigned char *)bd,count);
  1154. +#endif
  1155. +}
  1156. +
  1157. +//-----------------------------------EXTERNAL INTERFACE
  1158. +
  1159. +//-----get internal parallelism
  1160. +
  1161. +int get_internal_parallelism(void){
  1162. + return GROUP_PARALLELISM;
  1163. +}
  1164. +
  1165. +//-----get suggested cluster size
  1166. +
  1167. +int get_suggested_cluster_size(void){
  1168. + int r;
  1169. + r=GROUP_PARALLELISM+GROUP_PARALLELISM/10;
  1170. + if(r<GROUP_PARALLELISM+5) r=GROUP_PARALLELISM+5;
  1171. + return r;
  1172. +}
  1173. +
  1174. +//-----key structure
  1175. +
  1176. +void *get_key_struct(void){
  1177. + struct csa_keys_t *keys=(struct csa_keys_t *)MALLOC(sizeof(struct csa_keys_t));
  1178. + if(keys) {
  1179. + static const unsigned char pk[8] = { 0,0,0,0,0,0,0,0 };
  1180. + set_control_words(keys,pk,pk);
  1181. + }
  1182. + return keys;
  1183. +}
  1184. +
  1185. +void free_key_struct(void *keys){
  1186. + return FREE(keys);
  1187. +}
  1188. +
  1189. +//-----set control words
  1190. +
  1191. +static void schedule_key(struct csa_key_t *key, const unsigned char *pk){
  1192. + // could be made faster, but is not run often
  1193. + int bi,by;
  1194. + int i,j;
  1195. +// key
  1196. + memcpy(key->ck,pk,8);
  1197. +// precalculations for stream
  1198. + key_schedule_stream(key->ck,key->iA,key->iB);
  1199. + for(by=0;by<8;by++){
  1200. + for(bi=0;bi<8;bi++){
  1201. + key->ck_g[by][bi]=(key->ck[by]&(1<<bi))?FF1():FF0();
  1202. + }
  1203. + }
  1204. + for(by=0;by<8;by++){
  1205. + for(bi=0;bi<4;bi++){
  1206. + key->iA_g[by][bi]=(key->iA[by]&(1<<bi))?FF1():FF0();
  1207. + key->iB_g[by][bi]=(key->iB[by]&(1<<bi))?FF1():FF0();
  1208. + }
  1209. + }
  1210. +// precalculations for block
  1211. + key_schedule_block(key->ck,key->kk);
  1212. + for(i=0;i<56;i++){
  1213. + for(j=0;j<BYTES_PER_BATCH;j++){
  1214. + *(((unsigned char *)&key->kkmulti[i])+j)=key->kk[i];
  1215. + }
  1216. + }
  1217. +}
  1218. +
  1219. +void set_control_words(void *keys, const unsigned char *ev, const unsigned char *od){
  1220. + schedule_key(&((struct csa_keys_t *)keys)->even,ev);
  1221. + schedule_key(&((struct csa_keys_t *)keys)->odd,od);
  1222. +}
  1223. +
  1224. +void set_even_control_word(void *keys, const unsigned char *pk){
  1225. + schedule_key(&((struct csa_keys_t *)keys)->even,pk);
  1226. +}
  1227. +
  1228. +void set_odd_control_word(void *keys, const unsigned char *pk){
  1229. + schedule_key(&((struct csa_keys_t *)keys)->odd,pk);
  1230. +}
  1231. +
  1232. +//-----get control words
  1233. +
  1234. +void get_control_words(void *keys, unsigned char *even, unsigned char *odd){
  1235. + memcpy(even,&((struct csa_keys_t *)keys)->even.ck,8);
  1236. + memcpy(odd,&((struct csa_keys_t *)keys)->odd.ck,8);
  1237. +}
  1238. +
  1239. +//----- decrypt
  1240. +
  1241. +int decrypt_packets(void *keys, unsigned char **cluster){
  1242. + // statistics, currently unused
  1243. + int stat_no_scramble=0;
  1244. + int stat_reserved=0;
  1245. + int stat_decrypted[2]={0,0};
  1246. + int stat_decrypted_mini=0;
  1247. + unsigned char **clst;
  1248. + unsigned char **clst2;
  1249. + int grouped;
  1250. + int group_ev_od;
  1251. + int advanced;
  1252. + int can_advance;
  1253. + unsigned char *g_pkt[GROUP_PARALLELISM];
  1254. + int g_len[GROUP_PARALLELISM];
  1255. + int g_offset[GROUP_PARALLELISM];
  1256. + int g_n[GROUP_PARALLELISM];
  1257. + int g_residue[GROUP_PARALLELISM];
  1258. + unsigned char *pkt;
  1259. + int xc0,ev_od,len,offset,n,residue;
  1260. + struct csa_key_t* k;
  1261. + int i,j,iter,g;
  1262. + int t23,tsmall;
  1263. + int alive[24];
  1264. +//icc craziness int pad1=0; //////////align! FIXME
  1265. + unsigned char *encp[GROUP_PARALLELISM];
  1266. + MEMALIGN unsigned char stream_in[GROUP_PARALLELISM*8];
  1267. + MEMALIGN unsigned char stream_out[GROUP_PARALLELISM*8];
  1268. + MEMALIGN unsigned char ib[GROUP_PARALLELISM*8];
  1269. + MEMALIGN unsigned char block_out[GROUP_PARALLELISM*8];
  1270. +#ifdef COPY_UNALIGNED_PKT
  1271. + unsigned char *unaligned[GROUP_PARALLELISM];
  1272. + MEMALIGN unsigned char alignedBuff[GROUP_PARALLELISM][188];
  1273. +#endif
  1274. + struct stream_regs regs;
  1275. +
  1276. +//icc craziness i=(int)&pad1;//////////align!!! FIXME
  1277. +
  1278. + // build a list of packets to be processed
  1279. + clst=cluster;
  1280. + grouped=0;
  1281. + advanced=0;
  1282. + can_advance=1;
  1283. + group_ev_od=-1; // silence incorrect compiler warning
  1284. + pkt=*clst;
  1285. + do{ // find a new packet
  1286. + if(grouped==GROUP_PARALLELISM){
  1287. + // full
  1288. + break;
  1289. + }
  1290. + if(pkt==NULL){
  1291. + // no more ranges
  1292. + break;
  1293. + }
  1294. + if(pkt>=*(clst+1)){
  1295. + // out of this range, try next
  1296. + clst++;clst++;
  1297. + pkt=*clst;
  1298. + continue;
  1299. + }
  1300. +
  1301. + do{ // handle this packet
  1302. + xc0=pkt[3]&0xc0;
  1303. + DBG(fprintf(stderr," exam pkt=%p, xc0=%02x, can_adv=%i\n",pkt,xc0,can_advance));
  1304. + if(xc0==0x00){
  1305. + DBG(fprintf(stderr,"skip clear pkt %p (can_advance is %i)\n",pkt,can_advance));
  1306. + advanced+=can_advance;
  1307. + stat_no_scramble++;
  1308. + break;
  1309. + }
  1310. + if(xc0==0x40){
  1311. + DBG(fprintf(stderr,"skip reserved pkt %p (can_advance is %i)\n",pkt,can_advance));
  1312. + advanced+=can_advance;
  1313. + stat_reserved++;
  1314. + break;
  1315. + }
  1316. + if(xc0==0x80||xc0==0xc0){ // encrypted
  1317. + ev_od=(xc0&0x40)>>6; // 0 even, 1 odd
  1318. + if(grouped==0) group_ev_od=ev_od; // this group will be all even (or odd)
  1319. + if(group_ev_od==ev_od){ // could be added to group
  1320. + pkt[3]&=0x3f; // consider it decrypted now
  1321. + if(pkt[3]&0x20){ // incomplete packet
  1322. + offset=4+pkt[4]+1;
  1323. + len=188-offset;
  1324. + n=len>>3;
  1325. + residue=len-(n<<3);
  1326. + if(n==0){ // decrypted==encrypted!
  1327. + DBG(fprintf(stderr,"DECRYPTED MINI! (can_advance is %i)\n",can_advance));
  1328. + advanced+=can_advance;
  1329. + stat_decrypted_mini++;
  1330. + break; // this doesn't need more processing
  1331. + }
  1332. + }else{
  1333. + len=184;
  1334. + offset=4;
  1335. + n=23;
  1336. + residue=0;
  1337. + }
  1338. + g_pkt[grouped]=pkt;
  1339. + g_len[grouped]=len;
  1340. + g_offset[grouped]=offset;
  1341. + g_n[grouped]=n;
  1342. + g_residue[grouped]=residue;
  1343. + DBG(fprintf(stderr,"%2i: eo=%i pkt=%p len=%03i n=%2i residue=%i\n",grouped,ev_od,pkt,len,n,residue));
  1344. + grouped++;
  1345. + advanced+=can_advance;
  1346. + stat_decrypted[ev_od]++;
  1347. + }
  1348. + else{
  1349. + can_advance=0;
  1350. + DBG(fprintf(stderr,"skip pkt %p and can_advance set to 0\n",pkt));
  1351. + break; // skip and go on
  1352. + }
  1353. + }
  1354. + } while(0);
  1355. +
  1356. + if(can_advance){
  1357. + // move range start forward
  1358. + *clst+=188;
  1359. + }
  1360. + // next packet, if there is one
  1361. + pkt+=188;
  1362. + } while(1);
  1363. + DBG(fprintf(stderr,"-- result: grouped %i pkts, advanced %i pkts\n",grouped,advanced));
  1364. +
  1365. + // delete empty ranges and compact list
  1366. + clst2=cluster;
  1367. + for(clst=cluster;*clst!=NULL;clst+=2){
  1368. + // if not empty
  1369. + if(*clst<*(clst+1)){
  1370. + // it will remain
  1371. + *clst2=*clst;
  1372. + *(clst2+1)=*(clst+1);
  1373. + clst2+=2;
  1374. + }
  1375. + }
  1376. + *clst2=NULL;
  1377. +
  1378. + if(grouped==0){
  1379. + // no processing needed
  1380. + return advanced;
  1381. + }
  1382. +
  1383. + // sort them, longest payload first
  1384. + // we expect many n=23 packets and a few n<23
  1385. + DBG(fprintf(stderr,"PRESORTING\n"));
  1386. + for(i=0;i<grouped;i++){
  1387. + 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]));
  1388. + }
  1389. + // grouped is always <= GROUP_PARALLELISM
  1390. +
  1391. +#define g_swap(a,b) \
  1392. + pkt=g_pkt[a]; \
  1393. + g_pkt[a]=g_pkt[b]; \
  1394. + g_pkt[b]=pkt; \
  1395. +\
  1396. + len=g_len[a]; \
  1397. + g_len[a]=g_len[b]; \
  1398. + g_len[b]=len; \
  1399. +\
  1400. + offset=g_offset[a]; \
  1401. + g_offset[a]=g_offset[b]; \
  1402. + g_offset[b]=offset; \
  1403. +\
  1404. + n=g_n[a]; \
  1405. + g_n[a]=g_n[b]; \
  1406. + g_n[b]=n; \
  1407. +\
  1408. + residue=g_residue[a]; \
  1409. + g_residue[a]=g_residue[b]; \
  1410. + g_residue[b]=residue;
  1411. +
  1412. + // step 1: move n=23 packets before small packets
  1413. + t23=0;
  1414. + tsmall=grouped-1;
  1415. + for(;;){
  1416. + for(;t23<grouped;t23++){
  1417. + if(g_n[t23]!=23) break;
  1418. + }
  1419. +DBG(fprintf(stderr,"t23 after for =%i\n",t23));
  1420. +
  1421. + for(;tsmall>=0;tsmall--){
  1422. + if(g_n[tsmall]==23) break;
  1423. + }
  1424. +DBG(fprintf(stderr,"tsmall after for =%i\n",tsmall));
  1425. +
  1426. + if(tsmall-t23<1) break;
  1427. +
  1428. +DBG(fprintf(stderr,"swap t23=%i,tsmall=%i\n",t23,tsmall));
  1429. +
  1430. + g_swap(t23,tsmall);
  1431. +
  1432. + t23++;
  1433. + tsmall--;
  1434. +DBG(fprintf(stderr,"new t23=%i,tsmall=%i\n\n",t23,tsmall));
  1435. + }
  1436. + DBG(fprintf(stderr,"packets with n=23, t23=%i grouped=%i\n",t23,grouped));
  1437. + DBG(fprintf(stderr,"MIDSORTING\n"));
  1438. + for(i=0;i<grouped;i++){
  1439. + 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]));
  1440. + }
  1441. +
  1442. + // step 2: sort small packets in decreasing order of n (bubble sort is enough)
  1443. + for(i=t23;i<grouped;i++){
  1444. + for(j=i+1;j<grouped;j++){
  1445. + if(g_n[j]>g_n[i]){
  1446. + g_swap(i,j);
  1447. + }
  1448. + }
  1449. + }
  1450. + DBG(fprintf(stderr,"POSTSORTING\n"));
  1451. + for(i=0;i<grouped;i++){
  1452. + 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]));
  1453. + }
  1454. +
  1455. + // we need to know how many packets need 23 iterations, how many 22...
  1456. + for(i=0;i<=23;i++){
  1457. + alive[i]=0;
  1458. + }
  1459. + // count
  1460. + alive[23-1]=t23;
  1461. + for(i=t23;i<grouped;i++){
  1462. + alive[g_n[i]-1]++;
  1463. + }
  1464. + // integrate
  1465. + for(i=22;i>=0;i--){
  1466. + alive[i]+=alive[i+1];
  1467. + }
  1468. + DBG(fprintf(stderr,"ALIVE\n"));
  1469. + for(i=0;i<=23;i++){
  1470. + DBG(fprintf(stderr,"alive%2i=%i\n",i,alive[i]));
  1471. + }
  1472. +
  1473. + // choose key
  1474. + if(group_ev_od==0){
  1475. + k=&((struct csa_keys_t *)keys)->even;
  1476. + }
  1477. + else{
  1478. + k=&((struct csa_keys_t *)keys)->odd;
  1479. + }
  1480. +
  1481. + //INIT
  1482. +//#define INITIALIZE_UNUSED_INPUT
  1483. +#ifdef INITIALIZE_UNUSED_INPUT
  1484. +// unnecessary zeroing.
  1485. +// without this, we operate on uninitialized memory
  1486. +// when grouped<GROUP_PARALLELISM, but it's not a problem,
  1487. +// as final results will be discarded.
  1488. +// random data makes debugging sessions difficult.
  1489. + for(j=0;j<GROUP_PARALLELISM*8;j++) stream_in[j]=0;
  1490. +DBG(fprintf(stderr,"--- WARNING: you could gain speed by not initializing unused memory ---\n"));
  1491. +#else
  1492. +DBG(fprintf(stderr,"--- WARNING: DEBUGGING IS MORE DIFFICULT WHEN PROCESSING RANDOM DATA CHANGING AT EVERY RUN! ---\n"));
  1493. +#endif
  1494. +
  1495. + for(g=0;g<grouped;g++){
  1496. + encp[g]=g_pkt[g];
  1497. + DBG(fprintf(stderr,"header[%i]=%p (%02x)\n",g,encp[g],*(encp[g])));
  1498. + encp[g]+=g_offset[g]; // skip header
  1499. +#ifdef COPY_UNALIGNED_PKT
  1500. + if(((int)encp[g])&0x03) {
  1501. + memcpy(alignedBuff[g],encp[g],g_len[g]);
  1502. + unaligned[g]=encp[g];
  1503. + encp[g]=alignedBuff[g];
  1504. + }
  1505. + else unaligned[g]=0;
  1506. +#endif
  1507. + FFTABLEIN(stream_in,g,encp[g]);
  1508. + }
  1509. +//dump_mem("stream_in",stream_in,GROUP_PARALLELISM*8,BYPG);
  1510. +
  1511. +
  1512. + // ITER 0
  1513. +DBG(fprintf(stderr,">>>>>ITER 0\n"));
  1514. + iter=0;
  1515. + stream_cypher_group_init(&regs,k->iA_g,k->iB_g,stream_in);
  1516. + // fill first ib
  1517. + for(g=0;g<alive[iter];g++){
  1518. + COPY_8_BY(ib+8*g,encp[g]);
  1519. + }
  1520. +DBG(dump_mem("IB ",ib,8*alive[iter],8));
  1521. + // ITER 1..N-1
  1522. + for (iter=1;iter<23&&alive[iter-1]>0;iter++){
  1523. +DBG(fprintf(stderr,">>>>>ITER %i\n",iter));
  1524. + // alive and just dead packets: calc block
  1525. + block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]);
  1526. +DBG(dump_mem("BLO_ib ",block_out,8*alive[iter-1],8));
  1527. + // all packets (dead too): calc stream
  1528. + stream_cypher_group_normal(&regs,stream_out);
  1529. +//dump_mem("stream_out",stream_out,GROUP_PARALLELISM*8,BYPG);
  1530. +
  1531. + // alive packets: calc ib
  1532. + for(g=0;g<alive[iter];g++){
  1533. + FFTABLEOUT(ib+8*g,stream_out,g);
  1534. +DBG(dump_mem("stream_out_ib ",ib+8*g,8,8));
  1535. +// XOREQ8BY gcc bug? 2x4 ok, 8 ko UPDATE: result ok but speed 1-2% slower (!!!???)
  1536. +#if 1
  1537. + XOREQ_4_BY(ib+8*g,encp[g]+8);
  1538. + XOREQ_4_BY(ib+8*g+4,encp[g]+8+4);
  1539. +#else
  1540. + XOREQ_8_BY(ib+8*g,encp[g]+8);
  1541. +#endif
  1542. +DBG(dump_mem("after_stream_xor_ib ",ib+8*g,8,8));
  1543. + }
  1544. + // alive packets: decrypt data
  1545. + for(g=0;g<alive[iter];g++){
  1546. +DBG(dump_mem("before_ib_decrypt_data ",encp[g],8,8));
  1547. + XOR_8_BY(encp[g],ib+8*g,block_out+8*g);
  1548. +DBG(dump_mem("after_ib_decrypt_data ",encp[g],8,8));
  1549. + }
  1550. + // just dead packets: write decrypted data
  1551. + for(g=alive[iter];g<alive[iter-1];g++){
  1552. +DBG(dump_mem("jd_before_ib_decrypt_data ",encp[g],8,8));
  1553. + COPY_8_BY(encp[g],block_out+8*g);
  1554. +DBG(dump_mem("jd_after_ib_decrypt_data ",encp[g],8,8));
  1555. + }
  1556. + // just dead packets: decrypt residue
  1557. + for(g=alive[iter];g<alive[iter-1];g++){
  1558. +DBG(dump_mem("jd_before_decrypt_residue ",encp[g]+8,g_residue[g],g_residue[g]));
  1559. + FFTABLEOUTXORNBY(g_residue[g],encp[g]+8,stream_out,g);
  1560. +DBG(dump_mem("jd_after_decrypt_residue ",encp[g]+8,g_residue[g],g_residue[g]));
  1561. + }
  1562. + // alive packets: pointers++
  1563. + for(g=0;g<alive[iter];g++) encp[g]+=8;
  1564. + };
  1565. + // ITER N
  1566. +DBG(fprintf(stderr,">>>>>ITER 23\n"));
  1567. + iter=23;
  1568. + // calc block
  1569. + block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]);
  1570. +DBG(dump_mem("23BLO_ib ",block_out,8*alive[iter-1],8));
  1571. + // just dead packets: write decrypted data
  1572. + for(g=alive[iter];g<alive[iter-1];g++){
  1573. +DBG(dump_mem("23jd_before_ib_decrypt_data ",encp[g],8,8));
  1574. + COPY_8_BY(encp[g],block_out+8*g);
  1575. +DBG(dump_mem("23jd_after_ib_decrypt_data ",encp[g],8,8));
  1576. + }
  1577. + // no residue possible
  1578. + // so do nothing
  1579. +
  1580. + DBG(fprintf(stderr,"returning advanced=%i\n",advanced));
  1581. +
  1582. +#ifdef COPY_UNALIGNED_PKT
  1583. + for(g=0;g<grouped;g++)
  1584. + if(unaligned[g]) memcpy(unaligned[g],alignedBuff[g],g_len[g]);
  1585. +#endif
  1586. +
  1587. + M_EMPTY(); // restore CPU multimedia state
  1588. +
  1589. + return advanced;
  1590. +}
  1591. Index: ffdecsa/ffdecsa.h
  1592. ===================================================================
  1593. --- ffdecsa/ffdecsa.h (revision 0)
  1594. +++ ffdecsa/ffdecsa.h (working copy)
  1595. @@ -0,0 +1,62 @@
  1596. +/* FFdecsa -- fast decsa algorithm
  1597. + *
  1598. + * Copyright (C) 2003-2004 fatih89r
  1599. + *
  1600. + * This program is free software; you can redistribute it and/or modify
  1601. + * it under the terms of the GNU General Public License as published by
  1602. + * the Free Software Foundation; either version 2 of the License, or
  1603. + * (at your option) any later version.
  1604. + *
  1605. + * This program is distributed in the hope that it will be useful,
  1606. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1607. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1608. + * GNU General Public License for more details.
  1609. + *
  1610. + * You should have received a copy of the GNU General Public License
  1611. + * along with this program; if not, write to the Free Software
  1612. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1613. + */
  1614. +
  1615. +
  1616. +#ifndef FFDECSA_H
  1617. +#define FFDECSA_H
  1618. +
  1619. +//----- public interface
  1620. +
  1621. +// -- how many packets can be decrypted at the same time
  1622. +// This is an info about internal decryption parallelism.
  1623. +// You should try to call decrypt_packets with more packets than the number
  1624. +// returned here for performance reasons (use get_suggested_cluster_size to know
  1625. +// how many).
  1626. +int get_internal_parallelism(void);
  1627. +
  1628. +// -- how many packets you should have in a cluster when calling decrypt_packets
  1629. +// This is a suggestion to achieve optimal performance; typically a little
  1630. +// higher than what get_internal_parallelism returns.
  1631. +// Passing less packets could slow down the decryption.
  1632. +// Passing more packets is never bad (if you don't spend a lot of time building
  1633. +// the list).
  1634. +int get_suggested_cluster_size(void);
  1635. +
  1636. +// -- alloc & free the key structure
  1637. +void *get_key_struct(void);
  1638. +void free_key_struct(void *keys);
  1639. +
  1640. +// -- set control words, 8 bytes each
  1641. +void set_control_words(void *keys, const unsigned char *even, const unsigned char *odd);
  1642. +
  1643. +// -- set even control word, 8 bytes
  1644. +void set_even_control_word(void *keys, const unsigned char *even);
  1645. +
  1646. +// -- set odd control word, 8 bytes
  1647. +void set_odd_control_word(void *keys, const unsigned char *odd);
  1648. +
  1649. +// -- get control words, 8 bytes each
  1650. +//void get_control_words(void *keys, unsigned char *even, unsigned char *odd);
  1651. +
  1652. +// -- decrypt many TS packets
  1653. +// This interface is a bit complicated because it is designed for maximum speed.
  1654. +// Please read doc/how_to_use.txt.
  1655. +int decrypt_packets(void *keys, unsigned char **cluster);
  1656. +
  1657. +#endif
  1658. Index: ffdecsa/fftable.h
  1659. ===================================================================
  1660. --- ffdecsa/fftable.h (revision 0)
  1661. +++ ffdecsa/fftable.h (working copy)
  1662. @@ -0,0 +1,56 @@
  1663. +/* FFdecsa -- fast decsa algorithm
  1664. + *
  1665. + * Copyright (C) 2007 Dark Avenger
  1666. + * 2003-2004 fatih89r
  1667. + *
  1668. + * This program is free software; you can redistribute it and/or modify
  1669. + * it under the terms of the GNU General Public License as published by
  1670. + * the Free Software Foundation; either version 2 of the License, or
  1671. + * (at your option) any later version.
  1672. + *
  1673. + * This program is distributed in the hope that it will be useful,
  1674. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1675. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1676. + * GNU General Public License for more details.
  1677. + *
  1678. + * You should have received a copy of the GNU General Public License
  1679. + * along with this program; if not, write to the Free Software
  1680. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1681. + */
  1682. +
  1683. +#ifndef FFTABLE_H
  1684. +#define FFTABLE_H
  1685. +
  1686. +inline static void FFTABLEIN(unsigned char *tab, int g, unsigned char *data)
  1687. +{
  1688. +#if 0
  1689. + *(((int *)tab)+2*g)=*((int *)data);
  1690. + *(((int *)tab)+2*g+1)=*(((int *)data)+1);
  1691. +#else
  1692. + *(((long long *)tab)+g)=*((long long *)data);
  1693. +#endif
  1694. +}
  1695. +
  1696. +inline static void FFTABLEOUT(unsigned char *data, unsigned char *tab, int g)
  1697. +{
  1698. +#if 1
  1699. + *((int *)data)=*(((int *)tab)+2*g);
  1700. + *(((int *)data)+1)=*(((int *)tab)+2*g+1);
  1701. +#else
  1702. + *((long long *)data)=*(((long long *)tab)+g);
  1703. +#endif
  1704. +}
  1705. +
  1706. +inline static void FFTABLEOUTXORNBY(int n, unsigned char *data, unsigned char *tab, int g)
  1707. +{
  1708. + int j;
  1709. + for(j=0;j<n;j++) *(data+j)^=*(tab+8*g+j);
  1710. +}
  1711. +
  1712. +#undef XOREQ_BEST_BY
  1713. +inline static void XOREQ_BEST_BY(unsigned char *d, unsigned char *s)
  1714. +{
  1715. + XOR_BEST_BY(d, d, s);
  1716. +}
  1717. +
  1718. +#endif //FFTABLE_H
  1719. Index: ffdecsa/parallel_032_int.h
  1720. ===================================================================
  1721. --- ffdecsa/parallel_032_int.h (revision 0)
  1722. +++ ffdecsa/parallel_032_int.h (working copy)
  1723. @@ -0,0 +1,55 @@
  1724. +/* FFdecsa -- fast decsa algorithm
  1725. + *
  1726. + * Copyright (C) 2003-2004 fatih89r
  1727. + *
  1728. + * This program is free software; you can redistribute it and/or modify
  1729. + * it under the terms of the GNU General Public License as published by
  1730. + * the Free Software Foundation; either version 2 of the License, or
  1731. + * (at your option) any later version.
  1732. + *
  1733. + * This program is distributed in the hope that it will be useful,
  1734. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1735. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1736. + * GNU General Public License for more details.
  1737. + *
  1738. + * You should have received a copy of the GNU General Public License
  1739. + * along with this program; if not, write to the Free Software
  1740. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1741. + */
  1742. +
  1743. +#include "parallel_std_def.h"
  1744. +
  1745. +typedef unsigned int group;
  1746. +#define GROUP_PARALLELISM 32
  1747. +#define FF0() 0x0
  1748. +#define FF1() 0xffffffff
  1749. +
  1750. +/* 64 rows of 32 bits */
  1751. +
  1752. +inline static void FFTABLEIN(unsigned char *tab, int g, unsigned char *data){
  1753. + *(((int *)tab)+g)=*((int *)data);
  1754. + *(((int *)tab)+32+g)=*(((int *)data)+1);
  1755. +}
  1756. +
  1757. +inline static void FFTABLEOUT(unsigned char *data, unsigned char *tab, int g){
  1758. + *((int *)data)=*(((int *)tab)+g);
  1759. + *(((int *)data)+1)=*(((int *)tab)+32+g);
  1760. +}
  1761. +
  1762. +inline static void FFTABLEOUTXORNBY(int n, unsigned char *data, unsigned char *tab, int g){
  1763. + int j;
  1764. + for(j=0;j<n;j++){
  1765. + *(data+j)^=*(tab+4*(g+(j>=4?32-1:0))+j);
  1766. + }
  1767. +}
  1768. +
  1769. +typedef unsigned int batch;
  1770. +#define BYTES_PER_BATCH 4
  1771. +#define B_FFN_ALL_29() 0x29292929
  1772. +#define B_FFN_ALL_02() 0x02020202
  1773. +#define B_FFN_ALL_04() 0x04040404
  1774. +#define B_FFN_ALL_10() 0x10101010
  1775. +#define B_FFN_ALL_40() 0x40404040
  1776. +#define B_FFN_ALL_80() 0x80808080
  1777. +
  1778. +#define M_EMPTY()
  1779. Index: ffdecsa/parallel_064_long.h
  1780. ===================================================================
  1781. --- ffdecsa/parallel_064_long.h (revision 0)
  1782. +++ ffdecsa/parallel_064_long.h (working copy)
  1783. @@ -0,0 +1,39 @@
  1784. +/* FFdecsa -- fast decsa algorithm
  1785. + *
  1786. + * Copyright (C) 2007 Dark Avenger
  1787. + * 2003-2004 fatih89r
  1788. + *
  1789. + * This program is free software; you can redistribute it and/or modify
  1790. + * it under the terms of the GNU General Public License as published by
  1791. + * the Free Software Foundation; either version 2 of the License, or
  1792. + * (at your option) any later version.
  1793. + *
  1794. + * This program is distributed in the hope that it will be useful,
  1795. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1796. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1797. + * GNU General Public License for more details.
  1798. + *
  1799. + * You should have received a copy of the GNU General Public License
  1800. + * along with this program; if not, write to the Free Software
  1801. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1802. + */
  1803. +
  1804. +#include "parallel_std_def.h"
  1805. +
  1806. +typedef unsigned long long group;
  1807. +#define GROUP_PARALLELISM 64
  1808. +#define FF0() 0x0ULL
  1809. +#define FF1() 0xffffffffffffffffULL
  1810. +
  1811. +typedef unsigned long long batch;
  1812. +#define BYTES_PER_BATCH 8
  1813. +#define B_FFN_ALL_29() 0x2929292929292929ULL
  1814. +#define B_FFN_ALL_02() 0x0202020202020202ULL
  1815. +#define B_FFN_ALL_04() 0x0404040404040404ULL
  1816. +#define B_FFN_ALL_10() 0x1010101010101010ULL
  1817. +#define B_FFN_ALL_40() 0x4040404040404040ULL
  1818. +#define B_FFN_ALL_80() 0x8080808080808080ULL
  1819. +
  1820. +#define M_EMPTY()
  1821. +
  1822. +#include "fftable.h"
  1823. Index: ffdecsa/parallel_128_sse2.h
  1824. ===================================================================
  1825. --- ffdecsa/parallel_128_sse2.h (revision 0)
  1826. +++ ffdecsa/parallel_128_sse2.h (working copy)
  1827. @@ -0,0 +1,82 @@
  1828. +/* FFdecsa -- fast decsa algorithm
  1829. + *
  1830. + * Copyright (C) 2007 Dark Avenger
  1831. + * 2003-2004 fatih89r
  1832. + *
  1833. + * This program is free software; you can redistribute it and/or modify
  1834. + * it under the terms of the GNU General Public License as published by
  1835. + * the Free Software Foundation; either version 2 of the License, or
  1836. + * (at your option) any later version.
  1837. + *
  1838. + * This program is distributed in the hope that it will be useful,
  1839. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1840. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1841. + * GNU General Public License for more details.
  1842. + *
  1843. + * You should have received a copy of the GNU General Public License
  1844. + * along with this program; if not, write to the Free Software
  1845. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1846. + */
  1847. +
  1848. +#include <emmintrin.h>
  1849. +
  1850. +#define MEMALIGN_VAL 16
  1851. +
  1852. +union __u128i {
  1853. + unsigned int u[4];
  1854. + __m128i v;
  1855. +};
  1856. +
  1857. +static const union __u128i ff0 = {{0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U}};
  1858. +static const union __u128i ff1 = {{0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU}};
  1859. +
  1860. +typedef __m128i group;
  1861. +#define GROUP_PARALLELISM 128
  1862. +#define FF0() ff0.v
  1863. +#define FF1() ff1.v
  1864. +#define FFAND(a,b) _mm_and_si128((a),(b))
  1865. +#define FFOR(a,b) _mm_or_si128((a),(b))
  1866. +#define FFXOR(a,b) _mm_xor_si128((a),(b))
  1867. +#define FFNOT(a) _mm_xor_si128((a),FF1())
  1868. +#define MALLOC(X) _mm_malloc(X,16)
  1869. +#define FREE(X) _mm_free(X)
  1870. +
  1871. +/* BATCH */
  1872. +
  1873. +static const union __u128i ff29 = {{0x29292929U, 0x29292929U, 0x29292929U, 0x29292929U}};
  1874. +static const union __u128i ff02 = {{0x02020202U, 0x02020202U, 0x02020202U, 0x02020202U}};
  1875. +static const union __u128i ff04 = {{0x04040404U, 0x04040404U, 0x04040404U, 0x04040404U}};
  1876. +static const union __u128i ff10 = {{0x10101010U, 0x10101010U, 0x10101010U, 0x10101010U}};
  1877. +static const union __u128i ff40 = {{0x40404040U, 0x40404040U, 0x40404040U, 0x40404040U}};
  1878. +static const union __u128i ff80 = {{0x80808080U, 0x80808080U, 0x80808080U, 0x80808080U}};
  1879. +
  1880. +typedef __m128i batch;
  1881. +#define BYTES_PER_BATCH 16
  1882. +#define B_FFN_ALL_29() ff29.v
  1883. +#define B_FFN_ALL_02() ff02.v
  1884. +#define B_FFN_ALL_04() ff04.v
  1885. +#define B_FFN_ALL_10() ff10.v
  1886. +#define B_FFN_ALL_40() ff40.v
  1887. +#define B_FFN_ALL_80() ff80.v
  1888. +
  1889. +#define B_FFAND(a,b) FFAND(a,b)
  1890. +#define B_FFOR(a,b) FFOR(a,b)
  1891. +#define B_FFXOR(a,b) FFXOR(a,b)
  1892. +#define B_FFSH8L(a,n) _mm_slli_epi64((a),(n))
  1893. +#define B_FFSH8R(a,n) _mm_srli_epi64((a),(n))
  1894. +
  1895. +#define M_EMPTY()
  1896. +
  1897. +#undef BEST_SPAN
  1898. +#define BEST_SPAN 16
  1899. +
  1900. +#undef XOR_BEST_BY
  1901. +inline static void XOR_BEST_BY(unsigned char *d, unsigned char *s1, unsigned char *s2)
  1902. +{
  1903. + __m128i vs1 = _mm_load_si128((__m128i*)s1);
  1904. + __m128i vs2 = _mm_load_si128((__m128i*)s2);
  1905. + vs1 = _mm_xor_si128(vs1, vs2);
  1906. + _mm_store_si128((__m128i*)d, vs1);
  1907. +}
  1908. +
  1909. +#include "fftable.h"
  1910. Index: ffdecsa/parallel_generic.h
  1911. ===================================================================
  1912. --- ffdecsa/parallel_generic.h (revision 0)
  1913. +++ ffdecsa/parallel_generic.h (working copy)
  1914. @@ -0,0 +1,102 @@
  1915. +/* FFdecsa -- fast decsa algorithm
  1916. + *
  1917. + * Copyright (C) 2003-2004 fatih89r
  1918. + *
  1919. + * This program is free software; you can redistribute it and/or modify
  1920. + * it under the terms of the GNU General Public License as published by
  1921. + * the Free Software Foundation; either version 2 of the License, or
  1922. + * (at your option) any later version.
  1923. + *
  1924. + * This program is distributed in the hope that it will be useful,
  1925. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1926. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1927. + * GNU General Public License for more details.
  1928. + *
  1929. + * You should have received a copy of the GNU General Public License
  1930. + * along with this program; if not, write to the Free Software
  1931. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1932. + */
  1933. +
  1934. +
  1935. +
  1936. +#if 0
  1937. +//// generics
  1938. +#define COPY4BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
  1939. + *pd = *ps; }while(0)
  1940. +#define COPY8BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
  1941. + *pd = *ps; }while(0)
  1942. +#define COPY16BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
  1943. + *pd = *ps; \
  1944. + *(pd+1) = *(ps+1); }while(0)
  1945. +#define COPY32BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
  1946. + *pd = *ps; \
  1947. + *(pd+1) = *(ps+1) \
  1948. + *(pd+2) = *(ps+2) \
  1949. + *(pd+3) = *(ps+3); }while(0)
  1950. +#define XOR4BY(d,s1,s2) do{ int *pd=(int *)(d), *ps1=(int *)(s1), *ps2=(int *)(s2); \
  1951. + *pd = *ps1 ^ *ps2; }while(0)
  1952. +#define XOR8BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
  1953. + *pd = *ps1 ^ *ps2; }while(0)
  1954. +#define XOR16BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
  1955. + *pd = *ps1 ^ *ps2; \
  1956. + *(pd+8) = *(ps1+8) ^ *(ps2+8); }while(0)
  1957. +#define XOR32BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \
  1958. + *pd = *ps1 ^ *ps2; \
  1959. + *(pd+1) = *(ps1+1) ^ *(ps2+1); \
  1960. + *(pd+2) = *(ps1+2) ^ *(ps2+2); \
  1961. + *(pd+3) = *(ps1+3) ^ *(ps2+3); }while(0)
  1962. +#define XOR32BV(d,s1,s2) do{ int *const pd=(int *const)(d), *ps1=(const int *const)(s1), *ps2=(const int *const)(s2); \
  1963. + int z; \
  1964. + for(z=0;z<8;z++){ \
  1965. + pd[z]=ps1[z]^ps2[z]; \
  1966. + } \
  1967. + }while(0)
  1968. +#define XOREQ4BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
  1969. + *pd ^= *ps; }while(0)
  1970. +#define XOREQ8BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
  1971. + *pd ^= *ps; }while(0)
  1972. +#define XOREQ16BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
  1973. + *pd ^= *ps; \
  1974. + *(pd+1) ^=*(ps+1); }while(0)
  1975. +#define XOREQ32BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
  1976. + *pd ^= *ps; \
  1977. + *(pd+1) ^=*(ps+1); \
  1978. + *(pd+2) ^=*(ps+2); \
  1979. + *(pd+3) ^=*(ps+3); }while(0)
  1980. +#define XOREQ32BY4(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
  1981. + *pd ^= *ps; \
  1982. + *(pd+1) ^=*(ps+1); \
  1983. + *(pd+2) ^=*(ps+2); \
  1984. + *(pd+3) ^=*(ps+3); \
  1985. + *(pd+4) ^=*(ps+4); \
  1986. + *(pd+5) ^=*(ps+5); \
  1987. + *(pd+6) ^=*(ps+6); \
  1988. + *(pd+7) ^=*(ps+7); }while(0)
  1989. +#define XOREQ32BV(d,s) do{ unsigned char *pd=(unsigned char *)(d), *ps=(unsigned char *)(s); \
  1990. + int z; \
  1991. + for(z=0;z<32;z++){ \
  1992. + pd[z]^=ps[z]; \
  1993. + } \
  1994. + }while(0)
  1995. +
  1996. +#else
  1997. +#define XOR_4_BY(d,s1,s2) do{ int *pd=(int *)(d), *ps1=(int *)(s1), *ps2=(int *)(s2); \
  1998. + *pd = *ps1 ^ *ps2; }while(0)
  1999. +#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); \
  2000. + *pd = *ps1 ^ *ps2; }while(0)
  2001. +#define XOREQ_4_BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
  2002. + *pd ^= *ps; }while(0)
  2003. +#define XOREQ_8_BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
  2004. + *pd ^= *ps; }while(0)
  2005. +#define COPY_4_BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \
  2006. + *pd = *ps; }while(0)
  2007. +#define COPY_8_BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \
  2008. + *pd = *ps; }while(0)
  2009. +
  2010. +#define BEST_SPAN 8
  2011. +#define XOR_BEST_BY(d,s1,s2) do{ XOR_8_BY(d,s1,s2); }while(0);
  2012. +#define XOREQ_BEST_BY(d,s) do{ XOREQ_8_BY(d,s); }while(0);
  2013. +#define COPY_BEST_BY(d,s) do{ COPY_8_BY(d,s); }while(0);
  2014. +
  2015. +#define END_MM do{ }while(0);
  2016. +#endif
  2017. Index: ffdecsa/parallel_std_def.h
  2018. ===================================================================
  2019. --- ffdecsa/parallel_std_def.h (revision 0)
  2020. +++ ffdecsa/parallel_std_def.h (working copy)
  2021. @@ -0,0 +1,29 @@
  2022. +/* FFdecsa -- fast decsa algorithm
  2023. + *
  2024. + * Copyright (C) 2003-2004 fatih89r
  2025. + *
  2026. + * This program is free software; you can redistribute it and/or modify
  2027. + * it under the terms of the GNU General Public License as published by
  2028. + * the Free Software Foundation; either version 2 of the License, or
  2029. + * (at your option) any later version.
  2030. + *
  2031. + * This program is distributed in the hope that it will be useful,
  2032. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2033. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2034. + * GNU General Public License for more details.
  2035. + *
  2036. + * You should have received a copy of the GNU General Public License
  2037. + * along with this program; if not, write to the Free Software
  2038. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2039. + */
  2040. +
  2041. +#define FFXOR(a,b) ((a)^(b))
  2042. +#define FFAND(a,b) ((a)&(b))
  2043. +#define FFOR(a,b) ((a)|(b))
  2044. +#define FFNOT(a) (~(a))
  2045. +
  2046. +#define B_FFAND(a,b) ((a)&(b))
  2047. +#define B_FFOR(a,b) ((a)|(b))
  2048. +#define B_FFXOR(a,b) ((a)^(b))
  2049. +#define B_FFSH8L(a,n) ((a)<<(n))
  2050. +#define B_FFSH8R(a,n) ((a)>>(n))
  2051. Index: ffdecsa/stream.c
  2052. ===================================================================
  2053. --- ffdecsa/stream.c (revision 0)
  2054. +++ ffdecsa/stream.c (working copy)
  2055. @@ -0,0 +1,906 @@
  2056. +/* FFdecsa -- fast decsa algorithm
  2057. + *
  2058. + * Copyright (C) 2003-2004 fatih89r
  2059. + *
  2060. + * This program is free software; you can redistribute it and/or modify
  2061. + * it under the terms of the GNU General Public License as published by
  2062. + * the Free Software Foundation; either version 2 of the License, or
  2063. + * (at your option) any later version.
  2064. + *
  2065. + * This program is distributed in the hope that it will be useful,
  2066. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2067. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2068. + * GNU General Public License for more details.
  2069. + *
  2070. + * You should have received a copy of the GNU General Public License
  2071. + * along with this program; if not, write to the Free Software
  2072. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2073. + */
  2074. +
  2075. +
  2076. +
  2077. +// define statics only once, when STREAM_INIT
  2078. +#ifdef STREAM_INIT
  2079. +struct stream_regs {
  2080. + group A[32+10][4]; // 32 because we will move back (virtual shift register)
  2081. + group B[32+10][4]; // 32 because we will move back (virtual shift register)
  2082. + group X[4];
  2083. + group Y[4];
  2084. + group Z[4];
  2085. + group D[4];
  2086. + group E[4];
  2087. + group F[4];
  2088. + group p;
  2089. + group q;
  2090. + group r;
  2091. + };
  2092. +
  2093. +static inline void trasp64_32_88ccw(unsigned char *data){
  2094. +/* 64 rows of 32 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
  2095. +#define row ((unsigned int *)data)
  2096. + int i,j;
  2097. + for(j=0;j<64;j+=32){
  2098. + unsigned int t,b;
  2099. + for(i=0;i<16;i++){
  2100. + t=row[j+i];
  2101. + b=row[j+16+i];
  2102. + row[j+i] = (t&0x0000ffff) | ((b )<<16);
  2103. + row[j+16+i]=((t )>>16) | (b&0xffff0000) ;
  2104. + }
  2105. + }
  2106. + for(j=0;j<64;j+=16){
  2107. + unsigned int t,b;
  2108. + for(i=0;i<8;i++){
  2109. + t=row[j+i];
  2110. + b=row[j+8+i];
  2111. + row[j+i] = (t&0x00ff00ff) | ((b&0x00ff00ff)<<8);
  2112. + row[j+8+i] =((t&0xff00ff00)>>8) | (b&0xff00ff00);
  2113. + }
  2114. + }
  2115. + for(j=0;j<64;j+=8){
  2116. + unsigned int t,b;
  2117. + for(i=0;i<4;i++){
  2118. + t=row[j+i];
  2119. + b=row[j+4+i];
  2120. + row[j+i] =((t&0x0f0f0f0f)<<4) | (b&0x0f0f0f0f);
  2121. + row[j+4+i] = (t&0xf0f0f0f0) | ((b&0xf0f0f0f0)>>4);
  2122. + }
  2123. + }
  2124. + for(j=0;j<64;j+=4){
  2125. + unsigned int t,b;
  2126. + for(i=0;i<2;i++){
  2127. + t=row[j+i];
  2128. + b=row[j+2+i];
  2129. + row[j+i] =((t&0x33333333)<<2) | (b&0x33333333);
  2130. + row[j+2+i] = (t&0xcccccccc) | ((b&0xcccccccc)>>2);
  2131. + }
  2132. + }
  2133. + for(j=0;j<64;j+=2){
  2134. + unsigned int t,b;
  2135. + for(i=0;i<1;i++){
  2136. + t=row[j+i];
  2137. + b=row[j+1+i];
  2138. + row[j+i] =((t&0x55555555)<<1) | (b&0x55555555);
  2139. + row[j+1+i] = (t&0xaaaaaaaa) | ((b&0xaaaaaaaa)>>1);
  2140. + }
  2141. + }
  2142. +#undef row
  2143. +}
  2144. +
  2145. +static inline void trasp64_32_88cw(unsigned char *data){
  2146. +/* 64 rows of 32 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
  2147. +#define row ((unsigned int *)data)
  2148. + int i,j;
  2149. + for(j=0;j<64;j+=32){
  2150. + unsigned int t,b;
  2151. + for(i=0;i<16;i++){
  2152. + t=row[j+i];
  2153. + b=row[j+16+i];
  2154. + row[j+i] = (t&0x0000ffff) | ((b )<<16);
  2155. + row[j+16+i]=((t )>>16) | (b&0xffff0000) ;
  2156. + }
  2157. + }
  2158. + for(j=0;j<64;j+=16){
  2159. + unsigned int t,b;
  2160. + for(i=0;i<8;i++){
  2161. + t=row[j+i];
  2162. + b=row[j+8+i];
  2163. + row[j+i] = (t&0x00ff00ff) | ((b&0x00ff00ff)<<8);
  2164. + row[j+8+i] =((t&0xff00ff00)>>8) | (b&0xff00ff00);
  2165. + }
  2166. + }
  2167. + for(j=0;j<64;j+=8){
  2168. + unsigned int t,b;
  2169. + for(i=0;i<4;i++){
  2170. + t=row[j+i];
  2171. + b=row[j+4+i];
  2172. + row[j+i] =((t&0xf0f0f0f0)>>4) | (b&0xf0f0f0f0);
  2173. + row[j+4+i]= (t&0x0f0f0f0f) | ((b&0x0f0f0f0f)<<4);
  2174. + }
  2175. + }
  2176. + for(j=0;j<64;j+=4){
  2177. + unsigned int t,b;
  2178. + for(i=0;i<2;i++){
  2179. + t=row[j+i];
  2180. + b=row[j+2+i];
  2181. + row[j+i] =((t&0xcccccccc)>>2) | (b&0xcccccccc);
  2182. + row[j+2+i]= (t&0x33333333) | ((b&0x33333333)<<2);
  2183. + }
  2184. + }
  2185. + for(j=0;j<64;j+=2){
  2186. + unsigned int t,b;
  2187. + for(i=0;i<1;i++){
  2188. + t=row[j+i];
  2189. + b=row[j+1+i];
  2190. + row[j+i] =((t&0xaaaaaaaa)>>1) | (b&0xaaaaaaaa);
  2191. + row[j+1+i]= (t&0x55555555) | ((b&0x55555555)<<1);
  2192. + }
  2193. + }
  2194. +#undef row
  2195. +}
  2196. +
  2197. +//64-64----------------------------------------------------------
  2198. +static inline void trasp64_64_88ccw(unsigned char *data){
  2199. +/* 64 rows of 64 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
  2200. +#define row ((unsigned long long int *)data)
  2201. + int i,j;
  2202. + for(j=0;j<64;j+=64){
  2203. + unsigned long long int t,b;
  2204. + for(i=0;i<32;i++){
  2205. + t=row[j+i];
  2206. + b=row[j+32+i];
  2207. + row[j+i] = (t&0x00000000ffffffffULL) | ((b )<<32);
  2208. + row[j+32+i]=((t )>>32) | (b&0xffffffff00000000ULL) ;
  2209. + }
  2210. + }
  2211. + for(j=0;j<64;j+=32){
  2212. + unsigned long long int t,b;
  2213. + for(i=0;i<16;i++){
  2214. + t=row[j+i];
  2215. + b=row[j+16+i];
  2216. + row[j+i] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
  2217. + row[j+16+i]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
  2218. + }
  2219. + }
  2220. + for(j=0;j<64;j+=16){
  2221. + unsigned long long int t,b;
  2222. + for(i=0;i<8;i++){
  2223. + t=row[j+i];
  2224. + b=row[j+8+i];
  2225. + row[j+i] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
  2226. + row[j+8+i] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
  2227. + }
  2228. + }
  2229. + for(j=0;j<64;j+=8){
  2230. + unsigned long long int t,b;
  2231. + for(i=0;i<4;i++){
  2232. + t=row[j+i];
  2233. + b=row[j+4+i];
  2234. + row[j+i] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL);
  2235. + row[j+4+i] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
  2236. + }
  2237. + }
  2238. + for(j=0;j<64;j+=4){
  2239. + unsigned long long int t,b;
  2240. + for(i=0;i<2;i++){
  2241. + t=row[j+i];
  2242. + b=row[j+2+i];
  2243. + row[j+i] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL);
  2244. + row[j+2+i] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2);
  2245. + }
  2246. + }
  2247. + for(j=0;j<64;j+=2){
  2248. + unsigned long long int t,b;
  2249. + for(i=0;i<1;i++){
  2250. + t=row[j+i];
  2251. + b=row[j+1+i];
  2252. + row[j+i] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL);
  2253. + row[j+1+i] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
  2254. + }
  2255. + }
  2256. +#undef row
  2257. +}
  2258. +
  2259. +static inline void trasp64_64_88cw(unsigned char *data){
  2260. +/* 64 rows of 64 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
  2261. +#define row ((unsigned long long int *)data)
  2262. + int i,j;
  2263. + for(j=0;j<64;j+=64){
  2264. + unsigned long long int t,b;
  2265. + for(i=0;i<32;i++){
  2266. + t=row[j+i];
  2267. + b=row[j+32+i];
  2268. + row[j+i] = (t&0x00000000ffffffffULL) | ((b )<<32);
  2269. + row[j+32+i]=((t )>>32) | (b&0xffffffff00000000ULL) ;
  2270. + }
  2271. + }
  2272. + for(j=0;j<64;j+=32){
  2273. + unsigned long long int t,b;
  2274. + for(i=0;i<16;i++){
  2275. + t=row[j+i];
  2276. + b=row[j+16+i];
  2277. + row[j+i] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
  2278. + row[j+16+i]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
  2279. + }
  2280. + }
  2281. + for(j=0;j<64;j+=16){
  2282. + unsigned long long int t,b;
  2283. + for(i=0;i<8;i++){
  2284. + t=row[j+i];
  2285. + b=row[j+8+i];
  2286. + row[j+i] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
  2287. + row[j+8+i] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
  2288. + }
  2289. + }
  2290. + for(j=0;j<64;j+=8){
  2291. + unsigned long long int t,b;
  2292. + for(i=0;i<4;i++){
  2293. + t=row[j+i];
  2294. + b=row[j+4+i];
  2295. + row[j+i] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL);
  2296. + row[j+4+i] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
  2297. + }
  2298. + }
  2299. + for(j=0;j<64;j+=4){
  2300. + unsigned long long int t,b;
  2301. + for(i=0;i<2;i++){
  2302. + t=row[j+i];
  2303. + b=row[j+2+i];
  2304. + row[j+i] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL);
  2305. + row[j+2+i] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2);
  2306. + }
  2307. + }
  2308. + for(j=0;j<64;j+=2){
  2309. + unsigned long long int t,b;
  2310. + for(i=0;i<1;i++){
  2311. + t=row[j+i];
  2312. + b=row[j+1+i];
  2313. + row[j+i] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL);
  2314. + row[j+1+i] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1);
  2315. + }
  2316. + }
  2317. +#undef row
  2318. +}
  2319. +
  2320. +//64-128----------------------------------------------------------
  2321. +static inline void trasp64_128_88ccw(unsigned char *data){
  2322. +/* 64 rows of 128 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/
  2323. +#define halfrow ((unsigned long long int *)data)
  2324. + int i,j;
  2325. + for(j=0;j<64;j+=64){
  2326. + unsigned long long int t,b;
  2327. + for(i=0;i<32;i++){
  2328. + t=halfrow[2*(j+i)];
  2329. + b=halfrow[2*(j+32+i)];
  2330. + halfrow[2*(j+i)] = (t&0x00000000ffffffffULL) | ((b )<<32);
  2331. + halfrow[2*(j+32+i)]=((t )>>32) | (b&0xffffffff00000000ULL) ;
  2332. + t=halfrow[2*(j+i)+1];
  2333. + b=halfrow[2*(j+32+i)+1];
  2334. + halfrow[2*(j+i)+1] = (t&0x00000000ffffffffULL) | ((b )<<32);
  2335. + halfrow[2*(j+32+i)+1]=((t )>>32) | (b&0xffffffff00000000ULL) ;
  2336. + }
  2337. + }
  2338. + for(j=0;j<64;j+=32){
  2339. + unsigned long long int t,b;
  2340. + for(i=0;i<16;i++){
  2341. + t=halfrow[2*(j+i)];
  2342. + b=halfrow[2*(j+16+i)];
  2343. + halfrow[2*(j+i)] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
  2344. + halfrow[2*(j+16+i)]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
  2345. + t=halfrow[2*(j+i)+1];
  2346. + b=halfrow[2*(j+16+i)+1];
  2347. + halfrow[2*(j+i)+1] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
  2348. + halfrow[2*(j+16+i)+1]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
  2349. + }
  2350. + }
  2351. + for(j=0;j<64;j+=16){
  2352. + unsigned long long int t,b;
  2353. + for(i=0;i<8;i++){
  2354. + t=halfrow[2*(j+i)];
  2355. + b=halfrow[2*(j+8+i)];
  2356. + halfrow[2*(j+i)] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
  2357. + halfrow[2*(j+8+i)] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
  2358. + t=halfrow[2*(j+i)+1];
  2359. + b=halfrow[2*(j+8+i)+1];
  2360. + halfrow[2*(j+i)+1] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
  2361. + halfrow[2*(j+8+i)+1] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
  2362. + }
  2363. + }
  2364. + for(j=0;j<64;j+=8){
  2365. + unsigned long long int t,b;
  2366. + for(i=0;i<4;i++){
  2367. + t=halfrow[2*(j+i)];
  2368. + b=halfrow[2*(j+4+i)];
  2369. + halfrow[2*(j+i)] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL);
  2370. + halfrow[2*(j+4+i)] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
  2371. + t=halfrow[2*(j+i)+1];
  2372. + b=halfrow[2*(j+4+i)+1];
  2373. + halfrow[2*(j+i)+1] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL);
  2374. + halfrow[2*(j+4+i)+1] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4);
  2375. + }
  2376. + }
  2377. + for(j=0;j<64;j+=4){
  2378. + unsigned long long int t,b;
  2379. + for(i=0;i<2;i++){
  2380. + t=halfrow[2*(j+i)];
  2381. + b=halfrow[2*(j+2+i)];
  2382. + halfrow[2*(j+i)] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL);
  2383. + halfrow[2*(j+2+i)] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2);
  2384. + t=halfrow[2*(j+i)+1];
  2385. + b=halfrow[2*(j+2+i)+1];
  2386. + halfrow[2*(j+i)+1] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL);
  2387. + halfrow[2*(j+2+i)+1] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2);
  2388. + }
  2389. + }
  2390. + for(j=0;j<64;j+=2){
  2391. + unsigned long long int t,b;
  2392. + for(i=0;i<1;i++){
  2393. + t=halfrow[2*(j+i)];
  2394. + b=halfrow[2*(j+1+i)];
  2395. + halfrow[2*(j+i)] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL);
  2396. + halfrow[2*(j+1+i)] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
  2397. + t=halfrow[2*(j+i)+1];
  2398. + b=halfrow[2*(j+1+i)+1];
  2399. + halfrow[2*(j+i)+1] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL);
  2400. + halfrow[2*(j+1+i)+1] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1);
  2401. + }
  2402. + }
  2403. +#undef halfrow
  2404. +}
  2405. +
  2406. +static inline void trasp64_128_88cw(unsigned char *data){
  2407. +/* 64 rows of 128 bits transposition (bytes transp. - 8x8 rotate clockwise)*/
  2408. +#define halfrow ((unsigned long long int *)data)
  2409. + int i,j;
  2410. + for(j=0;j<64;j+=64){
  2411. + unsigned long long int t,b;
  2412. + for(i=0;i<32;i++){
  2413. + t=halfrow[2*(j+i)];
  2414. + b=halfrow[2*(j+32+i)];
  2415. + halfrow[2*(j+i)] = (t&0x00000000ffffffffULL) | ((b )<<32);
  2416. + halfrow[2*(j+32+i)]=((t )>>32) | (b&0xffffffff00000000ULL) ;
  2417. + t=halfrow[2*(j+i)+1];
  2418. + b=halfrow[2*(j+32+i)+1];
  2419. + halfrow[2*(j+i)+1] = (t&0x00000000ffffffffULL) | ((b )<<32);
  2420. + halfrow[2*(j+32+i)+1]=((t )>>32) | (b&0xffffffff00000000ULL) ;
  2421. + }
  2422. + }
  2423. + for(j=0;j<64;j+=32){
  2424. + unsigned long long int t,b;
  2425. + for(i=0;i<16;i++){
  2426. + t=halfrow[2*(j+i)];
  2427. + b=halfrow[2*(j+16+i)];
  2428. + halfrow[2*(j+i)] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
  2429. + halfrow[2*(j+16+i)]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
  2430. + t=halfrow[2*(j+i)+1];
  2431. + b=halfrow[2*(j+16+i)+1];
  2432. + halfrow[2*(j+i)+1] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16);
  2433. + halfrow[2*(j+16+i)+1]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ;
  2434. + }
  2435. + }
  2436. + for(j=0;j<64;j+=16){
  2437. + unsigned long long int t,b;
  2438. + for(i=0;i<8;i++){
  2439. + t=halfrow[2*(j+i)];
  2440. + b=halfrow[2*(j+8+i)];
  2441. + halfrow[2*(j+i)] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
  2442. + halfrow[2*(j+8+i)] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
  2443. + t=halfrow[2*(j+i)+1];
  2444. + b=halfrow[2*(j+8+i)+1];
  2445. + halfrow[2*(j+i)+1] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8);
  2446. + halfrow[2*(j+8+i)+1] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL);
  2447. + }
  2448. + }
  2449. + for(j=0;j<64;j+=8){
  2450. + unsigned long long int t,b;
  2451. + for(i=0;i<4;i++){
  2452. + t=halfrow[2*(j+i)];
  2453. + b=halfrow[2*(j+4+i)];
  2454. + halfrow[2*(j+i)] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL);
  2455. + halfrow[2*(j+4+i)] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
  2456. + t=halfrow[2*(j+i)+1];
  2457. + b=halfrow[2*(j+4+i)+1];
  2458. + halfrow[2*(j+i)+1] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL);
  2459. + halfrow[2*(j+4+i)+1] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4);
  2460. + }
  2461. + }
  2462. + for(j=0;j<64;j+=4){
  2463. + unsigned long long int t,b;
  2464. + for(i=0;i<2;i++){
  2465. + t=halfrow[2*(j+i)];
  2466. + b=halfrow[2*(j+2+i)];
  2467. + halfrow[2*(j+i)] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL);
  2468. + halfrow[2*(j+2+i)] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2);
  2469. + t=halfrow[2*(j+i)+1];
  2470. + b=halfrow[2*(j+2+i)+1];
  2471. + halfrow[2*(j+i)+1] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL);
  2472. + halfrow[2*(j+2+i)+1] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2);
  2473. + }
  2474. + }
  2475. + for(j=0;j<64;j+=2){
  2476. + unsigned long long int t,b;
  2477. + for(i=0;i<1;i++){
  2478. + t=halfrow[2*(j+i)];
  2479. + b=halfrow[2*(j+1+i)];
  2480. + halfrow[2*(j+i)] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL);
  2481. + halfrow[2*(j+1+i)] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1);
  2482. + t=halfrow[2*(j+i)+1];
  2483. + b=halfrow[2*(j+1+i)+1];
  2484. + halfrow[2*(j+i)+1] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL);
  2485. + halfrow[2*(j+1+i)+1] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1);
  2486. + }
  2487. + }
  2488. +#undef halfrow
  2489. +}
  2490. +#endif
  2491. +
  2492. +
  2493. +#ifdef STREAM_INIT
  2494. +void stream_cypher_group_init(
  2495. + struct stream_regs *regs,
  2496. + group iA[8][4], // [In] iA00,iA01,...iA73 32 groups | Derived from key.
  2497. + group iB[8][4], // [In] iB00,iB01,...iB73 32 groups | Derived from key.
  2498. + unsigned char *sb) // [In] (SB0,SB1,...SB7)...x32 32*8 bytes | Extra input.
  2499. +#endif
  2500. +#ifdef STREAM_NORMAL
  2501. +void stream_cypher_group_normal(
  2502. + struct stream_regs *regs,
  2503. + unsigned char *cb) // [Out] (CB0,CB1,...CB7)...x32 32*8 bytes | Output.
  2504. +#endif
  2505. +{
  2506. +#ifdef STREAM_INIT
  2507. + group in1[4];
  2508. + group in2[4];
  2509. +#endif
  2510. + group extra_B[4];
  2511. + group fa,fb,fc,fd,fe;
  2512. + group s1a,s1b,s2a,s2b,s3a,s3b,s4a,s4b,s5a,s5b,s6a,s6b,s7a,s7b;
  2513. + group next_E[4];
  2514. + group tmp0,tmp1,tmp2,tmp3,tmp4;
  2515. +#ifdef STREAM_INIT
  2516. + group *sb_g=(group *)sb;
  2517. +#endif
  2518. +#ifdef STREAM_NORMAL
  2519. + group *cb_g=(group *)cb;
  2520. +#endif
  2521. + int aboff;
  2522. + int i,j,k,b;
  2523. + int dbg;
  2524. +
  2525. +#ifdef STREAM_INIT
  2526. + DBG(fprintf(stderr,":::::::::: BEGIN STREAM INIT\n"));
  2527. +#endif
  2528. +#ifdef STREAM_NORMAL
  2529. + DBG(fprintf(stderr,":::::::::: BEGIN STREAM NORMAL\n"));
  2530. +#endif
  2531. +#ifdef STREAM_INIT
  2532. +for(j=0;j<64;j++){
  2533. + DBG(fprintf(stderr,"precall prerot stream_in[%2i]=",j));
  2534. + DBG(dump_mem("",sb+BYPG*j,BYPG,BYPG));
  2535. +}
  2536. +
  2537. +DBG(dump_mem("stream_prerot ",sb,GROUP_PARALLELISM*8,BYPG));
  2538. +#if GROUP_PARALLELISM==32
  2539. +trasp64_32_88ccw(sb);
  2540. +#endif
  2541. +#if GROUP_PARALLELISM==64
  2542. +trasp64_64_88ccw(sb);
  2543. +#endif
  2544. +#if GROUP_PARALLELISM==128
  2545. +trasp64_128_88ccw(sb);
  2546. +#endif
  2547. +DBG(dump_mem("stream_postrot",sb,GROUP_PARALLELISM*8,BYPG));
  2548. +
  2549. +for(j=0;j<64;j++){
  2550. + DBG(fprintf(stderr,"precall stream_in[%2i]=",j));
  2551. + DBG(dump_mem("",sb+BYPG*j,BYPG,BYPG));
  2552. +}
  2553. +#endif
  2554. +
  2555. + aboff=32;
  2556. +
  2557. +#ifdef STREAM_INIT
  2558. + // load first 32 bits of ck into A[aboff+0]..A[aboff+7]
  2559. + // load last 32 bits of ck into B[aboff+0]..B[aboff+7]
  2560. + // all other regs = 0
  2561. + for(i=0;i<8;i++){
  2562. + for(b=0;b<4;b++){
  2563. +DBG(fprintf(stderr,"dbg from iA A[%i][%i]=",i,b));
  2564. +DBG(dump_mem("",(unsigned char *)&iA[i][b],BYPG,BYPG));
  2565. +DBG(fprintf(stderr," dbg from iB B[%i][%i]=",i,b));
  2566. +DBG(dump_mem("",(unsigned char *)&iB[i][b],BYPG,BYPG));
  2567. + regs->A[aboff+i][b]=iA[i][b];
  2568. + regs->B[aboff+i][b]=iB[i][b];
  2569. + }
  2570. + }
  2571. + for(b=0;b<4;b++){
  2572. + regs->A[aboff+8][b]=FF0();
  2573. + regs->A[aboff+9][b]=FF0();
  2574. + regs->B[aboff+8][b]=FF0();
  2575. + regs->B[aboff+9][b]=FF0();
  2576. + }
  2577. + for(b=0;b<4;b++){
  2578. + regs->X[b]=FF0();
  2579. + regs->Y[b]=FF0();
  2580. + regs->Z[b]=FF0();
  2581. + regs->D[b]=FF0();
  2582. + regs->E[b]=FF0();
  2583. + regs->F[b]=FF0();
  2584. + }
  2585. + regs->p=FF0();
  2586. + regs->q=FF0();
  2587. + regs->r=FF0();
  2588. +#endif
  2589. +
  2590. +for(dbg=0;dbg<4;dbg++){
  2591. + DBG(fprintf(stderr,"dbg A0[%i]=",dbg));
  2592. + DBG(dump_mem("",(unsigned char *)&regs->A[aboff+0][dbg],BYPG,BYPG));
  2593. + DBG(fprintf(stderr,"dbg B0[%i]=",dbg));
  2594. + DBG(dump_mem("",(unsigned char *)&regs->B[aboff+0][dbg],BYPG,BYPG));
  2595. +}
  2596. +
  2597. +////////////////////////////////////////////////////////////////////////////////
  2598. +
  2599. + // EXTERNAL LOOP - 8 bytes per operation
  2600. + for(i=0;i<8;i++){
  2601. +
  2602. + DBG(fprintf(stderr,"--BEGIN EXTERNAL LOOP %i\n",i));
  2603. +
  2604. +#ifdef STREAM_INIT
  2605. + for(b=0;b<4;b++){
  2606. + in1[b]=sb_g[8*i+4+b];
  2607. + in2[b]=sb_g[8*i+b];
  2608. + }
  2609. +#endif
  2610. +
  2611. + // INTERNAL LOOP - 2 bits per iteration
  2612. + for(j=0; j<4; j++){
  2613. +
  2614. + DBG(fprintf(stderr,"---BEGIN INTERNAL LOOP %i (EXT %i, INT %i)\n",j,i,j));
  2615. +
  2616. + // from A0..A9, 35 bits are selected as inputs to 7 s-boxes
  2617. + // 5 bits input per s-box, 2 bits output per s-box
  2618. +
  2619. + // we can select bits with zero masking and shifting operations
  2620. + // and synthetize s-boxes with optimized boolean functions.
  2621. + // this is the actual reason we do all the crazy transposition
  2622. + // stuff to switch between normal and bit slice representations.
  2623. + // this code really flies.
  2624. +
  2625. + 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];
  2626. +/* 1000 1110 1110 0001 : lev 7: */ //tmp0=( fa^( fb^( ( ( ( fa|fb )^fc )|( fc^fd ) )^ALL_ONES ) ) );
  2627. +/* 1110 0010 0011 0011 : lev 6: */ //tmp1=( ( fa|fb )^( ( fc&( fa|( fb^fd ) ) )^ALL_ONES ) );
  2628. +/* 0011 0110 1000 1101 : lev 5: */ //tmp2=( fa^( ( fb&fd )^( ( fa&fd )|fc ) ) );
  2629. +/* 0101 0101 1001 0011 : lev 5: */ //tmp3=( ( fa&fc )^( fa^( ( fa&fb )|fd ) ) );
  2630. +/* 1000 1110 1110 0001 : lev 7: */ tmp0=FFXOR(fa,FFXOR(fb,FFXOR(FFOR(FFXOR(FFOR(fa,fb),fc),FFXOR(fc,fd)),FF1())));
  2631. +/* 1110 0010 0011 0011 : lev 6: */ tmp1=FFXOR(FFOR(fa,fb),FFXOR(FFAND(fc,FFOR(fa,FFXOR(fb,fd))),FF1()));
  2632. +/* 0011 0110 1000 1101 : lev 5: */ tmp2=FFXOR(fa,FFXOR(FFAND(fb,fd),FFOR(FFAND(fa,fd),fc)));
  2633. +/* 0101 0101 1001 0011 : lev 5: */ tmp3=FFXOR(FFAND(fa,fc),FFXOR(fa,FFOR(FFAND(fa,fb),fd)));
  2634. + s1a=FFXOR(tmp0,FFAND(fe,tmp1));
  2635. + s1b=FFXOR(tmp2,FFAND(fe,tmp3));
  2636. +//dump_mem("s1as1b-fe",&fe,BYPG,BYPG);
  2637. +//dump_mem("s1as1b-fa",&fa,BYPG,BYPG);
  2638. +//dump_mem("s1as1b-fb",&fb,BYPG,BYPG);
  2639. +//dump_mem("s1as1b-fc",&fc,BYPG,BYPG);
  2640. +//dump_mem("s1as1b-fd",&fd,BYPG,BYPG);
  2641. +
  2642. + 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];
  2643. +/* 1001 1110 0110 0001 : lev 6: */ //tmp0=( fa^( ( fb&( fc|fd ) )^( fc^( fd^ALL_ONES ) ) ) );
  2644. +/* 0000 0011 0111 1011 : lev 5: */ //tmp1=( ( fa&( fb^fd ) )|( ( fa|fb )&fc ) );
  2645. +/* 1100 0110 1101 0010 : lev 6: */ //tmp2=( ( fb&fd )^( ( fa&fd )|( fb^( fc^ALL_ONES ) ) ) );
  2646. +/* 0001 1110 1111 0101 : lev 5: */ //tmp3=( ( fa&fd )|( fa^( fb^( fc&fd ) ) ) );
  2647. +/* 1001 1110 0110 0001 : lev 6: */ tmp0=FFXOR(fa,FFXOR(FFAND(fb,FFOR(fc,fd)),FFXOR(fc,FFXOR(fd,FF1()))));
  2648. +/* 0000 0011 0111 1011 : lev 5: */ tmp1=FFOR(FFAND(fa,FFXOR(fb,fd)),FFAND(FFOR(fa,fb),fc));
  2649. +/* 1100 0110 1101 0010 : lev 6: */ tmp2=FFXOR(FFAND(fb,fd),FFOR(FFAND(fa,fd),FFXOR(fb,FFXOR(fc,FF1()))));
  2650. +/* 0001 1110 1111 0101 : lev 5: */ tmp3=FFOR(FFAND(fa,fd),FFXOR(fa,FFXOR(fb,FFAND(fc,fd))));
  2651. + s2a=FFXOR(tmp0,FFAND(fe,tmp1));
  2652. + s2b=FFXOR(tmp2,FFAND(fe,tmp3));
  2653. +
  2654. + 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];
  2655. +/* 0100 1011 1001 0110 : lev 5: */ //tmp0=( fa^( fb^( ( fc&( fa|fd ) )^fd ) ) );
  2656. +/* 1101 0101 1000 1100 : lev 7: */ //tmp1=( ( fa&fc )^( ( fa^fd )|( ( fb|fc )^( fd^ALL_ONES ) ) ) );
  2657. +/* 0010 0111 1101 1000 : lev 4: */ //tmp2=( fa^( ( ( fb^fc )&fd )^fc ) );
  2658. +/* 1111 1111 1111 1111 : lev 0: */ //tmp3=ALL_ONES;
  2659. +/* 0100 1011 1001 0110 : lev 5: */ tmp0=FFXOR(fa,FFXOR(fb,FFXOR(FFAND(fc,FFOR(fa,fd)),fd)));
  2660. +/* 1101 0101 1000 1100 : lev 7: */ tmp1=FFXOR(FFAND(fa,fc),FFOR(FFXOR(fa,fd),FFXOR(FFOR(fb,fc),FFXOR(fd,FF1()))));
  2661. +/* 0010 0111 1101 1000 : lev 4: */ tmp2=FFXOR(fa,FFXOR(FFAND(FFXOR(fb,fc),fd),fc));
  2662. +/* 1111 1111 1111 1111 : lev 0: */ tmp3=FF1();
  2663. + s3a=FFXOR(tmp0,FFAND(FFNOT(fe),tmp1));
  2664. + s3b=FFXOR(tmp2,FFAND(fe,tmp3));
  2665. +
  2666. + 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];
  2667. +/* 1011 0101 0100 1001 : lev 7: */ //tmp0=( fa^( ( fc&( fa^fd ) )|( fb^( fc|( fd^ALL_ONES ) ) ) ) );
  2668. +/* 0010 1101 0110 0110 : lev 6: */ //tmp1=( ( fa&fb )^( fb^( ( ( fa|fc )&fd )^fc ) ) );
  2669. +/* 0110 0111 1101 0000 : lev 7: */ //tmp2=( fa^( ( fb&fc )|( ( ( fa&( fb^fd ) )|fc )^fd ) ) );
  2670. +/* 1111 1111 1111 1111 : lev 0: */ //tmp3=ALL_ONES;
  2671. +/* 1011 0101 0100 1001 : lev 7: */ tmp0=FFXOR(fa,FFOR(FFAND(fc,FFXOR(fa,fd)),FFXOR(fb,FFOR(fc,FFXOR(fd,FF1())))));
  2672. +/* 0010 1101 0110 0110 : lev 6: */ tmp1=FFXOR(FFAND(fa,fb),FFXOR(fb,FFXOR(FFAND(FFOR(fa,fc),fd),fc)));
  2673. +/* 0110 0111 1101 0000 : lev 7: */ tmp2=FFXOR(fa,FFOR(FFAND(fb,fc),FFXOR(FFOR(FFAND(fa,FFXOR(fb,fd)),fc),fd)));
  2674. +/* 1111 1111 1111 1111 : lev 0: */ tmp3=FF1();
  2675. + s4a=FFXOR(tmp0,FFAND(fe,FFXOR(tmp1,tmp0)));
  2676. + s4b=FFXOR(FFXOR(s4a,tmp2),FFAND(fe,tmp3));
  2677. +
  2678. + 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];
  2679. +/* 1000 1111 0011 0010 : lev 7: */ //tmp0=( ( ( fa&( fb|fc ) )^fb )|( ( ( fa^fc )|fd )^ALL_ONES ) );
  2680. +/* 0110 1011 0000 1011 : lev 6: */ //tmp1=( fb^( ( fc^fd )&( fc^( fb|( fa^fd ) ) ) ) );
  2681. +/* 0001 1010 0111 1001 : lev 6: */ //tmp2=( ( fa&fc )^( fb^( ( fb|( fa^fc ) )&fd ) ) );
  2682. +/* 0101 1101 1101 0101 : lev 4: */ //tmp3=( ( ( fa^fb )&( fc^ALL_ONES ) )|fd );
  2683. +/* 1000 1111 0011 0010 : lev 7: */ tmp0=FFOR(FFXOR(FFAND(fa,FFOR(fb,fc)),fb),FFXOR(FFOR(FFXOR(fa,fc),fd),FF1()));
  2684. +/* 0110 1011 0000 1011 : lev 6: */ tmp1=FFXOR(fb,FFAND(FFXOR(fc,fd),FFXOR(fc,FFOR(fb,FFXOR(fa,fd)))));
  2685. +/* 0001 1010 0111 1001 : lev 6: */ tmp2=FFXOR(FFAND(fa,fc),FFXOR(fb,FFAND(FFOR(fb,FFXOR(fa,fc)),fd)));
  2686. +/* 0101 1101 1101 0101 : lev 4: */ tmp3=FFOR(FFAND(FFXOR(fa,fb),FFXOR(fc,FF1())),fd);
  2687. + s5a=FFXOR(tmp0,FFAND(fe,tmp1));
  2688. + s5b=FFXOR(tmp2,FFAND(fe,tmp3));
  2689. +
  2690. + 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];
  2691. +/* 0011 0110 0010 1101 : lev 6: */ //tmp0=( ( ( fa&fc )&fd )^( ( fb&( fa|fd ) )^fc ) );
  2692. +/* 1110 1110 1011 1011 : lev 3: */ //tmp1=( ( ( fa^fc )&fd )^ALL_ONES );
  2693. +/* 0101 1000 0110 0111 : lev 6: */ //tmp2=( ( fa&( fb|fc ) )^( fb^( ( fb&fc )|fd ) ) );
  2694. +/* 0001 0011 0000 0001 : lev 5: */ //tmp3=( fc&( ( fa&( fb^fd ) )^( fb|fd ) ) );
  2695. +/* 0011 0110 0010 1101 : lev 6: */ tmp0=FFXOR(FFAND(FFAND(fa,fc),fd),FFXOR(FFAND(fb,FFOR(fa,fd)),fc));
  2696. +/* 1110 1110 1011 1011 : lev 3: */ tmp1=FFXOR(FFAND(FFXOR(fa,fc),fd),FF1());
  2697. +/* 0101 1000 0110 0111 : lev 6: */ tmp2=FFXOR(FFAND(fa,FFOR(fb,fc)),FFXOR(fb,FFOR(FFAND(fb,fc),fd)));
  2698. +/* 0001 0011 0000 0001 : lev 5: */ tmp3=FFAND(fc,FFXOR(FFAND(fa,FFXOR(fb,fd)),FFOR(fb,fd)));
  2699. + s6a=FFXOR(tmp0,FFAND(fe,tmp1));
  2700. + s6b=FFXOR(tmp2,FFAND(fe,tmp3));
  2701. +
  2702. + 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];
  2703. +/* 0111 1000 1001 0110 : lev 5: */ //tmp0=( fb^( ( fc&fd )|( fa^( fc^fd ) ) ) );
  2704. +/* 0100 1001 0101 1011 : lev 6: */ //tmp1=( ( fb|fd )&( ( fa&fc )|( fb^( fc^fd ) ) ) );
  2705. +/* 0100 1001 1011 1001 : lev 5: */ //tmp2=( ( fa|fb )^( ( fc&( fb|fd ) )^fd ) );
  2706. +/* 1111 1111 1101 1101 : lev 3: */ //tmp3=( fd|( ( fa&fc )^ALL_ONES ) );
  2707. +/* 0111 1000 1001 0110 : lev 5: */ tmp0=FFXOR(fb,FFOR(FFAND(fc,fd),FFXOR(fa,FFXOR(fc,fd))));
  2708. +/* 0100 1001 0101 1011 : lev 6: */ tmp1=FFAND(FFOR(fb,fd),FFOR(FFAND(fa,fc),FFXOR(fb,FFXOR(fc,fd))));
  2709. +/* 0100 1001 1011 1001 : lev 5: */ tmp2=FFXOR(FFOR(fa,fb),FFXOR(FFAND(fc,FFOR(fb,fd)),fd));
  2710. +/* 1111 1111 1101 1101 : lev 3: */ tmp3=FFOR(fd,FFXOR(FFAND(fa,fc),FF1()));
  2711. + s7a=FFXOR(tmp0,FFAND(fe,tmp1));
  2712. + s7b=FFXOR(tmp2,FFAND(fe,tmp3));
  2713. +
  2714. +
  2715. +/*
  2716. + we have just done this:
  2717. +
  2718. + 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};
  2719. + 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};
  2720. + 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};
  2721. + 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};
  2722. + 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};
  2723. + 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};
  2724. + 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};
  2725. +
  2726. + s12 = sbox1[ (((A3>>0)&1)<<4) | (((A0>>2)&1)<<3) | (((A5>>1)&1)<<2) | (((A6>>3)&1)<<1) | (((A8>>0)&1)<<0) ]
  2727. + |sbox2[ (((A1>>1)&1)<<4) | (((A2>>2)&1)<<3) | (((A5>>3)&1)<<2) | (((A6>>0)&1)<<1) | (((A8>>1)&1)<<0) ];
  2728. + s34 = sbox3[ (((A0>>3)&1)<<4) | (((A1>>0)&1)<<3) | (((A4>>1)&1)<<2) | (((A4>>3)&1)<<1) | (((A5>>2)&1)<<0) ]
  2729. + |sbox4[ (((A2>>3)&1)<<4) | (((A0>>1)&1)<<3) | (((A1>>3)&1)<<2) | (((A3>>2)&1)<<1) | (((A7>>0)&1)<<0) ];
  2730. + s56 = sbox5[ (((A4>>2)&1)<<4) | (((A3>>3)&1)<<3) | (((A5>>0)&1)<<2) | (((A7>>1)&1)<<1) | (((A8>>2)&1)<<0) ]
  2731. + |sbox6[ (((A2>>1)&1)<<4) | (((A3>>1)&1)<<3) | (((A4>>0)&1)<<2) | (((A6>>2)&1)<<1) | (((A8>>3)&1)<<0) ];
  2732. + s7 = sbox7[ (((A1>>2)&1)<<4) | (((A2>>0)&1)<<3) | (((A6>>1)&1)<<2) | (((A7>>2)&1)<<1) | (((A7>>3)&1)<<0) ];
  2733. +*/
  2734. +
  2735. + // use 4x4 xor to produce extra nibble for T3
  2736. +
  2737. + 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]);
  2738. + 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]);
  2739. + 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]);
  2740. + 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]);
  2741. +for(dbg=0;dbg<4;dbg++){
  2742. + DBG(fprintf(stderr,"extra_B[%i]=",dbg));
  2743. + DBG(dump_mem("",(unsigned char *)&extra_B[dbg],BYPG,BYPG));
  2744. +}
  2745. +
  2746. + // T1 = xor all inputs
  2747. + // in1, in2, D are only used in T1 during initialisation, not generation
  2748. + for(b=0;b<4;b++){
  2749. + regs->A[aboff-1][b]=FFXOR(regs->A[aboff+9][b],regs->X[b]);
  2750. + }
  2751. +
  2752. +#ifdef STREAM_INIT
  2753. + for(b=0;b<4;b++){
  2754. + regs->A[aboff-1][b]=FFXOR(FFXOR(regs->A[aboff-1][b],regs->D[b]),((j % 2) ? in2[b] : in1[b]));
  2755. + }
  2756. +#endif
  2757. +
  2758. +for(dbg=0;dbg<4;dbg++){
  2759. + DBG(fprintf(stderr,"next_A0[%i]=",dbg));
  2760. + DBG(dump_mem("",(unsigned char *)&regs->A[aboff-1][dbg],BYPG,BYPG));
  2761. +}
  2762. +
  2763. + // T2 = xor all inputs
  2764. + // in1, in2 are only used in T1 during initialisation, not generation
  2765. + // if p=0, use this, if p=1, rotate the result left
  2766. + for(b=0;b<4;b++){
  2767. + regs->B[aboff-1][b]=FFXOR(FFXOR(regs->B[aboff+6][b],regs->B[aboff+9][b]),regs->Y[b]);
  2768. + }
  2769. +
  2770. +#ifdef STREAM_INIT
  2771. + for(b=0;b<4;b++){
  2772. + regs->B[aboff-1][b]=FFXOR(regs->B[aboff-1][b],((j % 2) ? in1[b] : in2[b]));
  2773. + }
  2774. +#endif
  2775. +
  2776. +for(dbg=0;dbg<4;dbg++){
  2777. + DBG(fprintf(stderr,"next_B0[%i]=",dbg));
  2778. + DBG(dump_mem("",(unsigned char *)&regs->B[aboff-1][dbg],BYPG,BYPG));
  2779. +}
  2780. +
  2781. + // if p=1, rotate left (yes, this is what we're doing)
  2782. + tmp3=regs->B[aboff-1][3];
  2783. + 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));
  2784. + 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));
  2785. + 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));
  2786. + regs->B[aboff-1][0]=FFXOR(regs->B[aboff-1][0],FFAND(FFXOR(regs->B[aboff-1][0],tmp3),regs->p));
  2787. +
  2788. +for(dbg=0;dbg<4;dbg++){
  2789. + DBG(fprintf(stderr,"next_B0[%i]=",dbg));
  2790. + DBG(dump_mem("",(unsigned char *)&regs->B[aboff-1][dbg],BYPG,BYPG));
  2791. +}
  2792. +
  2793. + // T3 = xor all inputs
  2794. + for(b=0;b<4;b++){
  2795. + regs->D[b]=FFXOR(FFXOR(regs->E[b],regs->Z[b]),extra_B[b]);
  2796. + }
  2797. +
  2798. +for(dbg=0;dbg<4;dbg++){
  2799. + DBG(fprintf(stderr,"D[%i]=",dbg));
  2800. + DBG(dump_mem("",(unsigned char *)&regs->D[dbg],BYPG,BYPG));
  2801. +}
  2802. +
  2803. + // T4 = sum, carry of Z + E + r
  2804. + for(b=0;b<4;b++){
  2805. + next_E[b]=regs->F[b];
  2806. + }
  2807. +
  2808. + tmp0=FFXOR(regs->Z[0],regs->E[0]);
  2809. + tmp1=FFAND(regs->Z[0],regs->E[0]);
  2810. + regs->F[0]=FFXOR(regs->E[0],FFAND(regs->q,FFXOR(regs->Z[0],regs->r)));
  2811. + tmp3=FFAND(tmp0,regs->r);
  2812. + tmp4=FFOR(tmp1,tmp3);
  2813. +
  2814. + tmp0=FFXOR(regs->Z[1],regs->E[1]);
  2815. + tmp1=FFAND(regs->Z[1],regs->E[1]);
  2816. + regs->F[1]=FFXOR(regs->E[1],FFAND(regs->q,FFXOR(regs->Z[1],tmp4)));
  2817. + tmp3=FFAND(tmp0,tmp4);
  2818. + tmp4=FFOR(tmp1,tmp3);
  2819. +
  2820. + tmp0=FFXOR(regs->Z[2],regs->E[2]);
  2821. + tmp1=FFAND(regs->Z[2],regs->E[2]);
  2822. + regs->F[2]=FFXOR(regs->E[2],FFAND(regs->q,FFXOR(regs->Z[2],tmp4)));
  2823. + tmp3=FFAND(tmp0,tmp4);
  2824. + tmp4=FFOR(tmp1,tmp3);
  2825. +
  2826. + tmp0=FFXOR(regs->Z[3],regs->E[3]);
  2827. + tmp1=FFAND(regs->Z[3],regs->E[3]);
  2828. + regs->F[3]=FFXOR(regs->E[3],FFAND(regs->q,FFXOR(regs->Z[3],tmp4)));
  2829. + tmp3=FFAND(tmp0,tmp4);
  2830. + regs->r=FFXOR(regs->r,FFAND(regs->q,FFXOR(FFOR(tmp1,tmp3),regs->r))); // ultimate carry
  2831. +
  2832. +/*
  2833. + we have just done this: (believe it or not)
  2834. +
  2835. + if (q) {
  2836. + F = Z + E + r;
  2837. + r = (F >> 4) & 1;
  2838. + F = F & 0x0f;
  2839. + }
  2840. + else {
  2841. + F = E;
  2842. + }
  2843. +*/
  2844. + for(b=0;b<4;b++){
  2845. + regs->E[b]=next_E[b];
  2846. + }
  2847. +for(dbg=0;dbg<4;dbg++){
  2848. + DBG(fprintf(stderr,"F[%i]=",dbg));
  2849. + DBG(dump_mem("",(unsigned char *)&regs->F[dbg],BYPG,BYPG));
  2850. +}
  2851. +DBG(fprintf(stderr,"r="));
  2852. +DBG(dump_mem("",(unsigned char *)&regs->r,BYPG,BYPG));
  2853. +for(dbg=0;dbg<4;dbg++){
  2854. + DBG(fprintf(stderr,"E[%i]=",dbg));
  2855. + DBG(dump_mem("",(unsigned char *)&regs->E[dbg],BYPG,BYPG));
  2856. +}
  2857. +
  2858. + // this simple instruction is virtually shifting all the shift registers
  2859. + aboff--;
  2860. +
  2861. +/*
  2862. + we've just done this:
  2863. +
  2864. + A9=A8;A8=A7;A7=A6;A6=A5;A5=A4;A4=A3;A3=A2;A2=A1;A1=A0;A0=next_A0;
  2865. + B9=B8;B8=B7;B7=B6;B6=B5;B5=B4;B4=B3;B3=B2;B2=B1;B1=B0;B0=next_B0;
  2866. +*/
  2867. +
  2868. + regs->X[0]=s1a;
  2869. + regs->X[1]=s2a;
  2870. + regs->X[2]=s3b;
  2871. + regs->X[3]=s4b;
  2872. + regs->Y[0]=s3a;
  2873. + regs->Y[1]=s4a;
  2874. + regs->Y[2]=s5b;
  2875. + regs->Y[3]=s6b;
  2876. + regs->Z[0]=s5a;
  2877. + regs->Z[1]=s6a;
  2878. + regs->Z[2]=s1b;
  2879. + regs->Z[3]=s2b;
  2880. + regs->p=s7a;
  2881. + regs->q=s7b;
  2882. +for(dbg=0;dbg<4;dbg++){
  2883. + DBG(fprintf(stderr,"X[%i]=",dbg));
  2884. + DBG(dump_mem("",(unsigned char *)&regs->X[dbg],BYPG,BYPG));
  2885. +}
  2886. +for(dbg=0;dbg<4;dbg++){
  2887. + DBG(fprintf(stderr,"Y[%i]=",dbg));
  2888. + DBG(dump_mem("",(unsigned char *)&regs->Y[dbg],BYPG,BYPG));
  2889. +}
  2890. +for(dbg=0;dbg<4;dbg++){
  2891. + DBG(fprintf(stderr,"Z[%i]=",dbg));
  2892. + DBG(dump_mem("",(unsigned char *)&regs->Z[dbg],BYPG,BYPG));
  2893. +}
  2894. +DBG(fprintf(stderr,"p="));
  2895. +DBG(dump_mem("",(unsigned char *)&regs->p,BYPG,BYPG));
  2896. +DBG(fprintf(stderr,"q="));
  2897. +DBG(dump_mem("",(unsigned char *)&regs->q,BYPG,BYPG));
  2898. +
  2899. +#ifdef STREAM_NORMAL
  2900. + // require 4 loops per output byte
  2901. + // 2 output bits are a function of the 4 bits of D
  2902. + // xor 2 by 2
  2903. + cb_g[8*i+7-2*j]=FFXOR(regs->D[2],regs->D[3]);
  2904. + cb_g[8*i+6-2*j]=FFXOR(regs->D[0],regs->D[1]);
  2905. +for(dbg=0;dbg<8;dbg++){
  2906. + DBG(fprintf(stderr,"op[%i]=",dbg));
  2907. + DBG(dump_mem("",(unsigned char *)&cb_g[8*i+dbg],BYPG,BYPG));
  2908. +}
  2909. +#endif
  2910. +
  2911. +DBG(fprintf(stderr,"---END INTERNAL LOOP\n"));
  2912. +
  2913. + } // INTERNAL LOOP
  2914. +
  2915. +DBG(fprintf(stderr,"--END EXTERNAL LOOP\n"));
  2916. +
  2917. + } // EXTERNAL LOOP
  2918. +
  2919. + // move 32 steps forward, ready for next call
  2920. + for(k=0;k<10;k++){
  2921. + for(b=0;b<4;b++){
  2922. +DBG(fprintf(stderr,"moving forward AB k=%i b=%i\n",k,b));
  2923. + regs->A[32+k][b]=regs->A[k][b];
  2924. + regs->B[32+k][b]=regs->B[k][b];
  2925. + }
  2926. + }
  2927. +
  2928. +
  2929. +////////////////////////////////////////////////////////////////////////////////
  2930. +
  2931. +#ifdef STREAM_NORMAL
  2932. +for(j=0;j<64;j++){
  2933. + DBG(fprintf(stderr,"postcall prerot cb[%2i]=",j));
  2934. + DBG(dump_mem("",(unsigned char *)(cb+BYPG*j),BYPG,BYPG));
  2935. +}
  2936. +
  2937. +#if GROUP_PARALLELISM==32
  2938. +trasp64_32_88cw(cb);
  2939. +#endif
  2940. +#if GROUP_PARALLELISM==64
  2941. +trasp64_64_88cw(cb);
  2942. +#endif
  2943. +#if GROUP_PARALLELISM==128
  2944. +trasp64_128_88cw(cb);
  2945. +#endif
  2946. +
  2947. +for(j=0;j<64;j++){
  2948. + DBG(fprintf(stderr,"postcall postrot cb[%2i]=",j));
  2949. + DBG(dump_mem("",(unsigned char *)(cb+BYPG*j),BYPG,BYPG));
  2950. +}
  2951. +#endif
  2952. +
  2953. +#ifdef STREAM_INIT
  2954. + DBG(fprintf(stderr,":::::::::: END STREAM INIT\n"));
  2955. +#endif
  2956. +#ifdef STREAM_NORMAL
  2957. + DBG(fprintf(stderr,":::::::::: END STREAM NORMAL\n"));
  2958. +#endif
  2959. +
  2960. +}
  2961. +
  2962. Index: globals.h
  2963. ===================================================================
  2964. --- globals.h (revision 11209)
  2965. +++ globals.h (working copy)
  2966. @@ -387,12 +387,12 @@
  2967. #define CS_ECM_RINGBUFFER_MAX 0x10 // max size for ECM last responsetimes ringbuffer. Keep this set to power of 2 values!
  2968.  
  2969. // Support for multiple CWs per channel and other encryption algos
  2970. -//#define WITH_EXTENDED_CW 1
  2971. +#define WITH_EXTENDED_CW 1
  2972.  
  2973. #define MAX_ECM_SIZE 596
  2974. -#define MAX_EMM_SIZE 512
  2975. +#define MAX_EMM_SIZE 1024
  2976.  
  2977. -#define CS_EMMCACHESIZE 512 //nr of EMMs that each reader will cache
  2978. +#define CS_EMMCACHESIZE 1024 //nr of EMMs that each reader will cache
  2979. #define MSGLOGSIZE 64 //size of string buffer for a ecm to return messages
  2980.  
  2981. #define D_TRACE 0x0001 // Generate very detailed error/trace messages per routine
  2982. @@ -423,6 +423,7 @@
  2983. /////////////////// readers that do not reed baudrate setting and timings are guarded by reader itself (large buffer built in): AFTER R_SMART
  2984. #define R_SMART 0x7 // Smartreader+
  2985. #define R_PCSC 0x8 // PCSC
  2986. +#define R_EMU 0x17 // Reader emu
  2987. /////////////////// proxy readers after R_CS378X
  2988. #define R_CAMD35 0x20 // Reader cascading camd 3.5x
  2989. #define R_CAMD33 0x21 // Reader cascading camd 3.3x
  2990. @@ -847,6 +848,13 @@
  2991. uint32_t class; // the class needed for some systems
  2992. time_t start; // startdate
  2993. time_t end; // enddate
  2994. +#ifdef WITH_EMU
  2995. + bool isKey;
  2996. + bool isData;
  2997. + char name[8];
  2998. + uint8_t *key;
  2999. + uint32_t keyLength;
  3000. +#endif
  3001. } S_ENTITLEMENT;
  3002.  
  3003. struct s_client ;
  3004. @@ -970,6 +978,7 @@
  3005. void (*post_process)(struct s_reader *);
  3006. int32_t (*get_emm_type)(struct emm_packet_t *, struct s_reader *);
  3007. int32_t (*get_emm_filter)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *);
  3008. + int32_t (*get_emm_filter_adv)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *, uint16_t, uint32_t, uint16_t);
  3009. int32_t (*get_tunemm_filter)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *);
  3010. };
  3011.  
  3012. @@ -1674,6 +1683,7 @@
  3013. #ifdef MODULE_GHTTP
  3014. uint8_t ghttp_use_ssl;
  3015. #endif
  3016. + FTAB emu_auproviders;
  3017. uint8_t cnxlastecm; // == 0 - las ecm has not been paired ecm, > 0 last ecm has been paired ecm
  3018. LLIST *emmstat; //emm stats
  3019. CS_MUTEX_LOCK emmstat_lock;
  3020. @@ -2141,6 +2151,18 @@
  3021. IN_ADDR_T scam_srvip;
  3022. struct s_ip *scam_allowed;
  3023. #endif
  3024. +
  3025. +#ifdef WITH_EMU
  3026. + char *emu_stream_source_host;
  3027. + int32_t emu_stream_source_port;
  3028. + char *emu_stream_source_auth_user;
  3029. + char *emu_stream_source_auth_password;
  3030. + int32_t emu_stream_relay_port;
  3031. + uint32_t emu_stream_ecm_delay;
  3032. + int8_t emu_stream_relay_enabled;
  3033. + int8_t emu_stream_emm_enabled;
  3034. +#endif
  3035. +
  3036. int32_t max_cache_time; //seconds ecms are stored in ecmcwcache
  3037. int32_t max_hitcache_time; //seconds hits are stored in cspec_hitcache (to detect dyn wait_time)
  3038.  
  3039. @@ -2313,4 +2335,6 @@
  3040. static inline bool caid_is_dre(uint16_t caid) { return caid == 0x4AE0 || caid == 0x4AE1;}
  3041. const char *get_cardsystem_desc_by_caid(uint16_t caid);
  3042.  
  3043. +FILTER* get_emu_prids_for_caid(struct s_reader *rdr, uint16_t caid);
  3044. +
  3045. #endif
  3046. Index: module-dvbapi.c
  3047. ===================================================================
  3048. --- module-dvbapi.c (revision 11209)
  3049. +++ module-dvbapi.c (working copy)
  3050. @@ -1440,7 +1440,15 @@
  3051. }
  3052. if(match)
  3053. {
  3054. - csystem = get_cardsystem_by_caid(caid);
  3055. + if(rdr->typ == R_EMU)
  3056. + {
  3057. + csystem = rdr->csystem;
  3058. + }
  3059. + else
  3060. + {
  3061. + csystem = get_cardsystem_by_caid(caid);
  3062. + }
  3063. +
  3064. if(csystem)
  3065. {
  3066. if(caid != ncaid)
  3067. @@ -1459,7 +1467,14 @@
  3068. }
  3069. else if (csystem->get_emm_filter)
  3070. {
  3071. - csystem->get_emm_filter(rdr, &dmx_filter, &filter_count);
  3072. + if(rdr->typ == R_EMU)
  3073. + {
  3074. + csystem->get_emm_filter_adv(rdr, &dmx_filter, &filter_count, caid, provid, demux[demux_index].program_number);
  3075. + }
  3076. + else
  3077. + {
  3078. + csystem->get_emm_filter(rdr, &dmx_filter, &filter_count);
  3079. + }
  3080. }
  3081. }
  3082. else
  3083. @@ -1560,7 +1575,7 @@
  3084. demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].table = 0;
  3085.  
  3086. cs_log("Demuxer %d ecmpid %d CAID: %04X ECM_PID: %04X PROVID: %06X %s", demux_id, demux[demux_id].ECMpidcount, caid, ecmpid, provid, txt);
  3087. - if(caid_is_irdeto(caid)) { demux[demux_id].emmstart.time = 1; } // marker to fetch emms early irdeto needs them!
  3088. + if(caid_is_irdeto(caid) || caid_is_dre(caid)) { demux[demux_id].emmstart.time = 1; } // marker to fetch emms early irdeto needs them!
  3089.  
  3090. demux[demux_id].ECMpidcount++;
  3091. }
  3092. @@ -3038,7 +3053,7 @@
  3093. openxcas_set_ecm_pid(demux[demux_id].ECMpids[found].ECM_PID);
  3094.  
  3095. // fixup for cas that need emm first!
  3096. - if(caid_is_irdeto(demux[demux_id].ECMpids[found].CAID)) { demux[demux_id].emmstart.time = 0; }
  3097. + if(caid_is_irdeto(demux[demux_id].ECMpids[found].CAID) || caid_is_dre(demux[demux_id].ECMpids[found].CAID)) { demux[demux_id].emmstart.time = 0; }
  3098. started = dvbapi_start_descrambling(demux_id, found, checked);
  3099. if(cfg.dvbapi_requestmode == 0 && started == 1) { return; } // in requestmode 0 we only start 1 ecm request at the time
  3100. }
  3101. @@ -4287,6 +4302,7 @@
  3102. if(filtertype == TYPE_ECM)
  3103. {
  3104. uint32_t chid = 0x10000;
  3105. + int8_t pvu_skip = 0;
  3106. ECM_REQUEST *er;
  3107.  
  3108. if(len != 0) // len = 0 receiver encountered an internal bufferoverflow!
  3109. @@ -4313,9 +4329,24 @@
  3110. return;
  3111. }
  3112.  
  3113. - if(curpid->table == buffer[0] && !caid_is_irdeto(curpid->CAID)) // wait for odd / even ecm change (only not for irdeto!)
  3114. - {
  3115. + if(curpid->CAID>>8 == 0x0E)
  3116. + {
  3117. + pvu_skip = 1;
  3118.  
  3119. + if(sctlen > 0xb)
  3120. + {
  3121. + if(buffer[0xb] > curpid->pvu_counter || (curpid->pvu_counter == 255 && buffer[0xb] == 0)
  3122. + || ((curpid->pvu_counter - buffer[0xb]) > 5))
  3123. + {
  3124. + curpid->pvu_counter = buffer[0xb];
  3125. + pvu_skip = 0;
  3126. + }
  3127. + }
  3128. + }
  3129. +
  3130. + if((curpid->table == buffer[0] && !caid_is_irdeto(curpid->CAID)) || pvu_skip) // wait for odd / even ecm change (only not for irdeto!)
  3131. + {
  3132. +
  3133. if(!(er = get_ecmtask()))
  3134. {
  3135. return;
  3136. @@ -6088,6 +6119,7 @@
  3137.  
  3138. delayer(er, delay);
  3139.  
  3140. + if(er->caid>>8 != 0x0E || !cfg.emu_stream_relay_enabled)
  3141. switch(selected_api)
  3142. {
  3143. #if defined(WITH_STAPI) || defined(WITH_STAPI5)
  3144. Index: module-dvbapi.h
  3145. ===================================================================
  3146. --- module-dvbapi.h (revision 11209)
  3147. +++ module-dvbapi.h (working copy)
  3148. @@ -135,6 +135,7 @@
  3149. ca_index_t index[MAX_STREAM_INDICES];
  3150. int8_t useMultipleIndices;
  3151. uint32_t streams;
  3152. + int16_t pvu_counter;
  3153. };
  3154.  
  3155. typedef struct filter_s
  3156. Index: module-emulator-dre2overcrypt.c
  3157. ===================================================================
  3158. --- module-emulator-dre2overcrypt.c (revision 0)
  3159. +++ module-emulator-dre2overcrypt.c (working copy)
  3160. @@ -0,0 +1,637 @@
  3161. +#include "globals.h"
  3162. +#ifdef WITH_EMU
  3163. +#include "oscam-string.h"
  3164. +#endif
  3165. +#include "module-emulator-st20.h"
  3166. +#include "module-emulator-dre2overcrypt.h"
  3167. +
  3168. +static uint16_t gId = 0xFFFF;
  3169. +static uint32_t gDecryptAddr;
  3170. +static uint32_t gRawSec = 0;
  3171. +static uint8_t gVersion = 0xFF;
  3172. +
  3173. +typedef struct data_block_t
  3174. +{
  3175. + uint8_t *data;
  3176. + uint32_t size;
  3177. + uint32_t used;
  3178. +} data_block;
  3179. +
  3180. +typedef struct memory_block_t
  3181. +{
  3182. + uint8_t *pos;
  3183. + uint8_t *end;
  3184. +} memory_block;
  3185. +
  3186. +static data_block raw_buffer = { NULL, 0, 0 };
  3187. +static data_block code_buffer = { NULL, 0, 0 };
  3188. +
  3189. +uint8_t initial_snippet[3694] =
  3190. +{
  3191. + 0x6F, 0xF0, 0x0E, 0x0D, 0x00, 0x00, 0x18, 0x75, 0xFF, 0x75, 0x63, 0x72, 0x2E, 0x2C, 0x17, 0x00,
  3192. + 0x00, 0x3F, 0x3D, 0x15, 0x00, 0x00, 0x9C, 0x00, 0xFB, 0xF7, 0xFA, 0xF5, 0x85, 0x4C, 0xFB, 0xF0,
  3193. + 0x04, 0xFB, 0xF8, 0xFB, 0xF1, 0xF7, 0xF0, 0x24, 0x0E, 0x42, 0xFF, 0x22, 0xF0, 0x41, 0x22, 0xF0,
  3194. + 0x60, 0xBF, 0x73, 0xFF, 0x24, 0x4B, 0x72, 0x9D, 0xD0, 0x70, 0x42, 0xF4, 0xBF, 0xA4, 0x70, 0xB1,
  3195. + 0x22, 0xF0, 0x40, 0x49, 0x00, 0x64, 0xFF, 0xB0, 0x25, 0x73, 0xD0, 0x24, 0x4C, 0x25, 0x72, 0xFF,
  3196. + 0x25, 0xFF, 0x21, 0x22, 0x29, 0xA2, 0x25, 0x72, 0xFF, 0x42, 0x21, 0xFB, 0xFA, 0xF6, 0x22, 0x26,
  3197. + 0x03, 0xFF, 0x80, 0x26, 0x2A, 0x0E, 0x80, 0x22, 0x2B, 0x07, 0xFF, 0x80, 0x22, 0x28, 0x05, 0x80,
  3198. + 0x26, 0x2C, 0x07, 0xFF, 0x80, 0x2C, 0x24, 0x05, 0x80, 0x27, 0x20, 0x09, 0xBF, 0x80, 0x26, 0x2E,
  3199. + 0x00, 0x80, 0x23, 0x73, 0x00, 0x22, 0xFF, 0x2C, 0x09, 0x80, 0x25, 0x22, 0x0B, 0x80, 0x25, 0xFF,
  3200. + 0x2C, 0x04, 0x80, 0x21, 0x21, 0x2F, 0x03, 0x2A, 0xFF, 0x24, 0x08, 0x80, 0x2A, 0x27, 0x0F, 0x80,
  3201. + 0x23, 0x7D, 0x2F, 0x8C, 0x00, 0x2D, 0x05, 0x80, 0x23, 0x2C, 0x84, 0x01, 0xFA, 0x90, 0x00, 0x2F,
  3202. + 0x78, 0x00, 0x26, 0x08, 0x80, 0x2E, 0x0A, 0xFF, 0x80, 0x80, 0x27, 0x24, 0x09, 0x80, 0x27, 0x2C,
  3203. + 0xCF, 0x06, 0x80, 0x27, 0x29, 0x78, 0x00, 0x6F, 0x00, 0x2A, 0x2F, 0xFF, 0x0D, 0x80, 0x28, 0x23,
  3204. + 0x05, 0x80, 0x2B, 0x28, 0xF7, 0x08, 0x80, 0x28, 0xB7, 0x00, 0x26, 0x2F, 0x0E, 0x80, 0xFF, 0x27,
  3205. + 0x25, 0x00, 0x80, 0x2B, 0x21, 0x06, 0x80, 0xFF, 0x2A, 0x25, 0x01, 0x80, 0x21, 0x28, 0x00, 0x80,
  3206. + 0xCB, 0x22, 0x2E, 0xB0, 0x01, 0x0D, 0x6D, 0x00, 0x88, 0x00, 0x28, 0x03, 0xFE, 0x91, 0x00, 0x0C,
  3207. + 0x80, 0x2C, 0x2D, 0x0E, 0x80, 0x2A, 0xB5, 0x04, 0xBC, 0x00, 0x2A, 0xD4, 0x00, 0x27, 0x0C, 0xE5,
  3208. + 0x00, 0x07, 0xFF, 0x80, 0x23, 0x2D, 0x0D, 0x80, 0x25, 0x21, 0x00, 0xFF, 0x80, 0x24, 0x24, 0x0D,
  3209. + 0x80, 0x24, 0x2B, 0x08, 0xFF, 0x80, 0x24, 0x2D, 0x0C, 0x80, 0x2D, 0x21, 0x0A, 0xFE, 0x0D, 0x10,
  3210. + 0x0C, 0x80, 0x28, 0x28, 0x02, 0x80, 0x26, 0xDF, 0x27, 0x0A, 0x80, 0x2A, 0x21, 0x24, 0x10, 0x20,
  3211. + 0x08, 0xEA, 0x85, 0x00, 0x03, 0x21, 0x10, 0x0A, 0x19, 0x10, 0x07, 0x80, 0x2F, 0xFE, 0xCF, 0x01,
  3212. + 0x2D, 0x0B, 0x80, 0x2A, 0x24, 0x00, 0x80, 0xFF, 0x29, 0x20, 0x0E, 0x80, 0x26, 0x22, 0x0A, 0x80,
  3213. + 0xFF, 0x21, 0x20, 0x25, 0x01, 0x2A, 0x21, 0x01, 0x80, 0xD3, 0x2A, 0x03, 0xBC, 0x00, 0x6F, 0x10,
  3214. + 0x24, 0x6F, 0x10, 0x21, 0x22, 0xEF, 0x03, 0x80, 0x2C, 0x02, 0x78, 0x10, 0x20, 0x29, 0x0E, 0xFF,
  3215. + 0x28, 0x27, 0x00, 0x80, 0x27, 0x2F, 0x03, 0x80, 0xFB, 0x29, 0x21, 0x8C, 0x00, 0x73, 0x45, 0x25,
  3216. + 0x71, 0x61, 0xFB, 0x2B, 0x96, 0x43, 0x01, 0x2D, 0x20, 0xAE, 0x70, 0x25, 0xFF, 0xB0, 0x22, 0xF0,
  3217. + 0x70, 0xF1, 0x41, 0x24, 0xF6, 0xF5, 0xC0, 0xA2, 0x12, 0x81, 0xA7, 0x17, 0x21, 0x1D, 0x42, 0x24,
  3218. + 0x7F, 0xFA, 0x21, 0x7D, 0x4C, 0x27, 0xF8, 0xD1, 0xC1, 0x10, 0xEF, 0x24, 0xF0, 0x21, 0xDD, 0xC7,
  3219. + 0x11, 0xF1, 0x21, 0xDD, 0xDF, 0x71, 0x21, 0x7D, 0x23, 0xF3, 0xCC, 0x10, 0x1D, 0x70, 0x6A, 0xBE,
  3220. + 0x10, 0x42, 0xB7, 0x13, 0x1F, 0xBE, 0x11, 0x7F, 0x43, 0xC4, 0x11, 0xEB, 0x7F, 0x43, 0xCA, 0x10,
  3221. + 0xDF, 0xF3, 0x11, 0xF1, 0x21, 0xDF, 0x77, 0x71, 0x21, 0x7F, 0xD8, 0x10, 0xDF, 0x21, 0x1F, 0xDE,
  3222. + 0x18, 0x3B, 0x1E, 0x44, 0xBF, 0x10, 0x7E, 0x21, 0x45, 0xC4, 0x11, 0x1A, 0x20, 0xFA, 0xCA, 0x10,
  3223. + 0xDE, 0x20, 0x22, 0xF1, 0x21, 0xDE, 0x71, 0x21, 0x3D, 0x7E, 0xD8, 0x10, 0xDE, 0x21, 0x1E, 0x70,
  3224. + 0x16, 0x20, 0xE2, 0x13, 0x7B, 0x22, 0x14, 0x16, 0x20, 0x22, 0x74, 0x21, 0x47, 0xC4, 0x10, 0xDE,
  3225. + 0x48, 0x21, 0x24, 0xF0, 0x22, 0xD4, 0x4F, 0x22, 0xF1, 0x22, 0xBF, 0xD4, 0x71, 0x22, 0x74, 0x23,
  3226. + 0xF3, 0x55, 0x20, 0x14, 0x3A, 0x39, 0x28, 0x18, 0x45, 0x21, 0x78, 0x21, 0x4E, 0x4C, 0x21, 0x78,
  3227. + 0x20, 0xFA, 0x53, 0x20, 0xD8, 0x7E, 0x22, 0xF1, 0x22, 0xD8, 0x71, 0x22, 0x5D, 0x78, 0x62, 0x20,
  3228. + 0xD8, 0x22, 0x18, 0x39, 0x28, 0x1A, 0x45, 0x21, 0x5B, 0x7A, 0x49, 0x4C, 0x21, 0x7A, 0x49, 0x53,
  3229. + 0x20, 0xDA, 0xAC, 0x21, 0xBF, 0xF1, 0x22, 0xDA, 0x71, 0x22, 0x7A, 0x62, 0x20, 0xDA, 0x7B, 0x22,
  3230. + 0x1A, 0x39, 0x27, 0x81, 0x21, 0x1A, 0x43, 0xBF, 0x10, 0xD1, 0x7A, 0x4B, 0x21, 0xD3, 0x20, 0xCA,
  3231. + 0x10, 0xDA, 0xD9, 0x21, 0xF1, 0x21, 0xE7, 0xDA, 0x71, 0x21, 0xBC, 0x20, 0xDE, 0x20, 0x1A, 0x70,
  3232. + 0x81, 0xAC, 0xD0, 0x20, 0xC7, 0x24, 0x22, 0x19, 0x45, 0x21, 0x79, 0x7A, 0x22, 0x79, 0xFA, 0x81,
  3233. + 0x21, 0xD9, 0x07, 0x31, 0xF1, 0x22, 0xD9, 0x71, 0x22, 0x7D, 0x79, 0x62, 0x20, 0xD9, 0x22, 0x19,
  3234. + 0x70, 0x81, 0xC4, 0x27, 0xAB, 0x22, 0x1B, 0x45, 0x21, 0x7B, 0x4B, 0x22, 0x7B, 0x52, 0x21, 0xDB,
  3235. + 0x7E, 0x35, 0x31, 0xF1, 0x22, 0xDB, 0x71, 0x22, 0x7B, 0x62, 0x20, 0x57, 0xDB, 0x22, 0x1B, 0x1E,
  3236. + 0x3A, 0x17, 0x45, 0x21, 0x77, 0xA8, 0x22, 0xF5, 0x77, 0xAE, 0x21, 0xD7, 0x63, 0x31, 0xF1, 0x22,
  3237. + 0xD7, 0x71, 0xBB, 0x22, 0x77, 0x62, 0x20, 0xD7, 0x22, 0x17, 0x1E, 0x38, 0x82, 0x1B, 0x22, 0x13,
  3238. + 0xD0, 0x20, 0x22, 0x73, 0xEF, 0x11, 0x8B, 0x30, 0x53, 0x20, 0xFD, 0xD3, 0x91, 0x31, 0xF1, 0x22,
  3239. + 0xD3, 0x71, 0x22, 0x73, 0xBE, 0x62, 0x20, 0xD3, 0x22, 0x13, 0x70, 0x82, 0xF2, 0x26, 0x82, 0xDB,
  3240. + 0x22, 0x12, 0x88, 0x31, 0x72, 0x44, 0x4C, 0x21, 0x72, 0x44, 0xFA, 0x53, 0x20, 0xD2, 0xBF, 0x31,
  3241. + 0xF1, 0x22, 0xD2, 0x71, 0x22, 0x5D, 0x72, 0x62, 0x20, 0xD2, 0x22, 0x12, 0xA8, 0x3A, 0x15, 0x88,
  3242. + 0x31, 0x5B, 0x75, 0x46, 0x4C, 0x21, 0x75, 0x46, 0x53, 0x20, 0xD5, 0xED, 0x31, 0xBF, 0xF1, 0x22,
  3243. + 0xD5, 0x71, 0x22, 0x75, 0x62, 0x20, 0xD5, 0x6B, 0x22, 0x15, 0xA8, 0x3A, 0x11, 0x45, 0x21, 0x71,
  3244. + 0x4F, 0x4C, 0x21, 0xF3, 0x71, 0x4F, 0x53, 0x20, 0x1A, 0x42, 0xF1, 0x22, 0xD1, 0x71, 0xFB, 0x22,
  3245. + 0x71, 0x62, 0x20, 0xD1, 0x22, 0x11, 0x70, 0x82, 0x16, 0x7C, 0x37, 0x21, 0x1C, 0x16, 0x21, 0x7C,
  3246. + 0x1B, 0x23, 0x44, 0x40, 0xCA, 0x10, 0xFD, 0xDC, 0x4A, 0x42, 0xF1, 0x21, 0xDC, 0x71, 0x21, 0x7C,
  3247. + 0x6E, 0xD8, 0x10, 0xDC, 0x21, 0x1C, 0x32, 0x49, 0x22, 0x10, 0x45, 0x21, 0x47, 0x70, 0x21, 0x4A,
  3248. + 0x4C, 0x21, 0x75, 0x40, 0x53, 0x20, 0xD0, 0x7B, 0x42, 0xBF, 0xF1, 0x22, 0xD0, 0x71, 0x22, 0x70,
  3249. + 0x62, 0x20, 0xD0, 0xB3, 0x22, 0x10, 0x32, 0x4A, 0x2B, 0x31, 0x21, 0x7B, 0xEF, 0x12, 0x7B, 0xFA,
  3250. + 0xF5, 0x11, 0xDB, 0xAB, 0x41, 0xF1, 0x21, 0xDB, 0x71, 0x21, 0x74, 0x45, 0x30, 0xB0, 0x40, 0x1B,
  3251. + 0x32, 0x48, 0x51, 0x21, 0x11, 0xBE, 0x11, 0xE5, 0x71, 0xC3, 0x12, 0x71, 0xC9, 0x11, 0xD8, 0x42,
  3252. + 0xF1, 0x21, 0xD1, 0x73, 0x71, 0x21, 0x2B, 0x40, 0xDE, 0x40, 0x11, 0x70, 0x51, 0xDF, 0x16, 0x57,
  3253. + 0x51, 0x21, 0x10, 0xBE, 0x11, 0x70, 0xD5, 0x22, 0x70, 0xDB, 0x21, 0x7D, 0xD0, 0x07, 0x51, 0xF1,
  3254. + 0x21, 0xD0, 0x71, 0x21, 0x8D, 0x40, 0xAA, 0x0C, 0x50, 0x10, 0xF0, 0x49, 0x1E, 0xBE, 0x10, 0x7E,
  3255. + 0xA8, 0x21, 0x7E, 0xBA, 0xAE, 0x20, 0xDE, 0x33, 0x50, 0xF1, 0xDE, 0x71, 0x32, 0x20, 0xDE, 0xD9,
  3256. + 0x1E, 0xF0, 0x49, 0xE3, 0x31, 0x75, 0x4D, 0xC4, 0x10, 0x75, 0x4D, 0x77, 0x24, 0xF0, 0xD5, 0x58,
  3257. + 0x50, 0xF1, 0xD5, 0x71, 0xFD, 0x30, 0xAF, 0xD5, 0x15, 0x70, 0x51, 0xF2, 0x26, 0x51, 0xB5, 0x31,
  3258. + 0x72, 0xEA, 0xE9, 0x31, 0x72, 0xEF, 0x30, 0xD2, 0x7D, 0x50, 0xF1, 0xD2, 0x71, 0xA6, 0xCF, 0x30,
  3259. + 0xD2, 0x12, 0x68, 0x59, 0x87, 0x31, 0x73, 0xA8, 0x21, 0x73, 0xBA, 0xAE, 0x20, 0xD3, 0xA2, 0x50,
  3260. + 0xF1, 0xD3, 0x71, 0xA1, 0x30, 0xD3, 0xD9, 0x13, 0x68, 0x59, 0x44, 0x21, 0x74, 0x4B, 0xC4, 0x10,
  3261. + 0x74, 0x4B, 0x77, 0x24, 0xF0, 0xD4, 0xC7, 0x50, 0xF1, 0xD4, 0x71, 0x61, 0x20, 0xCF, 0xD4, 0x14,
  3262. + 0x70, 0x51, 0xC4, 0x47, 0x11, 0x41, 0x71, 0x21, 0x9A, 0xA8, 0x20, 0xD2, 0xE7, 0x50, 0x24, 0xF0,
  3263. + 0xE6, 0x40, 0xB5, 0x20, 0xD1, 0xA5, 0x72, 0x2B, 0x40, 0xD1, 0xEF, 0x40, 0xC4, 0x47, 0x16, 0x16,
  3264. + 0x20, 0x76, 0xB9, 0x21, 0xC3, 0x51, 0x0F, 0x60, 0x24, 0xF0, 0xD6, 0x15, 0x61, 0xF1, 0x7F, 0xD6,
  3265. + 0x71, 0x76, 0x23, 0xF3, 0xD6, 0x16, 0xD7, 0x59, 0x72, 0x59, 0x31, 0x77, 0x79, 0x22, 0x37, 0x60,
  3266. + 0x24, 0xF0, 0xD7, 0x3D, 0x61, 0xB7, 0xF1, 0xD7, 0x71, 0x73, 0x30, 0xD7, 0x17, 0xD7, 0x58, 0x85,
  3267. + 0x55, 0x1F, 0xD0, 0x20, 0x7F, 0xBB, 0x31, 0x7F, 0xC1, 0x30, 0xDF, 0x64, 0x60, 0xF7, 0xF1, 0xDF,
  3268. + 0x71, 0x03, 0x20, 0xDF, 0x1F, 0x70, 0x85, 0x6E, 0xF2, 0x26, 0x86, 0x22, 0x16, 0xBE, 0x10, 0x22,
  3269. + 0x76, 0x77, 0x42, 0xF5, 0x76, 0x7E, 0x41, 0xD6, 0x8B, 0x61, 0xF1, 0x22, 0xD6, 0x71, 0xB9, 0x22,
  3270. + 0x22, 0x60, 0x90, 0x60, 0x16, 0x70, 0x86, 0xDF, 0x16, 0x86, 0x55, 0x19, 0xBE, 0x10, 0x79, 0xEF,
  3271. + 0x11, 0x79, 0xF5, 0x10, 0xD9, 0xB7, 0x60, 0xB7, 0xF1, 0xD9, 0x71, 0x17, 0x30, 0xD9, 0x19, 0xA2,
  3272. + 0x69, 0x1A, 0xF6, 0xBE, 0x10, 0x7A, 0x48, 0xC4, 0x10, 0x7A, 0x48, 0x24, 0xF0, 0xDD, 0xDA, 0xDC,
  3273. + 0x60, 0xF1, 0xDA, 0x71, 0xBC, 0x20, 0xDA, 0x1A, 0xAA, 0xA2, 0x69, 0x18, 0xBE, 0x10, 0x78, 0xA8,
  3274. + 0x21, 0x78, 0xAE, 0x20, 0xD8, 0x6E, 0x01, 0x70, 0xF1, 0xD8, 0x71, 0x90, 0x20, 0xD8, 0x18, 0xA2,
  3275. + 0x68, 0x9F, 0x87, 0x1B, 0x41, 0x24, 0xFA, 0xA6, 0x42, 0xAC, 0x41, 0xDB, 0xF6, 0xB3, 0x41, 0xDB,
  3276. + 0x71, 0x45, 0x30, 0xDB, 0x1B, 0x70, 0x87, 0x54, 0x1E, 0x70, 0x16, 0x74, 0x1C, 0x1E, 0x70, 0x7C,
  3277. + 0xBB, 0x31, 0x7C, 0xC1, 0x30, 0xDD, 0xDC, 0x4B, 0x70, 0xF1, 0xDC, 0x71, 0x5C, 0x40, 0xDC, 0x1C,
  3278. + 0xAA, 0x36, 0x79, 0x1D, 0x1E, 0x70, 0x7D, 0x1C, 0x21, 0x7D, 0x23, 0x20, 0xDD, 0x6E, 0x70, 0x70,
  3279. + 0xF1, 0xDD, 0x71, 0xD7, 0x10, 0xDD, 0x1D, 0x36, 0x77, 0xFE, 0xE2, 0x12, 0x40, 0xD1, 0x70, 0x71,
  3280. + 0xF2, 0xF1, 0xD2, 0xBF, 0x70, 0x41, 0x71, 0xFC, 0xF2, 0xF1, 0x91, 0x70, 0x23, 0xEB, 0xFB, 0x72,
  3281. + 0x97, 0x70, 0x70, 0x9E, 0x70, 0x71, 0x81, 0xD1, 0xBF, 0x41, 0x71, 0xF9, 0xA2, 0x62, 0x0F, 0x8A,
  3282. + 0x7A, 0x42, 0x50, 0x98, 0x77, 0xBF, 0x70, 0xA5, 0x7F, 0x8F, 0x71, 0x85, 0x93, 0x71, 0x47, 0x98,
  3283. + 0x73, 0xF1, 0x85, 0x9E, 0x71, 0xE8, 0x70, 0xCD, 0x77, 0xA3, 0x80, 0x62, 0x0C, 0x4A, 0x8A, 0x76,
  3284. + 0x86, 0xE4, 0x78, 0x86, 0xF0, 0x7F, 0x02, 0x89, 0x81, 0x93, 0x71, 0x45, 0x44, 0x98, 0x73, 0x81,
  3285. + 0x9E, 0x71, 0x3E, 0x80, 0xCD, 0x74, 0x42, 0xFF, 0x7C, 0x05, 0x83, 0xE4, 0x78, 0x83, 0x1B, 0x8B,
  3286. + 0x54, 0x8D, 0x39, 0x82, 0xE8, 0x74, 0x45, 0x82, 0x2A, 0x1F, 0x87, 0x43, 0xFF, 0x7C, 0x82, 0xE4,
  3287. + 0x78, 0x82, 0x9C, 0x8F, 0x02, 0x89, 0xD4, 0xE4, 0x78, 0x1B, 0x8B, 0x44, 0xFF, 0x72, 0x0E, 0xE2,
  3288. + 0x12, 0x2A, 0x23, 0xFF, 0x4F, 0x21, 0xFB, 0x23, 0x1C, 0x21, 0x40, 0x24, 0xFF, 0xFA, 0x40, 0xD1,
  3289. + 0x23, 0x1C, 0x71, 0x70, 0xF2, 0xE9, 0xF1, 0xC1, 0x30, 0x1B, 0x91, 0xF1, 0x19, 0x91, 0x4F, 0x24,
  3290. + 0xF6, 0x3F, 0x23, 0x1C, 0xF2, 0xF1, 0x24, 0xFB, 0x19, 0x90, 0xCF, 0x72, 0xB5, 0x48, 0xAD, 0x71,
  3291. + 0x07, 0x05, 0x93, 0x21, 0x44, 0x0D, 0x90, 0x18, 0x3A, 0x11, 0x94, 0x18, 0x19, 0x9F, 0xF6, 0x23,
  3292. + 0x18, 0x2E, 0x9F, 0xE2, 0x12, 0x7F, 0x29, 0x2E, 0x49, 0x21, 0xFB, 0x24, 0x10, 0x11, 0x93, 0x3B,
  3293. + 0x24, 0x10, 0x54, 0x9F, 0xF6, 0x24, 0x10, 0x69, 0x9F, 0x7B, 0x93, 0x33, 0x2B, 0x4E, 0x0D, 0x90,
  3294. + 0x86, 0x94, 0x23, 0x10, 0x62, 0x82, 0x1D, 0x95, 0xA0, 0x62, 0x82, 0x29, 0x91, 0xA3, 0x92, 0x6E,
  3295. + 0x83, 0xD1, 0x70, 0x45, 0xAD, 0x71, 0x04, 0x56, 0x7B, 0x93, 0x29, 0x40, 0x0D, 0x90, 0x14, 0x11,
  3296. + 0x94, 0x14, 0x8F, 0x9F, 0x67, 0xF6, 0x23, 0x14, 0xA4, 0x9F, 0x7B, 0x93, 0x26, 0x45, 0x83, 0x90,
  3297. + 0xC2, 0x4B, 0x94, 0x24, 0x53, 0x9F, 0xA0, 0x90, 0x68, 0x9F, 0x7A, 0x94, 0x23, 0x4A, 0xD7, 0x21,
  3298. + 0xFB, 0x22, 0x10, 0x94, 0x22, 0x18, 0x9F, 0x24, 0xF6, 0xA9, 0x22, 0x2D, 0x9F, 0x7A, 0x94, 0x20,
  3299. + 0x0C, 0x90, 0x24, 0xFF, 0x94, 0x24, 0xB0, 0x07, 0xAF, 0xA0, 0x90, 0x1C, 0xAF, 0x3F, 0x93, 0x28,
  3300. + 0x2E, 0x47, 0x90, 0x24, 0x82, 0x10, 0x94, 0x24, 0x7D, 0xAF, 0xA0, 0x90, 0x92, 0xAA, 0xAC, 0x72,
  3301. + 0x3F, 0x93, 0x4C, 0xDF, 0x21, 0xD4, 0x4D, 0x21, 0xD5, 0x52, 0x00, 0x42, 0x21, 0xFF, 0x14, 0x25,
  3302. + 0x71, 0x28, 0x2B, 0x95, 0xD0, 0x70, 0xF9, 0xA5, 0xA1, 0x12, 0xE2, 0x12, 0x21, 0x4E, 0x21, 0xD8,
  3303. + 0x22, 0x57, 0x40, 0x21, 0xD9, 0x26, 0xB2, 0x18, 0x2C, 0xB0, 0x29, 0x30, 0xBB, 0xFF, 0x23, 0x44,
  3304. + 0x21, 0xD6, 0x23, 0x45, 0x21, 0xD7, 0xEA, 0x26, 0xB2, 0x16, 0x2C, 0xB0, 0x27, 0x30, 0xBB, 0x46,
  3305. + 0x21, 0xD2, 0xAF, 0x24, 0x40, 0x21, 0xD3, 0x26, 0xB2, 0x12, 0x2C, 0xB0, 0x25, 0xDC, 0x99, 0x10,
  3306. + 0x33, 0xB8, 0x25, 0x73, 0x21, 0x94, 0x10, 0x6B, 0x2A, 0xBF, 0x9A, 0xD0, 0x70, 0x41, 0xF4, 0xA7,
  3307. + 0x32, 0xB4, 0x70, 0x5F, 0xC1, 0xC0, 0xA2, 0x21, 0x01, 0x9D, 0xB0, 0x47, 0xA1, 0xB0, 0x7B, 0x28,
  3308. + 0x9F, 0x90, 0xBF, 0x71, 0x6B, 0x27, 0x99, 0xA6, 0xBF, 0xDA, 0x9D, 0xB0, 0x49, 0xA1, 0xB0, 0x25,
  3309. + 0x9E, 0xC1, 0xBF, 0x71, 0x6B, 0x53, 0x24, 0x98, 0xD7, 0xBF, 0x9D, 0xB0, 0x4F, 0xA1, 0xB0, 0x22,
  3310. + 0x42, 0x00, 0xF6, 0xF4, 0xBF, 0x21, 0x97, 0x08, 0xCF, 0x25, 0x73, 0x22, 0x4B, 0xDF, 0x25, 0x71,
  3311. + 0x6C, 0x2F, 0x9C, 0x23, 0xCF, 0x71, 0x6C, 0x79, 0x2E, 0x99, 0x10, 0x3B, 0xCC, 0x00, 0x25, 0x73,
  3312. + 0x46, 0x4F, 0xC0, 0x95, 0x2C, 0x53, 0xCD, 0x22, 0xEC, 0xB0, 0x6C, 0x98, 0x11, 0x3B, 0xCF, 0x22,
  3313. + 0xAD, 0x4A, 0x4F, 0xC0, 0x29, 0x9B, 0x54, 0xCC, 0x40, 0x4F, 0xC0, 0x28, 0xDC, 0x99, 0x12, 0x33,
  3314. + 0xB3, 0x25, 0x73, 0x41, 0x4F, 0xC0, 0x27, 0x94, 0x5A, 0xCA, 0xC9, 0x42, 0x4F, 0xC0, 0x26, 0x92,
  3315. + 0xCA, 0xC9, 0x43, 0x4F, 0xC0, 0x2B, 0x25, 0x90, 0xCA, 0xC9, 0x44, 0x4F, 0xC0, 0x23, 0xF1, 0xB0,
  3316. + 0xCC, 0xC5, 0x4C, 0x98, 0xB4, 0x1D, 0xC0, 0x6C, 0x22, 0x38, 0xC0, 0xCC, 0xC7, 0x21, 0xC4, 0xC1,
  3317. + 0x35, 0x21, 0xDB, 0xCA, 0x21, 0xD6, 0xC1, 0x20, 0x91, 0x29, 0xDA, 0xE8, 0xC0, 0x63, 0x6D, 0x2E,
  3318. + 0x11, 0xD8, 0x9D, 0xB0, 0xFA, 0xC0, 0x6D, 0x2D, 0xB4, 0xC0, 0x3A, 0x14, 0xDC, 0x21, 0x7E, 0xC0,
  3319. + 0x6D, 0x2C, 0x93, 0x29, 0xDA, 0xBB, 0xB0, 0x53, 0x6D, 0x2B, 0xFF, 0xCA, 0x87, 0xD1, 0x29, 0x61,
  3320. + 0xDB, 0x48, 0x5D, 0xD0, 0x49, 0x28, 0x74, 0xD8, 0x97, 0xD4, 0x27, 0x07, 0xC0, 0x14, 0xDC, 0x22,
  3321. + 0x6F, 0xD1, 0x35, 0x26, 0xFF, 0xCA, 0x22, 0x0C, 0xD0, 0x6D, 0x24, 0x42, 0x02, 0xF4, 0xD6, 0x86,
  3322. + 0x94, 0x10, 0x6D, 0x23, 0xA5, 0xB0, 0xF2, 0xD8, 0x87, 0xD1, 0x27, 0xDB, 0x22, 0x78, 0x9A, 0xD1,
  3323. + 0x3A, 0xD9, 0x8C, 0xC5, 0x4D, 0x25, 0x71, 0x6E, 0x52, 0xC1, 0x8A, 0xF2, 0xD8, 0x4E, 0x4F, 0xE0,
  3324. + 0x2E, 0xD6, 0xB0, 0xF2, 0xD8, 0x1D, 0xC0, 0x6E, 0x55, 0x2D, 0xC9, 0xCA, 0x23, 0xC4, 0xC0, 0x6E,
  3325. + 0x8B, 0xDB, 0x23, 0xD6, 0xC0, 0x31, 0x6E, 0x9E, 0xD9, 0x98, 0xB4, 0x7E, 0xC0, 0x6E, 0x29, 0x66,
  3326. + 0xEA, 0x61, 0xE1, 0x09, 0x28, 0x28, 0xDB, 0x0C, 0xD0, 0x6E, 0xDA, 0xCB, 0xB1, 0xE1, 0xEC, 0xCB,
  3327. + 0xB1, 0xE1, 0x60, 0xFE, 0xCB, 0xB1, 0xE1, 0x10, 0xD9, 0x9D, 0xB0, 0xAF, 0xC0, 0x6E, 0x22, 0xC4,
  3328. + 0xDB, 0xA6, 0x4E, 0xC0, 0x6E, 0x21, 0xD7, 0xD8, 0xAF, 0xE3, 0x20, 0xC9, 0xCA, 0x21, 0x9F, 0x4C,
  3329. + 0x25, 0x71, 0x6F, 0x2F, 0x8C, 0xDB, 0x4E, 0xE0, 0x6F, 0x99, 0x2E, 0xEF, 0xDB, 0xD6, 0xC0, 0x6F,
  3330. + 0x2C, 0x02, 0xEB, 0xE8, 0xC0, 0x6F, 0x99, 0x2B, 0x15, 0xEB, 0xBF, 0xD0, 0x6F, 0x2A, 0x28, 0xDA,
  3331. + 0x7E, 0xC0, 0x6F, 0x68, 0x4F, 0xB1, 0xF2, 0xD8, 0x57, 0xF1, 0x28, 0xED, 0xED, 0x6F, 0x27, 0xFF,
  3332. + 0xCA, 0xD5, 0x23, 0x90, 0xF1, 0x25, 0x02, 0xEA, 0x23, 0xFA, 0xC0, 0x6F, 0x24, 0x4A, 0x15, 0xEA,
  3333. + 0x23, 0xB5, 0xF1, 0x23, 0x28, 0xDA, 0xFF, 0xF2, 0x22, 0xDB, 0xCA, 0xEA, 0xFF, 0xF2, 0x21, 0x4E,
  3334. + 0xDA, 0x23, 0x4E, 0xC0, 0x61, 0x2F, 0x2F, 0xAC, 0xF2, 0xFB, 0x57, 0xF0, 0x61, 0x2F, 0x65, 0xEB,
  3335. + 0x23, 0x4E, 0xE0, 0x61, 0x73, 0x2F, 0x2D, 0xBA, 0xFA, 0xFF, 0xF1, 0x61, 0x2F, 0x2C, 0x3E, 0x0B,
  3336. + 0x6E, 0x61, 0xE0, 0x61, 0x2F, 0x2A, 0xF2, 0xFE, 0x61, 0x2F, 0xB5, 0xEB, 0x5D, 0x24, 0xD6, 0xC0,
  3337. + 0x61, 0x2F, 0x28, 0xBA, 0xFA, 0x24, 0xBB, 0xB0, 0xD7, 0x61, 0x2F, 0x27, 0x4E, 0xDA, 0x24, 0xBF,
  3338. + 0xD0, 0x61, 0x2F, 0x9C, 0xF1, 0xFB, 0x56, 0xF1, 0x61, 0x2F, 0x24, 0x66, 0xEB, 0xE8, 0xC0, 0x61,
  3339. + 0x73, 0x2F, 0x23, 0xCA, 0x0B, 0xEC, 0xB0, 0x61, 0x2F, 0x22, 0xDE, 0x0B, 0x4E, 0xAF, 0xC0, 0x61,
  3340. + 0x2F, 0x20, 0x02, 0xE8, 0x98, 0xB4, 0x23, 0xD8, 0x01, 0xB3, 0x2E, 0x2F, 0xDB, 0xCA, 0x73, 0xE1,
  3341. + 0x61, 0x2E, 0x6E, 0xFB, 0x23, 0x62, 0xEC, 0x01, 0x2E, 0x82, 0xC1, 0x7C, 0xE8, 0x28, 0x11, 0x2E,
  3342. + 0x2B, 0x37, 0xFA, 0x2D, 0x23, 0x3C, 0x11, 0x2E, 0x2A, 0x3B, 0xEF, 0x23, 0x69, 0x12, 0xC3, 0xDB,
  3343. + 0x92, 0xBD, 0x13, 0x27, 0x18, 0x0B, 0x69, 0x12, 0x26, 0x8C, 0xEB, 0x69, 0x12, 0x24, 0xD4, 0xC0,
  3344. + 0xB0, 0xC7, 0x1D, 0x23, 0x74, 0xDF, 0x24, 0x14, 0x11, 0x2E, 0x22, 0x5A, 0xED, 0xCA, 0x24, 0x88,
  3345. + 0x01, 0x2E, 0x20, 0x61, 0xDA, 0x24, 0x0C, 0xD0, 0xD7, 0x61, 0x2D, 0x2F, 0x15, 0xEA, 0x24, 0xA0,
  3346. + 0xB0, 0x61, 0x2D, 0x38, 0x68, 0xC1, 0xB9, 0x08, 0x7E, 0xC0, 0x61, 0x2D, 0x2D, 0xED, 0xC8, 0x98,
  3347. + 0xB4, 0x92, 0xD8, 0x01, 0x2D, 0x94, 0xFB, 0xEC, 0x01, 0x2D, 0xA7, 0xFB, 0x28, 0x11, 0x2D, 0x99,
  3348. + 0x29, 0xDB, 0xCA, 0x3C, 0x11, 0x2D, 0x28, 0x4E, 0xDA, 0x4C, 0x01, 0x2D, 0xF5, 0x26, 0x11, 0xDD,
  3349. + 0x43, 0x24, 0x31, 0x60, 0xBD, 0x40, 0xD0, 0xFF, 0x75, 0x21, 0xA0, 0x41, 0x60, 0x8F, 0xD2, 0x75,
  3350. + 0xFF, 0x74, 0x61, 0x2D, 0x23, 0x95, 0xD1, 0x71, 0xA9, 0x7F, 0x71, 0xD0, 0x06, 0x21, 0x20, 0x46,
  3351. + 0xB3, 0xDF, 0x81, 0xFF, 0x72, 0xC0, 0xA2, 0x41, 0xD1, 0x71, 0xC0, 0xA4, 0xDF, 0x21, 0x20, 0x41,
  3352. + 0xD0, 0x70, 0x10, 0x30, 0x41, 0x71, 0xFF, 0xE0, 0x71, 0x30, 0x60, 0x8F, 0x71, 0xE0, 0x40, 0xFE,
  3353. + 0xF4, 0x20, 0xBF, 0x40, 0xD0, 0x72, 0x30, 0xC0, 0xA7, 0xDF, 0x72, 0x30, 0x81, 0x72, 0xE0, 0x1F,
  3354. + 0x30, 0xA4, 0x40, 0xED, 0xB1, 0x3C, 0xB0, 0x20, 0x41, 0x43, 0x30, 0x20, 0x20, 0x00, 0xFF, 0x0D,
  3355. + 0x0B, 0x0A, 0x08, 0x02, 0x09, 0x01, 0x05, 0xFF, 0x0C, 0x0E, 0x03, 0x07, 0x04, 0x0F, 0x06, 0x0B,
  3356. + 0xFF, 0x0C, 0x08, 0x09, 0x0F, 0x04, 0x03, 0x00, 0x0D, 0x7F, 0x01, 0x0A, 0x0E, 0x06, 0x02, 0x07,
  3357. + 0x05, 0x62, 0x30, 0xFF, 0x0B, 0x06, 0x09, 0x00, 0x01, 0x0A, 0x05, 0x0E, 0xFF, 0x0D, 0x0C, 0x02,
  3358. + 0x08, 0x07, 0x0F, 0x05, 0x03, 0xFF, 0x0B, 0x04, 0x0A, 0x09, 0x01, 0x0C, 0x06, 0x0E, 0xFF, 0x08,
  3359. + 0x00, 0x07, 0x02, 0x0D, 0x02, 0x04, 0x0A, 0xFF, 0x0F, 0x0C, 0x01, 0x0E, 0x0B, 0x00, 0x09, 0x03,
  3360. + 0xFF, 0x08, 0x0D, 0x07, 0x06, 0x05, 0x04, 0x03, 0x05, 0xFB, 0x0A, 0x06, 0x95, 0x30, 0x0E, 0x02,
  3361. + 0x0C, 0x0F, 0x0D, 0xFF, 0x07, 0x08, 0x01, 0x05, 0x0A, 0x03, 0x02, 0x07, 0xFF, 0x04, 0x0D, 0x0E,
  3362. + 0x01, 0x08, 0x00, 0x0F, 0x0C, 0xFF, 0x09, 0x06, 0x0B, 0x05, 0x0C, 0x09, 0x03, 0x01, 0xFF, 0x0D,
  3363. + 0x07, 0x04, 0x06, 0x08, 0x0B, 0x02, 0x0A, 0xFF, 0x00, 0x0F, 0x0E, 0x05, 0x0D, 0x09, 0x01, 0x08,
  3364. + 0xFF, 0x06, 0x04, 0x03, 0x0A, 0x07, 0x02, 0x0E, 0x00, 0xFF, 0x0B, 0x0C, 0x0F, 0x71, 0x51, 0x25,
  3365. + 0xFA, 0x31, 0x5F, 0xD1, 0x32, 0xF6, 0x71, 0x54, 0xE0, 0x34, 0x57, 0xE0, 0x34, 0xF5, 0x5A, 0xE0,
  3366. + 0x34, 0x5D, 0xE0, 0x33, 0x70, 0x72, 0x69, 0x6E, 0xFF, 0x74, 0x66, 0x00, 0x69, 0x63, 0x67, 0x5F,
  3367. + 0x72, 0xFF, 0x75, 0x6E, 0x5F, 0x69, 0x6E, 0x5F, 0x74, 0x68, 0xFF, 0x72, 0x65, 0x61, 0x64, 0x73,
  3368. + 0x00, 0x6D, 0x61, 0xFF, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x66, 0x72, 0x65, 0xFF, 0x65, 0x00, 0x65,
  3369. + 0x78, 0x69, 0x74, 0x00, 0x73, 0xFF, 0x6E, 0x69, 0x70, 0x70, 0x65, 0x74, 0x5F, 0x64, 0xFF, 0x65,
  3370. + 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0xC7, 0x69, 0x7A, 0x65, 0x30, 0x46, 0x3B, 0x4F, 0x17,
  3371. + 0x44, 0x5F, 0x63, 0x57, 0x6F, 0x75, 0x6E, 0x37, 0x41, 0x63, 0x45, 0x47, 0x64, 0x6D, 0x4A, 0xFF,
  3372. + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5F, 0xBF, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x30,
  3373. + 0x48, 0x63, 0x7F, 0x72, 0x79, 0x70, 0x74, 0x00, 0x20, 0x20, 0x82, 0x90, 0xFF, 0x71, 0x21, 0x29,
  3374. + 0x9D, 0x20, 0x21, 0x28, 0x09, 0xFF, 0x20, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x20, 0xB7, 0x66,
  3375. + 0x75, 0x6E, 0x92, 0x42, 0x20, 0x63, 0x21, 0x40, 0x20, 0xFF, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x0A,
  3376. + 0x00, 0x60, 0xFF, 0xBB, 0x40, 0xD4, 0x77, 0x30, 0x40, 0xF9, 0x24, 0xEF, 0xA6, 0x40, 0xD0, 0x78,
  3377. + 0xD7, 0x40, 0x23, 0xA4, 0x74, 0xFF, 0x43, 0xF8, 0xD3, 0x70, 0x43, 0xF8, 0x78, 0x31, 0xFF, 0xFA,
  3378. + 0xD1, 0x73, 0x77, 0x31, 0xFA, 0xD2, 0x71, 0xFF, 0x30, 0x72, 0x30, 0x76, 0x2E, 0x9B, 0xC0, 0x21,
  3379. + 0x5F, 0xA0, 0x71, 0x32, 0x72, 0xE2, 0xE8, 0x43, 0x31, 0xEF, 0x41, 0xD7, 0xE1, 0x70, 0x81, 0xDD,
  3380. + 0x40, 0x70, 0xAE, 0x70, 0x00, 0x74, 0xFD, 0x81, 0xD5, 0x40, 0x74, 0xF9, 0xA2, 0x64, 0x0A, 0xB5,
  3381. + 0xEE, 0xF4, 0x20, 0xBB, 0x40, 0xD3, 0xD6, 0x42, 0xA1, 0x68, 0x47, 0xF7, 0x21, 0xFB, 0xD4, 0xDC,
  3382. + 0x43, 0x22, 0xAA, 0x73, 0x43, 0xD7, 0xF8, 0xD2, 0x72, 0xF0, 0x40, 0xD1, 0xE8, 0x43, 0x30, 0x71,
  3383. + 0xFF, 0x30, 0x76, 0x29, 0x95, 0xC0, 0xA9, 0x74, 0x71, 0x73, 0xE2, 0x76, 0x40, 0x51, 0x0D, 0x57,
  3384. + 0x0A, 0x73, 0x81, 0x28, 0x50, 0xDF, 0x73, 0xF9, 0xA2, 0x63, 0x04, 0x22, 0x50, 0x71, 0x21, 0xFF,
  3385. + 0x30, 0x72, 0xE0, 0x71, 0x21, 0x31, 0x72, 0xE1, 0xFF, 0x71, 0x22, 0x34, 0x73, 0xE0, 0x71, 0x22,
  3386. + 0x35, 0x5B, 0x73, 0xE1, 0x71, 0x50, 0x22, 0x54, 0x71, 0x51, 0x50, 0xF4, 0x20, 0xD5, 0xBC, 0xF8,
  3387. + 0x20, 0x22, 0xE7, 0x30, 0xD1, 0xD7, 0x40, 0x21, 0xA2, 0xD5, 0x75, 0xE8, 0x40, 0x71, 0x0B, 0x53,
  3388. + 0x71, 0x12, 0x51, 0x61, 0x0E, 0xDE, 0xF8, 0x21, 0x50, 0x25, 0xFA, 0xD2, 0x37, 0x51, 0xA2, 0x61,
  3389. + 0x7E, 0xE6, 0xA1, 0xD3, 0x40, 0xD1, 0x75, 0x71, 0x72, 0x0B, 0x50, 0xF5, 0x73, 0xCA, 0x51, 0xE2,
  3390. + 0xAA, 0x51, 0x43, 0xF2, 0xD1, 0x72, 0xF6, 0xAE, 0x52, 0x06, 0xB4, 0xF4, 0x21, 0x75, 0x76, 0x24,
  3391. + 0xFB, 0x7F, 0x43, 0x24, 0xF6, 0xC0, 0x22, 0xAE, 0x24, 0xE7, 0xA0, 0xFD, 0x30, 0x9A, 0x50, 0x47,
  3392. + 0x24, 0xF1, 0xD2, 0x06, 0x75, 0xBF, 0x51, 0xD5, 0x76, 0x51, 0xD6, 0x75, 0xF6, 0x50, 0xD0, 0xF7,
  3393. + 0x76, 0x30, 0xF4, 0xFB, 0x40, 0x70, 0x71, 0xF4, 0x70, 0x9F, 0x23, 0xF2, 0x24, 0xF6, 0x72, 0xED,
  3394. + 0x50, 0x01, 0x80, 0x0F, 0xFB, 0x75, 0xF1, 0x07, 0x61, 0xF1, 0xF4, 0x25, 0xFA, 0xC0, 0xFF, 0xAA,
  3395. + 0x70, 0xA9, 0x75, 0x81, 0xD5, 0x76, 0x81, 0xAF, 0xD6, 0x61, 0x0A, 0xF0, 0x10, 0x30, 0x01, 0x3A,
  3396. + 0x60, 0x71, 0xFF, 0x28, 0x9D, 0xA6, 0x21, 0x23, 0x29, 0xFA, 0x22, 0xFB, 0xF0, 0x00, 0x4A, 0x31,
  3397. + 0x20, 0x60, 0xB0, 0x4A, 0xD6, 0xFF, 0x21, 0x72, 0x21, 0x71, 0x28, 0x9A, 0x41, 0xF2, 0xFF, 0xD7,
  3398. + 0x21, 0x72, 0xD8, 0x10, 0x21, 0x71, 0x23, 0xFF, 0x93, 0x7B, 0x22, 0xC2, 0xC0, 0x21, 0xAB, 0x7B,
  3399. + 0xFF, 0x60, 0xCE, 0xC0, 0x21, 0xAA, 0x7B, 0x60, 0xCD, 0xFE, 0x6C, 0x60, 0x21, 0x71, 0x2E, 0x91,
  3400. + 0x23, 0x2E, 0x4D, 0x9F, 0xF0, 0xE0, 0x60, 0x4F, 0x21, 0x8C, 0x71, 0x80, 0x61, 0x60, 0xF5, 0x4E,
  3401. + 0x85, 0x62, 0x4D, 0x80, 0x61, 0x20, 0x71, 0x21, 0x9D, 0xDF, 0xAE, 0x24, 0xF2, 0x21, 0x32, 0xF6,
  3402. + 0x51, 0xAB, 0x72, 0xDB, 0x42, 0x9E, 0x8D, 0x61, 0x72, 0xEB, 0xA6, 0x65, 0x75, 0xF6, 0xFB, 0x42,
  3403. + 0xD2, 0x9A, 0x65, 0xA4, 0x40, 0x45, 0x95, 0xD2, 0xF3, 0x72, 0xC1, 0xB2, 0x61, 0x4B, 0x61, 0xBF,
  3404. + 0x68, 0xFC, 0xD0, 0xF1, 0x70, 0x30, 0x50, 0x0B, 0x60, 0x49, 0x31, 0x11, 0x00, 0x20, 0x05, 0xBF,
  3405. + 0x60, 0xBF, 0x73, 0x81, 0xD2, 0x73, 0xEC, 0x50, 0x21, 0xFF, 0xA4, 0x73, 0x25, 0xFA, 0x81, 0xD3,
  3406. + 0xF1, 0xA7, 0x7E, 0xE7, 0x61, 0xA8, 0x60, 0x02, 0x73, 0x72, 0xFC, 0x43, 0x30, 0xFD, 0x24, 0x82,
  3407. + 0x90, 0xD4, 0x03, 0x73, 0x51, 0xD3, 0x73, 0xB6, 0x06, 0x61, 0x74, 0x30, 0x12, 0x63, 0x74, 0x31,
  3408. + 0x19, 0x62, 0x61, 0xF7, 0x07, 0x70, 0x2F, 0x29, 0x90, 0x21, 0xAE, 0x70, 0x2F, 0xF7, 0x2F, 0x20,
  3409. + 0x40, 0xE9, 0x60, 0xA0, 0x70, 0x74, 0x32, 0xEF, 0x24, 0xF6, 0xA5, 0x80, 0x07, 0x70, 0x0D, 0x73,
  3410. + 0x83, 0xFF, 0xD3, 0x09, 0x80, 0x73, 0x82, 0xD3, 0x04, 0x80, 0xE8, 0x66, 0x50, 0xFB, 0x63, 0x3A,
  3411. + 0x61, 0x80, 0x52, 0x70, 0x00, 0x00, 0xFF, 0xAF, 0x00, 0x71, 0x22, 0x56, 0x49, 0x62, 0x00, 0x62,
  3412. + 0x70, 0xD0, 0xA9, 0x13, 0x62, 0x71, 0x68, 0x73, 0xD7, 0x67, 0x78, 0xEA, 0x67, 0x78, 0xF1, 0xAA,
  3413. + 0x67, 0x78, 0xF6, 0x67, 0x78, 0x05, 0x62, 0x70, 0x04, 0x62, 0x70, 0xFB, 0x7E, 0x67, 0x74, 0xFB,
  3414. + 0x12, 0x00, 0x00, 0x10, 0x14, 0x68, 0x73, 0xA5, 0xEF, 0xB3, 0x70, 0x23, 0xB7, 0x74, 0x62, 0x71,
  3415. + 0x3C, 0xB7, 0x74, 0x03, 0xAA, 0x62, 0x70, 0x4B, 0xB7, 0x74, 0x1A, 0x62, 0x70, 0x62, 0xB7, 0x74,
  3416. + 0xC0, 0xAA, 0xB3, 0x70, 0x06, 0x62, 0x70, 0x48, 0x9B, 0x78, 0x11, 0x62, 0x70, 0x1D, 0xAA, 0x62,
  3417. + 0x70, 0x29, 0x62, 0x70, 0x35, 0x62, 0x70, 0x44, 0x62, 0x70, 0x49, 0xAA, 0x62, 0x70, 0x51, 0x62,
  3418. + 0x70, 0x55, 0x62, 0x70, 0x5D, 0x62, 0x70, 0x61, 0xAA, 0x62, 0x70, 0x69, 0x62, 0x70, 0x6D, 0x62,
  3419. + 0x70, 0x75, 0x62, 0x70, 0x79, 0xAA, 0x62, 0x70, 0x81, 0x62, 0x70, 0x85, 0x62, 0x70, 0x8D, 0x62,
  3420. + 0x70, 0x94, 0xFE, 0x1F, 0x81, 0x15, 0x00, 0x00, 0x2E, 0x2E, 0x2F, 0x67, 0xFF, 0x65, 0x6E, 0x65,
  3421. + 0x72, 0x61, 0x74, 0x6F, 0x72, 0x7D, 0x2F, 0x6E, 0x40, 0x2E, 0x64, 0x62, 0x67, 0x00
  3422. +};
  3423. +
  3424. +static int32_t offtin(uint8_t *buf)
  3425. +{
  3426. + int32_t y;
  3427. + y = buf[7] & 0x7F;
  3428. + y = y * 256; y += buf[6];
  3429. + y = y * 256; y += buf[5];
  3430. + y = y * 256; y += buf[4];
  3431. + y = y * 256; y += buf[3];
  3432. + y = y * 256; y += buf[2];
  3433. + y = y * 256; y += buf[1];
  3434. + y = y * 256; y += buf[0];
  3435. + if(buf[7] & 0x80) y =- y;
  3436. + return y;
  3437. +}
  3438. +
  3439. +static int32_t bspatch(uint8_t *dest, uint8_t *src, int32_t src_len, uint8_t *patch)
  3440. +{
  3441. + int32_t i, newsize, bzctrllen, bzdatalen, oldpos, newpos, ctrl[3];
  3442. + uint8_t *cstream, *dstream, *estream;
  3443. +
  3444. + if(memcmp(patch, "BSDIFF40", 8)) return -1;
  3445. +
  3446. + bzctrllen = offtin(patch + 8);
  3447. + bzdatalen = offtin(patch + 16);
  3448. + newsize = offtin(patch + 24);
  3449. + if((bzctrllen < 0) || (bzdatalen < 0) || (newsize < 0)) return -1;
  3450. +
  3451. + oldpos = 0;
  3452. + newpos = 0;
  3453. + cstream = patch + 32;
  3454. + dstream = cstream + bzctrllen;
  3455. + estream = dstream + bzdatalen;
  3456. +
  3457. + while(newpos < newsize)
  3458. + {
  3459. + /* Read control data */
  3460. + for(i = 0; i < 3; i++)
  3461. + {
  3462. + ctrl[i] = offtin(cstream);
  3463. + cstream += 8;
  3464. + }
  3465. + /* Sanity-check */
  3466. + if((newpos + ctrl[0]) > newsize) return -1;
  3467. + /* Read diff string */
  3468. + memcpy(dest + newpos, dstream, ctrl[0]);
  3469. + dstream += ctrl[0];
  3470. + /* Add old data to diff string */
  3471. + for(i = 0; i < ctrl[0]; i++)
  3472. + {
  3473. + if(((oldpos + i) >= 0) && ((oldpos + i) < src_len)) dest[newpos + i] += src[oldpos + i];
  3474. + }
  3475. + /* Adjust pointers */
  3476. + newpos += ctrl[0];
  3477. + oldpos += ctrl[0];
  3478. + /* Sanity-check */
  3479. + if((newpos + ctrl[1]) > newsize) return -1;
  3480. + /* Read extra string */
  3481. + memcpy(dest + newpos, estream, ctrl[1]);
  3482. + estream += ctrl[1];
  3483. + /* Adjust pointers */
  3484. + newpos += ctrl[1];
  3485. + oldpos += ctrl[2];
  3486. + }
  3487. + return newsize;
  3488. +}
  3489. +
  3490. +static int32_t dre_unpack(uint8_t *dest, uint8_t *src, int32_t len)
  3491. +{
  3492. + uint8_t dbuf[0x1000], mask;
  3493. + int32_t i, soffs, doffs, dbidx, boffs, n;
  3494. +
  3495. + dbidx = 4078;
  3496. + memset(dbuf, 32, 4078);
  3497. + for(soffs = 0, doffs = 0; soffs < len; )
  3498. + {
  3499. + mask = src[soffs++];
  3500. + for(i = 0; i < 8 && soffs < len; i++, mask >>= 1)
  3501. + {
  3502. + if(mask & 1)
  3503. + {
  3504. + dest[doffs++] = dbuf[dbidx] = src[soffs++];
  3505. + dbidx = (dbidx + 1) & 0xfff;
  3506. + }
  3507. + else
  3508. + {
  3509. + boffs = src[soffs++];
  3510. + n = src[soffs++];
  3511. + boffs |= (n & 0xf0) << 4;
  3512. + n &= 0xf;
  3513. + n += 3;
  3514. + while(n--)
  3515. + {
  3516. + boffs &= 0xfff;
  3517. + dest[doffs++] = dbuf[dbidx] = dbuf[boffs++];
  3518. + dbidx = (dbidx + 1) & 0xfff;
  3519. + }
  3520. + }
  3521. + }
  3522. + }
  3523. + return doffs;
  3524. +}
  3525. +
  3526. +typedef struct
  3527. +{
  3528. + int32_t magic_number; /* magic number - value . */
  3529. + int32_t codesize; /* size of code in the rcu. */
  3530. + int32_t entrypointoffset; /* entrypoint offset into the code. */
  3531. + int32_t datasize; /* size of data region. */
  3532. + int32_t datalocationoffset; /* offset to place data at. */
  3533. + int32_t bsssize; /* size of bss region. */
  3534. + int32_t bsslocationoffset; /* offset to place bss at. */
  3535. + int32_t staticlinkoffset; /* offset to staticlink in data. */
  3536. + int32_t relsize; /* size of relocation table. */
  3537. + int32_t conssize; /* size of constructor table. */
  3538. + int32_t dessize; /* size of destructor table. */
  3539. + int32_t stacksize; /* size of stack this rcu needs. */
  3540. + int32_t heapsize; /* size of heap this rcu needs. */
  3541. + int32_t dbgfilenamesize; /* size of .dbg filename. */
  3542. + int32_t slot0; /* 4 words space for user use. */
  3543. + int32_t slot1;
  3544. + int32_t slot2;
  3545. + int32_t slot3;
  3546. +} rcu_header_t;
  3547. +
  3548. +static void rcu_load_offs(uint32_t *offs, uint8_t *buf, int32_t size)
  3549. +{
  3550. + uint32_t i;
  3551. + for(i = 0; i < size / sizeof(int32_t); i++)
  3552. + {
  3553. + offs[i] = (uint32_t)(buf[3 + i * 4] << 24) | (buf[2 + i * 4] << 16) | (buf[1 + i * 4] << 8) | buf[0 + i * 4];
  3554. + }
  3555. +}
  3556. +
  3557. +static void rcu_load(uint8_t *rcu)
  3558. +{
  3559. + int32_t rcu_data_size;
  3560. + uint32_t i;
  3561. + uint32_t nexports, nimports;
  3562. + rcu_header_t rcuh;
  3563. + uint8_t *ptr, *rcu_code, *rcu_data;
  3564. +// char *dbgfilename;
  3565. +
  3566. + rcu_load_offs((uint32_t *)&rcuh, rcu, sizeof(rcu_header_t));
  3567. + ptr = rcu + sizeof(rcu_header_t);
  3568. + rcu_code = ptr;
  3569. + ptr += rcuh.codesize;
  3570. + rcu_data_size = rcuh.datasize + rcuh.bsssize;
  3571. + rcu_data = ptr;
  3572. + ptr += rcuh.datasize;
  3573. +
  3574. + if(rcuh.relsize)
  3575. + {
  3576. + uint32_t relocations[rcuh.relsize / sizeof(int32_t)];
  3577. + rcu_load_offs(relocations, ptr, rcuh.relsize);
  3578. + ptr += rcuh.relsize;
  3579. + }
  3580. + if(rcuh.conssize)
  3581. + {
  3582. + uint32_t constructors[rcuh.conssize / sizeof(int32_t)];
  3583. + rcu_load_offs(constructors, ptr, rcuh.conssize);
  3584. + ptr += rcuh.conssize;
  3585. + }
  3586. + if(rcuh.dessize)
  3587. + {
  3588. + uint32_t destructors[rcuh.dessize / sizeof(int32_t)];
  3589. + rcu_load_offs(destructors, ptr, rcuh.dessize);
  3590. + ptr += rcuh.dessize;
  3591. + }
  3592. +// if(rcuh.dbgfilenamesize)
  3593. +// {
  3594. +// dbgfilename = (char *) ptr;
  3595. +// }
  3596. +
  3597. + ptr = rcu_data + rcu_data_size - 16 + 4;
  3598. + rcu_load_offs(&nexports, ptr, sizeof(int32_t));
  3599. + if(nexports)
  3600. + {
  3601. + uint32_t exports[nexports * 3];
  3602. + rcu_load_offs(exports, ptr - nexports * sizeof(int32_t) * 3, nexports * sizeof(int32_t) * 3);
  3603. + for(i = 0; i < nexports; i++)
  3604. + {
  3605. + char *symbol = (char *) (rcu_code + exports[0 + i * 3]);
  3606. + uint32_t faddr = exports[2 + i * 3];
  3607. + if(strcmp(symbol, "snippet_decrypt") == 0) gDecryptAddr = faddr;
  3608. + }
  3609. + }
  3610. + ptr -= nexports * 3 * sizeof(int32_t) + 8;
  3611. + rcu_load_offs(&nimports, ptr, sizeof(int32_t));
  3612. + if(nimports)
  3613. + {
  3614. + uint32_t imports[nimports * 3];
  3615. + rcu_load_offs(imports, ptr - nimports * sizeof(int32_t) * 3, nimports * sizeof(int32_t) * 3);
  3616. + }
  3617. +}
  3618. +
  3619. +static int32_t load_sections(uint8_t *body)
  3620. +{
  3621. + uint8_t section[4096];
  3622. + //uint8_t version;
  3623. + uint16_t sect_len, sect_no, last_sect_no, curr_sect_no = 0;
  3624. + //uint16_t table_id_extension;
  3625. + int32_t body_len, total_body_len = 0;
  3626. + //int32_t current_next_indicator;
  3627. + uint32_t i=0;
  3628. +
  3629. + while((i+3)<raw_buffer.used)
  3630. + {
  3631. + memcpy(section, raw_buffer.data+i, 3);
  3632. + i+=3;
  3633. + memcpy(&sect_len, section + 1, 2);
  3634. + sect_len = ntohs(sect_len) & 0xfff;
  3635. +
  3636. + memcpy(section + 3, raw_buffer.data+i, sect_len);
  3637. + i+=sect_len;
  3638. +
  3639. + if(section[0] != 0x91 || sect_len < (4 + 5)) continue;
  3640. +
  3641. + uint32_t crc = crc32(-1, section, sect_len + 3 - 4);
  3642. + uint32_t sect_crc = (uint32_t) section[sect_len - 1 + 3] << 24 | section[sect_len - 2 + 3] << 16 | section[sect_len - 3 + 3] << 8 | section[sect_len - 4 + 3];
  3643. + if(crc != sect_crc)
  3644. + {
  3645. + continue;
  3646. + }
  3647. +
  3648. + //table_id_extension = (section[3] << 8) | section[4];
  3649. + //version = (section[5] & 0x3e) >> 1;
  3650. + //current_next_indicator = section[5] & 1;
  3651. + sect_no = section[6];
  3652. + last_sect_no = section[7];
  3653. +
  3654. + if(curr_sect_no == 0)
  3655. + {
  3656. + gId = (section[13] << 8) | section[14];
  3657. + gVersion = (section[5] & 0x3e) >> 1;
  3658. + }
  3659. +
  3660. + if(curr_sect_no == sect_no)
  3661. + {
  3662. + body_len = sect_len - 5 - 4;
  3663. + memcpy(body, section + 8, body_len);
  3664. + total_body_len += body_len;
  3665. + body += body_len;
  3666. + curr_sect_no++;
  3667. + }
  3668. + if(curr_sect_no > last_sect_no) break;
  3669. + }
  3670. +
  3671. + return total_body_len;
  3672. +}
  3673. +
  3674. +static int32_t allocate_data_block(data_block *buff, uint32_t size)
  3675. +{
  3676. + if (buff->data == NULL)
  3677. + {
  3678. + buff->data = malloc(size);
  3679. + if (buff->data == NULL) { return -1; }
  3680. + buff->size = size;
  3681. + buff->used = 0;
  3682. + }
  3683. + if (buff->size < size)
  3684. + {
  3685. + uint8_t *new_buff;
  3686. +
  3687. + new_buff = malloc(size);
  3688. + if (new_buff == NULL) { return -1; }
  3689. + memcpy(new_buff, buff->data, buff->used);
  3690. +
  3691. + free(buff->data);
  3692. +
  3693. + buff->data = new_buff;
  3694. + buff->size = size;
  3695. + }
  3696. + return 0;
  3697. +}
  3698. +
  3699. +void Drecrypt2OverCW(uint16_t overcryptId, uint8_t *cw)
  3700. +{
  3701. + if(overcryptId == gId)
  3702. + {
  3703. + st20_run(code_buffer.data, code_buffer.used, gDecryptAddr, cw, overcryptId);
  3704. + }
  3705. + else
  3706. + {
  3707. + cs_log("[icg] ICG algo %04X not found", overcryptId);
  3708. + }
  3709. +}
  3710. +
  3711. +void Drecrypt2OverEMM(uint8_t *emm)
  3712. +{
  3713. + uint32_t dataLen;
  3714. +
  3715. + if(gVersion == (emm[5] & 0x3e) >> 1)
  3716. + {
  3717. + return;
  3718. + }
  3719. +
  3720. + if (gRawSec == 0)
  3721. + {
  3722. + if(emm[6] != 0)
  3723. + {
  3724. + return;
  3725. + }
  3726. + }
  3727. +
  3728. + if (emm[6] != gRawSec)
  3729. + {
  3730. + gRawSec = 0;
  3731. + return;
  3732. + }
  3733. +
  3734. + dataLen = ((emm[1] & 0xF) << 8) | emm[2];
  3735. + dataLen += 3;
  3736. + if(dataLen < 4)
  3737. + {
  3738. + return;
  3739. + }
  3740. +
  3741. + if (gRawSec == 0)
  3742. + {
  3743. + raw_buffer.used = 0;
  3744. + }
  3745. +
  3746. + if (allocate_data_block(&raw_buffer, raw_buffer.used + dataLen))
  3747. + {
  3748. + return;
  3749. + }
  3750. +
  3751. + memcpy(raw_buffer.data + raw_buffer.used, emm, dataLen);
  3752. + raw_buffer.used += dataLen;
  3753. +
  3754. + if (emm[6] != emm[7])
  3755. + {
  3756. + gRawSec++;
  3757. + return;
  3758. + }
  3759. +
  3760. + gRawSec = 0;
  3761. +
  3762. + int32_t patch_len, rcu_len, len, snip_len;
  3763. + uint8_t *buf = malloc(0x1000), *snip = malloc(0x10000), *rcu = malloc(0x10000), *patch = malloc(0x10000);
  3764. +
  3765. + if(buf == NULL || snip == NULL || rcu == NULL || patch == NULL) {printf("can't allocate memory\n"); return;}
  3766. +
  3767. + snip_len = (initial_snippet[4] << 24) | (initial_snippet[5] << 16) | (initial_snippet[6] << 8) | initial_snippet[7];
  3768. +
  3769. + if(dre_unpack(snip, initial_snippet + 8, sizeof(initial_snippet) - 8) >= snip_len)
  3770. + {
  3771. + len = load_sections(buf);
  3772. +
  3773. + patch_len = (buf[14] << 24) | (buf[15] << 16) | (buf[16] << 8) | buf[17];
  3774. + if(dre_unpack(patch, buf + 18, len - 18) >= patch_len)
  3775. + {
  3776. + rcu_len = bspatch(rcu, snip, snip_len, patch);
  3777. + if(rcu_len > 0)
  3778. + {
  3779. + rcu_load(rcu);
  3780. + allocate_data_block(&code_buffer,rcu_len);
  3781. + memcpy(code_buffer.data, rcu, rcu_len);
  3782. + code_buffer.used = (uint32_t) rcu_len;
  3783. + }
  3784. + }
  3785. + }
  3786. +
  3787. + //gId = (raw_buffer.data[13] << 8) | raw_buffer.data[14];
  3788. + //gVersion = (emm[5] & 0x3e) >> 1;
  3789. +
  3790. + free(buf);
  3791. + free(snip);
  3792. + free(rcu);
  3793. + free(patch);
  3794. +
  3795. + cs_log("[icg] snippet patch created. ICG algo %04X", gId);
  3796. +}
  3797. +
  3798. Index: module-emulator-dre2overcrypt.h
  3799. ===================================================================
  3800. --- module-emulator-dre2overcrypt.h (revision 0)
  3801. +++ module-emulator-dre2overcrypt.h (working copy)
  3802. @@ -0,0 +1,7 @@
  3803. +#ifndef DRE2_OVERCRYPT_H_
  3804. +#define DRE2_OVERCRYPT_H_
  3805. +
  3806. + void Drecrypt2OverCW(uint16_t overcryptId, uint8_t *cw);
  3807. + void Drecrypt2OverEMM(uint8_t *emm);
  3808. +
  3809. +#endif
  3810. Index: module-emulator-osemu.c
  3811. ===================================================================
  3812. --- module-emulator-osemu.c (revision 0)
  3813. +++ module-emulator-osemu.c (working copy)
  3814. @@ -0,0 +1,4291 @@
  3815. +#include "globals.h"
  3816. +#include "ffdecsa/ffdecsa.h"
  3817. +#include "cscrypt/bn.h"
  3818. +#include "cscrypt/des.h"
  3819. +#include "cscrypt/idea.h"
  3820. +#include "cscrypt/md5.h"
  3821. +
  3822. +#ifdef WITH_EMU
  3823. +#include "oscam-aes.h"
  3824. +#include "oscam-string.h"
  3825. +#include "oscam-config.h"
  3826. +#include "oscam-conf-chk.h"
  3827. +#include "oscam-time.h"
  3828. +#include "module-newcamd-des.h"
  3829. +// from reader-viaccess.c:
  3830. +void hdSurEncPhase1_D2_0F_11(uint8_t *CWs);
  3831. +void hdSurEncPhase2_D2_0F_11(uint8_t *CWs);
  3832. +void hdSurEncPhase1_D2_13_15(uint8_t *cws);
  3833. +void hdSurEncPhase2_D2_13_15(uint8_t *cws);
  3834. +#else
  3835. +#include "cscrypt/viades.h"
  3836. +#include "via3surenc.h"
  3837. +#endif
  3838. +
  3839. +#include "module-emulator-osemu.h"
  3840. +#include "module-emulator-stream.h"
  3841. +#include "module-emulator-dre2overcrypt.h"
  3842. +
  3843. +// Version info
  3844. +uint32_t GetOSemuVersion(void)
  3845. +{
  3846. + return atoi("$Version: 728 $"+10);
  3847. +}
  3848. +
  3849. +// Key DB
  3850. +static char *emu_keyfile_path = NULL;
  3851. +
  3852. +void set_emu_keyfile_path(const char *path)
  3853. +{
  3854. + if(emu_keyfile_path != NULL) {
  3855. + free(emu_keyfile_path);
  3856. + }
  3857. + emu_keyfile_path = (char*)malloc(strlen(path)+1);
  3858. + if(emu_keyfile_path == NULL) {
  3859. + return;
  3860. + }
  3861. + memcpy(emu_keyfile_path, path, strlen(path));
  3862. + emu_keyfile_path[strlen(path)] = 0;
  3863. +}
  3864. +
  3865. +int32_t CharToBin(uint8_t *out, const char *in, uint32_t inLen)
  3866. +{
  3867. + uint32_t i, tmp;
  3868. + for(i=0; i<inLen/2; i++) {
  3869. + if(sscanf(in + i*2, "%02X", &tmp) != 1) {
  3870. + return 0;
  3871. + }
  3872. + out[i] = (uint8_t)tmp;
  3873. + }
  3874. + return 1;
  3875. +}
  3876. +
  3877. +
  3878. +KeyDataContainer CwKeys = { NULL, 0, 0 };
  3879. +KeyDataContainer ViKeys = { NULL, 0, 0 };
  3880. +KeyDataContainer NagraKeys = { NULL, 0, 0 };
  3881. +KeyDataContainer IrdetoKeys = { NULL, 0, 0 };
  3882. +KeyDataContainer NDSKeys = { NULL, 0, 0 };
  3883. +KeyDataContainer BissKeys = { NULL, 0, 0 };
  3884. +KeyDataContainer PowervuKeys = { NULL, 0, 0 };
  3885. +KeyDataContainer DreKeys = { NULL, 0, 0 };
  3886. +
  3887. +static KeyDataContainer *GetKeyContainer(char identifier)
  3888. +{
  3889. + switch(identifier) {
  3890. + case 'W':
  3891. + return &CwKeys;
  3892. + case 'V':
  3893. + return &ViKeys;
  3894. + case 'N':
  3895. + return &NagraKeys;
  3896. + case 'I':
  3897. + return &IrdetoKeys;
  3898. + case 'S':
  3899. + return &NDSKeys;
  3900. + case 'F':
  3901. + return &BissKeys;
  3902. + case 'P':
  3903. + return &PowervuKeys;
  3904. + case 'D':
  3905. + return &DreKeys;
  3906. + default:
  3907. + return NULL;
  3908. + }
  3909. +}
  3910. +
  3911. +static void WriteKeyToFile(char identifier, uint32_t provider, const char *keyName, uint8_t *key, uint32_t keyLength, char* comment)
  3912. +{
  3913. + char line[1200], dateText[100];
  3914. + uint32_t pathLength;
  3915. + struct dirent *pDirent;
  3916. + DIR *pDir;
  3917. + char *path, *filepath, filename[EMU_KEY_FILENAME_MAX_LEN+1], *keyValue;
  3918. + FILE *file = NULL;
  3919. + uint8_t fileNameLen = strlen(EMU_KEY_FILENAME);
  3920. + time_t now;
  3921. + struct tm t;
  3922. +
  3923. + pathLength = strlen(emu_keyfile_path);
  3924. + path = (char*)malloc(pathLength+1);
  3925. + if(path == NULL) {
  3926. + return;
  3927. + }
  3928. + strncpy(path, emu_keyfile_path, pathLength+1);
  3929. +
  3930. + pathLength = strlen(path);
  3931. + if(pathLength >= fileNameLen && strcasecmp(path+pathLength-fileNameLen, EMU_KEY_FILENAME) == 0) {
  3932. + // cut file name
  3933. + path[pathLength-fileNameLen] = '\0';
  3934. + }
  3935. +
  3936. + pathLength = strlen(path);
  3937. + if(path[pathLength-1] == '/' || path[pathLength-1] == '\\') {
  3938. + // cut trailing /
  3939. + path[pathLength-1] = '\0';
  3940. + }
  3941. +
  3942. + pDir = opendir(path);
  3943. + if (pDir == NULL) {
  3944. + cs_log("cannot open key file path: %s", path);
  3945. + free(path);
  3946. + return;
  3947. + }
  3948. +
  3949. + while((pDirent = readdir(pDir)) != NULL) {
  3950. + if(strcasecmp(pDirent->d_name, EMU_KEY_FILENAME) == 0) {
  3951. + strncpy(filename, pDirent->d_name, sizeof(filename));
  3952. + break;
  3953. + }
  3954. + }
  3955. + closedir(pDir);
  3956. +
  3957. + if(pDirent == NULL) {
  3958. + strncpy(filename, EMU_KEY_FILENAME, sizeof(filename));
  3959. + }
  3960. +
  3961. + pathLength = strlen(path)+1+strlen(filename)+1;
  3962. + filepath = (char*)malloc(pathLength);
  3963. + if(filepath == NULL) {
  3964. + free(path);
  3965. + return;
  3966. + }
  3967. + snprintf(filepath, pathLength, "%s/%s", path, filename);
  3968. + free(path);
  3969. +
  3970. + cs_log("writing key file: %s", filepath);
  3971. +
  3972. + file = fopen(filepath, "a");
  3973. + free(filepath);
  3974. + if(file == NULL) {
  3975. + return;
  3976. + }
  3977. +
  3978. + now = time(NULL);
  3979. + localtime_r(&now, &t);
  3980. + strftime(dateText, sizeof(dateText)-1, "%c", &t);
  3981. +
  3982. + keyValue = (char*)malloc((keyLength*2)+1);
  3983. + if(keyValue == NULL) {
  3984. + fclose(file);
  3985. + return;
  3986. + }
  3987. + cs_hexdump(0, key, keyLength, keyValue, (keyLength*2)+1);
  3988. +
  3989. + if(comment)
  3990. + {
  3991. + snprintf(line, sizeof(line), "\n%c %08X %s %s ; added by OSEmu %s %s\n", identifier, provider, keyName, keyValue, dateText, comment);
  3992. + }
  3993. + else
  3994. + {
  3995. + snprintf(line, sizeof(line), "\n%c %04X %s %s ; added by OSEmu %s\n", identifier, provider, keyName, keyValue, dateText);
  3996. + }
  3997. + cs_log("[Emu] Key written: %c %08X %s %s", identifier, provider, keyName, keyValue);
  3998. + free(keyValue);
  3999. +
  4000. + fwrite(line, strlen(line), 1, file);
  4001. + fclose(file);
  4002. +}
  4003. +
  4004. +// key must come from malloc() !
  4005. +static int32_t SetKey(char identifier, uint32_t provider, const char *keyName, uint8_t *key,
  4006. + uint32_t keyLength, uint8_t writeKey, char *comment)
  4007. +{
  4008. + uint32_t i, j;
  4009. + uint8_t *tmpKey = NULL, *orgKey = NULL;
  4010. + KeyDataContainer *KeyDB;
  4011. + KeyData *tmpKeyData, *newKeyData;
  4012. + identifier = (char)toupper((int)identifier);
  4013. + uint8_t key_exists = 0;
  4014. +
  4015. + KeyDB = GetKeyContainer(identifier);
  4016. + if(KeyDB == NULL) {
  4017. + return 0;
  4018. + }
  4019. +
  4020. + // fix patched mgcamd format for Irdeto
  4021. + if(identifier == 'I' && provider < 0xFFFF) {
  4022. + provider = provider<<8;
  4023. + }
  4024. +
  4025. + // fix checksum for biss keys with a length of 6
  4026. + if(identifier == 'F' && keyLength == 6) {
  4027. +
  4028. + tmpKey = (uint8_t*)malloc(8*sizeof(uint8_t));
  4029. + if(tmpKey == NULL) {
  4030. + return 0;
  4031. + }
  4032. +
  4033. + tmpKey[0] = key[0];
  4034. + tmpKey[1] = key[1];
  4035. + tmpKey[2] = key[2];
  4036. + tmpKey[3] = ((key[0] + key[1] + key[2]) & 0xff);
  4037. + tmpKey[4] = key[3];
  4038. + tmpKey[5] = key[4];
  4039. + tmpKey[6] = key[5];
  4040. + tmpKey[7] = ((key[3] + key[4] + key[5]) & 0xff);
  4041. +
  4042. + orgKey = key;
  4043. + key = tmpKey;
  4044. + keyLength = 8;
  4045. + }
  4046. +
  4047. + for(i=0; i<KeyDB->keyCount; i++) {
  4048. + if(strcmp(KeyDB->EmuKeys[i].keyName, keyName)) {
  4049. + continue;
  4050. + }
  4051. +
  4052. + if( identifier == 'P' ) {
  4053. + if(writeKey) {
  4054. + if( (KeyDB->EmuKeys[i].provider & 0xFFFF0000) != (provider & 0xFFFF0000) ) { // mask out srvid, only compare group
  4055. + continue;
  4056. + }
  4057. + tmpKeyData = &KeyDB->EmuKeys[i];
  4058. + if(memcmp(tmpKeyData->key, key, tmpKeyData->keyLength < keyLength ? tmpKeyData->keyLength : keyLength) == 0) {
  4059. + key_exists = 1;
  4060. + continue;
  4061. + }
  4062. + provider = KeyDB->EmuKeys[i].provider; // set to matched full provider ( group + srvid )
  4063. + }
  4064. + else {
  4065. + if( KeyDB->EmuKeys[i].provider != provider ) {
  4066. + continue;
  4067. + }
  4068. + }
  4069. + }
  4070. + else {
  4071. + if(KeyDB->EmuKeys[i].provider != provider) {
  4072. + continue;
  4073. + }
  4074. + }
  4075. + key_exists = 1;
  4076. +
  4077. + // allow multiple keys for Irdeto and Powervu
  4078. + if(identifier == 'I')
  4079. + {
  4080. + // reject duplicates
  4081. + tmpKeyData = &KeyDB->EmuKeys[i];
  4082. + do {
  4083. + if(memcmp(tmpKeyData->key, key, tmpKeyData->keyLength < keyLength ? tmpKeyData->keyLength : keyLength) == 0) {
  4084. + if(tmpKey != NULL) {
  4085. + free(tmpKey);
  4086. + }
  4087. + return 0;
  4088. + }
  4089. + tmpKeyData = tmpKeyData->nextKey;
  4090. + }
  4091. + while(tmpKeyData != NULL);
  4092. +
  4093. + // add new key
  4094. + newKeyData = (KeyData*)malloc(sizeof(KeyData));
  4095. + if(newKeyData == NULL) {
  4096. + if(tmpKey != NULL) {
  4097. + free(tmpKey);
  4098. + }
  4099. + return 0;
  4100. + }
  4101. + newKeyData->identifier = identifier;
  4102. + newKeyData->provider = provider;
  4103. + if(strlen(keyName) < EMU_MAX_CHAR_KEYNAME) {
  4104. + strncpy(newKeyData->keyName, keyName, EMU_MAX_CHAR_KEYNAME);
  4105. + }
  4106. + else {
  4107. + memcpy(newKeyData->keyName, keyName, EMU_MAX_CHAR_KEYNAME);
  4108. + }
  4109. + newKeyData->keyName[EMU_MAX_CHAR_KEYNAME-1] = 0;
  4110. + newKeyData->key = key;
  4111. + newKeyData->keyLength = keyLength;
  4112. + newKeyData->nextKey = NULL;
  4113. +
  4114. + tmpKeyData = &KeyDB->EmuKeys[i];
  4115. + j = 0;
  4116. + while(tmpKeyData->nextKey != NULL) {
  4117. + if(j == 0xFE)
  4118. + {
  4119. + break;
  4120. + }
  4121. + tmpKeyData = tmpKeyData->nextKey;
  4122. + j++;
  4123. + }
  4124. + if(tmpKeyData->nextKey)
  4125. + {
  4126. + NULLFREE(tmpKeyData->nextKey->key);
  4127. + NULLFREE(tmpKeyData->nextKey);
  4128. + }
  4129. + tmpKeyData->nextKey = newKeyData;
  4130. +
  4131. + if(writeKey) {
  4132. + WriteKeyToFile(identifier, provider, keyName, key, keyLength, comment);
  4133. + }
  4134. + }
  4135. + else // identifier != 'I'
  4136. + {
  4137. + free(KeyDB->EmuKeys[i].key);
  4138. + KeyDB->EmuKeys[i].key = key;
  4139. + KeyDB->EmuKeys[i].keyLength = keyLength;
  4140. +
  4141. + if(writeKey) {
  4142. + WriteKeyToFile(identifier, provider, keyName, key, keyLength, comment);
  4143. + }
  4144. + }
  4145. +
  4146. + if(tmpKey != NULL) {
  4147. + free(orgKey);
  4148. + }
  4149. + if((identifier != 'P') | !writeKey){ // on pvu update continue loop to find others in group
  4150. + return 1;
  4151. + }
  4152. + }
  4153. +
  4154. + if(key_exists) {
  4155. + return 1;
  4156. + }
  4157. +
  4158. + if(KeyDB->keyCount+1 > KeyDB->keyMax) {
  4159. + if(KeyDB->EmuKeys == NULL) {
  4160. + KeyDB->EmuKeys = (KeyData*)malloc(sizeof(KeyData)*(KeyDB->keyMax+64));
  4161. + if(KeyDB->EmuKeys == NULL) {
  4162. + if(tmpKey != NULL) {
  4163. + free(tmpKey);
  4164. + }
  4165. + return 0;
  4166. + }
  4167. + KeyDB->keyMax+=64;
  4168. + }
  4169. + else {
  4170. + tmpKeyData = (KeyData*)realloc(KeyDB->EmuKeys, sizeof(KeyData)*(KeyDB->keyMax+16));
  4171. + if(tmpKeyData == NULL) {
  4172. + if(tmpKey != NULL) {
  4173. + free(tmpKey);
  4174. + }
  4175. + return 0;
  4176. + }
  4177. + KeyDB->EmuKeys = tmpKeyData;
  4178. + KeyDB->keyMax+=16;
  4179. + }
  4180. + }
  4181. +
  4182. + KeyDB->EmuKeys[KeyDB->keyCount].identifier = identifier;
  4183. + KeyDB->EmuKeys[KeyDB->keyCount].provider = provider;
  4184. + if(strlen(keyName) < EMU_MAX_CHAR_KEYNAME) {
  4185. + strncpy(KeyDB->EmuKeys[KeyDB->keyCount].keyName, keyName, EMU_MAX_CHAR_KEYNAME);
  4186. + }
  4187. + else {
  4188. + memcpy(KeyDB->EmuKeys[KeyDB->keyCount].keyName, keyName, EMU_MAX_CHAR_KEYNAME);
  4189. + }
  4190. + KeyDB->EmuKeys[KeyDB->keyCount].keyName[EMU_MAX_CHAR_KEYNAME-1] = 0;
  4191. + KeyDB->EmuKeys[KeyDB->keyCount].key = key;
  4192. + KeyDB->EmuKeys[KeyDB->keyCount].keyLength = keyLength;
  4193. + KeyDB->EmuKeys[KeyDB->keyCount].nextKey = NULL;
  4194. + KeyDB->keyCount++;
  4195. +
  4196. + if(writeKey) {
  4197. + WriteKeyToFile(identifier, provider, keyName, key, keyLength, comment);
  4198. + }
  4199. +
  4200. + if(tmpKey != NULL) {
  4201. + free(orgKey);
  4202. + }
  4203. + return 1;
  4204. +}
  4205. +
  4206. +static int32_t FindKey(char identifier, uint32_t provider, const char *keyName, uint8_t *key, uint32_t maxKeyLength,
  4207. + uint8_t isCriticalKey, uint8_t keyRef, uint8_t matchLength, uint32_t *getProvider)
  4208. +{
  4209. + uint32_t i;
  4210. + uint16_t j;
  4211. + uint8_t k;
  4212. + KeyDataContainer *KeyDB;
  4213. + KeyData *tmpKeyData;
  4214. +
  4215. + KeyDB = GetKeyContainer(identifier);
  4216. + if(KeyDB == NULL) {
  4217. + return 0;
  4218. + }
  4219. +
  4220. + k = 0;
  4221. + for(i=0; i<KeyDB->keyCount; i++) {
  4222. + if(identifier == 'P') {
  4223. + if( getProvider == NULL && (KeyDB->EmuKeys[i].provider & 0x0000FFFF) != provider ) { // mask out group, only compare srvid
  4224. + continue;
  4225. + }
  4226. + //provider = KeyDB->EmuKeys[i].provider; // set to matched full provider ( group + srvid )
  4227. + }
  4228. + else {
  4229. + if(getProvider == NULL && KeyDB->EmuKeys[i].provider != provider) {
  4230. + continue;
  4231. + }
  4232. + }
  4233. +
  4234. + if(strcmp(KeyDB->EmuKeys[i].keyName, keyName)) {
  4235. + continue;
  4236. + }
  4237. +
  4238. + //matchLength cannot be used when multiple keys are allowed
  4239. + //for a single provider/keyName combination.
  4240. + //Currently this is only the case for Irdeto keys.
  4241. + if(matchLength && KeyDB->EmuKeys[i].keyLength != maxKeyLength) {
  4242. + continue;
  4243. + }
  4244. +
  4245. + if(identifier == 'P') {
  4246. + if(k < keyRef) {
  4247. + k++;
  4248. + continue;
  4249. + }
  4250. + else {
  4251. + keyRef = 0;
  4252. + }
  4253. + }
  4254. +
  4255. + tmpKeyData = &KeyDB->EmuKeys[i];
  4256. +
  4257. + j = 0;
  4258. + while(j<keyRef && tmpKeyData->nextKey != NULL) {
  4259. + j++;
  4260. + tmpKeyData = tmpKeyData->nextKey;
  4261. + }
  4262. +
  4263. + if(j == keyRef) {
  4264. + memcpy(key, tmpKeyData->key, tmpKeyData->keyLength > maxKeyLength ? maxKeyLength : tmpKeyData->keyLength);
  4265. + if(tmpKeyData->keyLength < maxKeyLength) {
  4266. + memset(key+tmpKeyData->keyLength, 0, maxKeyLength - tmpKeyData->keyLength);
  4267. + }
  4268. + if(getProvider != NULL) {
  4269. + (*getProvider) = tmpKeyData->provider;
  4270. + }
  4271. + return 1;
  4272. + }
  4273. + else {
  4274. + break;
  4275. + }
  4276. + }
  4277. +
  4278. + if(isCriticalKey) {
  4279. + cs_log("[Emu] Key not found: %c %X %s", identifier, provider, keyName);
  4280. + }
  4281. + return 0;
  4282. +}
  4283. +
  4284. +// key must come from malloc() !
  4285. +static int32_t UpdateKey(char identifier, uint32_t provider, char *keyName, uint8_t *key, uint32_t keyLength, char *comment)
  4286. +{
  4287. + uint8_t keyRef = 0;
  4288. + uint8_t *tmpKey = (uint8_t*)malloc(sizeof(uint8_t)*keyLength);
  4289. + if(tmpKey == NULL)
  4290. + {
  4291. + return 0;
  4292. + }
  4293. +
  4294. + while(FindKey(identifier, provider, keyName, tmpKey, keyLength, 0, keyRef, 0, NULL))
  4295. + {
  4296. + if(memcmp(tmpKey, key, keyLength) == 0)
  4297. + {
  4298. + free(tmpKey);
  4299. + return 0;
  4300. + }
  4301. + if(keyRef == 0xFF)
  4302. + {
  4303. + break;
  4304. + }
  4305. + keyRef++;
  4306. + }
  4307. +
  4308. + free(tmpKey);
  4309. +
  4310. + return SetKey(identifier, provider, keyName, key, keyLength, 1, comment);
  4311. +}
  4312. +
  4313. +
  4314. +uint8_t read_emu_keyfile(const char *opath)
  4315. +{
  4316. + char line[1200], keyName[EMU_MAX_CHAR_KEYNAME], keyString[1026];
  4317. + uint32_t pathLength, provider, keyLength;
  4318. + uint8_t *key;
  4319. + struct dirent *pDirent;
  4320. + DIR *pDir;
  4321. + char *path, *filepath, filename[EMU_KEY_FILENAME_MAX_LEN+1];
  4322. + FILE *file = NULL;
  4323. + char identifier;
  4324. + uint8_t fileNameLen = strlen(EMU_KEY_FILENAME);
  4325. +
  4326. + pathLength = strlen(opath);
  4327. + path = (char*)malloc(pathLength+1);
  4328. + if(path == NULL) {
  4329. + return 0;
  4330. + }
  4331. + strncpy(path, opath, pathLength+1);
  4332. +
  4333. + pathLength = strlen(path);
  4334. + if(pathLength >= fileNameLen && strcasecmp(path+pathLength-fileNameLen, EMU_KEY_FILENAME) == 0) {
  4335. + // cut file name
  4336. + path[pathLength-fileNameLen] = '\0';
  4337. + }
  4338. +
  4339. + pathLength = strlen(path);
  4340. + if(path[pathLength-1] == '/' || path[pathLength-1] == '\\') {
  4341. + // cut trailing /
  4342. + path[pathLength-1] = '\0';
  4343. + }
  4344. +
  4345. + pDir = opendir(path);
  4346. + if (pDir == NULL) {
  4347. + cs_log("cannot open key file path: %s", path);
  4348. + free(path);
  4349. + return 0;
  4350. + }
  4351. +
  4352. + while((pDirent = readdir(pDir)) != NULL) {
  4353. + if(strcasecmp(pDirent->d_name, EMU_KEY_FILENAME) == 0) {
  4354. + strncpy(filename, pDirent->d_name, sizeof(filename));
  4355. + break;
  4356. + }
  4357. + }
  4358. + closedir(pDir);
  4359. +
  4360. + if(pDirent == NULL) {
  4361. + cs_log("key file not found in: %s", path);
  4362. + free(path);
  4363. + return 0;
  4364. + }
  4365. +
  4366. + pathLength = strlen(path)+1+strlen(filename)+1;
  4367. + filepath = (char*)malloc(pathLength);
  4368. + if(filepath == NULL) {
  4369. + free(path);
  4370. + return 0;
  4371. + }
  4372. + snprintf(filepath, pathLength, "%s/%s", path, filename);
  4373. + free(path);
  4374. +
  4375. + cs_log("reading key file: %s", filepath);
  4376. +
  4377. + file = fopen(filepath, "r");
  4378. + free(filepath);
  4379. + if(file == NULL) {
  4380. + return 0;
  4381. + }
  4382. +
  4383. + set_emu_keyfile_path(opath);
  4384. +
  4385. + while(fgets(line, 1200, file)) {
  4386. + if(sscanf(line, "%c %8x %11s %1024s", &identifier, &provider, keyName, keyString) != 4) {
  4387. + continue;
  4388. + }
  4389. +
  4390. + keyLength = strlen(keyString)/2;
  4391. + key = (uint8_t*)malloc(keyLength);
  4392. + if(key == NULL) {
  4393. + fclose(file);
  4394. + return 0;
  4395. + }
  4396. +
  4397. + CharToBin(key, keyString, strlen(keyString));
  4398. + if(!SetKey(identifier, provider, keyName, key, keyLength, 0, NULL)) {
  4399. + free(key);
  4400. + }
  4401. + }
  4402. + fclose(file);
  4403. +
  4404. + return 1;
  4405. +}
  4406. +
  4407. +#if !defined(__APPLE__) && !defined(__ANDROID__)
  4408. +extern uint8_t SoftCamKey_Data[] __asm__("_binary_SoftCam_Key_start");
  4409. +extern uint8_t SoftCamKey_DataEnd[] __asm__("_binary_SoftCam_Key_end");
  4410. +
  4411. +void read_emu_keymemory(void)
  4412. +{
  4413. + char *keyData, *line, *saveptr, keyName[EMU_MAX_CHAR_KEYNAME], keyString[1026];
  4414. + uint32_t provider, keyLength;
  4415. + uint8_t *key;
  4416. + char identifier;
  4417. +
  4418. + keyData = (char*)malloc(SoftCamKey_DataEnd-SoftCamKey_Data+1);
  4419. + if(keyData == NULL) {
  4420. + return;
  4421. + }
  4422. + memcpy(keyData, SoftCamKey_Data, SoftCamKey_DataEnd-SoftCamKey_Data);
  4423. + keyData[SoftCamKey_DataEnd-SoftCamKey_Data] = 0x00;
  4424. +
  4425. + line = strtok_r(keyData, "\n", &saveptr);
  4426. + while(line != NULL) {
  4427. + if(sscanf(line, "%c %8x %11s %1024s", &identifier, &provider, keyName, keyString) != 4) {
  4428. + line = strtok_r(NULL, "\n", &saveptr);
  4429. + continue;
  4430. + }
  4431. + keyLength = strlen(keyString)/2;
  4432. + key = (uint8_t*)malloc(keyLength);
  4433. + if(key == NULL) {
  4434. + free(keyData);
  4435. + return;
  4436. + }
  4437. +
  4438. + CharToBin(key, keyString, strlen(keyString));
  4439. + if(!SetKey(identifier, provider, keyName, key, keyLength, 0, NULL)) {
  4440. + free(key);
  4441. + }
  4442. + line = strtok_r(NULL, "\n", &saveptr);
  4443. + }
  4444. + free(keyData);
  4445. +}
  4446. +#endif
  4447. +
  4448. +// Shared functions
  4449. +
  4450. +static inline uint16_t GetEcmLen(const uint8_t *ecm)
  4451. +{
  4452. + return (((ecm[1] & 0x0f)<< 8) | ecm[2]) +3;
  4453. +}
  4454. +
  4455. +static void ReverseMem(uint8_t *in, int32_t len)
  4456. +{
  4457. + uint8_t temp;
  4458. + int32_t i;
  4459. + for(i = 0; i < (len / 2); i++) {
  4460. + temp = in[i];
  4461. + in[i] = in[len - i - 1];
  4462. + in[len - i - 1] = temp;
  4463. + }
  4464. +}
  4465. +
  4466. +static void ReverseMemInOut(uint8_t *out, const uint8_t *in, int32_t n)
  4467. +{
  4468. + if(n>0) {
  4469. + out+=n;
  4470. + do {
  4471. + *(--out)=*(in++);
  4472. + }
  4473. + while(--n);
  4474. + }
  4475. +}
  4476. +
  4477. +static int8_t EmuRSAInput(BIGNUM *d, const uint8_t *in, int32_t n, int8_t le)
  4478. +{
  4479. + int8_t result = 0;
  4480. +
  4481. + if(le) {
  4482. + uint8_t *tmp = (uint8_t *)malloc(sizeof(uint8_t)*n);
  4483. + if(tmp == NULL) {
  4484. + return 0;
  4485. + }
  4486. + ReverseMemInOut(tmp,in,n);
  4487. + result = BN_bin2bn(tmp,n,d)!=0;
  4488. + free(tmp);
  4489. + }
  4490. + else {
  4491. + result = BN_bin2bn(in,n,d)!=0;
  4492. + }
  4493. + return result;
  4494. +}
  4495. +
  4496. +static int32_t EmuRSAOutput(uint8_t *out, int32_t n, BIGNUM *r, int8_t le)
  4497. +{
  4498. + int32_t s = BN_num_bytes(r);
  4499. + if(s>n) {
  4500. + uint8_t *buff = (uint8_t *)malloc(sizeof(uint8_t)*s);
  4501. + if(buff == NULL) {
  4502. + return 0;
  4503. + }
  4504. + BN_bn2bin(r,buff);
  4505. + memcpy(out,buff+s-n,n);
  4506. + free(buff);
  4507. + }
  4508. + else if(s<n) {
  4509. + int32_t l=n-s;
  4510. + memset(out,0,l);
  4511. + BN_bn2bin(r,out+l);
  4512. + }
  4513. + else {
  4514. + BN_bn2bin(r,out);
  4515. + }
  4516. + if(le) {
  4517. + ReverseMem(out,n);
  4518. + }
  4519. + return s;
  4520. +}
  4521. +
  4522. +static int32_t EmuRSA(uint8_t *out, const uint8_t *in, int32_t n, BIGNUM *exp, BIGNUM *mod, int8_t le)
  4523. +{
  4524. + BN_CTX *ctx;
  4525. + BIGNUM *r, *d;
  4526. + int32_t result = 0;
  4527. +
  4528. + ctx = BN_CTX_new();
  4529. + r = BN_new();
  4530. + d = BN_new();
  4531. +
  4532. + if(EmuRSAInput(d,in,n,le) && BN_mod_exp(r,d,exp,mod,ctx)) {
  4533. + result = EmuRSAOutput(out,n,r,le);
  4534. + }
  4535. +
  4536. + BN_free(d);
  4537. + BN_free(r);
  4538. + BN_CTX_free(ctx);
  4539. + return result;
  4540. +}
  4541. +
  4542. +static inline void xxor(uint8_t *data, int32_t len, const uint8_t *v1, const uint8_t *v2)
  4543. +{
  4544. + uint32_t i;
  4545. + switch(len)
  4546. + {
  4547. + case 16:
  4548. + for(i = 8; i < 16; ++i)
  4549. + {
  4550. + data[i] = v1[i] ^ v2[i];
  4551. + }
  4552. + case 8:
  4553. + for(i = 4; i < 8; ++i)
  4554. + {
  4555. + data[i] = v1[i] ^ v2[i];
  4556. + }
  4557. + case 4:
  4558. + for(i = 0; i < 4; ++i)
  4559. + {
  4560. + data[i] = v1[i] ^ v2[i];
  4561. + }
  4562. + break;
  4563. + default:
  4564. + while(len--) { *data++ = *v1++ ^ *v2++; }
  4565. + break;
  4566. + }
  4567. +}
  4568. +
  4569. +static int8_t isValidDCW(uint8_t *dw)
  4570. +{
  4571. + if (((dw[0]+dw[1]+dw[2]) & 0xFF) != dw[3]) {
  4572. + return 0;
  4573. + }
  4574. + if (((dw[4]+dw[5]+dw[6]) & 0xFF) != dw[7]) {
  4575. + return 0;
  4576. + }
  4577. + if (((dw[8]+dw[9]+dw[10]) & 0xFF) != dw[11]) {
  4578. + return 0;
  4579. + }
  4580. + if (((dw[12]+dw[13]+dw[14]) & 0xFF) != dw[15]) {
  4581. + return 0;
  4582. + }
  4583. + return 1;
  4584. +}
  4585. +
  4586. +static inline uint8_t GetBit(uint8_t byte, uint8_t bitnb)
  4587. +{
  4588. + return ((byte&(1<<bitnb)) ? 1: 0);
  4589. +}
  4590. +
  4591. +static inline uint8_t SetBit(uint8_t val, uint8_t bitnb, uint8_t biton)
  4592. +{
  4593. + return (biton ? (val | (1<<bitnb)) : (val & ~(1<<bitnb)));
  4594. +}
  4595. +
  4596. +static void ExpandDesKey(unsigned char *key)
  4597. +{
  4598. + uint8_t i, j, parity;
  4599. + uint8_t tmpKey[7];
  4600. +
  4601. + memcpy(tmpKey, key, 7);
  4602. +
  4603. + key[0] = (tmpKey[0] & 0xFE);
  4604. + key[1] = ((tmpKey[0] << 7) | ((tmpKey[1] >> 1) & 0xFE));
  4605. + key[2] = ((tmpKey[1] << 6) | ((tmpKey[2] >> 2) & 0xFE));
  4606. + key[3] = ((tmpKey[2] << 5) | ((tmpKey[3] >> 3) & 0xFE));
  4607. + key[4] = ((tmpKey[3] << 4) | ((tmpKey[4] >> 4) & 0xFE));
  4608. + key[5] = ((tmpKey[4] << 3) | ((tmpKey[5] >> 5) & 0xFE));
  4609. + key[6] = ((tmpKey[5] << 2) | ((tmpKey[6] >> 6) & 0xFE));
  4610. + key[7] = (tmpKey[6] << 1);
  4611. +
  4612. + for (i = 0; i < 8; i++)
  4613. + {
  4614. + parity = 1;
  4615. + for (j = 1; j < 8; j++) if ((key[i] >> j) & 0x1) { parity = ~parity & 0x01; }
  4616. + key[i] |= parity;
  4617. + }
  4618. +}
  4619. +
  4620. +// Cryptoworks EMU
  4621. +static int8_t GetCwKey(uint8_t *buf,uint32_t ident, uint8_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey)
  4622. +{
  4623. +
  4624. + char keyName[EMU_MAX_CHAR_KEYNAME];
  4625. + uint32_t tmp;
  4626. +
  4627. + if((ident>>4)== 0xD02A) {
  4628. + keyIndex &=0xFE; // map to even number key indexes
  4629. + }
  4630. + if((ident>>4)== 0xD00C) {
  4631. + ident = 0x0D00C0; // map provider C? to C0
  4632. + }
  4633. + else if(keyIndex==6 && ((ident>>8) == 0x0D05)) {
  4634. + ident = 0x0D0504; // always use provider 04 system key
  4635. + }
  4636. +
  4637. + tmp = keyIndex;
  4638. + snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.2X", tmp);
  4639. + if(FindKey('W', ident, keyName, buf, keyLength, isCriticalKey, 0, 0, NULL)) {
  4640. + return 1;
  4641. + }
  4642. +
  4643. + return 0;
  4644. +}
  4645. +
  4646. +static const uint8_t cw_sbox1[64] = {
  4647. + 0xD8,0xD7,0x83,0x3D,0x1C,0x8A,0xF0,0xCF,0x72,0x4C,0x4D,0xF2,0xED,0x33,0x16,0xE0,
  4648. + 0x8F,0x28,0x7C,0x82,0x62,0x37,0xAF,0x59,0xB7,0xE0,0x00,0x3F,0x09,0x4D,0xF3,0x94,
  4649. + 0x16,0xA5,0x58,0x83,0xF2,0x4F,0x67,0x30,0x49,0x72,0xBF,0xCD,0xBE,0x98,0x81,0x7F,
  4650. + 0xA5,0xDA,0xA7,0x7F,0x89,0xC8,0x78,0xA7,0x8C,0x05,0x72,0x84,0x52,0x72,0x4D,0x38
  4651. +};
  4652. +static const uint8_t cw_sbox2[64] = {
  4653. + 0xD8,0x35,0x06,0xAB,0xEC,0x40,0x79,0x34,0x17,0xFE,0xEA,0x47,0xA3,0x8F,0xD5,0x48,
  4654. + 0x0A,0xBC,0xD5,0x40,0x23,0xD7,0x9F,0xBB,0x7C,0x81,0xA1,0x7A,0x14,0x69,0x6A,0x96,
  4655. + 0x47,0xDA,0x7B,0xE8,0xA1,0xBF,0x98,0x46,0xB8,0x41,0x45,0x9E,0x5E,0x20,0xB2,0x35,
  4656. + 0xE4,0x2F,0x9A,0xB5,0xDE,0x01,0x65,0xF8,0x0F,0xB2,0xD2,0x45,0x21,0x4E,0x2D,0xDB
  4657. +};
  4658. +static const uint8_t cw_sbox3[64] = {
  4659. + 0xDB,0x59,0xF4,0xEA,0x95,0x8E,0x25,0xD5,0x26,0xF2,0xDA,0x1A,0x4B,0xA8,0x08,0x25,
  4660. + 0x46,0x16,0x6B,0xBF,0xAB,0xE0,0xD4,0x1B,0x89,0x05,0x34,0xE5,0x74,0x7B,0xBB,0x44,
  4661. + 0xA9,0xC6,0x18,0xBD,0xE6,0x01,0x69,0x5A,0x99,0xE0,0x87,0x61,0x56,0x35,0x76,0x8E,
  4662. + 0xF7,0xE8,0x84,0x13,0x04,0x7B,0x9B,0xA6,0x7A,0x1F,0x6B,0x5C,0xA9,0x86,0x54,0xF9
  4663. +};
  4664. +static const uint8_t cw_sbox4[64] = {
  4665. + 0xBC,0xC1,0x41,0xFE,0x42,0xFB,0x3F,0x10,0xB5,0x1C,0xA6,0xC9,0xCF,0x26,0xD1,0x3F,
  4666. + 0x02,0x3D,0x19,0x20,0xC1,0xA8,0xBC,0xCF,0x7E,0x92,0x4B,0x67,0xBC,0x47,0x62,0xD0,
  4667. + 0x60,0x9A,0x9E,0x45,0x79,0x21,0x89,0xA9,0xC3,0x64,0x74,0x9A,0xBC,0xDB,0x43,0x66,
  4668. + 0xDF,0xE3,0x21,0xBE,0x1E,0x16,0x73,0x5D,0xA2,0xCD,0x8C,0x30,0x67,0x34,0x9C,0xCB
  4669. +};
  4670. +static const uint8_t AND_bit1[8] = {0x00,0x40,0x04,0x80,0x21,0x10,0x02,0x08};
  4671. +static const uint8_t AND_bit2[8] = {0x80,0x08,0x01,0x40,0x04,0x20,0x10,0x02};
  4672. +static const uint8_t AND_bit3[8] = {0x82,0x40,0x01,0x10,0x00,0x20,0x04,0x08};
  4673. +static const uint8_t AND_bit4[8] = {0x02,0x10,0x04,0x40,0x80,0x08,0x01,0x20};
  4674. +
  4675. +static void CW_SWAP_KEY(uint8_t *key)
  4676. +{
  4677. + uint8_t k[8];
  4678. + memcpy(k, key, 8);
  4679. + memcpy(key, key + 8, 8);
  4680. + memcpy(key + 8, k, 8);
  4681. +}
  4682. +
  4683. +static void CW_SWAP_DATA(uint8_t *k)
  4684. +{
  4685. + uint8_t d[4];
  4686. + memcpy(d, k + 4, 4);
  4687. + memcpy(k + 4 ,k ,4);
  4688. + memcpy(k, d, 4);
  4689. +}
  4690. +
  4691. +static void CW_DES_ROUND(uint8_t *d, uint8_t *k)
  4692. +{
  4693. + 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};
  4694. + uint8_t bb[44] = {0x80,0x08,0x10,0x02,0x08,0x40,0x01,0x20,0x40,0x80,0x04,0x10,0x04,0x01,0x01,0x02,0x20,0x20,0x02,0x01,
  4695. + 0x80,0x04,0x02,0x02,0x08,0x02,0x10,0x80,0x01,0x20,0x08,0x80,0x01,0x08,0x40,0x01,0x02,0x80,0x10,0x40,0x40,0x10,0x08,0x01
  4696. + };
  4697. + uint8_t ff[4] = {0x02,0x10,0x04,0x04};
  4698. + 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};
  4699. +
  4700. + 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;
  4701. +
  4702. + for (m = 0; m < 2; m++) {
  4703. + for(i = 0; i < 4; i++) {
  4704. + des_td[*p1++] =
  4705. + (m) ? ((d[*p2++]*2) & 0x3F) | ((d[*p3++] & 0x80) ? 0x01 : 0x00): (d[*p2++]/2) | ((d[*p3++] & 0x01) ? 0x80 : 0x00);
  4706. + }
  4707. + }
  4708. +
  4709. + for (i = 0; i < 8; i++) {
  4710. + c = (c) ? 0 : 1;
  4711. + r = (c) ? 6 : 7;
  4712. + n = (i) ? i-1 : 1;
  4713. + o = (c) ? ((k[n] & *f++) ? 1 : 0) : des_td[n];
  4714. + for (m = 1; m < r; m++) {
  4715. + o = (c) ? (o*2) | ((k[*a++] & *b++) ? 0x01 : 0x00) : (o/2) | ((k[*a++] & *b++) ? 0x80 : 0x00);
  4716. + }
  4717. + n = (i) ? n+1 : 0;
  4718. + des_td[n] = (c) ? des_td[n] ^ o : (o ^ des_td[n] )/4;
  4719. + }
  4720. +
  4721. + for( i = 0; i < 8; i++) {
  4722. + d[0] ^= (AND_bit1[i] & cw_sbox1[des_td[i]]);
  4723. + d[1] ^= (AND_bit2[i] & cw_sbox2[des_td[i]]);
  4724. + d[2] ^= (AND_bit3[i] & cw_sbox3[des_td[i]]);
  4725. + d[3] ^= (AND_bit4[i] & cw_sbox4[des_td[i]]);
  4726. + }
  4727. +
  4728. + CW_SWAP_DATA(d);
  4729. +}
  4730. +
  4731. +static void CW_48_Key(uint8_t *inkey, uint8_t *outkey, uint8_t algotype)
  4732. +{
  4733. + uint8_t Round_Counter, i = 8, *key128 = inkey, *key48 = inkey + 0x10;
  4734. + Round_Counter = 7 - (algotype & 7);
  4735. +
  4736. + memset(outkey, 0, 16);
  4737. + memcpy(outkey, key48, 6);
  4738. +
  4739. + for( ; i > Round_Counter; i--) {
  4740. + if (i > 1) {
  4741. + outkey[i-2] = key128[i];
  4742. + }
  4743. + }
  4744. +}
  4745. +
  4746. +static void CW_LS_DES_KEY(uint8_t *key,uint8_t Rotate_Counter)
  4747. +{
  4748. + uint8_t round[] = {1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,1};
  4749. + uint8_t i, n;
  4750. + uint16_t k[8];
  4751. +
  4752. + n = round[Rotate_Counter];
  4753. +
  4754. + for (i = 0; i < 8; i++) {
  4755. + k[i] = key[i];
  4756. + }
  4757. +
  4758. + for (i = 1; i < n + 1; i++) {
  4759. + k[7] = (k[7]*2) | ((k[4] & 0x008) ? 1 : 0);
  4760. + k[6] = (k[6]*2) | ((k[7] & 0xF00) ? 1 : 0);
  4761. + k[7] &=0xff;
  4762. + k[5] = (k[5]*2) | ((k[6] & 0xF00) ? 1 : 0);
  4763. + k[6] &=0xff;
  4764. + k[4] = ((k[4]*2) | ((k[5] & 0xF00) ? 1 : 0)) & 0xFF;
  4765. + k[5] &= 0xff;
  4766. + k[3] = (k[3]*2) | ((k[0] & 0x008) ? 1 : 0);
  4767. + k[2] = (k[2]*2) | ((k[3] & 0xF00) ? 1 : 0);
  4768. + k[3] &= 0xff;
  4769. + k[1] = (k[1]*2) | ((k[2] & 0xF00) ? 1 : 0);
  4770. + k[2] &= 0xff;
  4771. + k[0] = ((k[0]*2) | ((k[1] & 0xF00) ? 1 : 0)) & 0xFF;
  4772. + k[1] &= 0xff;
  4773. + }
  4774. + for (i = 0; i < 8; i++) {
  4775. + key[i] = (uint8_t) k[i];
  4776. + }
  4777. +}
  4778. +
  4779. +static void CW_RS_DES_KEY(uint8_t *k, uint8_t Rotate_Counter)
  4780. +{
  4781. + uint8_t i,c;
  4782. + for (i = 1; i < Rotate_Counter+1; i++) {
  4783. + c = (k[3] & 0x10) ? 0x80 : 0;
  4784. + k[3] /= 2;
  4785. + if (k[2] & 1) {
  4786. + k[3] |= 0x80;
  4787. + }
  4788. + k[2] /= 2;
  4789. + if (k[1] & 1) {
  4790. + k[2] |= 0x80;
  4791. + }
  4792. + k[1] /= 2;
  4793. + if (k[0] & 1) {
  4794. + k[1] |= 0x80;
  4795. + }
  4796. + k[0] /= 2;
  4797. + k[0] |= c ;
  4798. + c = (k[7] & 0x10) ? 0x80 : 0;
  4799. + k[7] /= 2;
  4800. + if (k[6] & 1) {
  4801. + k[7] |= 0x80;
  4802. + }
  4803. + k[6] /= 2;
  4804. + if (k[5] & 1) {
  4805. + k[6] |= 0x80;
  4806. + }
  4807. + k[5] /= 2;
  4808. + if (k[4] & 1) {
  4809. + k[5] |= 0x80;
  4810. + }
  4811. + k[4] /= 2;
  4812. + k[4] |= c;
  4813. + }
  4814. +}
  4815. +
  4816. +static void CW_RS_DES_SUBKEY(uint8_t *k, uint8_t Rotate_Counter)
  4817. +{
  4818. + uint8_t round[] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
  4819. + CW_RS_DES_KEY(k, round[Rotate_Counter]);
  4820. +}
  4821. +
  4822. +static void CW_PREP_KEY(uint8_t *key )
  4823. +{
  4824. + uint8_t DES_key[8],j;
  4825. + int32_t Round_Counter = 6,i,a;
  4826. + key[7] = 6;
  4827. + memset(DES_key, 0 , 8);
  4828. + do {
  4829. + a = 7;
  4830. + i = key[7];
  4831. + j = key[Round_Counter];
  4832. + do {
  4833. + DES_key[i] = ( (DES_key[i] * 2) | ((j & 1) ? 1: 0) ) & 0xFF;
  4834. + j /=2;
  4835. + i--;
  4836. + if (i < 0) {
  4837. + i = 6;
  4838. + }
  4839. + a--;
  4840. + }
  4841. + while (a >= 0);
  4842. + key[7] = i;
  4843. + Round_Counter--;
  4844. + }
  4845. + while ( Round_Counter >= 0 );
  4846. + a = DES_key[4];
  4847. + DES_key[4] = DES_key[6];
  4848. + DES_key[6] = a;
  4849. + DES_key[7] = (DES_key[3] * 16) & 0xFF;
  4850. + memcpy(key,DES_key,8);
  4851. + CW_RS_DES_KEY(key,4);
  4852. +}
  4853. +
  4854. +static void CW_L2DES(uint8_t *data, uint8_t *key, uint8_t algo)
  4855. +{
  4856. + uint8_t i, k0[22], k1[22];
  4857. + memcpy(k0,key,22);
  4858. + memcpy(k1,key,22);
  4859. + CW_48_Key(k0, k1,algo);
  4860. + CW_PREP_KEY(k1);
  4861. + for (i = 0; i< 2; i++) {
  4862. + CW_LS_DES_KEY( k1,15);
  4863. + CW_DES_ROUND( data ,k1);
  4864. + }
  4865. +}
  4866. +
  4867. +static void CW_R2DES(uint8_t *data, uint8_t *key, uint8_t algo)
  4868. +{
  4869. + uint8_t i, k0[22],k1[22];
  4870. + memcpy(k0,key,22);
  4871. + memcpy(k1,key,22);
  4872. + CW_48_Key(k0, k1, algo);
  4873. + CW_PREP_KEY(k1);
  4874. + for (i = 0; i< 2; i++) {
  4875. + CW_LS_DES_KEY(k1,15);
  4876. + }
  4877. + for (i = 0; i< 2; i++) {
  4878. + CW_DES_ROUND( data ,k1);
  4879. + CW_RS_DES_SUBKEY(k1,1);
  4880. + }
  4881. + CW_SWAP_DATA(data);
  4882. +}
  4883. +
  4884. +static void CW_DES(uint8_t *data, uint8_t *inkey, uint8_t m)
  4885. +{
  4886. + uint8_t key[22], i;
  4887. + memcpy(key, inkey + 9, 8);
  4888. + CW_PREP_KEY( key );
  4889. + for (i = 16; i > 0; i--) {
  4890. + if (m == 1) {
  4891. + CW_LS_DES_KEY(key, (uint8_t) (i-1));
  4892. + }
  4893. + CW_DES_ROUND( data ,key);
  4894. + if (m == 0) {
  4895. + CW_RS_DES_SUBKEY(key, (uint8_t) (i-1));
  4896. + }
  4897. + }
  4898. +}
  4899. +
  4900. +static void CW_DEC_ENC(uint8_t *d, uint8_t *k, uint8_t a,uint8_t m)
  4901. +{
  4902. + uint8_t n = m & 1;
  4903. + CW_L2DES(d , k, a);
  4904. + CW_DES (d , k, n);
  4905. + CW_R2DES(d , k, a);
  4906. + if (m & 2) {
  4907. + CW_SWAP_KEY(k);
  4908. + }
  4909. +}
  4910. +
  4911. +static void Cryptoworks3DES(uint8_t *data, uint8_t *key)
  4912. +{
  4913. + uint32_t ks1[32], ks2[32];
  4914. +
  4915. + des_set_key(key, ks1);
  4916. + des_set_key(key+8, ks2);
  4917. +
  4918. + des(data, ks1, 0);
  4919. + des(data, ks2, 1);
  4920. + des(data, ks1, 0);
  4921. +}
  4922. +
  4923. +static uint8_t CryptoworksProcessNano80(uint8_t *data, uint32_t caid, int32_t provider, uint8_t *opKey, uint8_t nanoLength, uint8_t nano80Algo)
  4924. +{
  4925. + int32_t i, j;
  4926. + uint8_t key[16], desKey[16], t[8], dat1[8], dat2[8], k0D00C000[16];
  4927. + if(nanoLength < 11) {
  4928. + return 0;
  4929. + }
  4930. + if(caid == 0x0D00 && provider != 0xA0 && !GetCwKey(k0D00C000, 0x0D00C0, 0, 16, 1)) {
  4931. + return 0;
  4932. + }
  4933. +
  4934. + if(nano80Algo > 1) {
  4935. + return 0;
  4936. + }
  4937. +
  4938. + memset(t, 0, 8);
  4939. + memcpy(dat1, data, 8);
  4940. +
  4941. + if(caid == 0x0D00 && provider != 0xA0) {
  4942. + memcpy(key, k0D00C000, 16);
  4943. + }
  4944. + else {
  4945. + memcpy(key, opKey, 16);
  4946. + }
  4947. + Cryptoworks3DES(data, key);
  4948. + memcpy(desKey, data, 8);
  4949. +
  4950. + memcpy(data, dat1, 8);
  4951. + if(caid == 0x0D00 && provider != 0xA0) {
  4952. + memcpy(key, &k0D00C000[8], 8);
  4953. + memcpy(&key[8], k0D00C000, 8);
  4954. + }
  4955. + else {
  4956. + memcpy(key, &opKey[8], 8);
  4957. + memcpy(&key[8], opKey, 8);
  4958. + }
  4959. + Cryptoworks3DES(data, key);
  4960. + memcpy(&desKey[8], data, 8);
  4961. +
  4962. + for(i=8; i+7<nanoLength; i+=8) {
  4963. + memcpy(dat1, &data[i], 8);
  4964. + memcpy(dat2, dat1, 8);
  4965. + memcpy(key, desKey, 16);
  4966. + Cryptoworks3DES(dat1, key);
  4967. + for(j=0; j<8; j++) {
  4968. + dat1[j] ^= t[j];
  4969. + }
  4970. + memcpy(&data[i], dat1, 8);
  4971. + memcpy(t, dat2, 8);
  4972. + }
  4973. +
  4974. + return data[10] + 5;
  4975. +}
  4976. +
  4977. +static void CryptoworksSignature(const uint8_t *data, uint32_t length, uint8_t *key, uint8_t *signature)
  4978. +{
  4979. + uint32_t i, sigPos;
  4980. + int8_t algo, first;
  4981. +
  4982. + algo = data[0] & 7;
  4983. + if(algo == 7) {
  4984. + algo = 6;
  4985. + }
  4986. + memset(signature, 0, 8);
  4987. + first = 1;
  4988. + sigPos = 0;
  4989. + for(i=0; i<length; i++) {
  4990. + signature[sigPos] ^= data[i];
  4991. + sigPos++;
  4992. +
  4993. + if(sigPos > 7) {
  4994. + if (first) {
  4995. + CW_L2DES(signature, key, algo);
  4996. + }
  4997. + CW_DES(signature, key, 1);
  4998. +
  4999. + sigPos = 0;
  5000. + first = 0;
  5001. + }
  5002. + }
  5003. + if(sigPos > 0) {
  5004. + CW_DES(signature, key, 1);
  5005. + }
  5006. + CW_R2DES(signature, key, algo);
  5007. +}
  5008. +
  5009. +static void CryptoworksDecryptDes(uint8_t *data, uint8_t algo, uint8_t *key)
  5010. +{
  5011. + int32_t i;
  5012. + uint8_t k[22], t[8];
  5013. +
  5014. + algo &= 7;
  5015. + if(algo<7) {
  5016. + CW_DEC_ENC(data, key, algo, 0);
  5017. + }
  5018. + else {
  5019. + memcpy(k, key, 22);
  5020. + for(i=0; i<3; i++) {
  5021. + CW_DEC_ENC(data, k, algo, i&1);
  5022. + memcpy(t,k,8);
  5023. + memcpy(k,k+8,8);
  5024. + memcpy(k+8,t,8);
  5025. + }
  5026. + }
  5027. +}
  5028. +
  5029. +static int8_t CryptoworksECM(uint32_t caid, uint8_t *ecm, uint8_t *cw)
  5030. +{
  5031. + uint32_t ident;
  5032. + uint8_t keyIndex = 0, nanoLength, newEcmLength, key[22], signature[8], nano80Algo = 1;
  5033. + int32_t provider = -1;
  5034. + uint16_t i, j, ecmLen = GetEcmLen(ecm);
  5035. +
  5036. + if(ecmLen < 8) {
  5037. + return 1;
  5038. + }
  5039. + if(ecm[7] != ecmLen - 8) {
  5040. + return 1;
  5041. + }
  5042. +
  5043. + memset(key, 0, 22);
  5044. +
  5045. + for(i = 8; i+1 < ecmLen; i += ecm[i+1] + 2) {
  5046. + if(ecm[i] == 0x83 && i+2 < ecmLen) {
  5047. + provider = ecm[i+2] & 0xFC;
  5048. + keyIndex = ecm[i+2] & 3;
  5049. + keyIndex = keyIndex ? 1 : 0;
  5050. + }
  5051. + else if(ecm[i] == 0x84 && i+3 < ecmLen) {
  5052. + //nano80Provider = ecm[i+2] & 0xFC;
  5053. + //nano80KeyIndex = ecm[i+2] & 3;
  5054. + //nano80KeyIndex = nano80KeyIndex ? 1 : 0;
  5055. + nano80Algo = ecm[i+3];
  5056. + }
  5057. + }
  5058. +
  5059. + if(provider < 0) {
  5060. + switch(caid) {
  5061. + case 0x0D00:
  5062. + provider = 0xC0;
  5063. + break;
  5064. + case 0x0D02:
  5065. + provider = 0xA0;
  5066. + break;
  5067. + case 0x0D03:
  5068. + provider = 0x04;
  5069. + break;
  5070. + case 0x0D05:
  5071. + provider = 0x04;
  5072. + break;
  5073. + default:
  5074. + return 1;
  5075. + }
  5076. + }
  5077. +
  5078. + ident = (caid << 8) | provider;
  5079. + if(!GetCwKey(key, ident, keyIndex, 16, 1)) {
  5080. + return 2;
  5081. + }
  5082. + if(!GetCwKey(&key[16], ident, 6, 6, 1)) {
  5083. + return 2;
  5084. + }
  5085. +
  5086. + for(i = 8; i+1 < ecmLen; i += ecm[i+1] + 2) {
  5087. + if(ecm[i] == 0x80 && i+2+7 < ecmLen && i+2+ecm[i+1] <= ecmLen
  5088. + && (provider == 0xA0 || provider == 0xC0 || provider == 0xC4 || provider == 0xC8)) {
  5089. + nanoLength = ecm[i+1];
  5090. + newEcmLength = CryptoworksProcessNano80(ecm+i+2, caid, provider, key, nanoLength, nano80Algo);
  5091. + if(newEcmLength == 0 || newEcmLength > ecmLen-(i+2+3)) {
  5092. + return 1;
  5093. + }
  5094. + ecm[i+2+3] = 0x81;
  5095. + ecm[i+2+4] = 0x70;
  5096. + ecm[i+2+5] = newEcmLength;
  5097. + ecm[i+2+6] = 0x81;
  5098. + ecm[i+2+7] = 0xFF;
  5099. + return CryptoworksECM(caid, ecm+i+2+3, cw);
  5100. + }
  5101. + }
  5102. +
  5103. + if(ecmLen - 15 < 1) {
  5104. + return 1;
  5105. + }
  5106. + CryptoworksSignature(ecm + 5, ecmLen - 15, key, signature);
  5107. + for(i = 8; i+1 < ecmLen; i += ecm[i+1]+2) {
  5108. + switch(ecm[i]) {
  5109. + case 0xDA:
  5110. + case 0xDB:
  5111. + case 0xDC:
  5112. + if(i+2+ecm[i+1] > ecmLen) {
  5113. + break;
  5114. + }
  5115. + for(j=0; j+7<ecm[i+1]; j+=8) {
  5116. + CryptoworksDecryptDes(&ecm[i+2+j], ecm[5], key);
  5117. + }
  5118. + break;
  5119. + case 0xDF:
  5120. + if(i+2+8 > ecmLen) {
  5121. + break;
  5122. + }
  5123. + if(memcmp(&ecm[i+2], signature, 8)) {
  5124. + return 6;
  5125. + }
  5126. + break;
  5127. + }
  5128. + }
  5129. +
  5130. + for(i = 8; i+1 < ecmLen; i += ecm[i+1]+2) {
  5131. + switch(ecm[i]) {
  5132. + case 0xDB:
  5133. + if(i+2+ecm[i+1] <= ecmLen && ecm[i+1]==16) {
  5134. + memcpy(cw, &ecm[i+2], 16);
  5135. + return 0;
  5136. + }
  5137. + break;
  5138. + }
  5139. + }
  5140. +
  5141. + return 5;
  5142. +}
  5143. +
  5144. +// SoftNDS EMU
  5145. +static const uint8_t nds_const[]= {0x0F,0x1E,0x2D,0x3C,0x4B,0x5A,0x69,0x78,0x87,0x96,0xA5,0xB4,0xC3,0xD2,0xE1,0xF0};
  5146. +
  5147. +uint8_t viasat_const[]= {
  5148. + 0x15,0x85,0xC5,0xE4,0xB8,0x52,0xEC,0xF7,0xC3,0xD9,0x08,0xBA,0x22,0x4A,0x66,0xF2,
  5149. + 0x82,0x15,0x4F,0xB2,0x18,0x48,0x63,0x97,0xDC,0x19,0xD8,0x51,0x9A,0x39,0xFC,0xCA,
  5150. + 0x1C,0x24,0xD0,0x65,0xA9,0x66,0x2D,0xD6,0x53,0x3B,0x86,0xBA,0x40,0xEA,0x4C,0x6D,
  5151. + 0xD9,0x1E,0x41,0x14,0xFE,0x15,0xAF,0xC3,0x18,0xC5,0xF8,0xA7,0xA8,0x01,0x00,0x01,
  5152. +};
  5153. +
  5154. +static int8_t SoftNDSECM(uint16_t caid, uint8_t *ecm, uint8_t *dw)
  5155. +{
  5156. + int32_t i;
  5157. + uint8_t *tDW, irdEcmLen, offsetCw = 0, offsetP2 = 0;
  5158. + uint8_t digest[16], md5_const[64];
  5159. + MD5_CTX mdContext;
  5160. + uint16_t ecmLen = GetEcmLen(ecm);
  5161. +
  5162. + if(ecmLen < 7) {
  5163. + return 1;
  5164. + }
  5165. +
  5166. + if(ecm[3] != 0x00 || ecm[4] != 0x00 || ecm[5] != 0x01) {
  5167. + return 1;
  5168. + }
  5169. +
  5170. + irdEcmLen = ecm[6];
  5171. + if(irdEcmLen < (10+3+8+4) || irdEcmLen+6 >= ecmLen) {
  5172. + return 1;
  5173. + }
  5174. +
  5175. + for(i=0; 10+i+2 < irdEcmLen; i++) {
  5176. + if(ecm[17+i] == 0x0F && ecm[17+i+1] == 0x40 && ecm[17+i+2] == 0x00) {
  5177. + offsetCw = 17+i+3;
  5178. + offsetP2 = offsetCw+9;
  5179. + }
  5180. + }
  5181. +
  5182. + if(offsetCw == 0 || offsetP2 == 0) {
  5183. + return 1;
  5184. + }
  5185. +
  5186. + if(offsetP2-7+4 > irdEcmLen) {
  5187. + return 1;
  5188. + }
  5189. +
  5190. + if(caid == 0x090F || caid == 0x093E) {
  5191. + memcpy(md5_const, viasat_const, 64);
  5192. + }
  5193. + else if(!FindKey('S', caid, "00", md5_const, 64, 1, 0, 0, NULL)) {
  5194. + return 2;
  5195. + }
  5196. +
  5197. + memset(dw,0,16);
  5198. + tDW = &dw[ecm[0]==0x81 ? 8 : 0];
  5199. +
  5200. + MD5_Init(&mdContext);
  5201. + MD5_Update(&mdContext, ecm+7, 10);
  5202. + MD5_Update(&mdContext, ecm+offsetP2, 4);
  5203. + MD5_Update(&mdContext, md5_const, 64);
  5204. + MD5_Update(&mdContext, nds_const, 16);
  5205. + MD5_Final(digest, &mdContext);
  5206. +
  5207. + for (i=0; i<8; i++) {
  5208. + tDW[i] = digest[i+8] ^ ecm[offsetCw+i];
  5209. + }
  5210. +
  5211. + if(((tDW[0]+tDW[1]+tDW[2])&0xFF)-tDW[3]) {
  5212. + return 6;
  5213. + }
  5214. + if(((tDW[4]+tDW[5]+tDW[6])&0xFF)-tDW[7]) {
  5215. + return 6;
  5216. + }
  5217. +
  5218. + return 0;
  5219. +}
  5220. +
  5221. +// Viaccess EMU
  5222. +static int8_t GetViaKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey)
  5223. +{
  5224. +
  5225. + char keyStr[EMU_MAX_CHAR_KEYNAME];
  5226. + snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
  5227. + if(FindKey('V', ident, keyStr, buf, keyLength, isCriticalKey, 0, 0, NULL)) {
  5228. + return 1;
  5229. + }
  5230. +
  5231. + if(ident == 0xD00040 && FindKey('V', 0x030B00, keyStr, buf, keyLength, isCriticalKey, 0, 0, NULL)) {
  5232. + return 1;
  5233. + }
  5234. +
  5235. + return 0;
  5236. +}
  5237. +
  5238. +static void Via1Mod(const uint8_t* key2, uint8_t* data)
  5239. +{
  5240. + int32_t kb, db;
  5241. + for (db=7; db>=0; db--) {
  5242. + for (kb=7; kb>3; kb--) {
  5243. + int32_t a0=kb^db;
  5244. + int32_t pos=7;
  5245. + if (a0&4) {
  5246. + a0^=7;
  5247. + pos^=7;
  5248. + }
  5249. + a0=(a0^(kb&3)) + (kb&3);
  5250. + if (!(a0&4)) {
  5251. + data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF));
  5252. + }
  5253. + }
  5254. + }
  5255. + for (db=0; db<8; db++) {
  5256. + for (kb=0; kb<4; kb++) {
  5257. + int32_t a0=kb^db;
  5258. + int32_t pos=7;
  5259. + if (a0&4) {
  5260. + a0^=7;
  5261. + pos^=7;
  5262. + }
  5263. + a0=(a0^(kb&3)) + (kb&3);
  5264. + if (!(a0&4)) {
  5265. + data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF));
  5266. + }
  5267. + }
  5268. + }
  5269. +}
  5270. +
  5271. +static void Via1Decode(uint8_t *data, uint8_t *key)
  5272. +{
  5273. + Via1Mod(key+8, data);
  5274. + nc_des(key, DES_ECM_CRYPT, data);
  5275. + Via1Mod(key+8, data);
  5276. +}
  5277. +
  5278. +static void Via1Hash(uint8_t *data, uint8_t *key)
  5279. +{
  5280. + Via1Mod(key+8, data);
  5281. + nc_des(key, DES_ECM_HASH, data);
  5282. + Via1Mod(key+8, data);
  5283. +}
  5284. +
  5285. +static inline void Via1DoHash(uint8_t *hashbuffer, uint8_t *pH, uint8_t data, uint8_t *hashkey)
  5286. +{
  5287. + hashbuffer[*pH] ^= data;
  5288. + (*pH)++;
  5289. +
  5290. + if(*pH == 8) {
  5291. + Via1Hash(hashbuffer, hashkey);
  5292. + *pH = 0;
  5293. + }
  5294. +}
  5295. +
  5296. +static int8_t Via1Decrypt(uint8_t* ecm, uint8_t* dw, uint32_t ident, uint8_t desKeyIndex)
  5297. +{
  5298. + uint8_t work_key[16];
  5299. + uint8_t *data, *des_data1, *des_data2;
  5300. + uint16_t ecmLen = GetEcmLen(ecm);
  5301. + int32_t msg_pos;
  5302. + int32_t encStart = 0, hash_start, i;
  5303. + uint8_t signature[8], hashbuffer[8], prepared_key[16], hashkey[16];
  5304. + uint8_t tmp, k, pH, foundData = 0;
  5305. +
  5306. + if (ident == 0) {
  5307. + return 4;
  5308. + }
  5309. + memset(work_key, 0, 16);
  5310. + if(!GetViaKey(work_key, ident, '0', desKeyIndex, 8, 1)) {
  5311. + return 2;
  5312. + }
  5313. +
  5314. + if(ecmLen < 11) {
  5315. + return 1;
  5316. + }
  5317. + data = ecm+9;
  5318. + des_data1 = dw;
  5319. + des_data2 = dw+8;
  5320. +
  5321. + msg_pos = 0;
  5322. + pH = 0;
  5323. + memset(hashbuffer, 0, sizeof(hashbuffer));
  5324. + memcpy(hashkey, work_key, sizeof(hashkey));
  5325. + memset(signature, 0, 8);
  5326. +
  5327. + while(9+msg_pos+2 < ecmLen) {
  5328. + switch (data[msg_pos]) {
  5329. + case 0xea:
  5330. + if(9+msg_pos+2+15 < ecmLen) {
  5331. + encStart = msg_pos + 2;
  5332. + memcpy(des_data1, &data[msg_pos+2], 8);
  5333. + memcpy(des_data2, &data[msg_pos+2+8], 8);
  5334. + foundData |= 1;
  5335. + }
  5336. + break;
  5337. + case 0xf0:
  5338. + if(9+msg_pos+2+7 < ecmLen) {
  5339. + memcpy(signature, &data[msg_pos+2], 8);
  5340. + foundData |= 2;
  5341. + }
  5342. + break;
  5343. + }
  5344. + msg_pos += data[msg_pos+1]+2;
  5345. + }
  5346. +
  5347. + if(foundData != 3) {
  5348. + return 1;
  5349. + }
  5350. +
  5351. + pH=i=0;
  5352. +
  5353. + if(data[0] == 0x9f && 10+data[1] <= ecmLen) {
  5354. + Via1DoHash(hashbuffer, &pH, data[i++], hashkey);
  5355. + Via1DoHash(hashbuffer, &pH, data[i++], hashkey);
  5356. +
  5357. + for (hash_start=0; hash_start < data[1]; hash_start++) {
  5358. + Via1DoHash(hashbuffer, &pH, data[i++], hashkey);
  5359. + }
  5360. +
  5361. + while (pH != 0) {
  5362. + Via1DoHash(hashbuffer, &pH, 0, hashkey);
  5363. + }
  5364. + }
  5365. +
  5366. + if (work_key[7] == 0) {
  5367. + for (; i < encStart + 16; i++) {
  5368. + Via1DoHash(hashbuffer, &pH, data[i], hashkey);
  5369. + }
  5370. + memcpy(prepared_key, work_key, 8);
  5371. + }
  5372. + else {
  5373. + prepared_key[0] = work_key[2];
  5374. + prepared_key[1] = work_key[3];
  5375. + prepared_key[2] = work_key[4];
  5376. + prepared_key[3] = work_key[5];
  5377. + prepared_key[4] = work_key[6];
  5378. + prepared_key[5] = work_key[0];
  5379. + prepared_key[6] = work_key[1];
  5380. + prepared_key[7] = work_key[7];
  5381. + memcpy(prepared_key+8, work_key+8, 8);
  5382. +
  5383. + if (work_key[7] & 1) {
  5384. + for (; i < encStart; i++) {
  5385. + Via1DoHash(hashbuffer, &pH, data[i], hashkey);
  5386. + }
  5387. +
  5388. + k = ((work_key[7] & 0xf0) == 0) ? 0x5a : 0xa5;
  5389. +
  5390. + for (i=0; i<8; i++) {
  5391. + tmp = des_data1[i];
  5392. + des_data1[i] = (k & hashbuffer[pH] ) ^ tmp;
  5393. + Via1DoHash(hashbuffer, &pH, tmp, hashkey);
  5394. + }
  5395. +
  5396. + for (i = 0; i < 8; i++) {
  5397. + tmp = des_data2[i];
  5398. + des_data2[i] = (k & hashbuffer[pH] ) ^ tmp;
  5399. + Via1DoHash(hashbuffer, &pH, tmp, hashkey);
  5400. + }
  5401. + }
  5402. + else {
  5403. + for (; i < encStart + 16; i++) {
  5404. + Via1DoHash(hashbuffer, &pH, data[i], hashkey);
  5405. + }
  5406. + }
  5407. + }
  5408. + Via1Decode(des_data1, prepared_key);
  5409. + Via1Decode(des_data2, prepared_key);
  5410. + Via1Hash(hashbuffer, hashkey);
  5411. + if(memcmp(signature, hashbuffer, 8)) {
  5412. + return 6;
  5413. + }
  5414. + return 0;
  5415. +}
  5416. +
  5417. +static int8_t Via26ProcessDw(uint8_t *indata, uint32_t ident, uint8_t desKeyIndex)
  5418. +{
  5419. + uint8_t pv1,pv2, i;
  5420. + uint8_t Tmp[8], T1Key[300], P1Key[8], KeyDes1[16], KeyDes2[16], XorKey[8];
  5421. + uint32_t ks1[32], ks2[32];
  5422. +
  5423. + if(!GetViaKey(T1Key, ident, 'T', 1, 300, 1)) {
  5424. + return 2;
  5425. + }
  5426. + if(!GetViaKey(P1Key, ident, 'P', 1, 8, 1)) {
  5427. + return 2;
  5428. + }
  5429. + if(!GetViaKey(KeyDes1, ident, 'D', 1, 16, 1)) {
  5430. + return 2;
  5431. + }
  5432. + if(!GetViaKey(KeyDes2, ident, '0', desKeyIndex, 16, 1)) {
  5433. + return 2;
  5434. + }
  5435. + if(!GetViaKey(XorKey, ident, 'X', 1, 8, 1)) {
  5436. + return 2;
  5437. + }
  5438. +
  5439. + for (i=0; i<8; i++) {
  5440. + pv1 = indata[i];
  5441. + Tmp[i] = T1Key[pv1];
  5442. + }
  5443. + for (i=0; i<8; i++) {
  5444. + pv1 = P1Key[i];
  5445. + pv2 = Tmp[pv1];
  5446. + indata[i]=pv2;
  5447. + }
  5448. +
  5449. + des_set_key(KeyDes1, ks1);
  5450. + des(indata, ks1, 1);
  5451. +
  5452. + for (i=0; i<8; i++) {
  5453. + indata[i] ^= XorKey[i];
  5454. + }
  5455. +
  5456. + des_set_key(KeyDes2, ks1);
  5457. + des_set_key(KeyDes2+8, ks2);
  5458. + des(indata, ks1, 0);
  5459. + des(indata, ks2, 1);
  5460. + des(indata, ks1, 0);
  5461. +
  5462. + for (i=0; i<8; i++) {
  5463. + indata[i] ^= XorKey[i];
  5464. + }
  5465. +
  5466. + des_set_key(KeyDes1, ks1);
  5467. + des(indata, ks1, 0);
  5468. +
  5469. + for (i=0; i<8; i++) {
  5470. + pv1 = indata[i];
  5471. + pv2 = P1Key[i];
  5472. + Tmp[pv2] = pv1;
  5473. + }
  5474. + for (i=0; i<8; i++) {
  5475. + pv1 = Tmp[i];
  5476. + pv2 = T1Key[pv1];
  5477. + indata[i] = pv2;
  5478. + }
  5479. + return 0;
  5480. +}
  5481. +
  5482. +static int8_t Via26Decrypt(uint8_t* source, uint8_t* dw, uint32_t ident, uint8_t desKeyIndex)
  5483. +{
  5484. + uint8_t tmpData[8], C1[8];
  5485. + uint8_t *pXorVector;
  5486. + int32_t i,j;
  5487. +
  5488. + if (ident == 0) {
  5489. + return 4;
  5490. + }
  5491. + if(!GetViaKey(C1, ident, 'C', 1, 8, 1)) {
  5492. + return 2;
  5493. + }
  5494. +
  5495. + for (i=0; i<2; i++) {
  5496. + memcpy(tmpData, source+ i*8, 8);
  5497. + Via26ProcessDw(tmpData, ident, desKeyIndex);
  5498. + if (i!=0) {
  5499. + pXorVector = source;
  5500. + }
  5501. + else {
  5502. + pXorVector = &C1[0];
  5503. + }
  5504. + for (j=0; j<8; j++) {
  5505. + dw[i*8+j] = tmpData[j]^pXorVector[j];
  5506. + }
  5507. + }
  5508. + return 0;
  5509. +}
  5510. +
  5511. +static void Via3Core(uint8_t *data, uint8_t Off, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key)
  5512. +{
  5513. + uint8_t i;
  5514. + uint32_t lR2, lR3, lR4, lR6, lR7;
  5515. +
  5516. + switch (ident) {
  5517. + case 0x032820: {
  5518. + for (i=0; i<4; i++) {
  5519. + data[i]^= XorKey[(Off+i) & 0x07];
  5520. + }
  5521. + lR2 = (data[0]^0xBD)+data[0];
  5522. + lR3 = (data[3]^0xEB)+data[3];
  5523. + lR2 = (lR2-lR3)^data[2];
  5524. + lR3 = ((0x39*data[1])<<2);
  5525. + data[4] = (lR2|lR3)+data[2];
  5526. + lR3 = ((((data[0]+6)^data[0]) | (data[2]<<1))^0x65)+data[0];
  5527. + lR2 = (data[1]^0xED)+data[1];
  5528. + lR7 = ((data[3]+0x29)^data[3])*lR2;
  5529. + data[5] = lR7+lR3;
  5530. + lR2 = ((data[2]^0x33)+data[2]) & 0x0A;
  5531. + lR3 = (data[0]+0xAD)^data[0];
  5532. + lR3 = lR3+lR2;
  5533. + lR2 = data[3]*data[3];
  5534. + lR7 = (lR2 | 1) + data[1];
  5535. + data[6] = (lR3|lR7)+data[1];
  5536. + lR3 = data[1] & 0x07;
  5537. + lR2 = (lR3-data[2]) & (data[0] | lR2 |0x01);
  5538. + data[7] = lR2+data[3];
  5539. + for (i=0; i<4; i++) {
  5540. + data[i+4] = T1Key[data[i+4]];
  5541. + }
  5542. + }
  5543. + break;
  5544. + case 0x030B00: {
  5545. + for (i=0; i<4; i++) {
  5546. + data[i]^= XorKey[(Off+i) & 0x07];
  5547. + }
  5548. + lR6 = (data[3] + 0x6E) ^ data[3];
  5549. + lR6 = (lR6*(data[2] << 1)) + 0x17;
  5550. + lR3 = (data[1] + 0x77) ^ data[1];
  5551. + lR4 = (data[0] + 0xD7) ^ data[0];
  5552. + data[4] = ((lR4 & lR3) | lR6) + data[0];
  5553. + lR4 = ((data[3] + 0x71) ^ data[3]) ^ 0x90;
  5554. + lR6 = (data[1] + 0x1B) ^ data[1];
  5555. + lR4 = (lR4*lR6) ^ data[0];
  5556. + data[5] = (lR4 ^ (data[2] << 1)) + data[1];
  5557. + lR3 = (data[3] * data[3])| 0x01;
  5558. + lR4 = (((data[2] ^ 0x35) + data[2]) | lR3) + data[2];
  5559. + lR6 = data[1] ^ (data[0] + 0x4A);
  5560. + data[6] = lR6 + lR4;
  5561. + lR3 = (data[0] * (data[2] << 1)) | data[1];
  5562. + lR4 = 0xFE - data[3];
  5563. + lR3 = lR4 ^ lR3;
  5564. + data[7] = lR3 + data[3];
  5565. + for (i=0; i<4; i++) {
  5566. + data[4+i] = T1Key[data[4+i]];
  5567. + }
  5568. + }
  5569. + break;
  5570. + default:
  5571. + break;
  5572. + }
  5573. +}
  5574. +
  5575. +static void Via3Fct1(uint8_t *data, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key)
  5576. +{
  5577. + uint8_t t;
  5578. + Via3Core(data, 0, ident, XorKey, T1Key);
  5579. +
  5580. + switch (ident) {
  5581. + case 0x032820: {
  5582. + t = data[4];
  5583. + data[4] = data[7];
  5584. + data[7] = t;
  5585. + }
  5586. + break;
  5587. + case 0x030B00: {
  5588. + t = data[5];
  5589. + data[5] = data[7];
  5590. + data[7] = t;
  5591. + }
  5592. + break;
  5593. + default:
  5594. + break;
  5595. + }
  5596. +}
  5597. +
  5598. +static void Via3Fct2(uint8_t *data, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key)
  5599. +{
  5600. + uint8_t t;
  5601. + Via3Core(data, 4, ident, XorKey, T1Key);
  5602. +
  5603. + switch (ident) {
  5604. + case 0x032820: {
  5605. + t = data[4];
  5606. + data[4] = data[7];
  5607. + data[7] = data[5];
  5608. + data[5] = data[6];
  5609. + data[6] = t;
  5610. + }
  5611. + break;
  5612. + case 0x030B00: {
  5613. + t = data[6];
  5614. + data[6] = data[7];
  5615. + data[7] = t;
  5616. + }
  5617. + break;
  5618. + default:
  5619. + break;
  5620. + }
  5621. +}
  5622. +
  5623. +static int8_t Via3ProcessDw(uint8_t *data, uint32_t ident, uint8_t desKeyIndex)
  5624. +{
  5625. + uint8_t i;
  5626. + uint8_t tmp[8], T1Key[300], P1Key[8], KeyDes[16], XorKey[8];
  5627. + uint32_t ks1[32], ks2[32];
  5628. +
  5629. + if(!GetViaKey(T1Key, ident, 'T', 1, 300, 1)) {
  5630. + return 2;
  5631. + }
  5632. + if(!GetViaKey(P1Key, ident, 'P', 1, 8, 1)) {
  5633. + return 2;
  5634. + }
  5635. + if(!GetViaKey(KeyDes, ident, '0', desKeyIndex, 16, 1)) {
  5636. + return 2;
  5637. + }
  5638. + if(!GetViaKey(XorKey, ident, 'X', 1, 8, 1)) {
  5639. + return 2;
  5640. + }
  5641. +
  5642. + for (i=0; i<4; i++) {
  5643. + tmp[i] = data[i+4];
  5644. + }
  5645. + Via3Fct1(tmp, ident, XorKey, T1Key);
  5646. + for (i=0; i<4; i++) {
  5647. + tmp[i] = data[i]^tmp[i+4];
  5648. + }
  5649. + Via3Fct2(tmp, ident, XorKey, T1Key);
  5650. + for (i=0; i<4; i++) {
  5651. + tmp[i]^= XorKey[i+4];
  5652. + }
  5653. + for (i=0; i<4; i++) {
  5654. + data[i] = data[i+4]^tmp[i+4];
  5655. + data[i+4] = tmp[i];
  5656. + }
  5657. +
  5658. + des_set_key(KeyDes, ks1);
  5659. + des_set_key(KeyDes+8, ks2);
  5660. +
  5661. + des(data, ks1, 0);
  5662. + des(data, ks2, 1);
  5663. + des(data, ks1, 0);
  5664. +
  5665. + for (i=0; i<4; i++) {
  5666. + tmp[i] = data[i+4];
  5667. + }
  5668. + Via3Fct2(tmp, ident, XorKey, T1Key);
  5669. + for (i=0; i<4; i++) {
  5670. + tmp[i] = data[i]^tmp[i+4];
  5671. + }
  5672. + Via3Fct1(tmp, ident, XorKey, T1Key);
  5673. + for (i=0; i<4; i++) {
  5674. + tmp[i]^= XorKey[i];
  5675. + }
  5676. + for (i=0; i<4; i++) {
  5677. + data[i] = data[i+4]^tmp[i+4];
  5678. + data[i+4] = tmp[i];
  5679. + }
  5680. + return 0;
  5681. +}
  5682. +
  5683. +static void Via3FinalMix(uint8_t *dw)
  5684. +{
  5685. + uint8_t tmp[4];
  5686. +
  5687. + memcpy(tmp, dw, 4);
  5688. + memcpy(dw, dw + 4, 4);
  5689. + memcpy(dw + 4, tmp, 4);
  5690. +
  5691. + memcpy(tmp, dw + 8, 4);
  5692. + memcpy(dw + 8, dw + 12, 4);
  5693. + memcpy(dw + 12, tmp, 4);
  5694. +}
  5695. +
  5696. +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)
  5697. +{
  5698. + int8_t aesAfterCore = 0;
  5699. + int8_t needsAES = (aesKeyIndex != 0xFF);
  5700. + uint8_t tmpData[8], C1[8];
  5701. + uint8_t *pXorVector;
  5702. + char aesKey[16];
  5703. + int32_t i, j;
  5704. +
  5705. + if(ident == 0) {
  5706. + return 4;
  5707. + }
  5708. + if(!GetViaKey(C1, ident, 'C', 1, 8, 1)) {
  5709. + return 2;
  5710. + }
  5711. + if(needsAES && !GetViaKey((uint8_t*)aesKey, ident, 'E', aesKeyIndex, 16, 1)) {
  5712. + return 2;
  5713. + }
  5714. + if(aesMode==0x0D || aesMode==0x11 || aesMode==0x15) {
  5715. + aesAfterCore = 1;
  5716. + }
  5717. +
  5718. + if(needsAES && !aesAfterCore) {
  5719. + if(aesMode == 0x0F) {
  5720. + hdSurEncPhase1_D2_0F_11(source);
  5721. + hdSurEncPhase2_D2_0F_11(source);
  5722. + }
  5723. + else if(aesMode == 0x13) {
  5724. + hdSurEncPhase1_D2_13_15(source);
  5725. + }
  5726. + struct aes_keys aes;
  5727. + aes_set_key(&aes, aesKey);
  5728. + aes_decrypt(&aes, source, 16);
  5729. + if(aesMode == 0x0F) {
  5730. + hdSurEncPhase1_D2_0F_11(source);
  5731. + }
  5732. + else if(aesMode == 0x13) {
  5733. + hdSurEncPhase2_D2_13_15(source);
  5734. + }
  5735. + }
  5736. +
  5737. + for(i=0; i<2; i++) {
  5738. + memcpy(tmpData, source+i*8, 8);
  5739. + Via3ProcessDw(tmpData, ident, desKeyIndex);
  5740. + if (i!=0) {
  5741. + pXorVector = source;
  5742. + }
  5743. + else {
  5744. + pXorVector = &C1[0];
  5745. + }
  5746. + for (j=0; j<8; j++) {
  5747. + dw[i*8+j] = tmpData[j]^pXorVector[j];
  5748. + }
  5749. + }
  5750. +
  5751. + if(needsAES && aesAfterCore) {
  5752. + if(aesMode == 0x11) {
  5753. + hdSurEncPhase1_D2_0F_11(dw);
  5754. + hdSurEncPhase2_D2_0F_11(dw);
  5755. + }
  5756. + else if(aesMode == 0x15) {
  5757. + hdSurEncPhase1_D2_13_15(dw);
  5758. + }
  5759. + struct aes_keys aes;
  5760. + aes_set_key(&aes, aesKey);
  5761. + aes_decrypt(&aes, dw, 16);
  5762. + if(aesMode == 0x11) {
  5763. + hdSurEncPhase1_D2_0F_11(dw);
  5764. + }
  5765. + if(aesMode == 0x15) {
  5766. + hdSurEncPhase2_D2_13_15(dw);
  5767. + }
  5768. + }
  5769. +
  5770. + if(ident == 0x030B00) {
  5771. + if(doFinalMix) {
  5772. + Via3FinalMix(dw);
  5773. + }
  5774. + if(!isValidDCW(dw)) {
  5775. + return 6;
  5776. + }
  5777. + }
  5778. + return 0;
  5779. +}
  5780. +
  5781. +static int8_t ViaccessECM(uint8_t *ecm, uint8_t *dw)
  5782. +{
  5783. + uint32_t currentIdent = 0;
  5784. + uint8_t nanoCmd = 0, nanoLen = 0, version = 0, providerKeyLen = 0, desKeyIndex = 0, aesMode = 0, aesKeyIndex = 0xFF;
  5785. + int8_t doFinalMix = 0, result = 1;
  5786. + uint16_t i = 0, keySelectPos = 0, ecmLen = GetEcmLen(ecm);
  5787. +
  5788. + for (i=4; i+2<ecmLen; ) {
  5789. + nanoCmd = ecm[i++];
  5790. + nanoLen = ecm[i++];
  5791. + if(i+nanoLen > ecmLen) {
  5792. + return 1;
  5793. + }
  5794. +
  5795. + switch (nanoCmd) {
  5796. + case 0x40:
  5797. + if (nanoLen < 0x03) {
  5798. + break;
  5799. + }
  5800. + version = ecm[i];
  5801. + if (nanoLen == 3) {
  5802. + currentIdent=((ecm[i]<<16)|(ecm[i+1]<<8))|(ecm[i+2]&0xF0);
  5803. + desKeyIndex = ecm[i+2]&0x0F;
  5804. + keySelectPos = i+3;
  5805. + }
  5806. + else {
  5807. + currentIdent =(ecm[i]<<16)|(ecm[i+1]<<8)|((ecm[i+2]>>4)&0x0F);
  5808. + desKeyIndex = ecm[i+3];
  5809. + keySelectPos = i+4;
  5810. + }
  5811. + providerKeyLen = nanoLen;
  5812. + break;
  5813. + case 0x90:
  5814. + if (nanoLen < 0x03) {
  5815. + break;
  5816. + }
  5817. + version = ecm[i];
  5818. + currentIdent= ((ecm[i]<<16)|(ecm[i+1]<<8))|(ecm[i+2]&0xF0);
  5819. + desKeyIndex = ecm[i+2]&0x0F;
  5820. + keySelectPos = i+4;
  5821. + if((version == 3) && (nanoLen > 3)) {
  5822. + desKeyIndex = ecm[i+(nanoLen-4)]&0x0F;
  5823. + }
  5824. + providerKeyLen = nanoLen;
  5825. + break;
  5826. + case 0x80:
  5827. + nanoLen = 0;
  5828. + break;
  5829. + case 0xD2:
  5830. + if (nanoLen < 0x02) {
  5831. + break;
  5832. + }
  5833. + aesMode = ecm[i];
  5834. + aesKeyIndex = ecm[i+1];
  5835. + break;
  5836. + case 0xDD:
  5837. + nanoLen = 0;
  5838. + break;
  5839. + case 0xEA:
  5840. + if (nanoLen < 0x10) {
  5841. + break;
  5842. + }
  5843. +
  5844. + if (version < 2) {
  5845. + return Via1Decrypt(ecm, dw, currentIdent, desKeyIndex);
  5846. + }
  5847. + else if (version == 2) {
  5848. + return Via26Decrypt(ecm + i, dw, currentIdent, desKeyIndex);
  5849. + }
  5850. + else if (version == 3) {
  5851. + doFinalMix = 0;
  5852. + if (currentIdent == 0x030B00 && providerKeyLen>3) {
  5853. + if(keySelectPos+2 >= ecmLen) {
  5854. + break;
  5855. + }
  5856. + if (ecm[keySelectPos]==0x05 && ecm[keySelectPos+1]==0x67 && (ecm[keySelectPos+2]==0x00 || ecm[keySelectPos+2]==0x01)) {
  5857. + if(ecm[keySelectPos+2]==0x01) {
  5858. + doFinalMix = 1;
  5859. + }
  5860. + }
  5861. + else {
  5862. + break;
  5863. + }
  5864. + }
  5865. + return Via3Decrypt(ecm + i, dw, currentIdent, desKeyIndex, aesKeyIndex, aesMode, doFinalMix);
  5866. + }
  5867. + break;
  5868. + default:
  5869. + break;
  5870. + }
  5871. + i += nanoLen;
  5872. + }
  5873. + return result;
  5874. +}
  5875. +
  5876. +// Nagra EMU
  5877. +static int8_t GetNagraKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint8_t isCriticalKey)
  5878. +{
  5879. + char keyStr[EMU_MAX_CHAR_KEYNAME];
  5880. + snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
  5881. + if(FindKey('N', ident, keyStr, buf, keyName == 'M' ? 64 : 16, isCriticalKey, 0, 0, NULL)) {
  5882. + return 1;
  5883. + }
  5884. +
  5885. + return 0;
  5886. +}
  5887. +
  5888. +static int8_t Nagra2Signature(const uint8_t *vkey, const uint8_t *sig, const uint8_t *msg, int32_t len)
  5889. +{
  5890. + uint8_t buff[16];
  5891. + uint8_t iv[8];
  5892. + int32_t i,j;
  5893. +
  5894. + memcpy(buff,vkey,sizeof(buff));
  5895. + for(i=0; i+7<len; i+=8) {
  5896. + IDEA_KEY_SCHEDULE ek;
  5897. + idea_set_encrypt_key(buff, &ek);
  5898. + memcpy(buff,buff+8,8);
  5899. + memset(iv,0,sizeof(iv));
  5900. + idea_cbc_encrypt(msg+i,buff+8,8,&ek,iv,IDEA_ENCRYPT);
  5901. + for(j=7; j>=0; j--) {
  5902. + buff[j+8]^=msg[i+j];
  5903. + }
  5904. + }
  5905. + buff[8]&=0x7F;
  5906. + return (memcmp(sig,buff+8,8)==0);
  5907. +}
  5908. +
  5909. +static int8_t DecryptNagra2ECM(uint8_t *in, uint8_t *out, const uint8_t *key, int32_t len, const uint8_t *vkey, uint8_t *keyM)
  5910. +{
  5911. + BIGNUM *exp, *mod;
  5912. + uint8_t iv[8];
  5913. + int32_t i = 0, sign = in[0] & 0x80;
  5914. + uint8_t binExp = 3;
  5915. + int8_t result = 1;
  5916. +
  5917. + exp = BN_new();
  5918. + mod = BN_new();
  5919. + BN_bin2bn(&binExp, 1, exp);
  5920. + BN_bin2bn(keyM, 64, mod);
  5921. +
  5922. + if(EmuRSA(out,in+1,64,exp,mod,1)<=0) {
  5923. + BN_free(exp);
  5924. + BN_free(mod);
  5925. + return 0;
  5926. + }
  5927. + out[63]|=sign;
  5928. + if(len>64) {
  5929. + memcpy(out+64,in+65,len-64);
  5930. + }
  5931. +
  5932. + memset(iv,0,sizeof(iv));
  5933. + if(in[0]&0x04) {
  5934. + uint8_t key1[8], key2[8];
  5935. + ReverseMemInOut(key1,&key[0],8);
  5936. + ReverseMemInOut(key2,&key[8],8);
  5937. +
  5938. + for(i=7; i>=0; i--) {
  5939. + ReverseMem(out+8*i,8);
  5940. + }
  5941. + des_ede2_cbc_decrypt(out, iv, key1, key2, len);
  5942. + for(i=7; i>=0; i--) {
  5943. + ReverseMem(out+8*i,8);
  5944. + }
  5945. + }
  5946. + else {
  5947. + IDEA_KEY_SCHEDULE ek;
  5948. + idea_set_encrypt_key(key, &ek);
  5949. + idea_cbc_encrypt(out, out, len&~7, &ek, iv, IDEA_DECRYPT);
  5950. + }
  5951. +
  5952. + ReverseMem(out,64);
  5953. + if(result && EmuRSA(out,out,64,exp,mod,0)<=0) {
  5954. + result = 0;
  5955. + }
  5956. + if(result && vkey && !Nagra2Signature(vkey,out,out+8,len-8)) {
  5957. + result = 0;
  5958. + }
  5959. +
  5960. + BN_free(exp);
  5961. + BN_free(mod);
  5962. + return result;
  5963. +}
  5964. +
  5965. +static int8_t Nagra2ECM(uint8_t *ecm, uint8_t *dw)
  5966. +{
  5967. + uint32_t ident, identMask, tmp1, tmp2, tmp3;
  5968. + uint8_t cmdLen, ideaKeyNr, *dec, ideaKey[16], vKey[16], m1Key[64], mecmAlgo = 0;
  5969. + int8_t useVerifyKey = 0;
  5970. + int32_t l=0, s;
  5971. + uint16_t i = 0, ecmLen = GetEcmLen(ecm);
  5972. +
  5973. + if(ecmLen < 8) {
  5974. + return 1;
  5975. + }
  5976. + cmdLen = ecm[4] - 5;
  5977. + ident = (ecm[5] << 8) + ecm[6];
  5978. + ideaKeyNr = (ecm[7]&0x10)>>4;
  5979. + if(ideaKeyNr) {
  5980. + ideaKeyNr = 1;
  5981. + }
  5982. + if(ident == 1283 || ident == 1285 || ident == 1297) {
  5983. + ident = 1281;
  5984. + }
  5985. + if(cmdLen <= 63 || ecmLen < cmdLen + 10) {
  5986. + return 1;
  5987. + }
  5988. +
  5989. + if(!GetNagraKey(ideaKey, ident, '0', ideaKeyNr, 1)) {
  5990. + return 2;
  5991. + }
  5992. + if(GetNagraKey(vKey, ident, 'V', 0, 0)) {
  5993. + useVerifyKey = 1;
  5994. + }
  5995. + if(!GetNagraKey(m1Key, ident, 'M', 1, 1)) {
  5996. + return 2;
  5997. + }
  5998. + ReverseMem(m1Key, 64);
  5999. +
  6000. + dec = (uint8_t*)malloc(sizeof(uint8_t)*cmdLen);
  6001. + if(dec == NULL) {
  6002. + return 7;
  6003. + }
  6004. + if(!DecryptNagra2ECM(ecm+9, dec, ideaKey, cmdLen, useVerifyKey?vKey:0, m1Key)) {
  6005. + free(dec);
  6006. + return 1;
  6007. + }
  6008. +
  6009. + for(i=(dec[14]&0x10)?16:20; i<cmdLen && l!=3; ) {
  6010. + switch(dec[i]) {
  6011. + case 0x10:
  6012. + case 0x11:
  6013. + if(i+10 < cmdLen && dec[i+1]==0x09) {
  6014. + s = (~dec[i])&1;
  6015. + mecmAlgo = dec[i+2]&0x60;
  6016. + memcpy(dw+(s<<3),&dec[i+3],8);
  6017. + i+=11;
  6018. + l|=(s+1);
  6019. + }
  6020. + else {
  6021. + i++;
  6022. + }
  6023. + break;
  6024. + case 0x00:
  6025. + i+=2;
  6026. + break;
  6027. + case 0x30:
  6028. + case 0x31:
  6029. + case 0x32:
  6030. + case 0x33:
  6031. + case 0x34:
  6032. + case 0x35:
  6033. + case 0x36:
  6034. + case 0xB0:
  6035. + if(i+1 < cmdLen) {
  6036. + i+=dec[i+1]+2;
  6037. + }
  6038. + else {
  6039. + i++;
  6040. + }
  6041. + break;
  6042. + default:
  6043. + i++;
  6044. + continue;
  6045. + }
  6046. + }
  6047. +
  6048. + free(dec);
  6049. +
  6050. + if(l!=3) {
  6051. + return 1;
  6052. + }
  6053. + if(mecmAlgo>0) {
  6054. + return 1;
  6055. + }
  6056. +
  6057. + identMask = ident & 0xFF00;
  6058. + if (identMask == 0x1100 || identMask == 0x500 || identMask == 0x3100) {
  6059. + memcpy(&tmp1, dw, 4);
  6060. + memcpy(&tmp2, dw + 4, 4);
  6061. + memcpy(&tmp3, dw + 12, 4);
  6062. + memcpy(dw, dw + 8, 4);
  6063. + memcpy(dw + 4, &tmp3, 4);
  6064. + memcpy(dw + 8, &tmp1, 4);
  6065. + memcpy(dw + 12, &tmp2, 4);
  6066. + }
  6067. + return 0;
  6068. +}
  6069. +
  6070. +// Irdeto EMU
  6071. +static int8_t GetIrdetoKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint8_t isCriticalKey, uint16_t *keyRef)
  6072. +{
  6073. + char keyStr[EMU_MAX_CHAR_KEYNAME];
  6074. +
  6075. + if(*keyRef > 0xFF)
  6076. + {
  6077. + return 0;
  6078. + }
  6079. +
  6080. + snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
  6081. + if(FindKey('I', ident, keyStr, buf, 16, *keyRef > 0 ? 0 : isCriticalKey, (uint8_t)*keyRef, 0, NULL)) {
  6082. + (*keyRef)++;
  6083. + return 1;
  6084. + }
  6085. +
  6086. + return 0;
  6087. +}
  6088. +
  6089. +static void Irdeto2Encrypt(uint8_t *data, const uint8_t *seed, const uint8_t *key, int32_t len)
  6090. +{
  6091. + const uint8_t *tmp = seed;;
  6092. + int32_t i;
  6093. + uint32_t ks1[32], ks2[32];
  6094. +
  6095. + des_set_key(key, ks1);
  6096. + des_set_key(key+8, ks2);
  6097. +
  6098. + len&=~7;
  6099. +
  6100. + for(i=0; i+7<len; i+=8) {
  6101. + xxor(&data[i],8,&data[i],tmp);
  6102. + tmp=&data[i];
  6103. + des(&data[i], ks1, 1);
  6104. + des(&data[i], ks2, 0);
  6105. + des(&data[i], ks1, 1);
  6106. + }
  6107. +}
  6108. +
  6109. +static void Irdeto2Decrypt(uint8_t *data, const uint8_t *seed, const uint8_t *key, int32_t len)
  6110. +{
  6111. + uint8_t buf[2][8];
  6112. + int32_t i, n=0;
  6113. + uint32_t ks1[32], ks2[32];
  6114. +
  6115. + des_set_key(key, ks1);
  6116. + des_set_key(key+8, ks2);
  6117. +
  6118. + len&=~7;
  6119. +
  6120. + memcpy(buf[n],seed,8);
  6121. + for(i=0; i+7<len; i+=8,data+=8,n^=1) {
  6122. + memcpy(buf[1-n],data,8);
  6123. + des(data, ks1, 0);
  6124. + des(data, ks2, 1);
  6125. + des(data, ks1, 0);
  6126. + xxor(data,8,data,buf[n]);
  6127. + }
  6128. +}
  6129. +
  6130. +static int8_t Irdeto2CalculateHash(const uint8_t *key, const uint8_t *iv, const uint8_t *data, int32_t len)
  6131. +{
  6132. + uint8_t cbuff[8];
  6133. + int32_t l, y;
  6134. + uint32_t ks1[32], ks2[32];
  6135. +
  6136. + des_set_key(key, ks1);
  6137. + des_set_key(key+8, ks2);
  6138. +
  6139. + memset(cbuff,0,sizeof(cbuff));
  6140. + len-=8;
  6141. +
  6142. + for(y=0; y<len; y+=8) {
  6143. + if(y<len-8) {
  6144. + xxor(cbuff,8,cbuff,&data[y]);
  6145. + }
  6146. + else {
  6147. + l=len-y;
  6148. + xxor(cbuff,l,cbuff,&data[y]);
  6149. + xxor(cbuff+l,8-l,cbuff+l,iv+8);
  6150. + }
  6151. +
  6152. + des(cbuff, ks1, 1);
  6153. + des(cbuff, ks2, 0);
  6154. + des(cbuff, ks1, 1);
  6155. + }
  6156. +
  6157. + return memcmp(cbuff,&data[len],8)==0;
  6158. +}
  6159. +
  6160. +static int8_t Irdeto2ECM(uint16_t caid, uint8_t *oecm, uint8_t *dw)
  6161. +{
  6162. + uint8_t keyNr=0, length, end, key[16], okeySeed[16], keySeed[16], keyIV[16], tmp[16];
  6163. + uint32_t i, l, ident;
  6164. + uint16_t key0Ref, keySeedRef, keyIVRef;
  6165. + uint8_t ecmCopy[EMU_MAX_ECM_LEN], *ecm = oecm;
  6166. + uint16_t ecmLen = GetEcmLen(ecm);
  6167. +
  6168. + if(ecmLen < 12) {
  6169. + return 1;
  6170. + }
  6171. +
  6172. + length = ecm[11];
  6173. + keyNr = ecm[9];
  6174. + ident = ecm[8] | caid << 8;
  6175. +
  6176. + if(ecmLen < length+12) {
  6177. + return 1;
  6178. + }
  6179. +
  6180. + key0Ref = 0;
  6181. + while(GetIrdetoKey(key, ident, '0', keyNr, 1, &key0Ref)) {
  6182. + keySeedRef = 0;
  6183. + while(GetIrdetoKey(okeySeed, ident, 'M', 1, 1, &keySeedRef)) {
  6184. + keyIVRef = 0;
  6185. + while(GetIrdetoKey(keyIV, ident, 'M', 2, 1, &keyIVRef)) {
  6186. +
  6187. + memcpy(keySeed, okeySeed, 16);
  6188. + memcpy(ecmCopy, oecm, ecmLen);
  6189. + ecm = ecmCopy;
  6190. +
  6191. + memset(tmp, 0, 16);
  6192. + Irdeto2Encrypt(keySeed, tmp, key, 16);
  6193. + ecm+=12;
  6194. + Irdeto2Decrypt(ecm, keyIV, keySeed, length);
  6195. + i=(ecm[0]&7)+1;
  6196. + end = length-8 < 0 ? 0 : length-8;
  6197. +
  6198. + while(i<end) {
  6199. + l = ecm[i+1] ? (ecm[i+1]&0x3F)+2 : 1;
  6200. + switch(ecm[i]) {
  6201. + case 0x10:
  6202. + case 0x50:
  6203. + if(l==0x13 && i<=length-8-l) {
  6204. + Irdeto2Decrypt(&ecm[i+3], keyIV, key, 16);
  6205. + }
  6206. + break;
  6207. + case 0x78:
  6208. + if(l==0x14 && i<=length-8-l) {
  6209. + Irdeto2Decrypt(&ecm[i+4], keyIV, key, 16);
  6210. + }
  6211. + break;
  6212. + }
  6213. + i+=l;
  6214. + }
  6215. +
  6216. + i=(ecm[0]&7)+1;
  6217. + if(Irdeto2CalculateHash(keySeed, keyIV, ecm-6, length+6)) {
  6218. + while(i<end) {
  6219. + l = ecm[i+1] ? (ecm[i+1]&0x3F)+2 : 1;
  6220. + switch(ecm[i]) {
  6221. + case 0x78:
  6222. + if(l==0x14 && i<=length-8-l) {
  6223. + memcpy(dw, &ecm[i+4], 16);
  6224. + return 0;
  6225. + }
  6226. + }
  6227. + i+=l;
  6228. + }
  6229. + }
  6230. + }
  6231. + if(keyIVRef == 0) {
  6232. + return 2;
  6233. + }
  6234. + }
  6235. + if(keySeedRef == 0) {
  6236. + return 2;
  6237. + }
  6238. + }
  6239. + if(key0Ref == 0) {
  6240. + return 2;
  6241. + }
  6242. +
  6243. + return 1;
  6244. +}
  6245. +
  6246. +// BISS Emu
  6247. +static int8_t BissECM(uint16_t UNUSED(caid), const uint8_t *ecm, int16_t ecmDataLen,
  6248. + uint8_t *dw, uint16_t srvid, uint16_t ecmpid)
  6249. +{
  6250. + uint8_t haveKey1 = 0, haveKey2 = 0;
  6251. + uint16_t ecmLen = 0, pid = 0;
  6252. + uint32_t i;
  6253. +
  6254. + //try using ecmpid if it seems to be valid
  6255. + if(ecmpid != 0) {
  6256. + haveKey1 = FindKey('F', (srvid<<16)|ecmpid, "00", dw, 8, 1, 0, 0, NULL);
  6257. + haveKey2 = FindKey('F', (srvid<<16)|ecmpid, "01", &dw[8], 8, 1, 0, 0, NULL);
  6258. +
  6259. + if(haveKey1 && haveKey2) {return 0;}
  6260. + else if(haveKey1 && !haveKey2) {memcpy(&dw[8], dw, 8); return 0;}
  6261. + else if(!haveKey1 && haveKey2) {memcpy(dw, &dw[8], 8); return 0;}
  6262. + }
  6263. +
  6264. + //try to get the pid from oscam's fake ecm ([sid] ([pid1] [pid2] ... [pidx])
  6265. + if(ecmDataLen >= 3) {
  6266. + ecmLen = GetEcmLen(ecm);
  6267. +
  6268. + if(ecmLen > 7 && ecmLen <= ecmDataLen) {
  6269. + for(i=5; i+1<ecmLen; i+=2) {
  6270. + pid = b2i(2, ecm+i);
  6271. + haveKey1 = FindKey('F', (srvid<<16)|pid, "00", dw, 8, 1, 0, 0, NULL);
  6272. + haveKey2 = FindKey('F', (srvid<<16)|pid, "01", &dw[8], 8, 1, 0, 0, NULL);
  6273. +
  6274. + if(haveKey1 && haveKey2) {return 0;}
  6275. + else if(haveKey1 && !haveKey2) {memcpy(&dw[8], dw, 8); return 0;}
  6276. + else if(!haveKey1 && haveKey2) {memcpy(dw, &dw[8], 8); return 0;}
  6277. + }
  6278. + }
  6279. + }
  6280. +
  6281. + //fallback to default pid
  6282. + haveKey1 = FindKey('F', (srvid<<16)|0x1FFF, "00", dw, 8, 1, 0, 0, NULL);
  6283. + haveKey2 = FindKey('F', (srvid<<16)|0x1FFF, "01", &dw[8], 8, 1, 0, 0, NULL);
  6284. +
  6285. + if(haveKey1 && haveKey2) {return 0;}
  6286. + else if(haveKey1 && !haveKey2) {memcpy(&dw[8], dw, 8); return 0;}
  6287. + else if(!haveKey1 && haveKey2) {memcpy(dw, &dw[8], 8); return 0;}
  6288. +
  6289. + return 2;
  6290. +}
  6291. +
  6292. +//PowerVu Emu
  6293. +static int8_t GetPowervuKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey, uint16_t keyRef)
  6294. +{
  6295. + char keyStr[EMU_MAX_CHAR_KEYNAME];
  6296. +
  6297. + if(keyRef > 0xFF)
  6298. + {
  6299. + return 0;
  6300. + }
  6301. +
  6302. + snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
  6303. + if(FindKey('P', ident, keyStr, buf, keyLength, isCriticalKey, (uint8_t)keyRef, 0, NULL)) {
  6304. + return 1;
  6305. + }
  6306. +
  6307. + return 0;
  6308. +}
  6309. +
  6310. +static int8_t GetPowervuEmmKey(uint8_t *buf, uint32_t ident, char *keyName, uint32_t keyLength, uint8_t isCriticalKey, uint32_t *getProvider)
  6311. +{
  6312. + if(FindKey('P', ident, keyName, buf, keyLength, isCriticalKey, 0, 0, getProvider)) {
  6313. + return 1;
  6314. + }
  6315. +
  6316. + return 0;
  6317. +}
  6318. +
  6319. +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};
  6320. +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};
  6321. +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};
  6322. +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};
  6323. +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};
  6324. +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};
  6325. +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};
  6326. +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};
  6327. +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,
  6328. + 0xCC, 0xEF, 0x22, 0x64, 0x01, 0x2C, 0x12, 0xDE, 0xF4, 0x6E, 0x3C, 0xCD, 0x1A, 0x64, 0x63, 0x7C
  6329. + };
  6330. +
  6331. +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};
  6332. +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};
  6333. +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};
  6334. +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};
  6335. +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};
  6336. +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};
  6337. +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};
  6338. +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};
  6339. +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,
  6340. + 0xED, 0xE9, 0x47, 0x29, 0xC2, 0xA8, 0x92, 0xEF, 0xBA, 0x27, 0x22, 0x57, 0x76, 0x54, 0xC0, 0x59,
  6341. + };
  6342. +
  6343. +static uint8_t PowervuSbox(uint8_t *input, uint8_t mode)
  6344. +{
  6345. + uint8_t s_index, bit, last_index, last_bit;
  6346. + uint8_t const *Sbox1, *Sbox2, *Sbox3, *Sbox4, *Sbox5, *Sbox6, *Sbox7, *Sbox8, *Sbox9;
  6347. +
  6348. + if(mode)
  6349. + {
  6350. + Sbox1 = PowerVu_A0_S_1;
  6351. + Sbox2 = PowerVu_A0_S_2;
  6352. + Sbox3 = PowerVu_A0_S_3;
  6353. + Sbox4 = PowerVu_A0_S_4;
  6354. + Sbox5 = PowerVu_A0_S_5;
  6355. + Sbox6 = PowerVu_A0_S_6;
  6356. + Sbox7 = PowerVu_A0_S_7;
  6357. + Sbox8 = PowerVu_A0_S_8;
  6358. + Sbox9 = PowerVu_A0_S_9;
  6359. + }
  6360. + else
  6361. + {
  6362. + Sbox1 = PowerVu_00_S_1;
  6363. + Sbox2 = PowerVu_00_S_2;
  6364. + Sbox3 = PowerVu_00_S_3;
  6365. + Sbox4 = PowerVu_00_S_4;
  6366. + Sbox5 = PowerVu_00_S_5;
  6367. + Sbox6 = PowerVu_00_S_6;
  6368. + Sbox7 = PowerVu_00_S_7;
  6369. + Sbox8 = PowerVu_00_S_8;
  6370. + Sbox9 = PowerVu_00_S_9;
  6371. + }
  6372. +
  6373. + bit = (GetBit(input[2],0)<<2) | (GetBit(input[3],4)<<1) | (GetBit(input[5],3));
  6374. + s_index = (GetBit(input[0],0)<<3) | (GetBit(input[2],6)<<2) | (GetBit(input[2],4)<<1) | (GetBit(input[5],7));
  6375. + last_bit = GetBit(Sbox1[s_index],7-bit);
  6376. +
  6377. + bit = (GetBit(input[5],0)<<2) | (GetBit(input[4],0)<<1) | (GetBit(input[6],2));
  6378. + s_index = (GetBit(input[2],1)<<3) | (GetBit(input[2],2)<<2) | (GetBit(input[5],5)<<1) | (GetBit(input[5],1));
  6379. + last_bit = last_bit | (GetBit(Sbox2[s_index],7-bit)<<1);
  6380. +
  6381. + bit = (GetBit(input[6],0)<<2) | (GetBit(input[1],7)<<1) | (GetBit(input[6],7));
  6382. + s_index = (GetBit(input[1],3)<<3) | (GetBit(input[3],7)<<2) | (GetBit(input[1],5)<<1) | (GetBit(input[5],2));
  6383. + last_bit = last_bit | (GetBit(Sbox3[s_index], 7-bit)<<2);
  6384. +
  6385. + bit = (GetBit(input[1],0)<<2) | (GetBit(input[2],7)<<1) | (GetBit(input[2],5));
  6386. + s_index = (GetBit(input[6],3)<<3) | (GetBit(input[6],4)<<2) | (GetBit(input[6],6)<<1) | (GetBit(input[3],5));
  6387. + last_index = GetBit(Sbox4[s_index], 7-bit);
  6388. +
  6389. + bit = (GetBit(input[3],3)<<2) | (GetBit(input[4],6)<<1) | (GetBit(input[3],2));
  6390. + s_index = (GetBit(input[3],1)<<3) | (GetBit(input[4],5)<<2) | (GetBit(input[3],0)<<1) | (GetBit(input[4],7));
  6391. + last_index = last_index | (GetBit(Sbox5[s_index], 7-bit)<<1);
  6392. +
  6393. + bit = (GetBit(input[5],4)<<2) | (GetBit(input[4],4)<<1) | (GetBit(input[1],2));
  6394. + s_index = (GetBit(input[2],3)<<3) | (GetBit(input[6],5)<<2) | (GetBit(input[1],4)<<1) | (GetBit(input[4],1));
  6395. + last_index = last_index | (GetBit(Sbox6[s_index], 7-bit)<<2);
  6396. +
  6397. + bit = (GetBit(input[0],6)<<2) | (GetBit(input[0],7)<<1) | (GetBit(input[0],4));
  6398. + s_index = (GetBit(input[0],5)<<3) | (GetBit(input[0],3)<<2) | (GetBit(input[0],1)<<1) | (GetBit(input[0],2));
  6399. + last_index = last_index | (GetBit(Sbox7[s_index], 7-bit)<<3);
  6400. +
  6401. + bit = (GetBit(input[4],2)<<2) | (GetBit(input[4],3)<<1) | (GetBit(input[1],1));
  6402. + s_index = (GetBit(input[1],6)<<3) | (GetBit(input[6],1)<<2) | (GetBit(input[5],6)<<1) | (GetBit(input[3],6));
  6403. + last_index = last_index | (GetBit(Sbox8[s_index], 7-bit)<<4);
  6404. +
  6405. + return (GetBit(Sbox9[last_index&0x1f],7-last_bit)&1) ? 1: 0;
  6406. +}
  6407. +
  6408. +static void PowervuDecrypt(uint8_t *data, uint32_t length, uint8_t *key, uint8_t sbox)
  6409. +{
  6410. + uint32_t i;
  6411. + int32_t j, k;
  6412. + uint8_t curByte, tmpBit;
  6413. +
  6414. + for(i=0; i<length; i++)
  6415. + {
  6416. + curByte = data[i];
  6417. +
  6418. + for(j=7; j>=0; j--)
  6419. + {
  6420. + data[i] = SetBit(data[i], j,(GetBit(curByte,j)^PowervuSbox(key, sbox))^GetBit(key[0],7));
  6421. +
  6422. + tmpBit = GetBit(data[i],j)^(GetBit(key[6],0));
  6423. + if (tmpBit)
  6424. + {
  6425. + key[3] ^= 0x10;
  6426. + }
  6427. +
  6428. + for (k = 6; k > 0; k--)
  6429. + {
  6430. + key[k] = (key[k]>>1) | (key[k-1]<<7);
  6431. + }
  6432. + key[0] = (key[0]>>1);
  6433. +
  6434. + key[0] = SetBit(key[0], 7, tmpBit);
  6435. + }
  6436. + }
  6437. +}
  6438. +
  6439. +#define PVU_CW_VID 0 // VIDeo
  6440. +#define PVU_CW_HSD 1 // High Speed Data
  6441. +#define PVU_CW_A1 2 // Audio 1
  6442. +#define PVU_CW_A2 3 // Audio 2
  6443. +#define PVU_CW_A3 4 // Audio 3
  6444. +#define PVU_CW_A4 5 // Audio 4
  6445. +#define PVU_CW_UTL 6 // UTiLity
  6446. +#define PVU_CW_VBI 7 // Vertical Blanking Interval
  6447. +
  6448. +#define PVU_CONVCW_VID_ECM 0x80 // VIDeo
  6449. +#define PVU_CONVCW_HSD_ECM 0x40 // High Speed Data
  6450. +#define PVU_CONVCW_A1_ECM 0x20 // Audio 1
  6451. +#define PVU_CONVCW_A2_ECM 0x10 // Audio 2
  6452. +#define PVU_CONVCW_A3_ECM 0x08 // Audio 3
  6453. +#define PVU_CONVCW_A4_ECM 0x04 // Audio 4
  6454. +#define PVU_CONVCW_UTL_ECM 0x02 // UTiLity
  6455. +#define PVU_CONVCW_VBI_ECM 0x01 // Vertical Blanking Interval
  6456. +
  6457. +static uint8_t PowervuGetConvcwIndex(uint8_t ecmTag)
  6458. +{
  6459. + switch(ecmTag)
  6460. + {
  6461. + case PVU_CONVCW_VID_ECM:
  6462. + return PVU_CW_VID;
  6463. +
  6464. + case PVU_CONVCW_HSD_ECM:
  6465. + return PVU_CW_HSD;
  6466. +
  6467. + case PVU_CONVCW_A1_ECM:
  6468. + return PVU_CW_A1;
  6469. +
  6470. + case PVU_CONVCW_A2_ECM:
  6471. + return PVU_CW_A2;
  6472. +
  6473. + case PVU_CONVCW_A3_ECM:
  6474. + return PVU_CW_A3;
  6475. +
  6476. + case PVU_CONVCW_A4_ECM:
  6477. + return PVU_CW_A4;
  6478. +
  6479. + case PVU_CONVCW_UTL_ECM:
  6480. + return PVU_CW_UTL;
  6481. +
  6482. + case PVU_CONVCW_VBI_ECM:
  6483. + return PVU_CW_VBI;
  6484. +
  6485. + default:
  6486. + return PVU_CW_VBI;
  6487. + }
  6488. +}
  6489. +
  6490. +static uint16_t PowervuGetSeedIV(uint8_t seedType, uint8_t *ecm)
  6491. +{
  6492. + switch(seedType)
  6493. + {
  6494. + case PVU_CW_VID:
  6495. + return ((ecm[0x10] & 0x1F) <<3) | 0;
  6496. + case PVU_CW_HSD:
  6497. + return ((ecm[0x12] & 0x1F) <<3) | 2;
  6498. + case PVU_CW_A1:
  6499. + return ((ecm[0x11] & 0x3F) <<3) | 1;
  6500. + case PVU_CW_A2:
  6501. + return ((ecm[0x13] & 0x3F) <<3) | 1;
  6502. + case PVU_CW_A3:
  6503. + return ((ecm[0x19] & 0x3F) <<3) | 1;
  6504. + case PVU_CW_A4:
  6505. + return ((ecm[0x1A] & 0x3F) <<3) | 1;;
  6506. + case PVU_CW_UTL:
  6507. + return ((ecm[0x14] & 0x0F) <<3) | 4;
  6508. + case PVU_CW_VBI:
  6509. + return (((ecm[0x15] & 0xF8)>>3)<<3) | 5;
  6510. + default:
  6511. + return 0;
  6512. + }
  6513. +}
  6514. +
  6515. +static void PowervuExpandSeed(uint8_t seedType, uint8_t *seed)
  6516. +{
  6517. + uint8_t seedLength, i;
  6518. +
  6519. + switch(seedType)
  6520. + {
  6521. + case PVU_CW_VID:
  6522. + case PVU_CW_HSD:
  6523. + seedLength = 4;
  6524. + break;
  6525. + case PVU_CW_A1:
  6526. + case PVU_CW_A2:
  6527. + case PVU_CW_A3:
  6528. + case PVU_CW_A4:
  6529. + seedLength = 3;
  6530. + break;
  6531. + case PVU_CW_UTL:
  6532. + case PVU_CW_VBI:
  6533. + seedLength = 2;
  6534. + break;
  6535. + default:
  6536. + return;
  6537. + }
  6538. +
  6539. + for(i=seedLength; i<7; i++)
  6540. + {
  6541. + seed[i] = seed[i%seedLength];
  6542. + }
  6543. +}
  6544. +
  6545. +static void PowervuCalculateSeed(uint8_t seedType, uint8_t *ecm, uint8_t *seedBase, uint8_t *key, uint8_t *seed, uint8_t sbox)
  6546. +{
  6547. + uint16_t tmpSeed;
  6548. +
  6549. + tmpSeed = PowervuGetSeedIV(seedType, ecm+23);
  6550. + seed[0] = (tmpSeed>>2) & 0xFF;
  6551. + seed[1] = ((tmpSeed&0x3)<<6) | (seedBase[0]>>2);
  6552. + seed[2] = (seedBase[0]<<6) | (seedBase[1]>>2);
  6553. + seed[3] = (seedBase[1]<<6) | (seedBase[2]>>2);
  6554. + seed[4] = (seedBase[2]<<6) | (seedBase[3]>>2);
  6555. + seed[5] = (seedBase[3]<<6);
  6556. +
  6557. + PowervuDecrypt(seed, 6, key, sbox);
  6558. +
  6559. + seed[0] = (seed[1]<<2) | (seed[2]>>6);
  6560. + seed[1] = (seed[2]<<2) | (seed[3]>>6);
  6561. + seed[2] = (seed[3]<<2) | (seed[4]>>6);
  6562. + seed[3] = (seed[4]<<2) | (seed[5]>>6);
  6563. +}
  6564. +
  6565. +static void PowervuCalculateCw(uint8_t seedType, uint8_t *seed, uint8_t csaUsed,
  6566. + uint8_t *convolvedCw, uint8_t *cw, uint8_t *baseCw)
  6567. +{
  6568. + int32_t k;
  6569. +
  6570. + PowervuExpandSeed(seedType, seed);
  6571. +
  6572. + if(csaUsed)
  6573. + {
  6574. + for(k=0; k<7; k++)
  6575. + {
  6576. + seed[k] ^= baseCw[k];
  6577. + }
  6578. +
  6579. + cw[0] = seed[0] ^ convolvedCw[0];
  6580. + cw[1] = seed[1] ^ convolvedCw[1];
  6581. + cw[2] = seed[2] ^ convolvedCw[2];
  6582. + cw[3] = seed[3] ^ convolvedCw[3];
  6583. + cw[4] = seed[3] ^ convolvedCw[4];
  6584. + cw[5] = seed[4] ^ convolvedCw[5];
  6585. + cw[6] = seed[5] ^ convolvedCw[6];
  6586. + cw[7] = seed[6] ^ convolvedCw[7];
  6587. + }
  6588. + else
  6589. + {
  6590. + for(k=0; k<7; k++)
  6591. + {
  6592. + cw[k] = seed[k] ^ baseCw[k];
  6593. + }
  6594. + ExpandDesKey(cw);
  6595. + }
  6596. +}
  6597. +
  6598. +#ifdef WITH_EMU
  6599. +int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, uint16_t srvid, emu_stream_client_key_data *cdata, EXTENDED_CW* cw_ex)
  6600. +#else
  6601. +int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, emu_stream_client_key_data *cdata)
  6602. +#endif
  6603. +{
  6604. + int8_t ret = 1;
  6605. + uint16_t ecmLen = GetEcmLen(ecm);
  6606. + uint32_t ecmCrc32;
  6607. + uint8_t nanoCmd, nanoChecksum, keyType, fixedKey, oddKey, bid, csaUsed;
  6608. + uint16_t nanoLen;
  6609. + uint32_t channelId, ecmSrvid, keyIndex;
  6610. + uint32_t i, j, k;
  6611. + uint8_t convolvedCw[8][8];
  6612. + uint8_t ecmKey[7], tmpEcmKey[7], seedBase[4], baseCw[7], seed[8][8], cw[8][8];
  6613. + uint8_t decrypt_ok;
  6614. + uint8_t ecmPart1[14], ecmPart2[27];
  6615. + uint8_t sbox;
  6616. + uint16_t keyRef1, keyRef2;
  6617. +#ifdef WITH_EMU
  6618. + uint8_t *dwp;
  6619. + emu_stream_cw_item *cw_item;
  6620. + int8_t update_global_key = 0;
  6621. + int8_t update_global_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  6622. +
  6623. + memset(update_global_keys, 0, sizeof(update_global_keys));
  6624. +#endif
  6625. +
  6626. + if(ecmLen < 7)
  6627. + {
  6628. + return 1;
  6629. + }
  6630. +
  6631. + ecmCrc32 = b2i(4, ecm+ecmLen-4);
  6632. +
  6633. + if(fletcher_crc32(ecm, ecmLen-4) != ecmCrc32)
  6634. + {
  6635. + return 8;
  6636. + }
  6637. + ecmLen -= 4;
  6638. +
  6639. + for(i=0; i<8; i++) {
  6640. + memset(convolvedCw[i], 0, 8);
  6641. + }
  6642. +
  6643. + for(i=3; i+3<ecmLen; ) {
  6644. + nanoLen = (((ecm[i] & 0x0f)<< 8) | ecm[i+1]);
  6645. + i +=2;
  6646. + if(nanoLen > 0)
  6647. + {
  6648. + nanoLen--;
  6649. + }
  6650. + nanoCmd = ecm[i++];
  6651. + if(i+nanoLen > ecmLen) {
  6652. + return 1;
  6653. + }
  6654. +
  6655. + switch (nanoCmd) {
  6656. + case 0x27:
  6657. + if(nanoLen < 15)
  6658. + {
  6659. + break;
  6660. + }
  6661. +
  6662. + nanoChecksum = 0;
  6663. + for(j=4; j<15; j++)
  6664. + {
  6665. + nanoChecksum += ecm[i+j];
  6666. + }
  6667. +
  6668. + if(nanoChecksum != 0)
  6669. + {
  6670. + break;
  6671. + }
  6672. +
  6673. + keyType = PowervuGetConvcwIndex(ecm[i+4]);
  6674. + memcpy(convolvedCw[keyType], &ecm[i+6], 8);
  6675. + break;
  6676. +
  6677. + default:
  6678. + break;
  6679. + }
  6680. + i += nanoLen;
  6681. + }
  6682. +
  6683. + for(i=3; i+3<ecmLen; ) {
  6684. + nanoLen = (((ecm[i] & 0x0f)<< 8) | ecm[i+1]);
  6685. + i +=2;
  6686. + if(nanoLen > 0)
  6687. + {
  6688. + nanoLen--;
  6689. + }
  6690. + nanoCmd = ecm[i++];
  6691. + if(i+nanoLen > ecmLen) {
  6692. + return 1;
  6693. + }
  6694. +
  6695. + switch (nanoCmd) {
  6696. + case 0x20:
  6697. + if(nanoLen < 54)
  6698. + {
  6699. + break;
  6700. + }
  6701. +
  6702. + csaUsed = GetBit(ecm[i+7], 7);
  6703. + fixedKey = !GetBit(ecm[i+6], 5);
  6704. + oddKey = GetBit(ecm[i+6], 4);
  6705. + bid = (GetBit(ecm[i+7], 1)<<1) | GetBit(ecm[i+7], 0);
  6706. + sbox = GetBit(ecm[i+6], 3);
  6707. +
  6708. + keyIndex = (fixedKey<<3) | (bid<<2) | oddKey;
  6709. + channelId = b2i(2, ecm+i+23);
  6710. + ecmSrvid = (channelId >> 4) | ((channelId & 0xF) << 12);
  6711. +
  6712. + decrypt_ok = 0;
  6713. +
  6714. + memcpy(ecmPart1, ecm+i+8, 14);
  6715. + memcpy(ecmPart2, ecm+i+27, 27);
  6716. +
  6717. + keyRef1 = 0;
  6718. + keyRef2 = 0;
  6719. +
  6720. + do
  6721. + {
  6722. + if(!GetPowervuKey(ecmKey, ecmSrvid, '0', keyIndex, 7, 0, keyRef1++))
  6723. + {
  6724. + if(!GetPowervuKey(ecmKey, channelId, '0', keyIndex, 7, 0, keyRef2++))
  6725. + {
  6726. + cs_log("[Emu] Key not found: P %04X 0%X", ecmSrvid, keyIndex);
  6727. + return 2;
  6728. + }
  6729. + }
  6730. +
  6731. + PowervuDecrypt(ecm+i+8, 14, ecmKey, sbox);
  6732. + if((ecm[i+6] != ecm[i+6+7]) || (ecm[i+6+8] != ecm[i+6+15]))
  6733. + {
  6734. + memcpy(ecm+i+8, ecmPart1, 14);
  6735. + continue;
  6736. + }
  6737. +
  6738. + memcpy(tmpEcmKey, ecmKey, 7);
  6739. +
  6740. + PowervuDecrypt(ecm+i+27, 27, ecmKey, sbox);
  6741. + if((ecm[i+23] != ecm[i+23+29]) || (ecm[i+23+1] != ecm[i+23+30]))
  6742. + {
  6743. + memcpy(ecm+i+8, ecmPart1, 14);
  6744. + memcpy(ecm+i+27, ecmPart2, 27);
  6745. + continue;
  6746. + }
  6747. +
  6748. + decrypt_ok = 1;
  6749. + }
  6750. + while(!decrypt_ok);
  6751. +
  6752. + memcpy(seedBase, ecm+i+6+2, 4);
  6753. +
  6754. +#ifdef WITH_EMU
  6755. + if(cdata == NULL)
  6756. + {
  6757. + SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
  6758. + for(j=0; j<EMU_STREAM_SERVER_MAX_CONNECTIONS; j++)
  6759. + {
  6760. + if(!stream_server_has_ecm[j] && emu_stream_cur_srvid[j] == srvid)
  6761. + {
  6762. + update_global_key = 1;
  6763. + update_global_keys[j] = 1;
  6764. + }
  6765. + }
  6766. + SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
  6767. + }
  6768. +
  6769. + if(cdata != NULL || update_global_key || cw_ex != NULL)
  6770. +#else
  6771. + if(cdata != NULL)
  6772. +#endif
  6773. + {
  6774. + // Calculate all seeds
  6775. + for(j=0; j<8; j++)
  6776. + {
  6777. + memcpy(ecmKey, tmpEcmKey, 7);
  6778. + PowervuCalculateSeed(j, ecm+i, seedBase, ecmKey, seed[j], sbox);
  6779. + }
  6780. + }
  6781. + else
  6782. + {
  6783. + // Calculate only video seed
  6784. + memcpy(ecmKey, tmpEcmKey, 7);
  6785. + PowervuCalculateSeed(PVU_CW_VID, ecm+i, seedBase, ecmKey, seed[PVU_CW_VID], sbox);
  6786. + }
  6787. +
  6788. + memcpy(baseCw, ecm+i+6+8, 7);
  6789. +
  6790. +#ifdef WITH_EMU
  6791. + if(cdata != NULL || update_global_key || cw_ex != NULL)
  6792. +#else
  6793. + if(cdata != NULL)
  6794. +#endif
  6795. + {
  6796. + // Calculate all cws
  6797. + for(j=0; j<8; j++)
  6798. + {
  6799. + PowervuCalculateCw(j, seed[j], csaUsed, convolvedCw[j], cw[j], baseCw);
  6800. +
  6801. + if(csaUsed)
  6802. + {
  6803. + for(k = 0; k < 8; k += 4) {
  6804. + cw[j][k + 3] = ((cw[j][k] + cw[j][k + 1] + cw[j][k + 2]) & 0xff);
  6805. + }
  6806. + }
  6807. + }
  6808. +
  6809. +#ifdef WITH_EMU
  6810. + if(update_global_key)
  6811. + {
  6812. + for(j=0; j<EMU_STREAM_SERVER_MAX_CONNECTIONS; j++)
  6813. + {
  6814. + if(update_global_keys[j])
  6815. + {
  6816. + cw_item = (emu_stream_cw_item*)malloc(sizeof(emu_stream_cw_item));
  6817. + if(cw_item != NULL)
  6818. + {
  6819. + cw_item->csa_used = csaUsed;
  6820. + cw_item->is_even = ecm[0] == 0x80 ? 1 : 0;
  6821. + cs_ftime(&cw_item->write_time);
  6822. + add_ms_to_timeb(&cw_item->write_time, cfg.emu_stream_ecm_delay);
  6823. + memcpy(cw_item->cw, cw, sizeof(cw));
  6824. + ll_append(ll_emu_stream_delayed_keys[j], cw_item);
  6825. + }
  6826. + }
  6827. + }
  6828. + }
  6829. +
  6830. + if(cdata != NULL)
  6831. + {
  6832. +#endif
  6833. + for(j=0; j<8; j++)
  6834. + {
  6835. + if(csaUsed)
  6836. + {
  6837. + if(cdata->pvu_csa_ks[j] == NULL)
  6838. + { cdata->pvu_csa_ks[j] = get_key_struct(); }
  6839. +
  6840. + if(ecm[0] == 0x80)
  6841. + { set_even_control_word(cdata->pvu_csa_ks[j], cw[j]); }
  6842. + else
  6843. + { set_odd_control_word(cdata->pvu_csa_ks[j], cw[j]); }
  6844. +
  6845. + cdata->pvu_csa_used = 1;
  6846. + }
  6847. + else
  6848. + {
  6849. + if(ecm[0] == 0x80)
  6850. + { des_set_key(cw[j], cdata->pvu_des_ks[j][0]); }
  6851. + else
  6852. + { des_set_key(cw[j], cdata->pvu_des_ks[j][1]); }
  6853. +
  6854. + cdata->pvu_csa_used = 0;
  6855. + }
  6856. + }
  6857. +#ifdef WITH_EMU
  6858. + }
  6859. +
  6860. + if(cw_ex != NULL)
  6861. + {
  6862. + cw_ex->mode = CW_MODE_MULTIPLE_CW;
  6863. +
  6864. + if(csaUsed)
  6865. + {
  6866. + cw_ex->algo = CW_ALGO_CSA;
  6867. + cw_ex->algo_mode = CW_ALGO_MODE_ECB;
  6868. + }
  6869. + else
  6870. + {
  6871. + cw_ex->algo = CW_ALGO_DES;
  6872. + cw_ex->algo_mode = CW_ALGO_MODE_ECB;
  6873. + }
  6874. +
  6875. + for(j=0; j<4; j++)
  6876. + {
  6877. + dwp = cw_ex->audio[j];
  6878. +
  6879. + memset(dwp, 0, 16);
  6880. +
  6881. + if(ecm[0] == 0x80)
  6882. + {
  6883. + memcpy(dwp, cw[PVU_CW_A1+j], 8);
  6884. +
  6885. + if(csaUsed)
  6886. + {
  6887. + for(k = 0; k < 8; k += 4)
  6888. + {
  6889. + dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff);
  6890. + }
  6891. + }
  6892. + }
  6893. + else
  6894. + {
  6895. + memcpy(&dwp[8], cw[PVU_CW_A1+j], 8);
  6896. +
  6897. + if(csaUsed)
  6898. + {
  6899. + for(k = 8; k < 16; k += 4)
  6900. + {
  6901. + dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff);
  6902. + }
  6903. + }
  6904. + }
  6905. + }
  6906. +
  6907. + dwp = cw_ex->data;
  6908. +
  6909. + memset(dwp, 0, 16);
  6910. +
  6911. + if(ecm[0] == 0x80)
  6912. + {
  6913. + memcpy(dwp, cw[PVU_CW_HSD], 8);
  6914. +
  6915. + if(csaUsed)
  6916. + {
  6917. + for(k = 0; k < 8; k += 4)
  6918. + {
  6919. + dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff);
  6920. + }
  6921. + }
  6922. + }
  6923. + else
  6924. + {
  6925. + memcpy(&dwp[8], cw[PVU_CW_HSD], 8);
  6926. +
  6927. + if(csaUsed)
  6928. + {
  6929. + for(k = 8; k < 16; k += 4)
  6930. + {
  6931. + dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff);
  6932. + }
  6933. + }
  6934. + }
  6935. + }
  6936. +#endif
  6937. + }
  6938. + else
  6939. + {
  6940. + // Calculate only video cw
  6941. + PowervuCalculateCw(PVU_CW_VID, seed[PVU_CW_VID], csaUsed, convolvedCw[PVU_CW_VID], cw[PVU_CW_VID], baseCw);
  6942. + }
  6943. +
  6944. + memset(dw, 0, 16);
  6945. +
  6946. + if(ecm[0] == 0x80)
  6947. + {
  6948. + memcpy(dw, cw[PVU_CW_VID], 8);
  6949. +
  6950. + if(csaUsed)
  6951. + {
  6952. + for(k = 0; k < 8; k += 4)
  6953. + {
  6954. + dw[k + 3] = ((dw[k] + dw[k + 1] + dw[k + 2]) & 0xff);
  6955. + }
  6956. + }
  6957. + }
  6958. + else
  6959. + {
  6960. + memcpy(&dw[8], cw[PVU_CW_VID], 8);
  6961. +
  6962. + if(csaUsed)
  6963. + {
  6964. + for(k = 8; k < 16; k += 4)
  6965. + {
  6966. + dw[k + 3] = ((dw[k] + dw[k + 1] + dw[k + 2]) & 0xff);
  6967. + }
  6968. + }
  6969. + }
  6970. +
  6971. + return 0;
  6972. +
  6973. + default:
  6974. + break;
  6975. + }
  6976. + i += nanoLen;
  6977. + }
  6978. +
  6979. + return ret;
  6980. +}
  6981. +
  6982. +
  6983. +//Drecrypt EMU
  6984. +
  6985. +static int8_t GetDrecryptKey(uint8_t *buf, uint32_t keyIdent, uint16_t keyName, uint8_t isCriticalKey, uint8_t *keyRef)
  6986. +{
  6987. + char keyStr[EMU_MAX_CHAR_KEYNAME];
  6988. + snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%X", keyName);
  6989. + if(FindKey('D', keyIdent, keyStr, buf, 32, *keyRef > 0 ? 0 : isCriticalKey, *keyRef, 0, NULL)) {
  6990. + (*keyRef)++;
  6991. + return 1;
  6992. + }
  6993. +
  6994. + return 0;
  6995. +}
  6996. +
  6997. +static void DrecryptOver(const unsigned char *ECMdata, unsigned char *DW)
  6998. +{
  6999. + uint8_t key[8];
  7000. + char keyStr[EMU_MAX_CHAR_KEYNAME];
  7001. + uint32_t key_schedule[32];
  7002. +
  7003. + if(ECMdata[2] >= (43 + 4) && ECMdata[40] == 0x3A && ECMdata[41] == 0x4B)
  7004. + {
  7005. + snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%X", (ECMdata[42] & 0x0F));
  7006. +
  7007. + if(!FindKey('D', 0, keyStr, key, 8, 1, 0, 0, NULL))
  7008. + {
  7009. + return;
  7010. + }
  7011. +
  7012. + des_set_key(key, key_schedule);
  7013. +
  7014. + des(DW, key_schedule, 0); // even DW post-process
  7015. + des(DW + 8, key_schedule, 0); // odd DW post-process
  7016. + }
  7017. +};
  7018. +
  7019. +static uint32_t DrecryptGostDec(uint32_t inData)
  7020. +{
  7021. + static const uint8_t DrecryptSbox[128] = {
  7022. + 0x0E,0x04,0x0D,0x01,0x02,0x0F,0x0B,0x08,0x03,0x0A,0x06,0x0C,0x05,0x09,0x00,0x07,
  7023. + 0x0F,0x01,0x08,0x0E,0x06,0x0B,0x03,0x04,0x09,0x07,0x02,0x0D,0x0C,0x00,0x05,0x0A,
  7024. + 0x0A,0x00,0x09,0x0E,0x06,0x03,0x0F,0x05,0x01,0x0D,0x0C,0x07,0x0B,0x04,0x02,0x08,
  7025. + 0x07,0x0D,0x0E,0x03,0x00,0x06,0x09,0x0A,0x01,0x02,0x08,0x05,0x0B,0x0C,0x04,0x0F,
  7026. + 0x02,0x0C,0x04,0x01,0x07,0x0A,0x0B,0x06,0x08,0x05,0x03,0x0F,0x0D,0x00,0x0E,0x09,
  7027. + 0x0C,0x01,0x0A,0x0F,0x09,0x02,0x06,0x08,0x00,0x0D,0x03,0x04,0x0E,0x07,0x05,0x0B,
  7028. + 0x04,0x0B,0x02,0x0E,0x0F,0x00,0x08,0x0D,0x03,0x0C,0x09,0x07,0x05,0x0A,0x06,0x01,
  7029. + 0x0D,0x02,0x08,0x04,0x06,0x0F,0x0B,0x01,0x0A,0x09,0x03,0x0E,0x05,0x00,0x0C,0x07
  7030. + };
  7031. +
  7032. + uint8_t i, j;
  7033. +
  7034. + for(i=0;i<8;i++) {
  7035. + j= (inData >> 28) & 0x0F;
  7036. + inData= (inData << 4) | (DrecryptSbox[i*16 + j] & 0x0F);
  7037. + }
  7038. +
  7039. + inData= (inData << 11) | (inData >> 21);
  7040. +
  7041. + return (inData);
  7042. +}
  7043. +
  7044. +static void DrecryptDecrypt(uint8_t *Data, uint8_t *Key)
  7045. +{
  7046. + int32_t i, j;
  7047. + uint32_t L_part = 0, R_part = 0, temp = 0;
  7048. +
  7049. + for(i=0;i<4;i++) {
  7050. + L_part = (L_part << 8) | (Data[i] & 0xFF), R_part = (R_part << 8) | (Data[i+4] & 0xFF);
  7051. + }
  7052. +
  7053. + for(i=0;i<4;i++) {
  7054. + temp= ((Key[i*8+0] & 0xFF)<<24) | ((Key[i*8+1] & 0xFF)<<16) | ((Key[i*8+2] & 0xFF)<<8) | (Key[i*8+3] & 0xFF);
  7055. + R_part^= DrecryptGostDec(temp + L_part);
  7056. + temp= ((Key[i*8+4] & 0xFF)<<24) | ((Key[i*8+5] & 0xFF)<<16) | ((Key[i*8+6] & 0xFF)<<8) | (Key[i*8+7] & 0xFF);
  7057. + L_part^= DrecryptGostDec(temp + R_part);
  7058. + }
  7059. +
  7060. + for(j=0;j<3;j++) {
  7061. + for(i=3;i>=0;i--) {
  7062. + temp= ((Key[i*8+4] & 0xFF)<<24) | ((Key[i*8+5] & 0xFF)<<16) | ((Key[i*8+6] & 0xFF)<<8) | (Key[i*8+7] & 0xFF);
  7063. + R_part^= DrecryptGostDec(temp + L_part);
  7064. + temp= ((Key[i*8+0] & 0xFF)<<24) | ((Key[i*8+1] & 0xFF)<<16) | ((Key[i*8+2] & 0xFF)<<8) | (Key[i*8+3] & 0xFF);
  7065. + L_part^= DrecryptGostDec(temp + R_part);
  7066. + }
  7067. + }
  7068. +
  7069. + for(i=0;i<4;i++) Data[i] = (R_part >> i*8) & 0xFF, Data[i+4] = (L_part >> i*8) & 0xFF;
  7070. +}
  7071. +
  7072. +static void DrecryptPostCw(uint8_t* ccw)
  7073. +{
  7074. + uint32_t i, j;
  7075. + uint8_t tmp[4];
  7076. +
  7077. + for(i = 0; i < 4; i++) {
  7078. +
  7079. + for(j = 0; j < 4; j++) {
  7080. + tmp[j] = ccw[3 - j];
  7081. + }
  7082. +
  7083. + for(j = 0; j < 4; j++) {
  7084. + ccw[j] = tmp[j];
  7085. + }
  7086. +
  7087. + ccw += 4;
  7088. + }
  7089. +}
  7090. +
  7091. +static void DrecryptSwap(uint8_t* ccw)
  7092. +{
  7093. + uint32_t tmp1, tmp2;
  7094. +
  7095. + memcpy(&tmp1, ccw, 4);
  7096. + memcpy(&tmp2, ccw + 4, 4);
  7097. +
  7098. + memcpy(ccw, ccw + 8, 8);
  7099. +
  7100. + memcpy(ccw + 8 , &tmp1, 4);
  7101. + memcpy(ccw + 8 + 4, &tmp2, 4);
  7102. +}
  7103. +
  7104. +static int8_t Drecrypt2ECM(uint16_t caid, uint32_t provId, uint8_t *ecm, uint8_t *dw)
  7105. +{
  7106. + uint8_t keyType, keyIndex, keyRef, ccw[16], key[32];
  7107. + uint16_t keyName, overcryptId;
  7108. + uint32_t keyIdent;
  7109. +
  7110. + uint16_t ecmLen = GetEcmLen(ecm);
  7111. + if(ecmLen < 30 || caid != 0x4AE1) {
  7112. + return 1;
  7113. + }
  7114. +
  7115. + switch(provId & 0xFF)
  7116. + {
  7117. + case 0x11:
  7118. + case 0x14:
  7119. + break;
  7120. + default:
  7121. + return 1;
  7122. + }
  7123. +
  7124. + keyType = ecm[6];
  7125. + keyIndex = ecm[5];
  7126. +
  7127. + keyIdent = caid<<8 | provId;
  7128. + keyName = keyType<<8 | keyIndex;
  7129. +
  7130. + keyRef = 0;
  7131. + while(GetDrecryptKey(key, keyIdent, keyName, 1, &keyRef))
  7132. + {
  7133. + memcpy(ccw, ecm+13, 16);
  7134. + DrecryptPostCw(key);
  7135. + DrecryptPostCw(key+16);
  7136. + DrecryptDecrypt(ccw, key);
  7137. + DrecryptDecrypt(ccw+8, key);
  7138. +
  7139. + if(ecmLen >= 46 && ecm[43] == 1)
  7140. + {
  7141. + DrecryptSwap(ccw);
  7142. + overcryptId = b2i(2, &ecm[44]);
  7143. + Drecrypt2OverCW(overcryptId, ccw);
  7144. + memcpy(dw, ccw, 16);
  7145. + return 0;
  7146. + }
  7147. +
  7148. + DrecryptOver(ecm, ccw);
  7149. +
  7150. + if(isValidDCW(ccw)) {
  7151. + DrecryptSwap(ccw);
  7152. + memcpy(dw, ccw, 16);
  7153. + return 0;
  7154. + }
  7155. + }
  7156. + if(keyRef == 0) {
  7157. + return 2;
  7158. + }
  7159. +
  7160. + return 1;
  7161. +}
  7162. +
  7163. +const char* GetProcessECMErrorReason(int8_t result)
  7164. +{
  7165. + switch(result) {
  7166. + case 0:
  7167. + return "No error";
  7168. + case 1:
  7169. + return "ECM not supported";
  7170. + case 2:
  7171. + return "Key not found";
  7172. + case 3:
  7173. + return "Nano80 problem";
  7174. + case 4:
  7175. + return "Corrupt data";
  7176. + case 5:
  7177. + return "CW not found";
  7178. + case 6:
  7179. + return "CW checksum error";
  7180. + case 7:
  7181. + return "Out of memory";
  7182. + case 8:
  7183. + return "ECM checksum error";
  7184. + default:
  7185. + return "Unknown";
  7186. + }
  7187. +}
  7188. +
  7189. +/* Error codes
  7190. +0 OK
  7191. +1 ECM not supported
  7192. +2 Key not found
  7193. +3 Nano80 problem
  7194. +4 Corrupt data
  7195. +5 CW not found
  7196. +6 CW checksum error
  7197. +7 Out of memory
  7198. +*/
  7199. +#ifdef WITH_EMU
  7200. +int8_t ProcessECM(int16_t ecmDataLen, uint16_t caid, uint32_t provider, const uint8_t *ecm,
  7201. + uint8_t *dw, uint16_t srvid, uint16_t ecmpid, EXTENDED_CW* cw_ex)
  7202. +#else
  7203. +int8_t ProcessECM(int16_t ecmDataLen, uint16_t caid, uint32_t provider, const uint8_t *ecm,
  7204. + uint8_t *dw, uint16_t srvid, uint16_t ecmpid)
  7205. +#endif
  7206. +{
  7207. + int8_t result = 1, i;
  7208. + uint8_t ecmCopy[EMU_MAX_ECM_LEN];
  7209. + uint16_t ecmLen = 0;
  7210. +
  7211. + if(ecmDataLen < 3) {
  7212. + // accept requests without ecm only for biss
  7213. + if((caid>>8) != 0x26 && caid != 0xFFFF) {
  7214. + return 1;
  7215. + }
  7216. + }
  7217. + else {
  7218. + ecmLen = GetEcmLen(ecm);
  7219. + }
  7220. +
  7221. + if(ecmLen > ecmDataLen) {
  7222. + return 1;
  7223. + }
  7224. +
  7225. + if(ecmLen > EMU_MAX_ECM_LEN) {
  7226. + return 1;
  7227. + }
  7228. + memcpy(ecmCopy, ecm, ecmLen);
  7229. +
  7230. + if((caid>>8)==0x0D) {
  7231. + result = CryptoworksECM(caid,ecmCopy,dw);
  7232. + }
  7233. + else if((caid>>8)==0x09) {
  7234. + result = SoftNDSECM(caid,ecmCopy,dw);
  7235. + }
  7236. + else if(caid==0x0500) {
  7237. + result = ViaccessECM(ecmCopy,dw);
  7238. + }
  7239. + else if((caid>>8)==0x18) {
  7240. + result = Nagra2ECM(ecmCopy,dw);
  7241. + }
  7242. + else if((caid>>8)==0x06) {
  7243. + result = Irdeto2ECM(caid,ecmCopy,dw);
  7244. + }
  7245. + else if((caid>>8)==0x26 || caid == 0xFFFF) {
  7246. + result = BissECM(caid,ecm,ecmDataLen,dw,srvid,ecmpid);
  7247. + }
  7248. + else if((caid>>8)==0x0E) {
  7249. +#ifdef WITH_EMU
  7250. + result = PowervuECM(ecmCopy,dw,srvid,NULL,cw_ex);
  7251. +#else
  7252. + result = PowervuECM(ecmCopy,dw,NULL);
  7253. +#endif
  7254. + }
  7255. + else if(caid==0x4AE1) {
  7256. + result = Drecrypt2ECM(caid,provider,ecmCopy,dw);
  7257. + }
  7258. +
  7259. + // fix dcw checksum
  7260. + if(result == 0 && !((caid>>8)==0x0E)) {
  7261. + for(i = 0; i < 16; i += 4) {
  7262. + dw[i + 3] = ((dw[i] + dw[i + 1] + dw[i + 2]) & 0xff);
  7263. + }
  7264. + }
  7265. +
  7266. + if(result != 0) {
  7267. + cs_log("[Emu] ECM failed: %s", GetProcessECMErrorReason(result));
  7268. + }
  7269. +
  7270. + return result;
  7271. +}
  7272. +
  7273. +// Viaccess EMM EMU
  7274. +static int8_t ViaccessEMM(uint8_t *emm, uint32_t *keysAdded)
  7275. +{
  7276. + uint8_t nanoCmd = 0, subNanoCmd = 0, *tmp, *newKeyD0, *newEcmKey;
  7277. + uint16_t i = 0, j = 0, k = 0, emmLen = GetEcmLen(emm);
  7278. + uint8_t ecmKeys[6][16], keyD0[2], emmKey[16], emmXorKey[16], provName[17];
  7279. + uint8_t ecmKeyCount = 0, emmKeyIndex = 0, aesMode = 0x0D;
  7280. + uint8_t nanoLen = 0, subNanoLen = 0, haveEmmXorKey = 0, haveNewD0 = 0;
  7281. + uint32_t ui1, ui2, ui3, ecmKeyIndex[6], provider = 0, ecmProvider = 0;
  7282. + char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36];
  7283. + struct aes_keys aes;
  7284. +
  7285. + memset(keyD0, 0, 2);
  7286. + memset(ecmKeyIndex, 0, sizeof(uint32_t)*6);
  7287. +
  7288. + for(i=3; i+2<emmLen; ) {
  7289. + nanoCmd = emm[i++];
  7290. + nanoLen = emm[i++];
  7291. + if(i+nanoLen > emmLen) {
  7292. + return 1;
  7293. + }
  7294. +
  7295. + switch(nanoCmd) {
  7296. + case 0x90: {
  7297. + if(nanoLen < 3) {
  7298. + break;
  7299. + }
  7300. + ui1 = emm[i+2];
  7301. + ui2 = emm[i+1];
  7302. + ui3 = emm[i];
  7303. + provider = (ui1 | (ui2 << 8) | (ui3 << 16));
  7304. + if(provider == 0x00D00040) {
  7305. + ecmProvider = 0x030B00;
  7306. + }
  7307. + else {
  7308. + return 1;
  7309. + }
  7310. + break;
  7311. + }
  7312. + case 0xD2: {
  7313. + if(nanoLen < 2) {
  7314. + break;
  7315. + }
  7316. + emmKeyIndex = emm[i+1];
  7317. + break;
  7318. + }
  7319. + case 0x41: {
  7320. + if(nanoLen < 1) {
  7321. + break;
  7322. + }
  7323. + if(!GetViaKey(emmKey, provider, 'M', emmKeyIndex, 16, 1)) {
  7324. + return 2;
  7325. + }
  7326. + memset(provName, 0, 17);
  7327. + memset(emmXorKey, 0, 16);
  7328. + k = nanoLen < 16 ? nanoLen : 16;
  7329. + memcpy(provName, &emm[i], k);
  7330. + aes_set_key(&aes, (char*)emmKey);
  7331. + aes_decrypt(&aes, emmXorKey, 16);
  7332. + for(j=0; j<16; j++) {
  7333. + provName[j] ^= emmXorKey[j];
  7334. + }
  7335. + provName[k] = 0;
  7336. +
  7337. + if(strcmp((char*)provName, "TNTSAT") != 0 && strcmp((char*)provName, "TNTSATPRO") != 0
  7338. + &&strcmp((char*)provName, "CSAT V") != 0) {
  7339. + return 1;
  7340. + }
  7341. + break;
  7342. + }
  7343. + case 0xBA: {
  7344. + if(nanoLen < 2) {
  7345. + break;
  7346. + }
  7347. + GetViaKey(keyD0, ecmProvider, 'D', 0, 2, 0);
  7348. + ui1 = (emm[i] << 8) | emm[i+1];
  7349. + if( (uint32_t)((keyD0[0] << 8) | keyD0[1]) < ui1 || (keyD0[0] == 0x00 && keyD0[1] == 0x00)) {
  7350. + keyD0[0] = emm[i];
  7351. + keyD0[1] = emm[i+1];
  7352. + haveNewD0 = 1;
  7353. + break;
  7354. + }
  7355. + return 0;
  7356. + }
  7357. + case 0xBC: {
  7358. + break;
  7359. + }
  7360. + case 0x43: {
  7361. + if(nanoLen < 16) {
  7362. + break;
  7363. + }
  7364. + memcpy(emmXorKey, &emm[i], 16);
  7365. + haveEmmXorKey = 1;
  7366. + break;
  7367. + }
  7368. + case 0x44: {
  7369. + if(nanoLen < 3) {
  7370. + break;
  7371. + }
  7372. + if (!haveEmmXorKey) {
  7373. + memset(emmXorKey, 0, 16);
  7374. + }
  7375. + tmp = (uint8_t*)malloc(((nanoLen/16)+1)*16*sizeof(uint8_t));
  7376. + if(tmp == NULL) {
  7377. + return 7;
  7378. + }
  7379. + memcpy(tmp, &emm[i], nanoLen);
  7380. + aes_set_key(&aes, (char*)emmKey);
  7381. + for(j=0; j<nanoLen; j+=16) {
  7382. + aes_decrypt(&aes, emmXorKey, 16);
  7383. + for(k=0; k<16; k++) {
  7384. + tmp[j+k] ^= emmXorKey[k];
  7385. + }
  7386. + }
  7387. + memcpy(&emm[i-2], tmp, nanoLen);
  7388. + free(tmp);
  7389. + nanoLen = 0;
  7390. + i -= 2;
  7391. + break;
  7392. + }
  7393. + case 0x68: {
  7394. + if(ecmKeyCount > 5) {
  7395. + break;
  7396. + }
  7397. + for(j=i; j+2<i+nanoLen; ) {
  7398. + subNanoCmd = emm[j++];
  7399. + subNanoLen = emm[j++];
  7400. + if(j+subNanoLen > i+nanoLen) {
  7401. + break;
  7402. + }
  7403. + switch(subNanoCmd) {
  7404. + case 0xD2: {
  7405. + if(nanoLen < 2) {
  7406. + break;
  7407. + }
  7408. + aesMode = emm[j];
  7409. + emmKeyIndex = emm[j+1];
  7410. + break;
  7411. + }
  7412. + case 0x01: {
  7413. + if(nanoLen < 17) {
  7414. + break;
  7415. + }
  7416. + ecmKeyIndex[ecmKeyCount] = emm[j];
  7417. + memcpy(&ecmKeys[ecmKeyCount], &emm[j+1], 16);
  7418. + if(!GetViaKey(emmKey, provider, 'M', emmKeyIndex, 16, 1)) {
  7419. + break;
  7420. + }
  7421. +
  7422. + if(aesMode == 0x0F || aesMode == 0x11) {
  7423. + hdSurEncPhase1_D2_0F_11(ecmKeys[ecmKeyCount]);
  7424. + hdSurEncPhase2_D2_0F_11(ecmKeys[ecmKeyCount]);
  7425. + }
  7426. + else if(aesMode == 0x13 || aesMode == 0x15) {
  7427. + hdSurEncPhase1_D2_13_15(ecmKeys[ecmKeyCount]);
  7428. + }
  7429. + aes_set_key(&aes, (char*)emmKey);
  7430. + aes_decrypt(&aes, ecmKeys[ecmKeyCount], 16);
  7431. + if(aesMode == 0x0F || aesMode == 0x11) {
  7432. + hdSurEncPhase1_D2_0F_11(ecmKeys[ecmKeyCount]);
  7433. + }
  7434. + else if(aesMode == 0x13 || aesMode == 0x15) {
  7435. + hdSurEncPhase2_D2_13_15(ecmKeys[ecmKeyCount]);
  7436. + }
  7437. +
  7438. + ecmKeyCount++;
  7439. + break;
  7440. + }
  7441. + default:
  7442. + break;
  7443. + }
  7444. + j += subNanoLen;
  7445. + }
  7446. + break;
  7447. + }
  7448. + case 0xF0: {
  7449. + if(nanoLen != 4) {
  7450. + break;
  7451. + }
  7452. + ui1 = ((emm[i+2] << 8) | (emm[i+1] << 16) | (emm[i] << 24) | emm[i+3]);
  7453. + if(fletcher_crc32(emm + 3, emmLen - 11) != ui1) {
  7454. + return 4;
  7455. + }
  7456. +
  7457. + if(haveNewD0) {
  7458. + newKeyD0 = (uint8_t*)malloc(sizeof(uint8_t)*2);
  7459. + if(newKeyD0 == NULL) {
  7460. + return 7;
  7461. + }
  7462. + memcpy(newKeyD0, keyD0, 2);
  7463. + if(!SetKey('V', ecmProvider, "D0", newKeyD0, 2, 1, NULL)) {
  7464. + free(newKeyD0);
  7465. + }
  7466. + for(j=0; j<ecmKeyCount; j++) {
  7467. + newEcmKey = (uint8_t*)malloc(sizeof(uint8_t)*16);
  7468. + if(newEcmKey == NULL) {
  7469. + return 7;
  7470. + }
  7471. + memcpy(newEcmKey, ecmKeys[j], 16);
  7472. + snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "E%X", ecmKeyIndex[j]);
  7473. + if(!SetKey('V', ecmProvider, keyName, newEcmKey, 16, 1, NULL)) {
  7474. + free(newEcmKey);
  7475. + }
  7476. + (*keysAdded)++;
  7477. + cs_hexdump(0, ecmKeys[j], 16, keyValue, sizeof(keyValue));
  7478. + cs_log("[Emu] Key found in EMM: V %06X %s %s", ecmProvider, keyName, keyValue);
  7479. + }
  7480. + }
  7481. + break;
  7482. + }
  7483. + default:
  7484. + break;
  7485. + }
  7486. + i += nanoLen;
  7487. + }
  7488. + return 0;
  7489. +}
  7490. +
  7491. +// Irdeto2 EMM EMU
  7492. +static int8_t Irdeto2DoEMMTypeOP(uint32_t ident, uint8_t *emm, uint8_t *keySeed, uint8_t *keyIV, uint8_t *keyPMK,
  7493. + uint16_t emmLen, uint8_t startOffset, uint8_t length, uint32_t *keysAdded)
  7494. +{
  7495. + uint32_t end, i, l;
  7496. + uint8_t tmp[16], *newOpKey;
  7497. + char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36];
  7498. +
  7499. + memset(tmp, 0, 16);
  7500. + Irdeto2Encrypt(keySeed, tmp, keyPMK, 16);
  7501. + Irdeto2Decrypt(&emm[startOffset], keyIV, keySeed, length);
  7502. +
  7503. + i = 16;
  7504. + end = startOffset + (length-8 < 0 ? 0 : length-8);
  7505. +
  7506. + while(i<end) {
  7507. + l = emm[i+1] ? (emm[i+1]&0x3F)+2 : 1;
  7508. + switch(emm[i]) {
  7509. + case 0x10:
  7510. + case 0x50:
  7511. + if(l==0x13 && i<=startOffset+length-8-l) {
  7512. + Irdeto2Decrypt(&emm[i+3], keyIV, keyPMK, 16);
  7513. + }
  7514. + break;
  7515. + case 0x78:
  7516. + if(l==0x14 && i<=startOffset+length-8-l) {
  7517. + Irdeto2Decrypt(&emm[i+4], keyIV, keyPMK, 16);
  7518. + }
  7519. + break;
  7520. + }
  7521. + i+=l;
  7522. + }
  7523. +
  7524. + memmove(emm+6, emm+7, emmLen-7);
  7525. +
  7526. + i = 15;
  7527. + end = startOffset + (length-9 < 0 ? 0 : length-9);
  7528. +
  7529. + if(Irdeto2CalculateHash(keySeed, keyIV, emm+3, emmLen-4)) {
  7530. + while(i<end) {
  7531. + l = emm[i+1] ? (emm[i+1]&0x3F)+2 : 1;
  7532. + switch(emm[i]) {
  7533. + case 0x10:
  7534. + case 0x50:
  7535. + if(l==0x13 && i<=startOffset+length-9-l) {
  7536. + newOpKey = (uint8_t*)malloc(sizeof(uint8_t)*16);
  7537. + if(newOpKey == NULL) {
  7538. + return 7;
  7539. + }
  7540. + memcpy(newOpKey, &emm[i+3], 16);
  7541. + snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X", emm[i+2]>>2);
  7542. + if(!SetKey('I', ident, keyName, newOpKey, 16, 1, NULL)) {
  7543. + free(newOpKey);
  7544. + }
  7545. + (*keysAdded)++;
  7546. + cs_hexdump(0, &emm[i+3], 16, keyValue, sizeof(keyValue));
  7547. + cs_log("[Emu] Key found in EMM: I %06X %s %s", ident, keyName, keyValue);
  7548. + }
  7549. + }
  7550. + i+=l;
  7551. + }
  7552. +
  7553. + if(*keysAdded > 0) {
  7554. + return 0;
  7555. + }
  7556. + }
  7557. +
  7558. + return 1;
  7559. +}
  7560. +
  7561. +static int8_t Irdeto2DoEMMTypePMK(uint32_t ident, uint8_t *emm, uint8_t *keySeed, uint8_t *keyIV, uint8_t *keyPMK,
  7562. + uint16_t emmLen, uint8_t startOffset, uint8_t length, uint32_t *keysAdded)
  7563. +{
  7564. + uint32_t end, i, l, j;
  7565. + uint8_t *newPmkKey;
  7566. + char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36];
  7567. +
  7568. + Irdeto2Decrypt(&emm[startOffset], keyIV, keySeed, length);
  7569. +
  7570. + i = 13;
  7571. + end = startOffset + (length-8 < 0 ? 0 : length-8);
  7572. +
  7573. + while(i<end) {
  7574. + l = emm[i+1] ? (emm[i+1]&0x3F)+2 : 1;
  7575. + switch(emm[i]) {
  7576. + case 0x10:
  7577. + case 0x50:
  7578. + if(l==0x13 && i<=startOffset+length-8-l) {
  7579. + Irdeto2Decrypt(&emm[i+3], keyIV, keyPMK, 16);
  7580. + }
  7581. + break;
  7582. + case 0x78:
  7583. + if(l==0x14 && i<=startOffset+length-8-l) {
  7584. + Irdeto2Decrypt(&emm[i+4], keyIV, keyPMK, 16);
  7585. + }
  7586. + break;
  7587. + case 0x68:
  7588. + if(l==0x26 && i<=startOffset+length-8-l) {
  7589. + Irdeto2Decrypt(&emm[i+3], keyIV, keyPMK, 16*2);
  7590. + }
  7591. + break;
  7592. + }
  7593. + i+=l;
  7594. + }
  7595. +
  7596. + memmove(emm+7, emm+9, emmLen-9);
  7597. +
  7598. + i = 11;
  7599. + end = startOffset + (length-10 < 0 ? 0 : length-10);
  7600. +
  7601. + if(Irdeto2CalculateHash(keySeed, keyIV, emm+3, emmLen-5)) {
  7602. + while(i<end) {
  7603. + l = emm[i+1] ? (emm[i+1]&0x3F)+2 : 1;
  7604. + switch(emm[i]) {
  7605. + case 0x68:
  7606. + if(l==0x26 && i<=startOffset+length-10-l) {
  7607. + for(j=0; j<2; j++) {
  7608. + newPmkKey = (uint8_t*)malloc(sizeof(uint8_t)*16);
  7609. + if(newPmkKey == NULL) {
  7610. + return 7;
  7611. + }
  7612. + memcpy(newPmkKey, &emm[i+3+j*16], 16);
  7613. + snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "M%01X", 3+j);
  7614. + if(!SetKey('I', ident, keyName, newPmkKey, 16, 1, NULL)) {
  7615. + free(newPmkKey);
  7616. + }
  7617. + (*keysAdded)++;
  7618. + cs_hexdump(0, &emm[i+3+j*16], 16, keyValue, sizeof(keyValue));
  7619. + cs_log("[Emu] Key found in EMM: I %06X %s %s", ident, keyName, keyValue);
  7620. + }
  7621. + }
  7622. + }
  7623. + i+=l;
  7624. + }
  7625. +
  7626. + if(*keysAdded > 0) {
  7627. + return 0;
  7628. + }
  7629. + }
  7630. +
  7631. + return 1;
  7632. +}
  7633. +
  7634. +static const uint8_t fausto_xor[16] = { 0x22, 0x58, 0xBD, 0x85, 0x2E, 0x8E, 0x52, 0x80, 0xA3, 0x79, 0x98, 0x69, 0x68, 0xE2, 0xD8, 0x4D };
  7635. +
  7636. +static int8_t Irdeto2EMM(uint16_t caid, uint8_t *oemm, uint32_t *keysAdded)
  7637. +{
  7638. + uint8_t length, okeySeed[16], keySeed[16], keyIV[16], keyPMK[16], startOffset, emmType;
  7639. + uint32_t ident;
  7640. + uint16_t keySeedRef, keyIVRef, keyPMK0Ref, keyPMK1Ref, keyPMK0ERef, keyPMK1ERef;
  7641. + uint8_t emmCopy[EMU_MAX_EMM_LEN], *emm = oemm;
  7642. + uint16_t emmLen = GetEcmLen(emm);
  7643. +
  7644. + if(emmLen < 11) {
  7645. + return 1;
  7646. + }
  7647. +
  7648. + if(emm[3] == 0xC3 || emm[3] == 0xCB) {
  7649. + emmType = 2;
  7650. + startOffset = 11;
  7651. + }
  7652. + else {
  7653. + emmType = 1;
  7654. + startOffset = 10;
  7655. + }
  7656. +
  7657. + ident = emm[startOffset-2] | caid << 8;
  7658. + length = emm[startOffset-1];
  7659. +
  7660. +
  7661. + if(emmLen < length+startOffset) {
  7662. + return 1;
  7663. + }
  7664. +
  7665. + keySeedRef = 0;
  7666. + while(GetIrdetoKey(okeySeed, ident, 'M', emmType == 1 ? 0 : 0xA, 1, &keySeedRef)) {
  7667. + keyIVRef = 0;
  7668. + while(GetIrdetoKey(keyIV, ident, 'M', 2, 1, &keyIVRef)) {
  7669. +
  7670. + keyPMK0Ref = 0;
  7671. + keyPMK1Ref = 0;
  7672. + keyPMK0ERef = 0;
  7673. + keyPMK1ERef = 0;
  7674. +
  7675. + while(GetIrdetoKey(keyPMK, ident, 'M', emmType == 1 ? 3 : 0xB, 1, &keyPMK0Ref)) {
  7676. + memcpy(keySeed, okeySeed, 16);
  7677. + memcpy(emmCopy, oemm, emmLen);
  7678. + emm = emmCopy;
  7679. + if(emmType == 1) {
  7680. + if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
  7681. + return 0;
  7682. + }
  7683. + }
  7684. + else {
  7685. + if(Irdeto2DoEMMTypePMK(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
  7686. + return 0;
  7687. + }
  7688. + }
  7689. + }
  7690. +
  7691. + if(emmType == 1) {
  7692. + while(GetIrdetoKey(keyPMK, ident, 'M', 4, 1, &keyPMK1Ref)) {
  7693. + memcpy(keySeed, okeySeed, 16);
  7694. + memcpy(emmCopy, oemm, emmLen);
  7695. + emm = emmCopy;
  7696. + if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
  7697. + return 0;
  7698. + }
  7699. + }
  7700. +
  7701. + while(GetIrdetoKey(keyPMK, ident, 'M', 5, 1, &keyPMK0ERef)) {
  7702. + xxor(keyPMK, 16, keyPMK, fausto_xor);
  7703. + memcpy(keySeed, okeySeed, 16);
  7704. + memcpy(emmCopy, oemm, emmLen);
  7705. + emm = emmCopy;
  7706. + if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
  7707. + return 0;
  7708. + }
  7709. + }
  7710. +
  7711. + while(GetIrdetoKey(keyPMK, ident, 'M', 6, 1, &keyPMK1ERef)) {
  7712. + xxor(keyPMK, 16, keyPMK, fausto_xor);
  7713. + memcpy(keySeed, okeySeed, 16);
  7714. + memcpy(emmCopy, oemm, emmLen);
  7715. + emm = emmCopy;
  7716. + if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) {
  7717. + return 0;
  7718. + }
  7719. + }
  7720. + }
  7721. +
  7722. + if(keyPMK0Ref == 0 && keyPMK1Ref == 0 && keyPMK0ERef == 0 && keyPMK1ERef == 0) {
  7723. + return 2;
  7724. + }
  7725. + }
  7726. + if(keyIVRef == 0) {
  7727. + return 2;
  7728. + }
  7729. + }
  7730. + if(keySeedRef == 0) {
  7731. + return 2;
  7732. + }
  7733. +
  7734. + return 1;
  7735. +}
  7736. +
  7737. +int32_t GetIrdeto2Hexserial(uint16_t caid, uint8_t *hexserial)
  7738. +{
  7739. + uint32_t i, len;
  7740. + KeyDataContainer *KeyDB;
  7741. + KeyData *tmpKeyData;
  7742. +
  7743. + KeyDB = GetKeyContainer('I');
  7744. + if(KeyDB == NULL) {
  7745. + return 0;
  7746. + }
  7747. +
  7748. + for(i=0; i<KeyDB->keyCount; i++) {
  7749. +
  7750. + if(KeyDB->EmuKeys[i].provider>>8 != caid) {
  7751. + continue;
  7752. + }
  7753. + if(strcmp(KeyDB->EmuKeys[i].keyName, "MC")) {
  7754. + continue;
  7755. + }
  7756. +
  7757. + tmpKeyData = &KeyDB->EmuKeys[i];
  7758. +
  7759. + len = tmpKeyData->keyLength;
  7760. + if(len > 3)
  7761. + { len = 3; }
  7762. +
  7763. + memcpy(hexserial+(3-len), tmpKeyData->key, len);
  7764. + return 1;
  7765. + }
  7766. +
  7767. + return 0;
  7768. +}
  7769. +
  7770. +
  7771. +// PowerVu EMM EMU
  7772. +static int8_t PowervuEMM(uint8_t *emm, uint32_t *keysAdded)
  7773. +{
  7774. + uint8_t emmInfo, emmType, *newEcmKey;
  7775. + uint16_t emmLen = GetEcmLen(emm);
  7776. + uint32_t i, uniqueAddress, channelId;
  7777. + //uint32_t emmCrc32;
  7778. + uint8_t emmKey[7], tmpEmmKey[7], tmp[26];
  7779. + char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[16];
  7780. + char uaInfo[4+8+1];
  7781. +
  7782. + if(emmLen < 50)
  7783. + {
  7784. + return 1;
  7785. + }
  7786. +
  7787. + // looks like checksum does not work for all EMMs
  7788. + //emmCrc32 = b2i(4, emm+emmLen-4);
  7789. + //
  7790. + //if(fletcher_crc32(emm, emmLen-4) != emmCrc32)
  7791. + //{
  7792. + // return 8;
  7793. + //}
  7794. + emmLen -= 4;
  7795. +
  7796. + uniqueAddress = b2i(4, emm+12);
  7797. +
  7798. + snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.8X", uniqueAddress);
  7799. + if(!GetPowervuEmmKey(emmKey, 0, keyName, 7, 0, &channelId))
  7800. + {
  7801. + cs_log_dbg(D_EMM,"[Emu] EMM error: AU key for UA %s is missing", keyName);
  7802. + return 2;
  7803. + }
  7804. +
  7805. + for(i=19; i+27<=emmLen; i+=27) {
  7806. + emmInfo = emm[i];
  7807. +
  7808. + if(!GetBit(emmInfo, 7))
  7809. + {
  7810. + continue;
  7811. + }
  7812. +
  7813. + //keyNb = emm[i] & 0x0F;
  7814. +
  7815. + memcpy(tmp, emm+i+1, 26);
  7816. + memcpy(tmpEmmKey, emmKey, 7);
  7817. + PowervuDecrypt(emm+i+1, 26, tmpEmmKey, 0);
  7818. +
  7819. + if((emm[13] != emm[i+24]) || (emm[14] != emm[i+25]) || (emm[15] != emm[i+26]))
  7820. + {
  7821. + memcpy(emm+i+1, tmp, 26);
  7822. + memcpy(tmpEmmKey, emmKey, 7);
  7823. + PowervuDecrypt(emm+i+1, 26, tmpEmmKey, 1);
  7824. +
  7825. + if((emm[13] != emm[i+24]) || (emm[14] != emm[i+25]) || (emm[15] != emm[i+26]))
  7826. + {
  7827. + continue;
  7828. + }
  7829. + }
  7830. +
  7831. + emmType = emm[i+2] & 0x7F;
  7832. + if(emmType > 1)
  7833. + {
  7834. + continue;
  7835. + }
  7836. +
  7837. + if(emm[i+3] == 0 && emm[i+4] == 0)
  7838. + {
  7839. + cs_hexdump(0, &emm[i+3], 7, keyValue, sizeof(keyValue));
  7840. + cs_log("[Emu] Key found in EMM: P %.4X %s %s -> REJECTED (looks invalid) UA: %X", channelId, keyName, keyValue, uniqueAddress);
  7841. + continue;
  7842. + }
  7843. +
  7844. + newEcmKey = (uint8_t*)malloc(sizeof(uint8_t)*7);
  7845. + if(newEcmKey == NULL) {
  7846. + return 7;
  7847. + }
  7848. + memcpy(newEcmKey, &emm[i+3], 7);
  7849. + snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.2X", emmType);
  7850. + snprintf(uaInfo, sizeof(uaInfo), "UA: %08X", uniqueAddress);
  7851. + if(!SetKey('P', channelId<<16, keyName, newEcmKey, 7, 1, uaInfo)) {
  7852. + free(newEcmKey);
  7853. + }
  7854. + (*keysAdded)++;
  7855. + cs_hexdump(0, &emm[i+3], 7, keyValue, sizeof(keyValue));
  7856. + cs_log("[Emu] Key found in EMM: P %.4X %s %s ; UA: %X", channelId, keyName, keyValue, uniqueAddress);
  7857. + }
  7858. +
  7859. + return 0;
  7860. +}
  7861. +
  7862. +int32_t GetPowervuHexserials(uint16_t srvid, uint8_t hexserials[][4], int32_t length, int32_t* count)
  7863. +{
  7864. + uint32_t i,j;
  7865. + uint32_t groupid;
  7866. + int32_t len;
  7867. + KeyDataContainer *KeyDB;
  7868. +
  7869. + KeyDB = GetKeyContainer('P');
  7870. + if(KeyDB == NULL)
  7871. + { return 0; }
  7872. +
  7873. + (*count) = 0;
  7874. +
  7875. + for(i=0; i<KeyDB->keyCount && (*count)<length ; i++) {
  7876. +
  7877. + if(srvid != 0xFFFF && (KeyDB->EmuKeys[i].provider & 0x0000FFFF) != srvid)
  7878. + { continue; }
  7879. +
  7880. + groupid = KeyDB->EmuKeys[i].provider>>16;
  7881. +
  7882. + for(j=0; j<KeyDB->keyCount && (*count)<length ; j++) {
  7883. +
  7884. + if(srvid != 0xFFFF && KeyDB->EmuKeys[j].provider != groupid)
  7885. + { continue; }
  7886. +
  7887. + len = strlen(KeyDB->EmuKeys[j].keyName);
  7888. +
  7889. + if(len < 3)
  7890. + { continue;}
  7891. +
  7892. + if(len > 8)
  7893. + { len = 8; }
  7894. +
  7895. + memset(hexserials[*count], 0, 4);
  7896. + CharToBin(hexserials[(*count)]+(4-(len/2)), KeyDB->EmuKeys[j].keyName, len);
  7897. +
  7898. + (*count)++;
  7899. + }
  7900. + if(srvid == 0xFFFF) {
  7901. + return ((*count)>0);
  7902. + }
  7903. + }
  7904. +
  7905. + return 1;
  7906. +}
  7907. +
  7908. +
  7909. +// Drecrypt EMM EMU
  7910. +static int8_t GetDrecryptEMMKey(uint8_t *buf, uint32_t keyIdent, uint16_t keyName, uint8_t isCriticalKey)
  7911. +{
  7912. + char keyStr[EMU_MAX_CHAR_KEYNAME];
  7913. + snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "MK%X", keyName);
  7914. + return FindKey('D', keyIdent, keyStr, buf, 32, isCriticalKey, 0, 0, NULL);
  7915. +}
  7916. +
  7917. +static int8_t Drecrypt2EMM(uint16_t caid, uint32_t provId, uint8_t *emm, uint32_t *keysAdded)
  7918. +{
  7919. + uint16_t emmLen = GetEcmLen(emm);
  7920. + uint32_t keyIdent;
  7921. + uint16_t keyName;
  7922. + uint8_t emmKey[32];
  7923. + int32_t i;
  7924. + uint8_t *newEcmKey;
  7925. + uint8_t keynum, keyidx, keyclass, key1offset, key2offset;
  7926. + char newKeyName[EMU_MAX_CHAR_KEYNAME], keyValue[100];
  7927. +
  7928. + if(emmLen < 5 || caid != 0x4AE1) {
  7929. + return 1;
  7930. + }
  7931. +
  7932. + if(emm[0] == 0x91) {
  7933. + Drecrypt2OverEMM(emm);
  7934. + return 0;
  7935. + }
  7936. +
  7937. + switch(provId & 0xFF)
  7938. + {
  7939. + case 0x11:
  7940. + if (emmLen < (0x8B + 32)) return 0;
  7941. + if (emm[0] != 0x86 && emm[4] != 0x4D) return 0;
  7942. + keynum = 0x61; keyidx = 0x60; keyclass = 0x05; key1offset = 0x62; key2offset = 0x8B;
  7943. + break;
  7944. + case 0x14:
  7945. + if (emmLen < (0x6D + 32)) return 0;
  7946. + if (emm[0] != 0x86 && emm[4] != 0x02) return 0;
  7947. + keynum = 0x2C; keyidx = 0x30; keyclass = 0x26; key1offset = 0x35; key2offset = 0x6D;
  7948. + break;
  7949. + default:
  7950. + return 0;
  7951. + }
  7952. +
  7953. + keyIdent = caid<<8 | provId;
  7954. + keyName = emm[0x3]<<8 | emm[keynum];
  7955. +
  7956. + if(!GetDrecryptEMMKey(emmKey, keyIdent, keyName, 1)) {
  7957. + return 2;
  7958. + }
  7959. +
  7960. + //key #1
  7961. + for(i=0; i<4; i++) {
  7962. + DrecryptDecrypt(&emm[key1offset+(i*8)], emmKey);
  7963. + }
  7964. +
  7965. + //key #2
  7966. + for(i=0; i<4; i++) {
  7967. + DrecryptDecrypt(&emm[key2offset+(i*8)], emmKey);
  7968. + }
  7969. +
  7970. + //key #1
  7971. + keyName = emm[keyidx]<<8 | emm[keyclass];
  7972. + newEcmKey = (uint8_t*)malloc(sizeof(uint8_t)*32);
  7973. + if(newEcmKey == NULL) {
  7974. + return 7;
  7975. + }
  7976. + memcpy(newEcmKey, &emm[key1offset], 32);
  7977. + snprintf(newKeyName, EMU_MAX_CHAR_KEYNAME, "%.4X", keyName);
  7978. + if(!UpdateKey('D', keyIdent, newKeyName, newEcmKey, 32, NULL)) {
  7979. + free(newEcmKey);
  7980. + }
  7981. + (*keysAdded)++;
  7982. + cs_hexdump(0, &emm[key1offset], 32, keyValue, sizeof(keyValue));
  7983. + cs_log("[Emu] Key found in EMM: D %.6X %s %s", keyIdent, newKeyName, keyValue);
  7984. +
  7985. + //key #2
  7986. + keyName = (emm[keyidx] == 0x56 ? 0x3B00 : 0x5600) | emm[keyclass];
  7987. + newEcmKey = (uint8_t*)malloc(sizeof(uint8_t)*32);
  7988. + if(newEcmKey == NULL) {
  7989. + return 7;
  7990. + }
  7991. + memcpy(newEcmKey, &emm[key2offset], 32);
  7992. + snprintf(newKeyName, EMU_MAX_CHAR_KEYNAME, "%.4X", keyName);
  7993. + if(!UpdateKey('D', keyIdent, newKeyName, newEcmKey, 32, NULL)) {
  7994. + free(newEcmKey);
  7995. + }
  7996. + (*keysAdded)++;
  7997. + cs_hexdump(0, &emm[key2offset], 32, keyValue, sizeof(keyValue));
  7998. + cs_log("[Emu] Key found in EMM: D %.6X %s %s", keyIdent, newKeyName, keyValue);
  7999. +
  8000. + return 0;
  8001. +}
  8002. +
  8003. +int32_t GetDrecryptHexserials(uint16_t caid, uint8_t *hexserials, int32_t length, int32_t* count)
  8004. +{
  8005. + uint32_t i;
  8006. + int32_t len;
  8007. + KeyDataContainer *KeyDB;
  8008. +
  8009. + KeyDB = GetKeyContainer('D');
  8010. + if(KeyDB == NULL)
  8011. + { return 0; }
  8012. +
  8013. + (*count) = 0;
  8014. +
  8015. + for(i=0; i<KeyDB->keyCount && (*count)<length ; i++) {
  8016. +
  8017. + if(KeyDB->EmuKeys[i].provider>>8 != caid)
  8018. + { continue; }
  8019. +
  8020. + len = strlen(KeyDB->EmuKeys[i].keyName);
  8021. +
  8022. + if(len < 6)
  8023. + { continue; }
  8024. +
  8025. + if(memcmp(KeyDB->EmuKeys[i].keyName, "MK", 2))
  8026. + { continue; }
  8027. +
  8028. + CharToBin(&hexserials[(*count)], KeyDB->EmuKeys[i].keyName+2, 2);
  8029. +
  8030. + (*count)++;
  8031. + }
  8032. +
  8033. + return 1;
  8034. +}
  8035. +
  8036. +const char* GetProcessEMMErrorReason(int8_t result)
  8037. +{
  8038. + switch(result) {
  8039. + case 0:
  8040. + return "No error";
  8041. + case 1:
  8042. + return "EMM not supported";
  8043. + case 2:
  8044. + return "Key not found";
  8045. + case 3:
  8046. + return "Nano80 problem";
  8047. + case 4:
  8048. + return "Corrupt data";
  8049. + case 5:
  8050. + return "Unknown";
  8051. + case 6:
  8052. + return "Checksum error";
  8053. + case 7:
  8054. + return "Out of memory";
  8055. + case 8:
  8056. + return "EMM checksum error";
  8057. + default:
  8058. + return "Unknown";
  8059. + }
  8060. +}
  8061. +
  8062. +/* Error codes
  8063. +0 OK
  8064. +1 EMM not supported
  8065. +2 Key not found
  8066. +3 Nano80 problem
  8067. +4 Corrupt data
  8068. +5
  8069. +6 Checksum error
  8070. +7 Out of memory
  8071. +*/
  8072. +int8_t ProcessEMM(uint16_t caid, uint32_t provider, const uint8_t *emm, uint32_t *keysAdded)
  8073. +{
  8074. + int8_t result = 1;
  8075. + uint8_t emmCopy[EMU_MAX_EMM_LEN];
  8076. + uint16_t emmLen = GetEcmLen(emm);
  8077. +
  8078. + if(emmLen > EMU_MAX_EMM_LEN) {
  8079. + return 1;
  8080. + }
  8081. + memcpy(emmCopy, emm, emmLen);
  8082. + *keysAdded = 0;
  8083. +
  8084. + if(caid==0x0500) {
  8085. + result = ViaccessEMM(emmCopy, keysAdded);
  8086. + }
  8087. + else if((caid>>8)==0x06) {
  8088. + result = Irdeto2EMM(caid, emmCopy, keysAdded);
  8089. + }
  8090. + else if((caid>>8)==0x0E) {
  8091. + result = PowervuEMM(emmCopy, keysAdded);
  8092. + if(result == 2) { // missing key already logged
  8093. + return 2;
  8094. + }
  8095. + }
  8096. + else if(caid==0x4AE1) {
  8097. + result = Drecrypt2EMM(caid, provider, emmCopy, keysAdded);
  8098. + }
  8099. +
  8100. + if(result != 0) {
  8101. + cs_log_dbg(D_EMM,"[Emu] EMM failed: %s", GetProcessEMMErrorReason(result));
  8102. + }
  8103. +
  8104. + return result;
  8105. +}
  8106. Index: module-emulator-osemu.h
  8107. ===================================================================
  8108. --- module-emulator-osemu.h (revision 0)
  8109. +++ module-emulator-osemu.h (working copy)
  8110. @@ -0,0 +1,114 @@
  8111. +#include "globals.h"
  8112. +#include "module-emulator-stream.h"
  8113. +
  8114. +#ifndef EMULATOR_H_
  8115. +#define EMULATOR_H_
  8116. +
  8117. +#define EMU_MAX_CHAR_KEYNAME 12
  8118. +#define EMU_KEY_FILENAME "SoftCam.Key"
  8119. +#define EMU_KEY_FILENAME_MAX_LEN 31
  8120. +#define EMU_MAX_ECM_LEN MAX_ECM_SIZE
  8121. +#define EMU_MAX_EMM_LEN MAX_EMM_SIZE
  8122. +
  8123. + typedef struct KeyData KeyData;
  8124. +
  8125. + struct KeyData {
  8126. + char identifier;
  8127. + uint32_t provider;
  8128. + char keyName[EMU_MAX_CHAR_KEYNAME];
  8129. + uint8_t *key;
  8130. + uint32_t keyLength;
  8131. + KeyData *nextKey;
  8132. + };
  8133. +
  8134. + typedef struct {
  8135. + KeyData *EmuKeys;
  8136. + uint32_t keyCount;
  8137. + uint32_t keyMax;
  8138. + } KeyDataContainer;
  8139. +
  8140. + extern KeyDataContainer CwKeys;
  8141. + extern KeyDataContainer ViKeys;
  8142. + extern KeyDataContainer NagraKeys;
  8143. + extern KeyDataContainer IrdetoKeys;
  8144. + extern KeyDataContainer NDSKeys;
  8145. + extern KeyDataContainer BissKeys;
  8146. + extern KeyDataContainer PowervuKeys;
  8147. + extern KeyDataContainer DreKeys;
  8148. + extern uint8_t viasat_const[];
  8149. +
  8150. + uint32_t GetOSemuVersion(void);
  8151. +
  8152. + void set_emu_keyfile_path(const char *path);
  8153. + uint8_t read_emu_keyfile(const char *path);
  8154. +
  8155. +#if !defined(__APPLE__) && !defined(__ANDROID__)
  8156. + void read_emu_keymemory(void);
  8157. +#endif
  8158. +
  8159. + int32_t CharToBin(uint8_t *out, const char *in, uint32_t inLen);
  8160. +
  8161. + /* Error codes
  8162. + 0 OK
  8163. + 1 ECM not supported
  8164. + 2 Key not found
  8165. + 3 Nano80 problem
  8166. + 4 Corrupt data
  8167. + 5 CW not found
  8168. + 6 CW checksum error
  8169. + 7 Out of memory
  8170. + */
  8171. +#ifdef WITH_EMU
  8172. + int8_t ProcessECM(int16_t ecmDataLen, uint16_t caid, uint32_t provider, const uint8_t *ecm,
  8173. + uint8_t *dw, uint16_t srvid, uint16_t ecmpid, EXTENDED_CW* cw_ex);
  8174. +#else
  8175. + int8_t ProcessECM(int16_t ecmDataLen, uint16_t caid, uint32_t provider, const uint8_t *ecm,
  8176. + uint8_t *dw, uint16_t srvid, uint16_t ecmpid);
  8177. +#endif
  8178. +
  8179. + const char* GetProcessECMErrorReason(int8_t result);
  8180. +
  8181. + /* Error codes
  8182. + 0 OK
  8183. + 1 EMM not supported
  8184. + 2 Key not found
  8185. + 3 Nano80 problem
  8186. + 4 Corrupt data
  8187. + 5
  8188. + 6 Checksum error
  8189. + 7 Out of memory
  8190. + */
  8191. + int8_t ProcessEMM(uint16_t caid, uint32_t provider, const uint8_t *emm, uint32_t *keysAdded);
  8192. +
  8193. + const char* GetProcessEMMErrorReason(int8_t result);
  8194. +
  8195. + //hexserial must be of type "uint8_t hexserial[3]"
  8196. + //returns 0 on error, 1 on success
  8197. + int32_t GetIrdeto2Hexserial(uint16_t caid, uint8_t* hexserial);
  8198. +
  8199. + //hexserials must be of type "uint8_t hexserials[length][4]"
  8200. + //if srvid == 0xFFFF all serials are returned (no srvid filtering)
  8201. + //returns 0 on error, 1 on success
  8202. + int32_t GetPowervuHexserials(uint16_t srvid, uint8_t hexserials[][4], int32_t length, int32_t* count);
  8203. +
  8204. + //hexserials must be of type "uint8_t hexserials[length]"
  8205. + //returns 0 on error, 1 on success
  8206. + int32_t GetDrecryptHexserials(uint16_t caid, uint8_t* hexserials, int32_t length, int32_t* count);
  8207. +
  8208. +
  8209. +#define PVU_CW_VID 0 // VIDeo
  8210. +#define PVU_CW_HSD 1 // High Speed Data
  8211. +#define PVU_CW_A1 2 // Audio 1
  8212. +#define PVU_CW_A2 3 // Audio 2
  8213. +#define PVU_CW_A3 4 // Audio 3
  8214. +#define PVU_CW_A4 5 // Audio 4
  8215. +#define PVU_CW_UTL 6 // UTiLity
  8216. +#define PVU_CW_VBI 7 // Vertical Blanking Interval
  8217. +
  8218. +#ifdef WITH_EMU
  8219. + int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, uint16_t srvid, emu_stream_client_key_data *cdata, EXTENDED_CW* cw_ex);
  8220. +#else
  8221. + int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, emu_stream_client_key_data *cdata);
  8222. +#endif
  8223. +
  8224. +#endif
  8225. Index: module-emulator-st20.c
  8226. ===================================================================
  8227. --- module-emulator-st20.c (revision 0)
  8228. +++ module-emulator-st20.c (working copy)
  8229. @@ -0,0 +1,393 @@
  8230. +#include "globals.h"
  8231. +#include "module-emulator-st20.h"
  8232. +
  8233. +#define IPTR 0
  8234. +#define WPTR 1
  8235. +#define AREG 2
  8236. +#define BREG 3
  8237. +#define CREG 4
  8238. +
  8239. +#define FLASHS 0x7FE00000
  8240. +#define FLASHE 0x7FFFFFFF
  8241. +#define RAMS 0x40000000
  8242. +#define RAME 0x401FFFFF
  8243. +#define IRAMS 0x80000000
  8244. +#define IRAME 0x800017FF
  8245. +
  8246. +#define ERR_ILL_OP -1
  8247. +#define ERR_CNT -2
  8248. +
  8249. +// ----------------------------------------------------------------
  8250. +
  8251. +#define STACKMAX 16
  8252. +#define STACKMASK (STACKMAX-1)
  8253. +
  8254. +typedef struct
  8255. +{
  8256. + uint32_t Iptr, Wptr;
  8257. + uint8_t *flash, *ram;
  8258. + uint32_t flashSize, ramSize;
  8259. + int32_t sptr, stack[STACKMAX];
  8260. + uint8_t iram[0x1800];
  8261. + int32_t invalid;
  8262. + int32_t verbose;
  8263. +} st20_context_t;
  8264. +
  8265. +
  8266. +void st20_set_flash(st20_context_t *ctx, uint8_t *m, int32_t len);
  8267. +void st20_set_ram(st20_context_t *ctx, uint8_t *m, int32_t len);
  8268. +void st20_init(st20_context_t *ctx, uint32_t IPtr, uint32_t WPtr, int32_t verbose);
  8269. +void st20_free(st20_context_t *ctx);
  8270. +
  8271. +void st20_set_call_frame(st20_context_t *ctx, uint32_t raddr, int32_t p1, int32_t p2, int32_t p3);
  8272. +
  8273. +
  8274. +uint32_t st20_get_reg(st20_context_t *ctx, int32_t reg);
  8275. +void st20_set_reg(st20_context_t *ctx, int32_t reg, uint32_t val);
  8276. +uint8_t st20_rbyte(st20_context_t *ctx, uint32_t off);
  8277. +void st20_wbyte(st20_context_t *ctx, uint32_t off, uint8_t val);
  8278. +
  8279. +#define get_misalign(_a) *(_a)
  8280. +#define put_misalign(_b,_a) *(_a)=(_b)
  8281. +
  8282. +#define UINT32_LE(a) get_misalign((uint32_t *)(a))
  8283. +#define UINT16_LE(a) get_misalign((uint16_t *)(a))
  8284. +#define UINT8_LE(a) *((uint8_t *)a)
  8285. +#define BYTE4_LE(a,b) put_misalign(b,(uint32_t *)(a))
  8286. +#define BYTE2_LE(a,b) put_misalign(b,(uint16_t *)(a))
  8287. +#define BYTE1_LE(a,b) *(uint8_t *)(a)=(b)
  8288. +
  8289. +#define INVALID_VALUE 0xCCCCCCCC
  8290. +#define ERRORVAL 0xDEADBEEF
  8291. +
  8292. +#define MININT 0x7FFFFFFF
  8293. +#define MOSTPOS 0x7FFFFFFF
  8294. +#define MOSTNEG 0x80000000
  8295. +
  8296. +#define POP() ctx->stack[(ctx->sptr++)&STACKMASK]
  8297. +
  8298. +#define PUSH(v) do { int32_t __v=(v); ctx->stack[(--ctx->sptr)&STACKMASK]=__v; } while(0)
  8299. +#define DROP(n) ctx->sptr+=n
  8300. +
  8301. +#define AAA ctx->stack[ctx->sptr&STACKMASK]
  8302. +#define BBB ctx->stack[(ctx->sptr+1)&STACKMASK]
  8303. +#define CCC ctx->stack[(ctx->sptr+2)&STACKMASK]
  8304. +
  8305. +#define GET_OP() operand|=op1&0x0F
  8306. +#define CLEAR_OP() operand=0
  8307. +#define JUMP(x) ctx->Iptr+=(x)
  8308. +#define POP64() ({ uint32_t __b=POP(); ((uint64_t)POP()<<32)|__b; })
  8309. +#define PUSHPOP(op,val) do { int32_t __a=val; AAA op##= (__a); } while(0)
  8310. +
  8311. +#define RB(off) UINT8_LE(st20_addr(ctx, off))
  8312. +#define RW(off) UINT32_LE(st20_addr(ctx, off))
  8313. +#define WW(off,val) BYTE4_LE(st20_addr(ctx, off),val)
  8314. +
  8315. +uint32_t st20_get_reg(st20_context_t *ctx, int32_t reg)
  8316. +{
  8317. + switch(reg)
  8318. + {
  8319. + case IPTR:
  8320. + return ctx->Iptr;
  8321. + case WPTR:
  8322. + return ctx->Wptr;
  8323. + case AREG:
  8324. + return AAA;
  8325. + case BREG:
  8326. + return BBB;
  8327. + case CREG:
  8328. + return CCC;
  8329. + }
  8330. + return 0;
  8331. +}
  8332. +
  8333. +void st20_set_reg(st20_context_t *ctx, int32_t reg, uint32_t val)
  8334. +{
  8335. + switch(reg)
  8336. + {
  8337. + case IPTR: ctx->Iptr = val; return;
  8338. + case WPTR: ctx->Wptr = val; return;
  8339. + case AREG: AAA=val; return;
  8340. + case BREG: BBB=val; return;
  8341. + case CREG: CCC=val; return;
  8342. + }
  8343. +}
  8344. +
  8345. +uint8_t *st20_addr(st20_context_t *ctx, uint32_t off)
  8346. +{
  8347. + if(off >= FLASHS && off <= FLASHE) return &ctx->flash[off - FLASHS];
  8348. +
  8349. + else if(off >= RAMS && off <= RAME) return &ctx->ram[off - RAMS];
  8350. +
  8351. + else if(off >= IRAMS && off <= IRAME) return &ctx->iram[off - IRAMS];
  8352. +
  8353. + ctx->invalid = ERRORVAL;
  8354. + return (uint8_t *)&ctx->invalid;
  8355. +
  8356. +}
  8357. +
  8358. +uint32_t st20_rword(st20_context_t *ctx, uint32_t off)
  8359. +{
  8360. + return UINT32_LE(st20_addr(ctx, off));
  8361. +}
  8362. +
  8363. +uint16_t st20_rshort(st20_context_t *ctx, uint32_t off)
  8364. +{
  8365. + return UINT16_LE(st20_addr(ctx, off));
  8366. +}
  8367. +
  8368. +uint8_t st20_rbyte(st20_context_t *ctx, uint32_t off)
  8369. +{
  8370. + return UINT8_LE(st20_addr(ctx, off));
  8371. +}
  8372. +
  8373. +void st20_wword(st20_context_t *ctx, uint32_t off, uint32_t val)
  8374. +{
  8375. + BYTE4_LE(st20_addr(ctx, off), val);
  8376. +}
  8377. +
  8378. +void st20_wshort(st20_context_t *ctx, uint32_t off, uint16_t val)
  8379. +{
  8380. + BYTE2_LE(st20_addr(ctx, off), val);
  8381. +}
  8382. +
  8383. +void st20_wbyte(st20_context_t *ctx, uint32_t off, uint8_t val)
  8384. +{
  8385. + BYTE1_LE(st20_addr(ctx, off), val);
  8386. +}
  8387. +
  8388. +#define OP_COL 20
  8389. +#define LOG_OP(op) //printf("%s\n",op);
  8390. +
  8391. +int32_t st20_decode(st20_context_t *ctx, int32_t count)
  8392. +{
  8393. + int32_t operand = 0;
  8394. +
  8395. + CLEAR_OP();
  8396. + while(ctx->Iptr != 0)
  8397. + {
  8398. + int32_t a, op1 = RB(ctx->Iptr++);
  8399. + GET_OP();
  8400. + switch(op1 >> 4)
  8401. + {
  8402. + case 0x0: // j / jump
  8403. + LOG_OP("j");
  8404. + JUMP(operand);
  8405. + CLEAR_OP();
  8406. + break;
  8407. + case 0x1: // ldlp
  8408. + LOG_OP("ldlp");
  8409. + PUSH(ctx->Wptr + (operand * 4));
  8410. + CLEAR_OP();
  8411. + break;
  8412. + case 0x2: // positive prefix
  8413. + LOG_OP("pfix");
  8414. + operand <<= 4;
  8415. + break;
  8416. + case 0x3: // ldnl
  8417. + LOG_OP("ldnl");
  8418. + AAA=RW(AAA + (operand * 4));
  8419. + CLEAR_OP();
  8420. + break;
  8421. + case 0x4: // ldc
  8422. + LOG_OP("ldc");
  8423. + PUSH(operand);
  8424. + CLEAR_OP();
  8425. + break;
  8426. + case 0x5: // ldnlp
  8427. + LOG_OP("ldnlp");
  8428. + PUSHPOP(+, operand * 4);
  8429. + CLEAR_OP();
  8430. + break;
  8431. + case 0x6: // negative prefix
  8432. + LOG_OP("nfix");
  8433. + operand = (~operand) << 4;
  8434. + break;
  8435. + case 0x7: // ldl
  8436. + LOG_OP("ldl");
  8437. + PUSH(RW(ctx->Wptr + (operand * 4)));
  8438. + CLEAR_OP();
  8439. + break;
  8440. + case 0x8: // adc
  8441. + LOG_OP("adc");
  8442. + PUSHPOP(+, operand);
  8443. + CLEAR_OP();
  8444. + break;
  8445. + case 0x9: // call
  8446. + LOG_OP("call");
  8447. + ctx->Wptr -= 16;
  8448. + WW(ctx->Wptr, ctx->Iptr); WW(ctx->Wptr + 4, POP()); WW(ctx->Wptr + 8, POP()); WW(ctx->Wptr + 12, POP());
  8449. + PUSH(ctx->Iptr);
  8450. + JUMP(operand);
  8451. + CLEAR_OP();
  8452. + break;
  8453. + case 0xA: // cj / conditional jump
  8454. + LOG_OP("cj");
  8455. + if(AAA) { DROP(1); } else { JUMP(operand); }
  8456. + CLEAR_OP();
  8457. + break;
  8458. + case 0xB: // ajw / adjust workspace
  8459. + LOG_OP("ajw");
  8460. + ctx->Wptr += operand * 4;
  8461. + CLEAR_OP();
  8462. + break;
  8463. + case 0xC: // eqc / equals constant
  8464. + LOG_OP("eqc");
  8465. + AAA = (operand == AAA ? 1 : 0);
  8466. + CLEAR_OP();
  8467. + break;
  8468. + case 0xD: // stl
  8469. + LOG_OP("stl");
  8470. + WW(ctx->Wptr + (operand * 4), POP());
  8471. + CLEAR_OP();
  8472. + break;
  8473. + case 0xE: // stnl
  8474. + LOG_OP("stnl");
  8475. + a = POP(); WW(a + (operand * 4), POP());
  8476. + CLEAR_OP();
  8477. + break;
  8478. + case 0xF: // opr (secondary ins)
  8479. + switch(operand)
  8480. + {
  8481. + case 0x00: LOG_OP("rev"); a = AAA; AAA = BBB; BBB = a; break;
  8482. + case 0x01: LOG_OP("lb"); AAA = RB(AAA); break;
  8483. + case 0x02: LOG_OP("bsub"); PUSHPOP(+, POP()); break;
  8484. + case 0x04: LOG_OP("diff"); PUSHPOP(-, POP()); break;
  8485. + case 0x05: LOG_OP("add"); PUSHPOP(+, POP()); break;
  8486. + case 0x06: LOG_OP("gcall"); a = AAA; AAA = ctx->Iptr; ctx->Iptr = a; break;
  8487. + case 0x08: LOG_OP("prod"); PUSHPOP(*, POP()); break;
  8488. + case 0x09: LOG_OP("gt"); a=POP(); AAA = (AAA > a); break;
  8489. + case 0x0A: LOG_OP("wsub"); a=POP(); AAA = a + (AAA * 4); break;
  8490. + case 0x0C: LOG_OP("sub"); PUSHPOP(-, POP()); break;
  8491. + case 0x1A: LOG_OP("ldiv"); { a = POP(); uint64_t ll = POP64(); PUSH(ll % (uint32_t)a); PUSH(ll / (uint32_t)a); } break;
  8492. + case 0x1B: LOG_OP("ldpi"); PUSHPOP(+, ctx->Iptr); break;
  8493. + case 0x1D: LOG_OP("xdble"); CCC = BBB; BBB = (AAA >= 0 ? 0 : -1); break;
  8494. + case 0x1F: LOG_OP("rem"); PUSHPOP(%, POP()); break;
  8495. + case 0x20: LOG_OP("ret"); ctx->Iptr = RW(ctx->Wptr); ctx->Wptr = ctx->Wptr + 16; break;
  8496. + case 0x2C:
  8497. + LOG_OP("div");
  8498. + PUSHPOP( /, POP());
  8499. + break;
  8500. + case 0x30: LOG_OP("nop"); break;
  8501. + case 0x32: LOG_OP("not"); AAA =~ AAA; break;
  8502. + case 0x33: LOG_OP("xor"); PUSHPOP(^, POP()); break;
  8503. + case 0x34: LOG_OP("bcnt"); PUSHPOP(*, 4); break;
  8504. + case 0x35: LOG_OP("lshr"); { a = POP(); uint64_t ll = POP64() >> a; PUSH((ll >> 32) & 0xFFFFFFFF); PUSH(ll & 0xFFFFFFFF); } break;
  8505. + case 0x36: LOG_OP("lshl"); { a = POP(); uint64_t ll = POP64() << a; PUSH((ll >> 32) & 0xFFFFFFFF); PUSH(ll & 0xFFFFFFFF); } break;
  8506. + case 0x3B: LOG_OP("sb"); a = POP(); st20_wbyte(ctx, a, POP()); break;
  8507. + case 0x3F: LOG_OP("wcnt"); a = POP(); PUSH(a & 3); PUSH((uint32_t)a >> 2); break;
  8508. + case 0x40: LOG_OP("shr"); a = POP(); AAA = (uint32_t)AAA >> a; break;
  8509. + case 0x41: LOG_OP("shl"); a = POP(); AAA = (uint32_t)AAA << a; break;
  8510. + case 0x42: LOG_OP("mint"); PUSH(MOSTNEG); break;
  8511. + case 0x46: LOG_OP("and"); PUSHPOP(&, POP()); break;
  8512. + case 0x4A: LOG_OP("move"); { a = POP(); int32_t b = POP(); int32_t c = POP(); while(a--) st20_wbyte(ctx, b++, st20_rbyte(ctx, c++)); } break;
  8513. + case 0x4B: LOG_OP("or"); PUSHPOP(|, POP()); break;
  8514. + case 0x53: LOG_OP("mul"); PUSHPOP(*, POP()); break;
  8515. + case 0x5A: LOG_OP("dup"); PUSH(AAA); break;
  8516. + case 0x5F: LOG_OP("gtu"); a = POP(); AAA = ((uint32_t)AAA > (uint32_t)a); break;
  8517. + case 0x78: LOG_OP("bitrevnbits"); { a = POP(); int32_t b = POP(); int32_t bb = 0; while(a--){bb <<= 1; bb |= b & 1; b >>= 1;} PUSH(bb);} break;
  8518. + case 0xCA: LOG_OP("ls"); AAA = st20_rshort(ctx, AAA); break;
  8519. + default:
  8520. + //printf("unknown opcode %X\n", operand);
  8521. + cs_log("[icg] unknown opcode %X", operand);
  8522. + return ERR_ILL_OP;
  8523. + }
  8524. + CLEAR_OP();
  8525. + break;
  8526. + }
  8527. +
  8528. + if(--count <= 0 && operand == 0)
  8529. + {
  8530. + return ERR_CNT;
  8531. + }
  8532. +}
  8533. + return 0;
  8534. +}
  8535. +
  8536. +void st20_set_flash(st20_context_t *ctx, uint8_t *m, int32_t len)
  8537. +{
  8538. + if(ctx->flash) free(ctx->flash);
  8539. + ctx->flash = malloc(len);
  8540. + if(ctx->flash && m) memcpy(ctx->flash, m, len);
  8541. + else memset(ctx->flash, 0, len);
  8542. + ctx->flashSize = len;
  8543. +}
  8544. +
  8545. +void st20_set_ram(st20_context_t *ctx, uint8_t *m, int32_t len)
  8546. +{
  8547. + if(ctx->ram) free(ctx->ram);
  8548. + ctx->ram = malloc(len);
  8549. + if(ctx->ram && m) memcpy(ctx->ram, m, len);
  8550. + else memset(ctx->ram, 0, len);
  8551. + ctx->ramSize = len;
  8552. +}
  8553. +
  8554. +void st20_init(st20_context_t *ctx, uint32_t IPtr, uint32_t WPtr, int32_t verbose)
  8555. +{
  8556. + ctx->Wptr = WPtr; ctx->Iptr = IPtr;
  8557. + memset(ctx->stack, INVALID_VALUE, sizeof(ctx->stack)); ctx->sptr = STACKMAX - 3;
  8558. + memset(ctx->iram, 0, sizeof(ctx->iram));
  8559. + ctx->verbose = verbose;
  8560. +}
  8561. +
  8562. +void st20_free(st20_context_t *ctx)
  8563. +{
  8564. + if(ctx->flash) free(ctx->flash);
  8565. + if(ctx->ram) free(ctx->ram);
  8566. + ctx->flash = NULL;
  8567. + ctx->ram = NULL;
  8568. +}
  8569. +
  8570. +void st20_set_call_frame(st20_context_t *ctx, uint32_t raddr, int32_t p1, int32_t p2, int32_t p3)
  8571. +{
  8572. + ctx->Wptr -= 16;
  8573. + st20_wword(ctx, ctx->Wptr, raddr); // RET
  8574. + st20_wword(ctx, ctx->Wptr + 4, p1); //Areg
  8575. + st20_wword(ctx, ctx->Wptr + 8, p1); //Breg
  8576. + st20_wword(ctx, ctx->Wptr + 12, p1); //Creg
  8577. + st20_wword(ctx, ctx->Wptr + 16, p2);
  8578. + st20_wword(ctx, ctx->Wptr + 20, p3);
  8579. + st20_set_reg(ctx, AREG, raddr); // RET
  8580. +}
  8581. +
  8582. +int32_t st20_run(uint8_t* snip, uint32_t snip_len, int32_t addr, uint8_t *data, uint16_t overcryptId)
  8583. +{
  8584. + int32_t error, i, n;
  8585. + st20_context_t ctx;
  8586. +
  8587. + //printf("exec_snip addr = 0x%X\n", addr);
  8588. + cs_log("[icg] decrypt address = 0x%X, id = %04X", addr, overcryptId);
  8589. +
  8590. + //printf("CW: "); for(i = 0; i < 16; i++) printf("%02X ", data[i]); printf("\n");
  8591. + cs_log("[icg] CW: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X "
  8592. + ,data[0], data[1], data[2] , data[3] , data[4] , data[5] , data[6] , data[7]
  8593. + ,data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
  8594. + for(n=0;n<2;n++)
  8595. + {
  8596. + memset(&ctx, 0, sizeof(st20_context_t));
  8597. + st20_set_ram(&ctx, NULL, 0x1000);
  8598. + st20_set_flash(&ctx, snip + 0x48, (int) (snip_len - 0x48));
  8599. + st20_init(&ctx, FLASHS + addr, RAMS + 0x100, 1);
  8600. + st20_set_call_frame(&ctx, 0, RAMS, RAMS, RAMS);
  8601. + for(i = 0; i < 8; i++) st20_wbyte(&ctx, RAMS + i, data[i+n*8]);
  8602. + error = st20_decode(&ctx, 800000);
  8603. + //printf("ret = %d, AREG = %X\n", error, st20_get_reg(&ctx, AREG));
  8604. + cs_log("[icg] ret = %d, AREG = %X", error, st20_get_reg(&ctx, AREG));
  8605. + for(i = 0; i < 8; i++) data[i+n*8] = st20_rbyte(&ctx, RAMS + i);
  8606. + st20_free(&ctx);
  8607. + }
  8608. +
  8609. + //printf("DW: "); for(i = 0; i < 16; i++) printf("%02X ", data[i]); printf("\n");
  8610. + cs_log("[icg] DW: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X "
  8611. + ,data[0], data[1], data[2] , data[3] , data[4] , data[5] , data[6] , data[7]
  8612. + ,data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
  8613. +
  8614. +
  8615. + if(error < 0)
  8616. + {
  8617. + cs_log("[icg] st20 processing failed with error %d", error);
  8618. + return 0;
  8619. + }
  8620. +
  8621. + return 1;
  8622. +}
  8623. Index: module-emulator-st20.h
  8624. ===================================================================
  8625. --- module-emulator-st20.h (revision 0)
  8626. +++ module-emulator-st20.h (working copy)
  8627. @@ -0,0 +1,6 @@
  8628. +#ifndef ST20_H_
  8629. +#define ST20_H_
  8630. +
  8631. + int32_t st20_run(uint8_t* snip, uint32_t snip_len, int32_t addr, uint8_t *data, uint16_t overcryptId);
  8632. +
  8633. +#endif
  8634. Index: module-emulator-stream.c
  8635. ===================================================================
  8636. --- module-emulator-stream.c (revision 0)
  8637. +++ module-emulator-stream.c (working copy)
  8638. @@ -0,0 +1,1071 @@
  8639. +#include "globals.h"
  8640. +#include "cscrypt/des.h"
  8641. +
  8642. +#ifdef WITH_EMU
  8643. +#include "oscam-string.h"
  8644. +#include "oscam-config.h"
  8645. +#include "oscam-time.h"
  8646. +#include "oscam-net.h"
  8647. +
  8648. +extern int32_t exit_oscam;
  8649. +#endif
  8650. +
  8651. +#include "ffdecsa/ffdecsa.h"
  8652. +#include "module-emulator-osemu.h"
  8653. +#include "module-emulator-stream.h"
  8654. +
  8655. +typedef struct
  8656. +{
  8657. + int32_t connfd;
  8658. + int32_t connid;
  8659. +} emu_stream_client_conn_data;
  8660. +
  8661. +int8_t stream_server_thread_init = 0;
  8662. +char emu_stream_source_host[256] = {"127.0.0.1"};
  8663. +int32_t emu_stream_source_port = 8001;
  8664. +char *emu_stream_source_auth = NULL;
  8665. +int32_t emu_stream_relay_port = 17999;
  8666. +int8_t emu_stream_emm_enabled = 0;
  8667. +uint32_t cluster_size = 50;
  8668. +
  8669. +static uint8_t emu_stream_server_mutex_init = 0;
  8670. +static pthread_mutex_t emu_stream_server_mutex;
  8671. +static int32_t glistenfd, gconncount = 0, gconnfd[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  8672. +
  8673. +#ifdef WITH_EMU
  8674. +pthread_mutex_t emu_fixed_key_srvid_mutex;
  8675. +uint16_t emu_stream_cur_srvid[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  8676. +int8_t stream_server_has_ecm[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  8677. +
  8678. +pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  8679. +emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  8680. +LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  8681. +#endif
  8682. +
  8683. +static void SearchTsPackets(uint8_t *buf, uint32_t bufLength, uint16_t *packetSize, uint16_t *startOffset)
  8684. +{
  8685. + uint32_t i;
  8686. +
  8687. + (*packetSize) = 0;
  8688. + (*startOffset) = 0;
  8689. +
  8690. + for(i=0; i<bufLength; i++) {
  8691. + if(buf[i] == 0x47) {
  8692. + if((buf[i+188] == 0x47) & (buf[i+376] == 0x47)) { //if three packets align, probably safe to assume correct size.
  8693. + (*packetSize) = 188;
  8694. + (*startOffset) = i;
  8695. + return;
  8696. + }
  8697. + else if((buf[i+204] == 0x47) & (buf[i+408] == 0x47)) {
  8698. + (*packetSize) = 204;
  8699. + (*startOffset) = i;
  8700. + return;
  8701. + }
  8702. + else if((buf[i+208] == 0x47) & (buf[i+416] == 0x47)) {
  8703. + (*packetSize) = 208;
  8704. + (*startOffset) = i;
  8705. + return;
  8706. + }
  8707. + }
  8708. + }
  8709. +}
  8710. +
  8711. +typedef void (*ts_data_callback)(emu_stream_client_data *cdata);
  8712. +
  8713. +static void ParseTSData(uint8_t table_id, uint8_t table_mask, uint8_t min_table_length, int8_t* flag, uint8_t* data,
  8714. + uint16_t data_length, uint16_t* data_pos, int8_t payloadStart, uint8_t* buf, int32_t len,
  8715. + ts_data_callback func, emu_stream_client_data *cdata)
  8716. +{
  8717. + uint16_t section_length;
  8718. + int32_t i;
  8719. + int8_t found_start = 0;
  8720. + uint16_t offset = 0;
  8721. + int32_t free_data_length;
  8722. + int32_t copySize;
  8723. +
  8724. + if(len < 1)
  8725. + { return; }
  8726. +
  8727. + if(*flag == 0 && !payloadStart)
  8728. + { return; }
  8729. +
  8730. + if(*flag == 0)
  8731. + {
  8732. + *data_pos = 0;
  8733. + offset = 1 + buf[0];
  8734. + }
  8735. + else if(payloadStart)
  8736. + {
  8737. + offset = 1;
  8738. + }
  8739. +
  8740. + if(len-offset < 1)
  8741. + { return; }
  8742. +
  8743. + free_data_length = data_length - *data_pos;
  8744. + copySize = (len-offset) > free_data_length ? free_data_length : (len-offset);
  8745. +
  8746. + memcpy(data+(*data_pos), buf+offset, copySize);
  8747. + (*data_pos) += copySize;
  8748. +
  8749. + found_start = 0;
  8750. + for(i=0; i < *data_pos; i++)
  8751. + {
  8752. + if((data[i] & table_mask) == table_id)
  8753. + {
  8754. + if(i != 0)
  8755. + {
  8756. + if((*data_pos)-i > i)
  8757. + { memmove(data, &data[i], (*data_pos)-i); }
  8758. + else
  8759. + { memcpy(data, &data[i], (*data_pos)-i); }
  8760. +
  8761. + *data_pos -= i;
  8762. + }
  8763. + found_start = 1;
  8764. + break;
  8765. + }
  8766. + }
  8767. + if(!found_start)
  8768. + { *flag = 0; return; }
  8769. +
  8770. + *flag = 2;
  8771. +
  8772. + if(*data_pos < 3)
  8773. + { return; }
  8774. +
  8775. + section_length = SCT_LEN(data);
  8776. +
  8777. + if(section_length > data_length || section_length < min_table_length)
  8778. + { *flag = 0; return; }
  8779. +
  8780. + if((*data_pos) < section_length)
  8781. + { return; }
  8782. +
  8783. + func(cdata);
  8784. +
  8785. + found_start = 0;
  8786. + for(i=section_length; i < *data_pos; i++)
  8787. + {
  8788. + if((data[i] & table_mask) == table_id)
  8789. + {
  8790. + if((*data_pos)-i > i)
  8791. + { memmove(data, &data[i], (*data_pos)-i); }
  8792. + else
  8793. + { memcpy(data, &data[i], (*data_pos)-i); }
  8794. +
  8795. + *data_pos -= i;
  8796. + found_start = 1;
  8797. + break;
  8798. + }
  8799. + }
  8800. + if(!found_start)
  8801. + { *data_pos = 0; }
  8802. +
  8803. + *flag = 1;
  8804. +}
  8805. +
  8806. +static void ParsePATData(emu_stream_client_data *cdata)
  8807. +{
  8808. + uint8_t* data = cdata->data;
  8809. + uint16_t section_length = SCT_LEN(data);
  8810. + uint16_t srvid;
  8811. + int32_t i;
  8812. +
  8813. + for(i=8; i+7<section_length; i+=4)
  8814. + {
  8815. + srvid = b2i(2, data+i);
  8816. +
  8817. + if(srvid == 0)
  8818. + { continue; }
  8819. +
  8820. + if(cdata->srvid == srvid)
  8821. + {
  8822. + cdata->pmt_pid = b2i(2, data+i+2) & 0x1FFF;
  8823. + cs_log_dbg(D_READER, "[Emu] stream %i found pmt pid : 0x%04X (%i)",cdata->connid, cdata->pmt_pid, cdata->pmt_pid);
  8824. + break;
  8825. + }
  8826. + }
  8827. +}
  8828. +
  8829. +static void ParsePMTData(emu_stream_client_data *cdata)
  8830. +{
  8831. + uint8_t* data = cdata->data;
  8832. +
  8833. + uint16_t section_length = SCT_LEN(data);
  8834. + int32_t i;
  8835. + uint16_t program_info_length = 0, es_info_length = 0;
  8836. + uint8_t descriptor_tag = 0, descriptor_length = 0;
  8837. + uint8_t stream_type;
  8838. + uint16_t stream_pid, caid;
  8839. +
  8840. + program_info_length = b2i(2, data+10) &0xFFF;
  8841. +
  8842. + if(12+program_info_length >= section_length)
  8843. + { return; }
  8844. +
  8845. + for(i=12; i+1 < 12+program_info_length; i+=descriptor_length+2)
  8846. + {
  8847. + descriptor_tag = data[i];
  8848. + descriptor_length = data[i+1];
  8849. +
  8850. + if(descriptor_length < 1)
  8851. + { break; }
  8852. +
  8853. + if(i+1+descriptor_length >= 12+program_info_length)
  8854. + { break; }
  8855. +
  8856. + if(descriptor_tag == 0x09 && descriptor_length >= 4)
  8857. + {
  8858. + caid = b2i(2, data+i+2);
  8859. +
  8860. + if(caid>>8 == 0x0E)
  8861. + {
  8862. + cdata->ecm_pid = b2i(2, data+i+4) &0x1FFF;
  8863. + cs_log_dbg(D_READER, "[Emu] stream %i found ecm pid : 0x%04X (%i)",cdata->connid, cdata->ecm_pid, cdata->ecm_pid);
  8864. + break;
  8865. + }
  8866. + }
  8867. + }
  8868. +
  8869. + for(i=12+program_info_length; i+4<section_length; i+=5+es_info_length)
  8870. + {
  8871. + stream_type = data[i];
  8872. + stream_pid = b2i(2, data+i+1) &0x1FFF;
  8873. + es_info_length = b2i(2, data+i+3) &0xFFF;
  8874. +
  8875. + if(stream_type == 0x01 || stream_type == 0x02 || stream_type == 0x10 || stream_type == 0x1B
  8876. + || stream_type == 0x24 || stream_type == 0x42 || stream_type == 0x80 || stream_type == 0xD1
  8877. + || stream_type == 0xEA)
  8878. + {
  8879. + cdata->video_pid = stream_pid;
  8880. + cs_log_dbg(D_READER, "[Emu] stream %i found video pid: 0x%04X (%i)",cdata->connid, stream_pid, stream_pid);
  8881. + }
  8882. +
  8883. + else if(stream_type == 0x03 || stream_type == 0x04 || stream_type == 0x05 || stream_type == 0x06 ||
  8884. + stream_type == 0x0F || stream_type == 0x11 || stream_type == 0x81 || stream_type == 0x87)
  8885. + {
  8886. + if(cdata->audio_pid_count >= EMU_STREAM_MAX_AUDIO_SUB_TRACKS)
  8887. + { continue; }
  8888. +
  8889. + cdata->audio_pids[cdata->audio_pid_count] = stream_pid;
  8890. + cdata->audio_pid_count++;
  8891. + cs_log_dbg(D_READER, "[Emu] stream %i found audio pid: 0x%04X (%i)", cdata->connid, stream_pid, stream_pid);
  8892. + }
  8893. + }
  8894. +}
  8895. +
  8896. +static void ParseECMData(emu_stream_client_data *cdata)
  8897. +{
  8898. + uint8_t* data = cdata->data;
  8899. + uint16_t section_length = SCT_LEN(data);
  8900. + uint8_t dcw[16];
  8901. +
  8902. + if(section_length < 0xb)
  8903. + { return; }
  8904. +
  8905. + if(data[0xb] > cdata->ecm_nb || (cdata->ecm_nb == 255 && data[0xb] == 0)
  8906. + || ((cdata->ecm_nb - data[0xb]) > 5))
  8907. + {
  8908. + cdata->ecm_nb = data[0xb];
  8909. +#ifdef WITH_EMU
  8910. + PowervuECM(data, dcw, cdata->srvid, &cdata->key, NULL);
  8911. +#else
  8912. + PowervuECM(data, dcw, &cdata->key);
  8913. +#endif
  8914. + }
  8915. +}
  8916. +
  8917. +//#ifdef WITH_EMU
  8918. +//static void ParseTSPackets(emu_stream_client_conn_data *conndata, emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
  8919. +//#else
  8920. +static void ParseTSPackets(emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
  8921. +//#endif
  8922. +{
  8923. + uint32_t i, j, k;
  8924. + uint32_t tsHeader;
  8925. + uint16_t pid, offset;
  8926. + uint8_t scramblingControl, payloadStart, oddeven;
  8927. + int8_t oddKeyUsed;
  8928. + uint32_t *deskey;
  8929. + uint8_t *pdata;
  8930. + uint8_t *packetClusterA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS][64]; //separate cluster arrays for video and each audio track
  8931. + uint8_t *packetClusterV[256];
  8932. + void *csakeyA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0};
  8933. + void *csakeyV = 0;
  8934. + emu_stream_client_key_data *keydata;
  8935. + uint32_t scrambled_packets = 0;
  8936. + uint32_t scrambled_packetsA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0};
  8937. + packetClusterV[0] = NULL;
  8938. + uint32_t cs =0; //video cluster start
  8939. + uint32_t ce =1; //video cluster end
  8940. + uint32_t csa[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0}; //cluster index for audio tracks
  8941. + uint32_t keysAdded = 0;
  8942. + uint8_t *cptr;
  8943. +
  8944. + for(i=0; i<bufLength; i+=packetSize)
  8945. + {
  8946. + tsHeader = b2i(4, stream_buf+i);
  8947. + pid = (tsHeader & 0x1fff00) >> 8;
  8948. + scramblingControl = tsHeader & 0xc0;
  8949. + payloadStart = (tsHeader & 0x400000) >> 22;
  8950. +
  8951. + if(tsHeader & 0x20)
  8952. + { offset = 4 + stream_buf[i+4] + 1; }
  8953. + else
  8954. + { offset = 4; }
  8955. +
  8956. + if(packetSize-offset < 1)
  8957. + { continue; }
  8958. +
  8959. + if( pid == 0x01 && emu_stream_emm_enabled && !data->emm_pid ) // CAT
  8960. + {
  8961. + cptr = stream_buf+i+offset;
  8962. + j = 0;
  8963. + while (cptr != NULL)
  8964. + {
  8965. + cptr = memchr (stream_buf+i+offset+j, 0x0E,100);
  8966. + if (cptr != NULL)
  8967. + {
  8968. + if (*(cptr+1) == 00)
  8969. + {
  8970. + data->emm_pid = (b2i(2,cptr+2) & 0x1FFF);
  8971. + cs_log_dbg(D_READER|D_EMM, "[Emu] stream %i found emm pid : 0x%04X (%i)",data->connid, data->emm_pid, data->emm_pid);
  8972. + break;
  8973. + }
  8974. + j = cptr - stream_buf +i + 1;
  8975. + }
  8976. + }
  8977. + }
  8978. +
  8979. + if(pid == data->emm_pid && data->emm_pid)
  8980. + {
  8981. + ProcessEMM(0x0E00,0x0,stream_buf+i+offset+1, &keysAdded);
  8982. + if(keysAdded)
  8983. + {
  8984. + cs_log("[Emu] stream %i found %i keys.",data->connid, keysAdded);
  8985. + }
  8986. +
  8987. + }
  8988. +
  8989. + if(data->have_pat_data != 1)
  8990. + {
  8991. + if(pid == 0)
  8992. + {
  8993. + ParseTSData(0x00, 0xFF, 16, &data->have_pat_data, data->data, sizeof(data->data), &data->data_pos, payloadStart,
  8994. + stream_buf+i+offset, packetSize-offset, ParsePATData, data);
  8995. + }
  8996. +
  8997. + continue;
  8998. + }
  8999. +
  9000. + if(!data->pmt_pid)
  9001. + {
  9002. + data->have_pat_data = 0;
  9003. + continue;
  9004. + }
  9005. +
  9006. + if(data->have_pmt_data != 1)
  9007. + {
  9008. + if(pid == data->pmt_pid)
  9009. + {
  9010. + ParseTSData(0x02, 0xFF, 21, &data->have_pmt_data, data->data, sizeof(data->data), &data->data_pos, payloadStart,
  9011. + stream_buf+i+offset, packetSize-offset, ParsePMTData, data);
  9012. + }
  9013. +
  9014. + continue;
  9015. + }
  9016. +
  9017. + if(data->ecm_pid && pid == data->ecm_pid)
  9018. + {
  9019. +#ifdef WITH_EMU
  9020. + stream_server_has_ecm[data->connid] = 1;
  9021. +#endif
  9022. +
  9023. + ParseTSData(0x80, 0xFE, 10, &data->have_ecm_data, data->data, sizeof(data->data), &data->data_pos, payloadStart,
  9024. + stream_buf+i+offset, packetSize-offset, ParseECMData, data);
  9025. + continue;
  9026. + }
  9027. +
  9028. + if(scramblingControl == 0)
  9029. + { continue; }
  9030. +
  9031. + if(!(stream_buf[i+3] & 0x10))
  9032. + {
  9033. + stream_buf[i+3] &= 0x3F;
  9034. + continue;
  9035. + }
  9036. +
  9037. + oddKeyUsed = scramblingControl == 0xC0 ? 1 : 0;
  9038. +
  9039. +#ifdef WITH_EMU
  9040. + if(!stream_server_has_ecm[data->connid])
  9041. + {
  9042. + keydata = &emu_fixed_key_data[data->connid];
  9043. + SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[data->connid]);
  9044. + data->key.pvu_csa_used = keydata->pvu_csa_used;
  9045. + }
  9046. + else
  9047. + {
  9048. +#endif
  9049. + keydata = &data->key;
  9050. +#ifdef WITH_EMU
  9051. + }
  9052. +#endif
  9053. +
  9054. + if(keydata->pvu_csa_used)
  9055. + {
  9056. + oddeven = scramblingControl; // for detecting odd/even switch
  9057. +
  9058. + if(pid == data->video_pid) // start with video pid, since it is most dominant
  9059. + {
  9060. + csakeyV = keydata->pvu_csa_ks[PVU_CW_VID];
  9061. +
  9062. + if(csakeyV !=NULL)
  9063. + {
  9064. + cs=0;
  9065. + ce=1;
  9066. + packetClusterV[cs] = stream_buf+i; // set first cluster start
  9067. + packetClusterV[ce] = stream_buf+i+packetSize -1;
  9068. + scrambled_packets=1;
  9069. +
  9070. + for(j=i+packetSize; j<bufLength; j+=packetSize) // Now iterate through the rest of the packets and create clusters for batch decryption
  9071. + {
  9072. + tsHeader = b2i(4, stream_buf+j);
  9073. + pid = (tsHeader & 0x1fff00) >> 8;
  9074. + if(pid == data->video_pid)
  9075. + {
  9076. + if(oddeven != (tsHeader & 0xc0)) // changed key so stop adding clusters
  9077. + {
  9078. + break;
  9079. + }
  9080. + if(cs > ce) // First video packet for each cluster
  9081. + {
  9082. + packetClusterV[cs] = stream_buf+j;
  9083. + ce = cs +1;
  9084. + }
  9085. +
  9086. + scrambled_packets++;
  9087. + }
  9088. + else
  9089. + {
  9090. + if(cs < ce) // First non-video packet - need to set end of video cluster
  9091. + {
  9092. + packetClusterV[ce] = stream_buf+j -1;
  9093. + cs = ce +1;
  9094. + }
  9095. +
  9096. + if((tsHeader & 0xc0) ==0) {
  9097. + continue;
  9098. + }
  9099. +
  9100. + if(oddeven != (tsHeader & 0xc0)) // changed key so stop adding clusters
  9101. + {
  9102. + j=bufLength; // to break out of outer loop also
  9103. + break;
  9104. + }
  9105. +
  9106. + for(k=0; k<data->audio_pid_count; k++) // Check for audio tracks and create single packet clusters
  9107. + {
  9108. + if(pid == data->audio_pids[k])
  9109. + {
  9110. + packetClusterA[k][csa[k]] = stream_buf+j;
  9111. + csa[k]++;
  9112. + packetClusterA[k][csa[k]] = stream_buf+j+packetSize -1;
  9113. + csa[k]++;
  9114. + scrambled_packetsA[k]++;
  9115. + }
  9116. + }
  9117. + }
  9118. + }
  9119. +
  9120. + if( cs > ce ) // last packet was not a video packet, so set null for end of all clusters
  9121. + { packetClusterV[cs] = NULL; }
  9122. + else
  9123. + {
  9124. + if(scrambled_packets>1) // last packet was a video packet, so set end of cluster to end of last packet
  9125. + {
  9126. + packetClusterV[ce] = stream_buf+j -1;
  9127. + }
  9128. + packetClusterV[ce+1] = NULL; // add null to end of cluster list
  9129. + }
  9130. +
  9131. + while( j >= cluster_size )
  9132. + { j = decrypt_packets(csakeyV, packetClusterV); }
  9133. +
  9134. + for(k=0; k<data->audio_pid_count; k++)
  9135. + {
  9136. + if(scrambled_packetsA[k]) // if audio track has scrambled packets, set null to mark end and decrypt
  9137. + {
  9138. + csakeyA[k] = keydata->pvu_csa_ks[PVU_CW_A1+k];
  9139. + packetClusterA[k][csa[k]] = NULL;
  9140. + decrypt_packets(csakeyA[k], packetClusterA[k]);
  9141. + csa[k]=0;
  9142. + scrambled_packetsA[k] = 0;
  9143. + }
  9144. + }
  9145. + }
  9146. + }
  9147. + else
  9148. + {
  9149. + for(j=0; j<data->audio_pid_count; j++)
  9150. + if(pid == data->audio_pids[j])
  9151. + { csakeyA[0] = keydata->pvu_csa_ks[PVU_CW_A1+j]; }
  9152. +
  9153. + if(csakeyA[0] != NULL)
  9154. + {
  9155. + packetClusterA[0][0] = stream_buf+i;
  9156. + packetClusterA[0][1] = stream_buf+i+packetSize -1;
  9157. + packetClusterA[0][2] = NULL;
  9158. + decrypt_packets(csakeyA[0], packetClusterA[0]);
  9159. + }
  9160. + }
  9161. + }
  9162. + else
  9163. + {
  9164. + deskey = NULL;
  9165. +
  9166. + if(pid == data->video_pid)
  9167. + { deskey = keydata->pvu_des_ks[PVU_CW_VID][oddKeyUsed]; }
  9168. + else
  9169. + {
  9170. + for(j=0; j<data->audio_pid_count; j++)
  9171. + if(pid == data->audio_pids[j])
  9172. + { deskey = keydata->pvu_des_ks[PVU_CW_A1+j][oddKeyUsed]; }
  9173. + }
  9174. +
  9175. + if(deskey != NULL)
  9176. + {
  9177. + for(j=offset; j+7<188; j+=8)
  9178. + {
  9179. + pdata = stream_buf+i+j;
  9180. + des(pdata, deskey, 0);
  9181. + }
  9182. +
  9183. + stream_buf[i+3] &= 0x3F;
  9184. + }
  9185. + }
  9186. +
  9187. +#ifdef WITH_EMU
  9188. + if(!stream_server_has_ecm[data->connid])
  9189. + {
  9190. + SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[data->connid]);
  9191. + }
  9192. +#endif
  9193. + }
  9194. +}
  9195. +
  9196. +static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *stream_path)
  9197. +{
  9198. + struct sockaddr_in cservaddr;
  9199. + IN_ADDR_T in_addr;
  9200. +
  9201. + int32_t streamfd = socket(AF_INET, SOCK_STREAM, 0);
  9202. + if(streamfd == -1)
  9203. + { return -1; }
  9204. +
  9205. + struct timeval tv;
  9206. + tv.tv_sec = 2;
  9207. + tv.tv_usec = 0;
  9208. + if (setsockopt(streamfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv))
  9209. + {
  9210. + cs_log("[Emu] error: setsockopt() failed for SO_RCVTIMEO");
  9211. + return -1;
  9212. + }
  9213. +
  9214. + bzero(&cservaddr, sizeof(cservaddr));
  9215. + cservaddr.sin_family = AF_INET;
  9216. + cs_resolve(emu_stream_source_host, &in_addr, NULL, NULL);
  9217. + SIN_GET_ADDR(cservaddr) = in_addr;
  9218. + cservaddr.sin_port = htons(emu_stream_source_port);
  9219. +
  9220. + if(connect(streamfd, (struct sockaddr *)&cservaddr, sizeof(cservaddr)) == -1)
  9221. + { return -1; }
  9222. + if(emu_stream_source_auth)
  9223. + {
  9224. + snprintf(http_buf, http_buf_len, "GET %s HTTP/1.1\nHost: %s:%u\n"
  9225. + "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n"
  9226. + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
  9227. + "Accept-Language: en-US\n"
  9228. + "Authorization: Basic %s\n"
  9229. + "Connection: keep-alive\n\n", stream_path, emu_stream_source_host, emu_stream_source_port, emu_stream_source_auth);
  9230. + }
  9231. + else
  9232. + {
  9233. + snprintf(http_buf, http_buf_len, "GET %s HTTP/1.1\nHost: %s:%u\n"
  9234. + "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n"
  9235. + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
  9236. + "Accept-Language: en-US\n"
  9237. + "Connection: keep-alive\n\n", stream_path, emu_stream_source_host, emu_stream_source_port);
  9238. + }
  9239. +
  9240. + if(send(streamfd, http_buf, strlen(http_buf), 0) == -1)
  9241. + { return -1; }
  9242. +
  9243. + return streamfd;
  9244. +}
  9245. +
  9246. +static void stream_client_disconnect(emu_stream_client_conn_data *conndata)
  9247. +{
  9248. + int32_t i;
  9249. +
  9250. +#ifdef WITH_EMU
  9251. + SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
  9252. + emu_stream_cur_srvid[conndata->connid] = NO_SRVID_VALUE;
  9253. + stream_server_has_ecm[conndata->connid] = 0;
  9254. + SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
  9255. +#endif
  9256. +
  9257. + SAFE_MUTEX_LOCK(&emu_stream_server_mutex);
  9258. + for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
  9259. + {
  9260. + if(gconnfd[i] == conndata->connfd)
  9261. + {
  9262. + gconnfd[i] = -1;
  9263. + gconncount--;
  9264. + }
  9265. + }
  9266. + SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex);
  9267. +
  9268. + shutdown(conndata->connfd, 2);
  9269. + close(conndata->connfd);
  9270. +
  9271. + cs_log("[Emu] stream client %i disconnected",conndata->connid);
  9272. +
  9273. + NULLFREE(conndata);
  9274. +}
  9275. +
  9276. +static void *stream_client_handler(void *arg)
  9277. +{
  9278. +#define EMU_DVB_MAX_TS_PACKETS 278
  9279. +#define EMU_DVB_BUFFER_SIZE_CSA 188*EMU_DVB_MAX_TS_PACKETS
  9280. +#define EMU_DVB_BUFFER_WAIT_CSA 188*(EMU_DVB_MAX_TS_PACKETS-128)
  9281. +#define EMU_DVB_BUFFER_SIZE_DES 188*32
  9282. +#define EMU_DVB_BUFFER_WAIT_DES 188*29
  9283. +#define EMU_DVB_BUFFER_SIZE EMU_DVB_BUFFER_SIZE_CSA
  9284. +
  9285. + emu_stream_client_conn_data *conndata = (emu_stream_client_conn_data *)arg;
  9286. + char *http_buf, stream_path[255], stream_path_copy[255];
  9287. + int32_t streamfd;
  9288. + int32_t clientStatus, streamStatus;
  9289. + uint8_t *stream_buf;
  9290. + uint16_t packetCount = 0, packetSize = 0, startOffset = 0;
  9291. + uint32_t remainingDataPos, remainingDataLength;
  9292. + int32_t cur_dvb_buffer_size, cur_dvb_buffer_wait;
  9293. + int32_t bytesRead = 0;
  9294. + emu_stream_client_data *data;
  9295. + int8_t streamConnectErrorCount = 0;
  9296. + int8_t streamDataErrorCount = 0;
  9297. + int32_t i, srvidtmp;
  9298. + char *saveptr, *token;
  9299. + char http_version[4];
  9300. + int32_t http_status_code = 0;
  9301. +
  9302. + cs_log("[Emu] stream client %i connected", conndata->connid);
  9303. +
  9304. + if(!cs_malloc(&http_buf, 1024))
  9305. + {
  9306. + stream_client_disconnect(conndata);
  9307. + return NULL;
  9308. + }
  9309. +
  9310. + if(!cs_malloc(&stream_buf, EMU_DVB_BUFFER_SIZE))
  9311. + {
  9312. + NULLFREE(http_buf);
  9313. + stream_client_disconnect(conndata);
  9314. + return NULL;
  9315. + }
  9316. +
  9317. + if(!cs_malloc(&data, sizeof(emu_stream_client_data)))
  9318. + {
  9319. + NULLFREE(http_buf);
  9320. + NULLFREE(stream_buf);
  9321. + stream_client_disconnect(conndata);
  9322. + return NULL;
  9323. + }
  9324. +
  9325. + clientStatus = recv(conndata->connfd, http_buf, 1024, 0);
  9326. + if(clientStatus < 1)
  9327. + {
  9328. + NULLFREE(http_buf);
  9329. + NULLFREE(stream_buf);
  9330. + NULLFREE(data);
  9331. + stream_client_disconnect(conndata);
  9332. + return NULL;
  9333. + }
  9334. +
  9335. + http_buf[1023] = '\0';
  9336. + if(sscanf(http_buf, "GET %254s ", stream_path) < 1)
  9337. + {
  9338. + NULLFREE(http_buf);
  9339. + NULLFREE(stream_buf);
  9340. + NULLFREE(data);
  9341. + stream_client_disconnect(conndata);
  9342. + return NULL;
  9343. + }
  9344. +
  9345. + cs_strncpy(stream_path_copy, stream_path, sizeof(stream_path));
  9346. +
  9347. + token = strtok_r(stream_path_copy, ":", &saveptr);
  9348. +
  9349. + for(i=0; token != NULL && i<3; i++)
  9350. + {
  9351. + token = strtok_r(NULL, ":", &saveptr);
  9352. + if(token == NULL)
  9353. + { break; }
  9354. + }
  9355. + if(token != NULL)
  9356. + {
  9357. + if(sscanf(token, "%x", &srvidtmp) < 1)
  9358. + {
  9359. + token = NULL;
  9360. + }
  9361. + else
  9362. + {
  9363. + data->srvid = srvidtmp & 0xFFFF;
  9364. + }
  9365. + }
  9366. +
  9367. + if(token == NULL)
  9368. + {
  9369. + NULLFREE(http_buf);
  9370. + NULLFREE(stream_buf);
  9371. + NULLFREE(data);
  9372. + stream_client_disconnect(conndata);
  9373. + return NULL;
  9374. + }
  9375. +
  9376. +#ifdef WITH_EMU
  9377. + SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
  9378. + emu_stream_cur_srvid[conndata->connid] = data->srvid;
  9379. + stream_server_has_ecm[conndata->connid] = 0;
  9380. + SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
  9381. +#endif
  9382. +
  9383. + cs_log("[Emu] stream client %i request %s", conndata->connid, stream_path);
  9384. +
  9385. + snprintf(http_buf, 1024, "HTTP/1.0 200 OK\nConnection: Close\nContent-Type: video/mpeg\nServer: stream_enigma2\n\n");
  9386. + clientStatus = send(conndata->connfd, http_buf, strlen(http_buf), 0);
  9387. +
  9388. + data->connid = conndata->connid;
  9389. +
  9390. + while(!exit_oscam && clientStatus != -1 && streamConnectErrorCount < 3 && streamDataErrorCount < 15)
  9391. + {
  9392. + streamfd = connect_to_stream(http_buf, 1024, stream_path);
  9393. + if(streamfd == -1)
  9394. + {
  9395. + cs_log("[Emu] warning: stream client %i cannot connect to stream source", conndata->connid);
  9396. + streamConnectErrorCount++;
  9397. + cs_sleepms(500);
  9398. + continue;
  9399. + }
  9400. +
  9401. + streamStatus = 0;
  9402. + bytesRead = 0;
  9403. +
  9404. + while(!exit_oscam && clientStatus != -1 && streamStatus != -1 && streamConnectErrorCount < 3 && streamDataErrorCount < 15)
  9405. + {
  9406. + if(data->key.pvu_csa_used)
  9407. + {
  9408. + cur_dvb_buffer_size = EMU_DVB_BUFFER_SIZE_CSA;
  9409. + cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_CSA;
  9410. + }
  9411. + else
  9412. + {
  9413. + cur_dvb_buffer_size = EMU_DVB_BUFFER_SIZE_DES;
  9414. + cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_DES;
  9415. + }
  9416. +
  9417. + streamStatus = recv(streamfd, stream_buf+bytesRead, cur_dvb_buffer_size-bytesRead, MSG_WAITALL);
  9418. + if(streamStatus == -1)
  9419. + {
  9420. + streamDataErrorCount++;
  9421. + break;
  9422. + }
  9423. +
  9424. + if(streamStatus == 0)
  9425. + {
  9426. + cs_log("[Emu] warning: stream client %i no data from stream source", conndata->connid);
  9427. + streamDataErrorCount++; // 2 sec timeout * 15 = 30 seconds no data -> close
  9428. + cs_sleepms(100);
  9429. + continue;
  9430. + }
  9431. +
  9432. + if(streamStatus < cur_dvb_buffer_size-bytesRead) // probably just received header but no stream
  9433. + {
  9434. + if(!bytesRead && streamStatus > 13 &&
  9435. + sscanf((const char*)stream_buf, "HTTP/%3s %d ", http_version , &http_status_code) == 2 &&
  9436. + http_status_code != 200)
  9437. + {
  9438. + cs_log("[Emu] error: stream client %i got %d response from stream source", conndata->connid, http_status_code);
  9439. + streamConnectErrorCount++;
  9440. + cs_sleepms(100);
  9441. + break;
  9442. + }
  9443. + else
  9444. + {
  9445. + cs_log_dbg(0, "[Emu] warning: stream client %i non-full buffer from stream source", conndata->connid);
  9446. + }
  9447. + }
  9448. +
  9449. + streamConnectErrorCount = 0;
  9450. + streamDataErrorCount = 0;
  9451. + bytesRead += streamStatus;
  9452. +
  9453. + if(bytesRead >= cur_dvb_buffer_wait)
  9454. + {
  9455. + startOffset = 0;
  9456. + if(stream_buf[0] != 0x47 || packetSize == 0) // only search if not starting on ts packet or unknown packet size
  9457. + {
  9458. + SearchTsPackets(stream_buf, bytesRead, &packetSize, &startOffset);
  9459. + }
  9460. + if(packetSize == 0)
  9461. + {
  9462. + bytesRead = 0;
  9463. + }
  9464. + else
  9465. + {
  9466. + packetCount = ((bytesRead-startOffset) / packetSize);
  9467. +
  9468. +//#ifdef WITH_EMU
  9469. +// ParseTSPackets(conndata, data, stream_buf+startOffset, packetCount*packetSize, packetSize);
  9470. +//#else
  9471. + ParseTSPackets(data, stream_buf+startOffset, packetCount*packetSize, packetSize);
  9472. +//#endif
  9473. + clientStatus = send(conndata->connfd, stream_buf+startOffset, packetCount*packetSize, 0);
  9474. +
  9475. + remainingDataPos = startOffset+(packetCount*packetSize);
  9476. + remainingDataLength = bytesRead-remainingDataPos;
  9477. +
  9478. + if(remainingDataPos < remainingDataLength)
  9479. + { memmove(stream_buf, stream_buf+remainingDataPos, remainingDataLength); }
  9480. + else
  9481. + { memcpy(stream_buf, stream_buf+remainingDataPos, remainingDataLength); }
  9482. +
  9483. + bytesRead = remainingDataLength;
  9484. + }
  9485. + }
  9486. + }
  9487. +
  9488. + close(streamfd);
  9489. + }
  9490. +
  9491. + NULLFREE(http_buf);
  9492. + NULLFREE(stream_buf);
  9493. + for(i=0; i<8; i++)
  9494. + {
  9495. + if(data->key.pvu_csa_ks[i])
  9496. + { free_key_struct(data->key.pvu_csa_ks[i]); }
  9497. + }
  9498. + NULLFREE(data);
  9499. +
  9500. + stream_client_disconnect(conndata);
  9501. + return NULL;
  9502. +}
  9503. +
  9504. +void *stream_server(void *UNUSED(a))
  9505. +{
  9506. + struct sockaddr_in servaddr, cliaddr;
  9507. + socklen_t clilen;
  9508. + int32_t connfd, reuse = 1, i;
  9509. + int8_t connaccepted;
  9510. + emu_stream_client_conn_data *conndata;
  9511. +
  9512. + cluster_size = get_internal_parallelism();
  9513. + cs_log("[Emu] info: FFDecsa parallel mode = %d", cluster_size);
  9514. +
  9515. + if(!emu_stream_server_mutex_init)
  9516. + {
  9517. + SAFE_MUTEX_INIT(&emu_stream_server_mutex, NULL);
  9518. + emu_stream_server_mutex_init = 1;
  9519. + }
  9520. +
  9521. +#ifdef WITH_EMU
  9522. + SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
  9523. + for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
  9524. + {
  9525. + emu_stream_cur_srvid[i] = NO_SRVID_VALUE;
  9526. + stream_server_has_ecm[i] = 0;
  9527. + }
  9528. + SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
  9529. +#endif
  9530. +
  9531. + for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
  9532. + {
  9533. + gconnfd[i] = -1;
  9534. + }
  9535. +
  9536. + glistenfd = socket(AF_INET, SOCK_STREAM, 0);
  9537. + if(glistenfd == -1)
  9538. + {
  9539. + cs_log("[Emu] error: cannot create stream server socket");
  9540. + return NULL;
  9541. + }
  9542. +
  9543. + bzero(&servaddr,sizeof(servaddr));
  9544. + servaddr.sin_family = AF_INET;
  9545. + servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  9546. + servaddr.sin_port = htons(emu_stream_relay_port);
  9547. + setsockopt(glistenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
  9548. +
  9549. + if(bind(glistenfd,(struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
  9550. + {
  9551. + cs_log("[Emu] error: cannot bind to stream server socket");
  9552. + close(glistenfd);
  9553. + return NULL;
  9554. + }
  9555. +
  9556. + if(listen(glistenfd, 3) == -1)
  9557. + {
  9558. + cs_log("[Emu] error: cannot listen to stream server socket");
  9559. + close(glistenfd);
  9560. + return NULL;
  9561. + }
  9562. +
  9563. + while(!exit_oscam)
  9564. + {
  9565. + clilen = sizeof(cliaddr);
  9566. + connfd = accept(glistenfd,(struct sockaddr *)&cliaddr, &clilen);
  9567. +
  9568. + if(connfd == -1)
  9569. + {
  9570. + cs_log("[Emu] error: accept() failed");
  9571. + break;
  9572. + }
  9573. +
  9574. + connaccepted = 0;
  9575. +
  9576. + if(cs_malloc(&conndata, sizeof(emu_stream_client_conn_data)))
  9577. + {
  9578. + SAFE_MUTEX_LOCK(&emu_stream_server_mutex);
  9579. + if(gconncount < EMU_STREAM_SERVER_MAX_CONNECTIONS)
  9580. + {
  9581. + for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
  9582. + {
  9583. + if(gconnfd[i] == -1)
  9584. + {
  9585. + gconnfd[i] = connfd;
  9586. + gconncount++;
  9587. + connaccepted = 1;
  9588. +
  9589. + conndata->connfd = connfd;
  9590. + conndata->connid = i;
  9591. +
  9592. + break;
  9593. + }
  9594. + }
  9595. + }
  9596. + SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex);
  9597. + }
  9598. +
  9599. + if(connaccepted)
  9600. + {
  9601. + int on = 1;
  9602. + if (setsockopt(connfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on))<0)
  9603. + {
  9604. + cs_log("[Emu] error: stream client %i setsockopt() failed for TCP_NODELAY", conndata->connid);
  9605. + }
  9606. +
  9607. + start_thread("emu stream client", stream_client_handler, (void*)conndata, NULL, 1, 0);
  9608. + }
  9609. + else
  9610. + {
  9611. + shutdown(connfd, 2);
  9612. + close(connfd);
  9613. + cs_log("[Emu] error: stream server client dropped because of too many connections (%i)", EMU_STREAM_SERVER_MAX_CONNECTIONS);
  9614. + }
  9615. +
  9616. + cs_sleepms(20);
  9617. + }
  9618. +
  9619. + close(glistenfd);
  9620. +
  9621. + return NULL;
  9622. +}
  9623. +
  9624. +#ifdef WITH_EMU
  9625. +void *stream_key_delayer(void *UNUSED(arg))
  9626. +{
  9627. + int32_t i, j;
  9628. + emu_stream_client_key_data* cdata;
  9629. + LL_ITER it;
  9630. + emu_stream_cw_item *item;
  9631. + struct timeb t_now;
  9632. +
  9633. + while(!exit_oscam)
  9634. + {
  9635. + cs_ftime(&t_now);
  9636. +
  9637. + for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
  9638. + {
  9639. + it = ll_iter_create(ll_emu_stream_delayed_keys[i]);
  9640. + while((item = ll_iter_next(&it)))
  9641. + {
  9642. + if(comp_timeb(&t_now, &item->write_time) < 0)
  9643. + {
  9644. + break;
  9645. + }
  9646. +
  9647. + SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[i]);
  9648. +
  9649. + cdata = &emu_fixed_key_data[i];
  9650. +
  9651. + for(j=0; j<8; j++)
  9652. + {
  9653. + if(item->csa_used)
  9654. + {
  9655. + if(cdata->pvu_csa_ks[j] == NULL)
  9656. + { cdata->pvu_csa_ks[j] = get_key_struct(); }
  9657. +
  9658. + if(item->is_even)
  9659. + { set_even_control_word(cdata->pvu_csa_ks[j], item->cw[j]); }
  9660. + else
  9661. + { set_odd_control_word(cdata->pvu_csa_ks[j], item->cw[j]); }
  9662. +
  9663. + cdata->pvu_csa_used = 1;
  9664. + }
  9665. + else
  9666. + {
  9667. + if(item->is_even)
  9668. + { des_set_key(item->cw[j], cdata->pvu_des_ks[j][0]); }
  9669. + else
  9670. + { des_set_key(item->cw[j], cdata->pvu_des_ks[j][1]); }
  9671. +
  9672. + cdata->pvu_csa_used = 0;
  9673. + }
  9674. + }
  9675. +
  9676. + SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[i]);
  9677. +
  9678. + ll_iter_remove_data(&it);
  9679. + }
  9680. + }
  9681. +
  9682. + cs_sleepms(25);
  9683. + }
  9684. +
  9685. + return NULL;
  9686. +}
  9687. +#endif
  9688. +
  9689. +void stop_stream_server(void)
  9690. +{
  9691. + int32_t i;
  9692. +
  9693. + SAFE_MUTEX_LOCK(&emu_stream_server_mutex);
  9694. + for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
  9695. + {
  9696. + if(gconnfd[i] != -1)
  9697. + {
  9698. + shutdown(gconnfd[i], 2);
  9699. + close(gconnfd[i]);
  9700. + gconnfd[i] = -1;
  9701. + }
  9702. + }
  9703. +
  9704. + gconncount = 0;
  9705. + SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex);
  9706. +
  9707. + shutdown(glistenfd, 2);
  9708. + close(glistenfd);
  9709. +}
  9710. Index: module-emulator-stream.h
  9711. ===================================================================
  9712. --- module-emulator-stream.h (revision 0)
  9713. +++ module-emulator-stream.h (working copy)
  9714. @@ -0,0 +1,64 @@
  9715. +#ifndef EMU_STREAM_SERVER_H_
  9716. +#define EMU_STREAM_SERVER_H_
  9717. +
  9718. +#define EMU_STREAM_SERVER_MAX_CONNECTIONS 8
  9719. +#define EMU_STREAM_MAX_AUDIO_SUB_TRACKS 16
  9720. +
  9721. + typedef struct
  9722. + {
  9723. + uint32_t pvu_des_ks[8][2][32];
  9724. + int8_t pvu_csa_used;
  9725. + void* pvu_csa_ks[8];
  9726. + } emu_stream_client_key_data;
  9727. +
  9728. + typedef struct
  9729. + {
  9730. + int32_t connid;
  9731. + int8_t have_pat_data;
  9732. + int8_t have_pmt_data;
  9733. + int8_t have_ecm_data;
  9734. + uint8_t data[1024+208];
  9735. + uint16_t data_pos;
  9736. + uint16_t srvid;
  9737. + uint16_t pmt_pid;
  9738. + uint16_t ecm_pid;
  9739. + uint16_t emm_pid;
  9740. + uint16_t video_pid;
  9741. + uint16_t audio_pids[EMU_STREAM_MAX_AUDIO_SUB_TRACKS];
  9742. + uint8_t audio_pid_count;
  9743. + int16_t ecm_nb;
  9744. + emu_stream_client_key_data key;
  9745. + } emu_stream_client_data;
  9746. +
  9747. + extern char emu_stream_source_host[256];
  9748. + extern int32_t emu_stream_source_port;
  9749. + extern char *emu_stream_source_auth;
  9750. + extern int32_t emu_stream_relay_port;
  9751. + extern int8_t emu_stream_emm_enabled;
  9752. +
  9753. + extern int8_t stream_server_thread_init;
  9754. +
  9755. + void *stream_server(void *a);
  9756. + void stop_stream_server(void);
  9757. +
  9758. +#ifdef WITH_EMU
  9759. + typedef struct
  9760. + {
  9761. + struct timeb write_time;
  9762. + int8_t csa_used;
  9763. + int8_t is_even;
  9764. + uint8_t cw[8][8];
  9765. + } emu_stream_cw_item;
  9766. +
  9767. + extern pthread_mutex_t emu_fixed_key_srvid_mutex;
  9768. + extern uint16_t emu_stream_cur_srvid[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  9769. + extern int8_t stream_server_has_ecm[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  9770. +
  9771. + extern pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  9772. + extern emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  9773. + extern LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
  9774. +
  9775. + void *stream_key_delayer(void *arg);
  9776. +#endif
  9777. +
  9778. +#endif
  9779. Index: module-emulator.c
  9780. ===================================================================
  9781. --- module-emulator.c (revision 0)
  9782. +++ module-emulator.c (working copy)
  9783. @@ -0,0 +1,715 @@
  9784. +#include "globals.h"
  9785. +#include "oscam-string.h"
  9786. +#include "oscam-config.h"
  9787. +#include "oscam-conf-chk.h"
  9788. +#include "oscam-time.h"
  9789. +#include "module-emulator-osemu.h"
  9790. +#include "module-emulator-stream.h"
  9791. +
  9792. +// oscam virtual emu card reader
  9793. +#define CS_OK 1
  9794. +#define CS_ERROR 0
  9795. +
  9796. +static int32_t emu_do_ecm(struct s_reader *UNUSED(rdr), const struct ecm_request_t *er, struct s_ecm_answer *ea)
  9797. +{
  9798. + if (!ProcessECM(er->ecmlen, er->caid, er->prid, er->ecm, ea->cw, er->srvid, er->pid, &ea->cw_ex)) {
  9799. + return CS_OK;
  9800. + }
  9801. +
  9802. + return CS_ERROR;
  9803. +}
  9804. +
  9805. +static void refresh_entitlements(struct s_reader *reader);
  9806. +
  9807. +static int32_t emu_do_emm(struct s_reader *rdr, struct emm_packet_t *emm)
  9808. +{
  9809. + uint32_t keysAdded = 0;
  9810. +
  9811. + if(emm->emmlen < 3) {
  9812. + return CS_ERROR;
  9813. + }
  9814. +
  9815. + if(SCT_LEN(emm->emm) > emm->emmlen) {
  9816. + return CS_ERROR;
  9817. + }
  9818. +
  9819. + if(!ProcessEMM(b2i(2, emm->caid), b2i(4, emm->provid), emm->emm, &keysAdded)) {
  9820. + if(keysAdded > 0) { refresh_entitlements(rdr); }
  9821. + return CS_OK;
  9822. + }
  9823. +
  9824. + return CS_ERROR;
  9825. +}
  9826. +
  9827. +static int32_t EMU_Init(struct s_reader *reader);
  9828. +
  9829. +static int32_t emu_card_info(struct s_reader *rdr) {
  9830. + EMU_Init(rdr);
  9831. + return CS_OK;
  9832. +}
  9833. +
  9834. +static int32_t emu_card_init(struct s_reader *UNUSED(rdr), struct s_ATR *UNUSED(atr))
  9835. +{return CS_ERROR;}
  9836. +
  9837. +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))
  9838. +{return CS_ERROR;}
  9839. +
  9840. +
  9841. +int32_t emu_get_via3_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
  9842. +{
  9843. + uint32_t provid = 0;
  9844. +
  9845. + if(ep->emm[3] == 0x90 && ep->emm[4] == 0x03)
  9846. + {
  9847. + provid = b2i(3, ep->emm+5);
  9848. + provid &=0xFFFFF0;
  9849. + i2b_buf(4, provid, ep->provid);
  9850. + }
  9851. +
  9852. + switch(ep->emm[0])
  9853. + {
  9854. + case 0x88:
  9855. + ep->type = UNIQUE;
  9856. + memset(ep->hexserial, 0, 8);
  9857. + memcpy(ep->hexserial, ep->emm + 4, 4);
  9858. + rdr_log_dbg(rdr, D_EMM, "UNIQUE");
  9859. + return 1;
  9860. +
  9861. + case 0x8A:
  9862. + case 0x8B:
  9863. + ep->type = GLOBAL;
  9864. + rdr_log_dbg(rdr, D_EMM, "GLOBAL");
  9865. + return 1;
  9866. +
  9867. + case 0x8C:
  9868. + case 0x8D:
  9869. + ep->type = SHARED;
  9870. + rdr_log_dbg(rdr, D_EMM, "SHARED (part)");
  9871. + // We need those packets to pass otherwise we would never
  9872. + // be able to complete EMM reassembly
  9873. + return 1;
  9874. +
  9875. + case 0x8E:
  9876. + ep->type = SHARED;
  9877. + rdr_log_dbg(rdr, D_EMM, "SHARED");
  9878. + memset(ep->hexserial, 0, 8);
  9879. + memcpy(ep->hexserial, ep->emm + 3, 3);
  9880. + return 1;
  9881. +
  9882. + default:
  9883. + ep->type = UNKNOWN;
  9884. + rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
  9885. + return 1;
  9886. + }
  9887. +}
  9888. +
  9889. +int32_t emu_get_ird2_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
  9890. +{
  9891. + int32_t l = (ep->emm[3] & 0x07);
  9892. + int32_t base = (ep->emm[3] >> 3);
  9893. + char dumprdrserial[l * 3], dumpemmserial[l * 3];
  9894. +
  9895. + switch(l)
  9896. + {
  9897. +
  9898. + case 0:
  9899. + // global emm, 0 bytes addressed
  9900. + ep->type = GLOBAL;
  9901. + rdr_log_dbg(rdr, D_EMM, "GLOBAL base = %02x", base);
  9902. + return 1;
  9903. +
  9904. + case 2:
  9905. + // shared emm, 2 bytes addressed
  9906. + ep->type = SHARED;
  9907. + memset(ep->hexserial, 0, 8);
  9908. + memcpy(ep->hexserial, ep->emm + 4, l);
  9909. + cs_hexdump(1, rdr->hexserial, l, dumprdrserial, sizeof(dumprdrserial));
  9910. + cs_hexdump(1, ep->hexserial, l, dumpemmserial, sizeof(dumpemmserial));
  9911. + rdr_log_dbg_sensitive(rdr, D_EMM, "SHARED l = %d ep = {%s} rdr = {%s} base = %02x", l,
  9912. + dumpemmserial, dumprdrserial, base);
  9913. + return 1;
  9914. +
  9915. + case 3:
  9916. + // unique emm, 3 bytes addressed
  9917. + ep->type = UNIQUE;
  9918. + memset(ep->hexserial, 0, 8);
  9919. + memcpy(ep->hexserial, ep->emm + 4, l);
  9920. + cs_hexdump(1, rdr->hexserial, l, dumprdrserial, sizeof(dumprdrserial));
  9921. + cs_hexdump(1, ep->hexserial, l, dumpemmserial, sizeof(dumpemmserial));
  9922. + rdr_log_dbg_sensitive(rdr, D_EMM, "UNIQUE l = %d ep = {%s} rdr = {%s} base = %02x", l,
  9923. + dumpemmserial, dumprdrserial, base);
  9924. + return 1;
  9925. +
  9926. + default:
  9927. + ep->type = UNKNOWN;
  9928. + rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
  9929. + return 1;
  9930. + }
  9931. +}
  9932. +
  9933. +int32_t emu_get_pvu_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
  9934. +{
  9935. + if(ep->emm[0] == 0x82)
  9936. + {
  9937. + ep->type = UNIQUE;
  9938. + memset(ep->hexserial, 0, 8);
  9939. + memcpy(ep->hexserial, ep->emm + 12, 4);
  9940. + }
  9941. + else
  9942. + {
  9943. + ep->type = UNKNOWN;
  9944. + rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
  9945. + }
  9946. + return 1;
  9947. +}
  9948. +
  9949. +int32_t emu_get_dre2_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
  9950. +{
  9951. + if(ep->emm[0] == 0x91)
  9952. + {
  9953. + ep->type = GLOBAL;
  9954. + rdr_log_dbg(rdr, D_EMM, "GLOBAL");
  9955. + return 1;
  9956. + }
  9957. + else
  9958. + {
  9959. + switch(ep->emm[0])
  9960. + {
  9961. + case 0x86:
  9962. + ep->type = SHARED;
  9963. + memset(ep->hexserial, 0, 8);
  9964. + ep->hexserial[0] = ep->emm[3];
  9965. + return 1;;
  9966. +
  9967. + default:
  9968. + ep->type = UNKNOWN;
  9969. + return 1;
  9970. + }
  9971. + }
  9972. +}
  9973. +
  9974. +static int32_t emu_get_emm_type(struct emm_packet_t *ep, struct s_reader *rdr)
  9975. +{
  9976. + switch(b2i(2, ep->caid)>>8)
  9977. + {
  9978. + case 0x05:
  9979. + return emu_get_via3_emm_type(ep, rdr);
  9980. +
  9981. + case 0x06:
  9982. + return emu_get_ird2_emm_type(ep, rdr);
  9983. +
  9984. + case 0x0E:
  9985. + return emu_get_pvu_emm_type(ep, rdr);
  9986. +
  9987. + case 0x4A:
  9988. + return emu_get_dre2_emm_type(ep, rdr);
  9989. +
  9990. + default:
  9991. + break;
  9992. + }
  9993. +
  9994. + return CS_ERROR;
  9995. +}
  9996. +
  9997. +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))
  9998. +{
  9999. + if(*emm_filters == NULL)
  10000. + {
  10001. + const unsigned int max_filter_count = 1;
  10002. +
  10003. + if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
  10004. + { return CS_ERROR; }
  10005. +
  10006. + struct s_csystem_emm_filter *filters = *emm_filters;
  10007. + *filter_count = 0;
  10008. +
  10009. + int32_t idx = 0;
  10010. +
  10011. + filters[idx].type = EMM_GLOBAL;
  10012. + filters[idx].enabled = 1;
  10013. + filters[idx].filter[0] = 0x8A;
  10014. + filters[idx].mask[0] = 0xFE;
  10015. + filters[idx].filter[3] = 0x80;
  10016. + filters[idx].mask[3] = 0x80;
  10017. + idx++;
  10018. +
  10019. + *filter_count = idx;
  10020. + }
  10021. +
  10022. + return CS_OK;
  10023. +}
  10024. +
  10025. +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))
  10026. +{
  10027. + uint8_t hexserial[3], prid[4];
  10028. + FILTER* emu_provids;
  10029. + int8_t have_provid = 0, have_serial = 0;
  10030. + int32_t i;
  10031. +
  10032. + if(GetIrdeto2Hexserial(caid, hexserial))
  10033. + { have_serial = 1; }
  10034. +
  10035. + emu_provids = get_emu_prids_for_caid(rdr, caid);
  10036. + if(emu_provids != NULL && emu_provids->nprids > 0)
  10037. + { have_provid = 1;}
  10038. +
  10039. + if(*emm_filters == NULL)
  10040. + {
  10041. + const unsigned int max_filter_count = have_serial + (2*(have_provid ? emu_provids->nprids : 0));
  10042. + if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
  10043. + { return CS_ERROR; }
  10044. +
  10045. + struct s_csystem_emm_filter *filters = *emm_filters;
  10046. + *filter_count = 0;
  10047. +
  10048. + unsigned int idx = 0;
  10049. +
  10050. + if(have_serial)
  10051. + {
  10052. + filters[idx].type = EMM_UNIQUE;
  10053. + filters[idx].enabled = 1;
  10054. + filters[idx].filter[0] = 0x82;
  10055. + filters[idx].mask[0] = 0xFF;
  10056. + filters[idx].filter[1] = 0xFB;
  10057. + filters[idx].mask[1] = 0x07;
  10058. + memcpy(&filters[idx].filter[2], hexserial, 3);
  10059. + memset(&filters[idx].mask[2], 0xFF, 3);
  10060. + idx++;
  10061. + }
  10062. +
  10063. + for(i=0; have_provid && i<emu_provids->nprids; i++)
  10064. + {
  10065. + i2b_buf(4, emu_provids->prids[i], prid);
  10066. +
  10067. + filters[idx].type = EMM_UNIQUE;
  10068. + filters[idx].enabled = 1;
  10069. + filters[idx].filter[0] = 0x82;
  10070. + filters[idx].mask[0] = 0xFF;
  10071. + filters[idx].filter[1] = 0xFB;
  10072. + filters[idx].mask[1] = 0x07;
  10073. + memcpy(&filters[idx].filter[2], &prid[1], 3);
  10074. + memset(&filters[idx].mask[2], 0xFF, 3);
  10075. + idx++;
  10076. +
  10077. + filters[idx].type = EMM_SHARED;
  10078. + filters[idx].enabled = 1;
  10079. + filters[idx].filter[0] = 0x82;
  10080. + filters[idx].mask[0] = 0xFF;
  10081. + filters[idx].filter[1] = 0xFA;
  10082. + filters[idx].mask[1] = 0x07;
  10083. + memcpy(&filters[idx].filter[2], &prid[1], 2);
  10084. + memset(&filters[idx].mask[2], 0xFF, 2);
  10085. + idx++;
  10086. + }
  10087. +
  10088. + *filter_count = idx;
  10089. + }
  10090. +
  10091. + return CS_OK;
  10092. +}
  10093. +
  10094. +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)
  10095. +{
  10096. + uint8_t hexserials[16][4];
  10097. + int32_t i, count = 0;
  10098. +
  10099. + if(!GetPowervuHexserials(srvid, hexserials, 16, &count))
  10100. + { return CS_ERROR; }
  10101. +
  10102. + if(*emm_filters == NULL)
  10103. + {
  10104. + const unsigned int max_filter_count = count;
  10105. + if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
  10106. + { return CS_ERROR; }
  10107. +
  10108. + struct s_csystem_emm_filter *filters = *emm_filters;
  10109. + *filter_count = 0;
  10110. +
  10111. + int32_t idx = 0;
  10112. +
  10113. + for(i=0; i<count; i++)
  10114. + {
  10115. + filters[idx].type = EMM_UNIQUE;
  10116. + filters[idx].enabled = 1;
  10117. + filters[idx].filter[0] = 0x82;
  10118. + filters[idx].filter[10] = hexserials[i][0];
  10119. + filters[idx].filter[11] = hexserials[i][1];
  10120. + filters[idx].filter[12] = hexserials[i][2];
  10121. + filters[idx].filter[13] = hexserials[i][3];
  10122. + filters[idx].mask[0] = 0xFF;
  10123. + filters[idx].mask[10] = 0xFF;
  10124. + filters[idx].mask[11] = 0xFF;
  10125. + filters[idx].mask[12] = 0xFF;
  10126. + filters[idx].mask[13] = 0xFF;
  10127. + idx++;
  10128. + }
  10129. +
  10130. + *filter_count = idx;
  10131. + }
  10132. +
  10133. + return CS_OK;
  10134. +}
  10135. +
  10136. +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 UNUSED(provid))
  10137. +{
  10138. + uint8_t hexserials[8];
  10139. + int32_t i, count = 0;
  10140. +
  10141. + if(!GetDrecryptHexserials(caid, hexserials, 8, &count))
  10142. + { count = 0; }
  10143. +
  10144. + if(*emm_filters == NULL)
  10145. + {
  10146. + const unsigned int max_filter_count = 1 + count;
  10147. + if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
  10148. + { return CS_ERROR; }
  10149. +
  10150. + struct s_csystem_emm_filter *filters = *emm_filters;
  10151. + *filter_count = 0;
  10152. +
  10153. + int32_t idx = 0;
  10154. +
  10155. + filters[idx].type = EMM_GLOBAL;
  10156. + filters[idx].enabled = 1;
  10157. + filters[idx].filter[0] = 0x91;
  10158. + filters[idx].mask[0] = 0xFF;
  10159. + idx++;
  10160. +
  10161. + for(i=0; i<count; i++)
  10162. + {
  10163. + filters[idx].type = EMM_SHARED;
  10164. + filters[idx].enabled = 1;
  10165. + filters[idx].filter[0] = 0x86;
  10166. + filters[idx].filter[1] = hexserials[i];
  10167. + filters[idx].mask[0] = 0xFF;
  10168. + filters[idx].mask[1] = 0xFF;
  10169. + idx++;
  10170. + }
  10171. +
  10172. + *filter_count = idx;
  10173. + }
  10174. +
  10175. + return CS_OK;
  10176. +}
  10177. +
  10178. +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)
  10179. +{
  10180. + switch(caid>>8)
  10181. + {
  10182. + case 0x05:
  10183. + return emu_get_via3_emm_filter(rdr, emm_filters, filter_count, caid, provid);
  10184. +
  10185. + case 0x06:
  10186. + return emu_get_ird2_emm_filter(rdr, emm_filters, filter_count, caid, provid);
  10187. +
  10188. + case 0x0E:
  10189. + return emu_get_pvu_emm_filter(rdr, emm_filters, filter_count, caid, provid, srvid);
  10190. +
  10191. + case 0x4A:
  10192. + return emu_get_dre2_emm_filter(rdr, emm_filters, filter_count, caid, provid);
  10193. +
  10194. + default:
  10195. + break;
  10196. + }
  10197. +
  10198. + return CS_ERROR;
  10199. +}
  10200. +
  10201. +const struct s_cardsystem reader_emu =
  10202. +{
  10203. + .desc = "emu",
  10204. + .caids = (uint16_t[]){ 0x0D, 0x09, 0x0500, 0x18, 0x06, 0x26, 0xFFFF, 0x0E, 0x4A, 0 },
  10205. + .do_ecm = emu_do_ecm,
  10206. + .do_emm = emu_do_emm,
  10207. + .card_info = emu_card_info,
  10208. + .card_init = emu_card_init,
  10209. + .get_emm_type = emu_get_emm_type,
  10210. + .get_emm_filter = emu_get_emm_filter, //needed to pass checks
  10211. + .get_emm_filter_adv = emu_get_emm_filter_adv,
  10212. +};
  10213. +
  10214. +
  10215. +#define CR_OK 0
  10216. +#define CR_ERROR 1
  10217. +
  10218. +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)
  10219. +{
  10220. + if(!rdr->ll_entitlements) { rdr->ll_entitlements = ll_create("ll_entitlements"); }
  10221. +
  10222. + S_ENTITLEMENT *item;
  10223. + if(cs_malloc(&item, sizeof(S_ENTITLEMENT)))
  10224. + {
  10225. +
  10226. + // fill item
  10227. + item->caid = caid;
  10228. + item->provid = provid;
  10229. + item->id = 0;
  10230. + item->class = 0;
  10231. + item->start = 0;
  10232. + item->end = 2147472000;
  10233. + item->type = 0;
  10234. + item->isKey = 1;
  10235. + memcpy(item->name, keyName, 8);
  10236. + item->key = key;
  10237. + item->keyLength = keyLength;
  10238. + item->isData = isData;
  10239. +
  10240. + //add item
  10241. + ll_append(rdr->ll_entitlements, item);
  10242. + }
  10243. +}
  10244. +
  10245. +static uint8_t oneByte = 0x01;
  10246. +
  10247. +static void refresh_entitlements(struct s_reader *reader)
  10248. +{
  10249. + uint32_t i;
  10250. + KeyData *tmpKeyData;
  10251. +
  10252. + if(reader->ll_entitlements)
  10253. + { ll_clear_data(reader->ll_entitlements); }
  10254. +
  10255. + for(i=0; i<CwKeys.keyCount; i++)
  10256. + emu_add_entitlement(reader, CwKeys.EmuKeys[i].provider>>8, CwKeys.EmuKeys[i].provider&0xFF,
  10257. + CwKeys.EmuKeys[i].key, CwKeys.EmuKeys[i].keyName, CwKeys.EmuKeys[i].keyLength, 0);
  10258. +
  10259. + for(i=0; i<ViKeys.keyCount; i++)
  10260. + emu_add_entitlement(reader, 0x500, ViKeys.EmuKeys[i].provider, ViKeys.EmuKeys[i].key, ViKeys.EmuKeys[i].keyName,
  10261. + ViKeys.EmuKeys[i].keyLength, 0);
  10262. +
  10263. + for(i=0; i<NagraKeys.keyCount; i++)
  10264. + emu_add_entitlement(reader, 0x1801, NagraKeys.EmuKeys[i].provider, NagraKeys.EmuKeys[i].key, NagraKeys.EmuKeys[i].keyName,
  10265. + NagraKeys.EmuKeys[i].keyLength, 0);
  10266. +
  10267. + for(i=0; i<IrdetoKeys.keyCount; i++) {
  10268. + tmpKeyData = &IrdetoKeys.EmuKeys[i];
  10269. + do {
  10270. + emu_add_entitlement(reader, tmpKeyData->provider>>8, tmpKeyData->provider&0xFF, tmpKeyData->key, tmpKeyData->keyName, tmpKeyData->keyLength, 0);
  10271. + tmpKeyData = tmpKeyData->nextKey;
  10272. + }
  10273. + while(tmpKeyData!= NULL);
  10274. + }
  10275. +
  10276. + for(i=0; i<NDSKeys.keyCount; i++)
  10277. + { emu_add_entitlement(reader, NDSKeys.EmuKeys[i].provider, 0, NDSKeys.EmuKeys[i].key, NDSKeys.EmuKeys[i].keyName, NDSKeys.EmuKeys[i].keyLength, 0); }
  10278. +
  10279. + emu_add_entitlement(reader, 0x090F, 0, viasat_const, "00", 64, 1);
  10280. + emu_add_entitlement(reader, 0x093E, 0, viasat_const, "00", 64, 1);
  10281. +
  10282. + for(i=0; i<BissKeys.keyCount; i++)
  10283. + { emu_add_entitlement(reader, 0x2600, BissKeys.EmuKeys[i].provider, BissKeys.EmuKeys[i].key, BissKeys.EmuKeys[i].keyName, BissKeys.EmuKeys[i].keyLength, 0); }
  10284. +
  10285. + emu_add_entitlement(reader, 0xFFFF, 0, &oneByte, "00", 1, 1);
  10286. +
  10287. + for(i=0; i<PowervuKeys.keyCount; i++)
  10288. + emu_add_entitlement(reader, 0x0E00, PowervuKeys.EmuKeys[i].provider, PowervuKeys.EmuKeys[i].key, PowervuKeys.EmuKeys[i].keyName,
  10289. + PowervuKeys.EmuKeys[i].keyLength, 0);
  10290. +
  10291. + for(i=0; i<DreKeys.keyCount; i++)
  10292. + emu_add_entitlement(reader, 0x4AE1, DreKeys.EmuKeys[i].provider, DreKeys.EmuKeys[i].key, DreKeys.EmuKeys[i].keyName,
  10293. + DreKeys.EmuKeys[i].keyLength, 0);
  10294. +}
  10295. +
  10296. +extern char cs_confdir[128];
  10297. +
  10298. +static void set_hexserial_to_version(struct s_reader *rdr)
  10299. +{
  10300. + char cVersion[32];
  10301. +
  10302. + uint32_t version = GetOSemuVersion();
  10303. + uint8_t hversion[2];
  10304. + memset(hversion, 0, 2);
  10305. + snprintf(cVersion, sizeof(cVersion), "%04d", version);
  10306. + CharToBin(hversion, cVersion, 4);
  10307. + rdr->hexserial[3] = hversion[0];
  10308. + rdr->hexserial[4] = hversion[1];
  10309. +}
  10310. +
  10311. +static void set_prids(struct s_reader *rdr)
  10312. +{
  10313. + int32_t i, j;
  10314. +
  10315. + rdr->nprov = 0;
  10316. +
  10317. + for(i = 0; (i < rdr->emu_auproviders.nfilts) && (rdr->nprov < CS_MAXPROV); i++)
  10318. + {
  10319. + for(j = 0; (j < rdr->emu_auproviders.filts[i].nprids) && (rdr->nprov < CS_MAXPROV); j++)
  10320. + {
  10321. + i2b_buf(4, rdr->emu_auproviders.filts[i].prids[j], rdr->prid[i]);
  10322. + rdr->nprov++;
  10323. + }
  10324. + }
  10325. +}
  10326. +
  10327. +FILTER* get_emu_prids_for_caid(struct s_reader *rdr, uint16_t caid)
  10328. +{
  10329. + int32_t i;
  10330. +
  10331. + for(i = 0; i < rdr->emu_auproviders.nfilts; i++)
  10332. + {
  10333. + if(caid == rdr->emu_auproviders.filts[i].caid)
  10334. + {
  10335. + return &rdr->emu_auproviders.filts[i];
  10336. + }
  10337. + }
  10338. +
  10339. + return NULL;
  10340. +}
  10341. +
  10342. +static int32_t EMU_Init(struct s_reader *reader)
  10343. +{
  10344. + int32_t i;
  10345. + char authtmp[128];
  10346. +
  10347. + if(stream_server_thread_init == 0)
  10348. + {
  10349. + stream_server_thread_init = 1;
  10350. +
  10351. + SAFE_MUTEX_INIT(&emu_fixed_key_srvid_mutex, NULL);
  10352. +
  10353. + for(i=0; i<EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
  10354. + {
  10355. + SAFE_MUTEX_INIT(&emu_fixed_key_data_mutex[i], NULL);
  10356. + ll_emu_stream_delayed_keys[i] = ll_create("ll_emu_stream_delayed_keys");
  10357. + memset(&emu_fixed_key_data[i], 0, sizeof(emu_stream_client_key_data));
  10358. + }
  10359. +
  10360. + start_thread("stream_key_delayer", stream_key_delayer, NULL, NULL, 1, 1);
  10361. +
  10362. + cs_strncpy(emu_stream_source_host, cfg.emu_stream_source_host, sizeof(emu_stream_source_host));
  10363. + emu_stream_source_port = cfg.emu_stream_source_port;
  10364. + emu_stream_relay_port = cfg.emu_stream_relay_port;
  10365. + emu_stream_emm_enabled = cfg.emu_stream_emm_enabled;
  10366. +
  10367. + if(cfg.emu_stream_source_auth_user && cfg.emu_stream_source_auth_password)
  10368. + {
  10369. + snprintf(authtmp, sizeof(authtmp), "%s:%s", cfg.emu_stream_source_auth_user, cfg.emu_stream_source_auth_password);
  10370. + b64encode(authtmp, strlen(authtmp), &emu_stream_source_auth);
  10371. + }
  10372. + else
  10373. + {
  10374. + NULLFREE(emu_stream_source_auth);
  10375. + }
  10376. +
  10377. + start_thread("stream_server", stream_server, NULL, NULL, 1, 1);
  10378. + }
  10379. +
  10380. + set_hexserial_to_version(reader);
  10381. +
  10382. +#if !defined(__APPLE__) && !defined(__ANDROID__)
  10383. + read_emu_keymemory();
  10384. +#endif
  10385. +
  10386. + set_emu_keyfile_path(cs_confdir);
  10387. +
  10388. + if(!read_emu_keyfile(cs_confdir)) {
  10389. + read_emu_keyfile("/var/keys/");
  10390. + }
  10391. +
  10392. + refresh_entitlements(reader);
  10393. +
  10394. + set_prids(reader);
  10395. +
  10396. + return CR_OK;
  10397. +}
  10398. +
  10399. +static int32_t EMU_GetStatus(struct s_reader *UNUSED(reader), int32_t *in) { *in = 1; return CR_OK; }
  10400. +static int32_t EMU_Activate(struct s_reader *UNUSED(reader), struct s_ATR *UNUSED(atr)) { return CR_OK; }
  10401. +static int32_t EMU_Transmit(struct s_reader *UNUSED(reader), uint8_t *UNUSED(buffer), uint32_t UNUSED(size),
  10402. + uint32_t UNUSED(expectedlen), uint32_t UNUSED(delay), uint32_t UNUSED(timeout)) { return CR_OK; }
  10403. +static int32_t EMU_Receive(struct s_reader *UNUSED(reader), uint8_t *UNUSED(buffer), uint32_t UNUSED(size),
  10404. + uint32_t UNUSED(delay), uint32_t UNUSED(timeout)) { return CR_OK; }
  10405. +static int32_t EMU_Close(struct s_reader *UNUSED(reader)) { return CR_OK; }
  10406. +static int32_t EMU_write_settings(struct s_reader *UNUSED(reader), struct s_cardreader_settings *UNUSED(s)) { return CR_OK; }
  10407. +static int32_t EMU_card_write(struct s_reader *UNUSED(pcsc_reader),const uchar *UNUSED(buf) ,uint8_t *UNUSED(cta_res),
  10408. + uint16_t *UNUSED(cta_lr),int32_t UNUSED(l)) { return CR_OK; }
  10409. +static int32_t EMU_set_protocol(struct s_reader *UNUSED(rdr),uint8_t *UNUSED(params),uint32_t *UNUSED(length),
  10410. + uint32_t UNUSED(len_request)) { return CR_OK; }
  10411. +
  10412. +const struct s_cardreader cardreader_emu =
  10413. +{
  10414. + .desc = "emu",
  10415. + .typ = R_EMU,
  10416. + .skip_extra_atr_parsing = 1,
  10417. + .reader_init = EMU_Init,
  10418. + .get_status = EMU_GetStatus,
  10419. + .activate = EMU_Activate,
  10420. + .transmit = EMU_Transmit,
  10421. + .receive = EMU_Receive,
  10422. + .close = EMU_Close,
  10423. + .write_settings = EMU_write_settings,
  10424. + .card_write = EMU_card_write,
  10425. + .set_protocol = EMU_set_protocol,
  10426. +};
  10427. +
  10428. +void add_emu_reader(void)
  10429. +{
  10430. + LL_ITER itr;
  10431. + struct s_reader *rdr;
  10432. + int8_t haveEmuReader = 0;
  10433. + char *emuName = "emulator";
  10434. + char *ctab, *ftab, *emu_auproviders;
  10435. +
  10436. + itr = ll_iter_create(configured_readers);
  10437. + while((rdr = ll_iter_next(&itr)))
  10438. + {
  10439. + if(rdr->typ == R_EMU) {
  10440. + haveEmuReader = 1;
  10441. + break;
  10442. + }
  10443. + }
  10444. +
  10445. + rdr = NULL;
  10446. +
  10447. + if(!haveEmuReader) {
  10448. + if(!cs_malloc(&rdr, sizeof(struct s_reader))) { return; }
  10449. + reader_set_defaults(rdr);
  10450. +
  10451. + rdr->enable = 1;
  10452. + rdr->typ = R_EMU;
  10453. + strncpy(rdr->label, emuName, strlen(emuName));
  10454. + strncpy(rdr->device, emuName, strlen(emuName));
  10455. +
  10456. + ctab = strdup("0D00,0D02,090F,0500,1801,0604,2600,FFFF,0E00,4AE1");
  10457. + chk_caidtab(ctab, &rdr->ctab);
  10458. + NULLFREE(ctab);
  10459. +
  10460. + ftab = strdup( "0D00:000000,000004,000010,000014,000020,0000C0,0000C4,0000C8,0000CC;"
  10461. + "0D02:000000,00008C,0000A0,0000A4,0000A8;"
  10462. + "090F:000000;"
  10463. + "0500:000000,030B00,023800,021110,007400,007800;"
  10464. + "1801:000000,007301,001101;"
  10465. + "0604:000000;"
  10466. + "2600:000000;"
  10467. + "FFFF:000000;"
  10468. + "0E00:000000;"
  10469. + "4AE1:000011,000014,0000FE;" );
  10470. +
  10471. + chk_ftab(ftab, &rdr->ftab);
  10472. + NULLFREE(ftab);
  10473. +
  10474. + emu_auproviders = strdup("0500:030B00;0604:010200;0E00:000000;4AE1:000011,000014,0000FE;");
  10475. + chk_ftab(emu_auproviders, &rdr->emu_auproviders);
  10476. + NULLFREE(emu_auproviders);
  10477. +
  10478. + rdr->cachemm = 2;
  10479. + rdr->rewritemm = 1;
  10480. + rdr->logemm = 2;
  10481. + rdr->deviceemm = 1;
  10482. +
  10483. + rdr->grp = 0x1ULL;
  10484. +
  10485. + rdr->crdr = &cardreader_emu;
  10486. +
  10487. + reader_fixups_fn(rdr);
  10488. + ll_append(configured_readers, rdr);
  10489. + }
  10490. +
  10491. +#ifdef HAVE_DVBAPI
  10492. + if(cfg.dvbapi_enabled && cfg.dvbapi_delayer < 60) {
  10493. + cfg.dvbapi_delayer = 60;
  10494. + }
  10495. +#endif
  10496. +
  10497. + cs_log("[Emu] oscam-emu version %d", GetOSemuVersion());
  10498. +}
  10499. Index: module-newcamd-des.c
  10500. ===================================================================
  10501. --- module-newcamd-des.c (revision 11209)
  10502. +++ module-newcamd-des.c (working copy)
  10503. @@ -5,10 +5,7 @@
  10504. #define DES_IP 1
  10505. #define DES_IP_1 2
  10506. #define DES_RIGHT 4
  10507. -#define DES_HASH 8
  10508.  
  10509. -#define DES_ECM_CRYPT 0
  10510. -#define DES_ECM_HASH DES_HASH
  10511. #define DES_ECS2_DECRYPT (DES_IP | DES_IP_1 | DES_RIGHT)
  10512. #define DES_ECS2_CRYPT (DES_IP | DES_IP_1)
  10513.  
  10514. @@ -356,7 +353,7 @@
  10515. swap(data - 4, data);
  10516. }
  10517.  
  10518. -static void nc_des(unsigned char key[], unsigned char mode, unsigned char data[])
  10519. +void nc_des(unsigned char key[], unsigned char mode, unsigned char data[])
  10520. {
  10521. unsigned char i;
  10522. unsigned char left[8];
  10523. Index: module-newcamd-des.h
  10524. ===================================================================
  10525. --- module-newcamd-des.h (revision 11209)
  10526. +++ module-newcamd-des.h (working copy)
  10527. @@ -1,8 +1,15 @@
  10528. #ifndef MODULE_NEWCAMD_DES_H_
  10529. #define MODULE_NEWCAMD_DES_H_
  10530.  
  10531. +#define DES_HASH 8
  10532. +
  10533. +#define DES_ECM_CRYPT 0
  10534. +#define DES_ECM_HASH DES_HASH
  10535. +
  10536. int nc_des_encrypt(unsigned char *buffer, int len, unsigned char *deskey);
  10537. int nc_des_decrypt(unsigned char *buffer, int len, unsigned char *deskey);
  10538. unsigned char *nc_des_login_key_get(unsigned char *key1, unsigned char *key2, int len, unsigned char *des16);
  10539.  
  10540. + void nc_des(unsigned char key[], unsigned char mode, unsigned char data[]);
  10541. +
  10542. #endif
  10543. Index: module-stat.c
  10544. ===================================================================
  10545. --- module-stat.c (revision 11209)
  10546. +++ module-stat.c (working copy)
  10547. @@ -886,7 +886,7 @@
  10548.  
  10549. uint16_t get_rdr_caid(struct s_reader *rdr)
  10550. {
  10551. - if(is_network_reader(rdr))
  10552. + if(is_network_reader(rdr) || rdr->typ == R_EMU)
  10553. {
  10554. return 0; //reader caid is not real caid
  10555. }
  10556. @@ -1284,7 +1284,7 @@
  10557. for(ea = er->matching_rdr; ea; ea = ea->next)
  10558. {
  10559. rdr = ea->reader;
  10560. - if(is_network_reader(rdr)) //reader caid is not real caid
  10561. + if(is_network_reader(rdr) || rdr->typ == R_EMU) //reader caid is not real caid
  10562. {
  10563. prv = ea;
  10564. continue; // proxy can convert or reject
  10565. Index: module-webif-tpl.c
  10566. ===================================================================
  10567. --- module-webif-tpl.c (revision 11209)
  10568. +++ module-webif-tpl.c (working copy)
  10569. @@ -456,6 +456,7 @@
  10570. check_conf(WITH_SSL, ptr2);
  10571. check_conf(WITH_STAPI, ptr2);
  10572. check_conf(WITH_STAPI5, ptr2);
  10573. + check_conf(WITH_EMU, ptr2);
  10574. } // for
  10575. if(ok == 0)
  10576. {
  10577. Index: module-webif.c
  10578. ===================================================================
  10579. --- module-webif.c (revision 11209)
  10580. +++ module-webif.c (working copy)
  10581. @@ -98,6 +98,7 @@
  10582. #define MNU_CFG_LCD 14
  10583. #define MNU_CFG_MONITOR 15
  10584. #define MNU_CFG_WEBIF 16
  10585. +#define MNU_CFG_STREAMRELAY 17
  10586.  
  10587. /* constants for files.html submenuactivating */
  10588. #define MNU_CFG_FVERSION 0
  10589. @@ -119,8 +120,9 @@
  10590. #define MNU_CFG_FCSS 16
  10591. #define MNU_CFG_FTWIN 17
  10592. #define MNU_CFG_FKEYCW 18
  10593. +#define MNU_CFG_FSOFTCAMKEY 19
  10594.  
  10595. -#define MNU_CFG_TOTAL_ITEMS 19 // sum of config or files submenuactivating above. Use it for "All inactive" in function calls too.
  10596. +#define MNU_CFG_TOTAL_ITEMS 20 // sum of config or files submenuactivating above. Use it for "All inactive" in function calls too.
  10597.  
  10598. static void set_status_info_var(struct templatevars *vars, char *varname, int no_data, char *fmt, double value) {
  10599. if (no_data)
  10600. @@ -942,6 +944,34 @@
  10601. }
  10602. #endif
  10603.  
  10604. +#ifdef WITH_EMU
  10605. +#include "module-emulator-stream.h"
  10606. +
  10607. +static char *send_oscam_config_streamrelay(struct templatevars *vars, struct uriparams *params)
  10608. +{
  10609. + setActiveSubMenu(vars, MNU_CFG_STREAMRELAY);
  10610. +
  10611. + webif_save_config("streamrelay", vars, params);
  10612. +
  10613. + tpl_printf(vars, TPLADD, "STREAM_SOURCE_HOST", "%s", cfg.emu_stream_source_host);
  10614. + tpl_printf(vars, TPLADD, "STREAM_SOURCE_PORT", "%d", cfg.emu_stream_source_port);
  10615. + if(cfg.emu_stream_source_auth_user)
  10616. + { tpl_printf(vars, TPLADD, "STREAM_SOURCE_AUTH_USER", "%s", cfg.emu_stream_source_auth_user); }
  10617. + if(cfg.emu_stream_source_auth_password)
  10618. + { tpl_printf(vars, TPLADD, "STREAM_SOURCE_AUTH_PASSWORD", "%s", cfg.emu_stream_source_auth_password); }
  10619. + tpl_printf(vars, TPLADD, "STREAM_RELAY_PORT", "%d", cfg.emu_stream_relay_port);
  10620. + tpl_printf(vars, TPLADD, "STREAM_ECM_DELAY", "%d", cfg.emu_stream_ecm_delay);
  10621. +
  10622. + tpl_printf(vars, TPLADD, "TMP", "STREAMRELAYENABLEDSELECTED%d", cfg.emu_stream_relay_enabled);
  10623. + tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
  10624. +
  10625. + tpl_printf(vars, TPLADD, "TMP", "STREAMEMMENABLEDSELECTED%d", cfg.emu_stream_emm_enabled);
  10626. + tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
  10627. +
  10628. + return tpl_getTpl(vars, "CONFIGSTREAMRELAY");
  10629. +}
  10630. +#endif
  10631. +
  10632. #ifdef MODULE_CCCAM
  10633. static char *send_oscam_config_cccam(struct templatevars *vars, struct uriparams *params)
  10634. {
  10635. @@ -1355,6 +1385,9 @@
  10636. #ifdef MODULE_SCAM
  10637. else if(!strcmp(part, "scam")) { return send_oscam_config_scam(vars, params); }
  10638. #endif
  10639. +#ifdef WITH_EMU
  10640. + else if(!strcmp(part, "streamrelay")) { return send_oscam_config_streamrelay(vars, params); }
  10641. +#endif
  10642. #ifdef MODULE_CCCAM
  10643. else if(!strcmp(part, "cccam")) { return send_oscam_config_cccam(vars, params); }
  10644. #endif
  10645. @@ -1793,7 +1826,7 @@
  10646. chk_reader("services", servicelabels, rdr);
  10647. chk_reader("lb_whitelist_services", servicelabelslb, rdr);
  10648.  
  10649. - if(is_network_reader(rdr)) //physical readers make trouble if re-started
  10650. + if(is_network_reader(rdr) || rdr->typ == R_EMU) //physical readers make trouble if re-started
  10651. {
  10652. restart_cardreader(rdr, 1);
  10653. }
  10654. @@ -2350,6 +2383,13 @@
  10655. tpl_printf(vars, TPLADD, "GBOXRESHARE", "%d", rdr->gbox_reshare);
  10656. #endif
  10657.  
  10658. +#ifdef WITH_EMU
  10659. + //emu_auproviders
  10660. + value = mk_t_ftab(&rdr->emu_auproviders);
  10661. + tpl_addVar(vars, TPLADD, "EMUAUPROVIDERS", value);
  10662. + free_mk_t(value);
  10663. +#endif
  10664. +
  10665. tpl_addVar(vars, TPLADD, "PROTOCOL", reader_get_type_desc(rdr, 0));
  10666.  
  10667. // Show only parameters which needed for the reader
  10668. @@ -2370,6 +2410,9 @@
  10669. case R_CAMD35 :
  10670. tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCAMD35BIT"));
  10671. break;
  10672. + case R_EMU :
  10673. + tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGEMUBIT"));
  10674. + break;
  10675. case R_CS378X :
  10676. tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCS378XBIT"));
  10677. break;
  10678. @@ -4047,9 +4090,38 @@
  10679.  
  10680. tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", "<BR><BR>New Structure:<BR>");
  10681. char tbuffer[83];
  10682. +#ifdef WITH_EMU
  10683. + char keyBuffer[1024];
  10684. +#endif
  10685. int jsondelimiter = 0;
  10686. while((item = ll_iter_next(&itr)))
  10687. {
  10688. +#ifdef WITH_EMU
  10689. + if(item->isKey) {
  10690. + tpl_addVar(vars, TPLADD, "ENTSTARTDATE", "");
  10691. + tpl_addVar(vars, TPLADD, "ENTENDDATE", "");
  10692. + cs_hexdump(0, item->key, item->keyLength, keyBuffer, sizeof(keyBuffer));
  10693. + tpl_addVar(vars, TPLADD, "ENTEXPIERED", "e_valid");
  10694. + tpl_printf(vars, TPLADD, "ENTCAID", "%04X", item->caid);
  10695. + if(item->caid == 0x2600) {
  10696. + tpl_printf(vars, TPLADD, "ENTPROVID", "%08X", item->provid);
  10697. + }
  10698. + else {
  10699. + tpl_printf(vars, TPLADD, "ENTPROVID", "%06X", item->provid);
  10700. + }
  10701. + tpl_addVar(vars, TPLADD, "ENTID", item->name);
  10702. + tpl_addVar(vars, TPLADD, "ENTCLASS", keyBuffer);
  10703. + if(item->isData) { tpl_addVar(vars, TPLADD, "ENTTYPE", "data"); }
  10704. + else { tpl_addVar(vars, TPLADD, "ENTTYPE", "key"); }
  10705. + tpl_addVar(vars, TPLADD, "ENTRESNAME", "");
  10706. +
  10707. + if((strcmp(getParam(params, "hideexpired"), "1") != 0) || (item->end > now))
  10708. + { tpl_addVar(vars, TPLAPPEND, "READERENTENTRY", tpl_getTpl(vars, "ENTITLEMENTITEMBIT")); }
  10709. +
  10710. + continue;
  10711. + }
  10712. +#endif
  10713. +
  10714. localtime_r(&item->start, &start_t);
  10715. localtime_r(&item->end, &end_t);
  10716.  
  10717. @@ -4516,6 +4588,9 @@
  10718. #else
  10719. filtered = (type == cl->typ);
  10720. #endif
  10721. +#ifdef WITH_EMU
  10722. + if(type == 'e' && cl->typ == 'r' && cl->reader->typ == R_EMU) filtered = 1;
  10723. +#endif
  10724. }
  10725. }
  10726.  
  10727. @@ -5923,6 +5998,9 @@
  10728. #ifdef MODULE_CONSTCW
  10729. { "constant.cw", MNU_CFG_FKEYCW, FTYPE_CONFIG }, // id 18
  10730. #endif
  10731. +#ifdef WITH_EMU
  10732. + { "SoftCam.Key", MNU_CFG_FSOFTCAMKEY,FTYPE_CONFIG }, // id 19
  10733. +#endif
  10734. { NULL, 0, 0 },
  10735. };
  10736.  
  10737. @@ -6388,7 +6466,7 @@
  10738. else if(!proxy && rdr->csystem_active) // local active reader
  10739. {
  10740. csystem = rdr->csystem;
  10741. - caid = rdr->caid;
  10742. + if(rdr->typ != R_EMU) caid = rdr->caid;
  10743. }
  10744.  
  10745. if(csystem)
  10746. @@ -7393,8 +7471,8 @@
  10747. memcpy(*result + bufsize, buf2, n);
  10748. bufsize += n;
  10749.  
  10750. - //max request size 100kb
  10751. - if(bufsize > 102400)
  10752. + //max request size 200kb
  10753. + if(bufsize > 204800)
  10754. {
  10755. cs_log("error: too much data received from %s", cs_inet_ntoa(in));
  10756. NULLFREE(*result);
  10757. Index: oscam-chk.c
  10758. ===================================================================
  10759. --- oscam-chk.c (revision 11209)
  10760. +++ oscam-chk.c (working copy)
  10761. @@ -706,7 +706,7 @@
  10762. return 0;
  10763. }
  10764.  
  10765. - if(!is_network_reader(rdr) && ((rdr->caid >> 8) != ((er->caid >> 8) & 0xFF) && (rdr->caid >> 8) != ((er->ocaid >> 8) & 0xFF)))
  10766. + if(!(rdr->typ == R_EMU) && !is_network_reader(rdr) && ((rdr->caid >> 8) != ((er->caid >> 8) & 0xFF) && (rdr->caid >> 8) != ((er->ocaid >> 8) & 0xFF)))
  10767. {
  10768. if (!rdr->csystem)
  10769. return 0;
  10770. @@ -742,7 +742,7 @@
  10771. }
  10772.  
  10773. //Checking ident:
  10774. - if(!chk_rfilter(er, rdr))
  10775. + if(!(rdr->typ == R_EMU && (er->caid>>8 == 0x26 || er->caid == 0xFFFF)) && !chk_rfilter(er, rdr))
  10776. {
  10777. cs_log_dbg(D_TRACE, "r-filter reader %s", rdr->label);
  10778. return (0);
  10779. @@ -977,7 +977,7 @@
  10780.  
  10781. int32_t chk_caid_rdr(struct s_reader *rdr, uint16_t caid)
  10782. {
  10783. - if(is_network_reader(rdr))
  10784. + if(is_network_reader(rdr) || rdr->typ == R_EMU)
  10785. {
  10786. return 1; //reader caid is not real caid
  10787. }
  10788. Index: oscam-config-global.c
  10789. ===================================================================
  10790. --- oscam-config-global.c (revision 11209)
  10791. +++ oscam-config-global.c (working copy)
  10792. @@ -803,6 +803,30 @@
  10793. #else
  10794. static const struct config_list scam_opts[] = { DEF_LAST_OPT };
  10795. #endif
  10796. +
  10797. +#ifdef WITH_EMU
  10798. +static bool streamrelay_should_save_fn(void *UNUSED(var))
  10799. +{
  10800. + return 1;
  10801. +}
  10802. +static const struct config_list streamrelay_opts[] =
  10803. +{
  10804. + DEF_OPT_SAVE_FUNC(streamrelay_should_save_fn),
  10805. + DEF_OPT_STR("stream_source_host" , OFS(emu_stream_source_host), "127.0.0.1"),
  10806. + DEF_OPT_INT32("stream_source_port" , OFS(emu_stream_source_port), 8001),
  10807. + DEF_OPT_STR("stream_source_auth_user" , OFS(emu_stream_source_auth_user), NULL),
  10808. + DEF_OPT_STR("stream_source_auth_password" , OFS(emu_stream_source_auth_password), NULL),
  10809. + DEF_OPT_INT32("stream_relay_port" , OFS(emu_stream_relay_port), 17999),
  10810. + DEF_OPT_UINT32("stream_ecm_delay" , OFS(emu_stream_ecm_delay), 600),
  10811. + DEF_OPT_UINT8("stream_relay_enabled" , OFS(emu_stream_relay_enabled), 1),
  10812. + DEF_OPT_UINT8("stream_emm_enabled" , OFS(emu_stream_emm_enabled), 0),
  10813. + DEF_LAST_OPT
  10814. +};
  10815. +#else
  10816. +static const struct config_list streamrelay_opts[] = { DEF_LAST_OPT };
  10817. +#endif
  10818. +
  10819. +
  10820. #ifdef MODULE_RADEGAST
  10821. static bool radegast_should_save_fn(void *UNUSED(var))
  10822. {
  10823. @@ -1008,7 +1032,7 @@
  10824. DEF_OPT_STR("user" , OFS(dvbapi_usr), NULL),
  10825. DEF_OPT_INT8("read_sdt" , OFS(dvbapi_read_sdt), 0),
  10826. DEF_OPT_INT8("write_sdt_prov", OFS(dvbapi_write_sdt_prov), 0),
  10827. - DEF_OPT_INT8("extended_cw_api", OFS(dvbapi_extended_cw_api), 0),
  10828. + DEF_OPT_INT8("extended_cw_api", OFS(dvbapi_extended_cw_api), 1),
  10829. DEF_OPT_FUNC("boxtype" , OFS(dvbapi_boxtype), dvbapi_boxtype_fn),
  10830. DEF_OPT_FUNC("services" , OFS(dvbapi_sidtabs.ok), dvbapi_services_fn),
  10831. // OBSOLETE OPTIONS
  10832. @@ -1062,6 +1086,7 @@
  10833. { "cccam", cccam_opts },
  10834. { "pandora", pandora_opts },
  10835. { "scam", scam_opts },
  10836. + { "streamrelay", streamrelay_opts },
  10837. { "dvbapi", dvbapi_opts },
  10838. { "monitor", monitor_opts },
  10839. { "webif", webif_opts },
  10840. Index: oscam-config-reader.c
  10841. ===================================================================
  10842. --- oscam-config-reader.c (revision 11209)
  10843. +++ oscam-config-reader.c (working copy)
  10844. @@ -107,6 +107,7 @@
  10845. { "newcamd", R_NEWCAMD },
  10846. { "newcamd525", R_NEWCAMD },
  10847. { "newcamd524", R_NEWCAMD },
  10848. + { "emu", R_EMU },
  10849. { NULL , 0 }
  10850. }, *p;
  10851. int i;
  10852. @@ -445,6 +446,7 @@
  10853. if(ftab_type & FTAB_CHID) { rdr = container_of(setting, struct s_reader, fchid); }
  10854. if(ftab_type & FTAB_FBPCAID) { rdr = container_of(setting, struct s_reader, fallback_percaid); }
  10855. if(ftab_type & FTAB_LOCALCARDS) { rdr = container_of(setting, struct s_reader, localcards); }
  10856. + if(ftab_type & FTAB_EMUAU) { rdr = container_of(setting, struct s_reader, emu_auproviders); }
  10857. if(rdr)
  10858. { rdr->changes_since_shareupdate = 1; }
  10859. }
  10860. @@ -752,7 +754,7 @@
  10861. }
  10862.  
  10863.  
  10864. -static void reader_fixups_fn(void *var)
  10865. +void reader_fixups_fn(void *var)
  10866. {
  10867. struct s_reader *rdr = var;
  10868. #ifdef WITH_LB
  10869. @@ -887,6 +889,9 @@
  10870. #ifdef MODULE_GHTTP
  10871. DEF_OPT_UINT8("use_ssl" , OFS(ghttp_use_ssl), 0),
  10872. #endif
  10873. +#ifdef WITH_EMU
  10874. + DEF_OPT_FUNC_X("emu_auproviders" , OFS(emu_auproviders), ftab_fn, FTAB_READER | FTAB_EMUAU),
  10875. +#endif
  10876. DEF_OPT_INT8("deprecated" , OFS(deprecated), 0),
  10877. DEF_OPT_INT8("audisabled" , OFS(audisabled), 0),
  10878. DEF_OPT_FUNC("auprovid" , 0, auprovid_fn),
  10879. Index: oscam-config.h
  10880. ===================================================================
  10881. --- oscam-config.h (revision 11209)
  10882. +++ oscam-config.h (working copy)
  10883. @@ -22,6 +22,7 @@
  10884. int32_t free_readerdb(void);
  10885. int32_t write_server(void);
  10886. void reload_readerdb(void);
  10887. +void reader_fixups_fn(void *var);
  10888.  
  10889. void chk_sidtab(char *token, char *value, struct s_sidtab *sidtab);
  10890. int32_t init_sidtab(void);
  10891. @@ -60,7 +61,8 @@
  10892. FTAB_PROVID = 0x04,
  10893. FTAB_CHID = 0x08,
  10894. FTAB_FBPCAID = 0x10,
  10895. - FTAB_LOCALCARDS = 0x20
  10896. + FTAB_LOCALCARDS = 0x20,
  10897. + FTAB_EMUAU = 0x40
  10898. };
  10899.  
  10900. void ftab_fn(const char *token, char *value, void *setting, long ftab_type, FILE *f);
  10901. Index: oscam-ecm.c
  10902. ===================================================================
  10903. --- oscam-ecm.c (revision 11209)
  10904. +++ oscam-ecm.c (working copy)
  10905. @@ -1578,7 +1578,7 @@
  10906.  
  10907. if(reader && cw && rc < E_NOTFOUND)
  10908. {
  10909. - if(reader->disablecrccws == 0)
  10910. + if(reader->disablecrccws == 0 && ((er->caid>>8)!=0x0E))
  10911. {
  10912. for(i = 0; i < 16; i += 4)
  10913. {
  10914. Index: oscam-emm.c
  10915. ===================================================================
  10916. --- oscam-emm.c (revision 11209)
  10917. +++ oscam-emm.c (working copy)
  10918. @@ -50,7 +50,14 @@
  10919. unsigned int j, filter_count = 0;
  10920.  
  10921. // Call cardsystems emm filter
  10922. - csystem->get_emm_filter(rdr, &dmx_filter, &filter_count);
  10923. + if(rdr->typ == R_EMU)
  10924. + {
  10925. + return 1; //valid emm
  10926. + }
  10927. + else
  10928. + {
  10929. + csystem->get_emm_filter(rdr, &dmx_filter, &filter_count);
  10930. + }
  10931.  
  10932. // Only check matching emmtypes:
  10933. uint8_t org_emmtype;
  10934. @@ -205,6 +212,24 @@
  10935. rdr_log_dbg(reader, D_EMM, "reader auprovid = %06X fixup to %06X (ignoring last digit)", reader->auprovid, prid);
  10936. }
  10937.  
  10938. +#ifdef WITH_EMU
  10939. + if(reader->typ == R_EMU)
  10940. + {
  10941. + FILTER* emu_provids = get_emu_prids_for_caid(reader, caid);
  10942. + if(emu_provids != NULL)
  10943. + {
  10944. + for(i = 0; i < emu_provids->nprids; i++)
  10945. + {
  10946. + if(provid == emu_provids->prids[i])
  10947. + {
  10948. + return 1;
  10949. + }
  10950. + }
  10951. + }
  10952. + return 0;
  10953. + }
  10954. +#endif
  10955. +
  10956. if(prid == provid)
  10957. {
  10958. rdr_log_dbg(reader, D_EMM, "reader auprovid = %06X matching with emm provid = %06X -> SEND!", prid, provid);
  10959. Index: oscam-string.c
  10960. ===================================================================
  10961. --- oscam-string.c (revision 11209)
  10962. +++ oscam-string.c (working copy)
  10963. @@ -494,6 +494,62 @@
  10964. return crc ^ 0xffffffffL;
  10965. }
  10966.  
  10967. +static uint32_t fletcher_crc_table[256] = {
  10968. + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
  10969. + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
  10970. + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
  10971. + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
  10972. + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
  10973. + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
  10974. + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
  10975. + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
  10976. + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
  10977. + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
  10978. + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
  10979. + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
  10980. + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
  10981. + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
  10982. + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
  10983. + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
  10984. + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
  10985. + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
  10986. + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
  10987. + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
  10988. + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
  10989. + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
  10990. + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
  10991. + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
  10992. + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
  10993. + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
  10994. + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
  10995. + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
  10996. + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
  10997. + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
  10998. + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
  10999. + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
  11000. + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
  11001. + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
  11002. + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
  11003. + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
  11004. + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
  11005. + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
  11006. + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
  11007. + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
  11008. + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
  11009. + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
  11010. + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
  11011. +
  11012. +uint32_t fletcher_crc32(uint8_t *data, uint32_t len)
  11013. +{
  11014. + uint32_t i;
  11015. + uint32_t crc = 0xffffffff;
  11016. +
  11017. + for (i=0; i<len; i++)
  11018. + crc = (crc << 8) ^ fletcher_crc_table[((crc >> 24) ^ *data++) & 0xff];
  11019. +
  11020. + return crc;
  11021. +}
  11022. +
  11023. static uint16_t ccitt_crc_table [256] =
  11024. {
  11025. 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5,
  11026. Index: oscam-string.h
  11027. ===================================================================
  11028. --- oscam-string.h (revision 11209)
  11029. +++ oscam-string.h (working copy)
  11030. @@ -35,6 +35,7 @@
  11031. void get_random_bytes_init(void);
  11032. void get_random_bytes(uint8_t *dst, uint32_t dst_len);
  11033.  
  11034. +uint32_t fletcher_crc32(uint8_t *data, uint32_t len);
  11035. unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len);
  11036. uint16_t ccitt_crc(uint8_t *data, size_t length, uint16_t seed, uint16_t final);
  11037. uint32_t jhash(const char *key, size_t len);
  11038. Index: oscam.c
  11039. ===================================================================
  11040. --- oscam.c (revision 11209)
  11041. +++ oscam.c (working copy)
  11042. @@ -41,6 +41,11 @@
  11043. #include "reader-common.h"
  11044. #include "module-gbox.h"
  11045.  
  11046. +#ifdef WITH_EMU
  11047. + void add_emu_reader(void);
  11048. + void stop_stream_server(void);
  11049. +#endif
  11050. +
  11051. #ifdef WITH_SSL
  11052. #include <openssl/crypto.h>
  11053. #include <openssl/ssl.h>
  11054. @@ -408,6 +413,7 @@
  11055. write_conf(CW_CYCLE_CHECK, "CW Cycle Check support");
  11056. write_conf(LCDSUPPORT, "LCD support");
  11057. write_conf(LEDSUPPORT, "LED support");
  11058. + write_conf(WITH_EMU, "Emulator support");
  11059. switch (cs_getclocktype()) {
  11060. case CLOCK_TYPE_UNKNOWN : write_conf(CLOCKFIX, "Clockfix with UNKNOWN clock"); break;
  11061. case CLOCK_TYPE_REALTIME : write_conf(CLOCKFIX, "Clockfix with realtime clock"); break;
  11062. @@ -1588,6 +1594,9 @@
  11063. #ifdef CARDREADER_STINGER
  11064. &cardreader_stinger,
  11065. #endif
  11066. +#ifdef WITH_EMU
  11067. + &cardreader_emu,
  11068. +#endif
  11069. NULL
  11070. };
  11071.  
  11072. @@ -1759,6 +1768,9 @@
  11073.  
  11074. init_sidtab();
  11075. init_readerdb();
  11076. +#ifdef WITH_EMU
  11077. + add_emu_reader();
  11078. +#endif
  11079. cfg.account = init_userdb();
  11080. init_signal();
  11081. init_provid();
  11082. @@ -1842,6 +1854,9 @@
  11083. SAFE_COND_SIGNAL(&reader_check_sleep_cond); // Stop reader_check thread
  11084.  
  11085. // Cleanup
  11086. +#ifdef WITH_EMU
  11087. + stop_stream_server();
  11088. +#endif
  11089. #ifdef MODULE_GBOX
  11090. stop_sms_sender();
  11091. #endif
  11092. Index: reader-common.c
  11093. ===================================================================
  11094. --- reader-common.c (revision 11209)
  11095. +++ reader-common.c (working copy)
  11096. @@ -14,6 +14,7 @@
  11097. #include "reader-common.h"
  11098. //#include "csctapi/atr.h"
  11099. #include "csctapi/icc_async.h"
  11100. +#include "readers.h"
  11101.  
  11102. extern const struct s_cardsystem *cardsystems[];
  11103. extern char *RDR_CD_TXT[];
  11104. @@ -141,6 +142,19 @@
  11105. static int32_t reader_get_cardsystem(struct s_reader *reader, ATR *atr)
  11106. {
  11107. int32_t i;
  11108. +
  11109. +#ifdef WITH_EMU
  11110. + if(reader->typ == R_EMU)
  11111. + {
  11112. + NULLFREE(reader->csystem_data);
  11113. + rdr_log(reader, "found card system %s", reader_emu.desc);
  11114. + reader->csystem = &reader_emu;
  11115. + reader->csystem_active = true;
  11116. + led_status_found_cardsystem();
  11117. + return (reader->csystem_active);
  11118. + }
  11119. +#endif
  11120. +
  11121. for(i = 0; cardsystems[i]; i++)
  11122. {
  11123. NULLFREE(reader->csystem_data);
  11124. Index: reader-dre.c
  11125. ===================================================================
  11126. --- reader-dre.c (revision 11209)
  11127. +++ reader-dre.c (working copy)
  11128. @@ -2,6 +2,7 @@
  11129. #ifdef READER_DRE
  11130. #include "cscrypt/des.h"
  11131. #include "reader-common.h"
  11132. +#include "module-emulator-dre2overcrypt.h"
  11133.  
  11134. struct dre_data
  11135. {
  11136. @@ -20,6 +21,23 @@
  11137. return checksum;
  11138. }
  11139.  
  11140. +static int8_t isValidDCW(uint8_t *dw)
  11141. +{
  11142. + if (((dw[0]+dw[1]+dw[2]) & 0xFF) != dw[3]) {
  11143. + return 0;
  11144. + }
  11145. + if (((dw[4]+dw[5]+dw[6]) & 0xFF) != dw[7]) {
  11146. + return 0;
  11147. + }
  11148. + if (((dw[8]+dw[9]+dw[10]) & 0xFF) != dw[11]) {
  11149. + return 0;
  11150. + }
  11151. + if (((dw[12]+dw[13]+dw[14]) & 0xFF) != dw[15]) {
  11152. + return 0;
  11153. + }
  11154. + return 1;
  11155. +}
  11156. +
  11157. static int32_t dre_command(struct s_reader *reader, const uchar *cmd, int32_t cmdlen, unsigned char *cta_res, uint16_t *p_cta_lr) //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
  11158. {
  11159. uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 }; //any command starts with this,
  11160. @@ -146,7 +164,7 @@
  11161. int32_t endday = temp.tm_mday;
  11162. rdr_log(reader, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i, startyear, startmonth, startday,
  11163. endyear, endmonth, endday);
  11164. - cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, 0, start, end, 1, 1);
  11165. + cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, i, start, end, 1, 1);
  11166. }
  11167. }
  11168. return OK;
  11169. @@ -203,6 +221,7 @@
  11170. }
  11171.  
  11172. memset(reader->prid, 0x00, 8);
  11173. + reader->prid[0][3] = atr[6];
  11174.  
  11175. static const uchar cmd30[] =
  11176. {
  11177. @@ -269,9 +288,17 @@
  11178. reader->sa[0][3], cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)));
  11179.  
  11180. reader->nprov = 1;
  11181. -
  11182. +
  11183. + if(csystem_data->provider == 0x11)
  11184. + {
  11185. + memset(reader->prid[1], 0x00, 8);
  11186. + reader->prid[1][3] = 0xFE;
  11187. + reader->nprov = 2;
  11188. + }
  11189. +
  11190. if(!dre_set_provider_info(reader))
  11191. { return ERROR; } //fatal error
  11192. +
  11193.  
  11194. rdr_log(reader, "ready for requests");
  11195. return OK;
  11196. @@ -312,6 +339,8 @@
  11197. static int32_t dre_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
  11198. {
  11199. def_resp;
  11200. + uint16_t overcryptId;
  11201. + uint8_t tmp[16];
  11202. char tmp_dbg[256];
  11203. struct dre_data *csystem_data = reader->csystem_data;
  11204. if(reader->caid == 0x4ae0)
  11205. @@ -352,14 +381,33 @@
  11206. rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 5, tmp_dbg, sizeof(tmp_dbg)));
  11207. rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 37, 4, tmp_dbg, sizeof(tmp_dbg)));
  11208. ecmcmd51[33] = csystem_data->provider; //no part of sig
  11209. +
  11210. if((dre_cmd(ecmcmd51))) //ecm request
  11211. {
  11212. if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
  11213. { return ERROR; } //exit if response is not 90 00
  11214. +
  11215. + if(er->ecm[2] >= 46 && er->ecm[43] == 1)
  11216. + {
  11217. + memcpy(tmp, cta_res + 11, 8);
  11218. + memcpy(tmp + 8, cta_res + 3, 8);
  11219. + overcryptId = b2i(2, &er->ecm[44]);
  11220. + rdr_log_dbg(reader, D_READER, "ICG ID: %04X", overcryptId);
  11221. + Drecrypt2OverCW(overcryptId,tmp);
  11222. + memcpy(ea->cw, tmp, 16);
  11223. + return OK;
  11224. + }
  11225. +
  11226. DREover(er->ecm, cta_res + 3);
  11227. - memcpy(ea->cw, cta_res + 11, 8);
  11228. - memcpy(ea->cw + 8, cta_res + 3, 8);
  11229. - return OK;
  11230. +
  11231. + if(isValidDCW(cta_res + 3))
  11232. + {
  11233. +
  11234. +
  11235. + memcpy(ea->cw, cta_res + 11, 8);
  11236. + memcpy(ea->cw + 8, cta_res + 3, 8);
  11237. + return OK;
  11238. + }
  11239. }
  11240. }
  11241. return ERROR;
  11242. @@ -394,6 +442,10 @@
  11243. memset(ep->hexserial, 0, 8);
  11244. ep->hexserial[0] = ep->emm[3];
  11245. return ep->hexserial[0] == rdr->sa[0][0];
  11246. +
  11247. + case 0x91:
  11248. + ep->type = GLOBAL;
  11249. + return 1;
  11250.  
  11251. default:
  11252. ep->type = UNKNOWN;
  11253. @@ -405,7 +457,7 @@
  11254. {
  11255. if(*emm_filters == NULL)
  11256. {
  11257. - const unsigned int max_filter_count = 7;
  11258. + const unsigned int max_filter_count = 8;
  11259. if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
  11260. { return ERROR; }
  11261.  
  11262. @@ -477,6 +529,12 @@
  11263. filters[idx].mask[0] = 0xFF;
  11264. //FIXME: No filter for hexserial
  11265. idx++;
  11266. +
  11267. + filters[idx].type = EMM_GLOBAL;
  11268. + filters[idx].enabled = 1;
  11269. + filters[idx].filter[0] = 0x91;
  11270. + filters[idx].mask[0] = 0xFF;
  11271. + idx++;
  11272.  
  11273. *filter_count = idx;
  11274. }
  11275. @@ -491,6 +549,8 @@
  11276.  
  11277. if(reader->caid == 0x4ae1)
  11278. {
  11279. + if(reader->caid != b2i(2, ep->caid)) return ERROR;
  11280. +
  11281. if(ep->type == UNIQUE && ep->emm[39] == 0x3d)
  11282. {
  11283. /* For new package activation. */
  11284. @@ -502,7 +562,7 @@
  11285. if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
  11286. { return ERROR; }
  11287. }
  11288. - else
  11289. + else if(ep->emm[4] == 0x02 && csystem_data->provider != 0x11)
  11290. {
  11291. uchar emmcmd52[0x3a];
  11292. emmcmd52[0] = 0x52;
  11293. @@ -519,6 +579,45 @@
  11294. { return ERROR; } //exit if response is not 90 00
  11295. }
  11296. }
  11297. + else if(ep->emm[0] == 0x86 && ep->emm[4] == 0x4D && csystem_data->provider == 0x11)
  11298. + {
  11299. + uchar emmcmd52[0x3a];
  11300. + emmcmd52[0] = 0x52;
  11301. + emmcmd52[1] = 0x01;
  11302. + emmcmd52[2] = ep->emm[5];
  11303. + emmcmd52[3] = 0x01;
  11304. + emmcmd52[4] = ep->emm[3];
  11305. + emmcmd52[5] = 0;
  11306. + emmcmd52[6] = 0;
  11307. + emmcmd52[7] = 0;
  11308. + emmcmd52[9] = 0x01;
  11309. + emmcmd52[10] = 0x01;
  11310. + emmcmd52[11] = 0;
  11311. + memcpy(emmcmd52 + 13, ep->emm + 0x5C, 4);
  11312. + int32_t i;
  11313. + for(i = 0; i < 2; i++)
  11314. + {
  11315. + //memcpy(emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
  11316. + emmcmd52[8] = ep->emm[0x61+i*0x29];
  11317. + if(i == 0) emmcmd52[12] = ep->emm[0x60] == 0x56 ? 0x56:0x3B;
  11318. + else emmcmd52[12] = ep->emm[0x60] == 0x56 ? 0x3B:0x56;
  11319. + memcpy(emmcmd52 + 0x11, ep->emm + 0x62 + i * 0x29, 40);
  11320. +
  11321. + // check for shared address
  11322. + if(ep->emm[3] != reader->sa[0][0])
  11323. + { return OK; } // ignore, wrong address
  11324. + emmcmd52[0x39] = csystem_data->provider;
  11325. + if((dre_cmd(emmcmd52)))
  11326. + if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
  11327. + { return ERROR; } //exit if response is not 90 00
  11328. + }
  11329. + }
  11330. + else if(ep->type == GLOBAL && ep->emm[0] == 0x91)
  11331. + {
  11332. + Drecrypt2OverEMM(ep->emm);
  11333. + return OK;
  11334. + }
  11335. + else return ERROR;
  11336. }
  11337. else
  11338. {
  11339. Index: readers.h
  11340. ===================================================================
  11341. --- readers.h (revision 11209)
  11342. +++ readers.h (working copy)
  11343. @@ -15,5 +15,6 @@
  11344. extern const struct s_cardsystem reader_bulcrypt;
  11345. extern const struct s_cardsystem reader_griffin;
  11346. extern const struct s_cardsystem reader_dgcrypt;
  11347. +extern const struct s_cardsystem reader_emu;
  11348.  
  11349. #endif
  11350. Index: webif/config/dvbapi.html
  11351. ===================================================================
  11352. --- webif/config/dvbapi.html (revision 11209)
  11353. +++ webif/config/dvbapi.html (working copy)
  11354. @@ -53,7 +53,7 @@
  11355. </TD>
  11356. </TR>
  11357. <TR><TD><A>Write detected prov name to srvid:</A></TD><TD><input name="write_sdt_prov" type="checkbox" value="1" ##WRITESDTPROVCHECKED##><label></label>
  11358. - <!-- <TR><TD><A>API for extended CWs</A></TD>
  11359. + <TR><TD><A>API for extended CWs</A></TD>
  11360. <TD>
  11361. <select name="extended_cw_api">
  11362. <option value="0" ##EXTENDEDCWAPISELECTED0##>0 - none (disabled)</option>
  11363. @@ -61,4 +61,4 @@
  11364. <option value="2" ##EXTENDEDCWAPISELECTED2##>2 - OE2.0</option>
  11365. </select>
  11366. </TD>
  11367. - </TR> -->
  11368. \ No newline at end of file
  11369. + </TR>
  11370. \ No newline at end of file
  11371. Index: webif/config/menu.html
  11372. ===================================================================
  11373. --- webif/config/menu.html (revision 11209)
  11374. +++ webif/config/menu.html (working copy)
  11375. @@ -16,6 +16,7 @@
  11376. ##TPLCONFIGMENUDVBAPI## <!-- CMENUACTIVE13 -->
  11377. ##TPLCONFIGMENULCD## <!-- CMENUACTIVE14 -->
  11378. ##TPLCONFIGMENUMONITOR## <!-- CMENUACTIVE15 -->
  11379. +##TPLCONFIGMENUSTREAMRELAY##<!-- CMENUACTIVE17 -->
  11380. <LI CLASS="##CMENUACTIVE16##"><A HREF="config.html?part=webif">WebIf</A></LI>
  11381. </UL>
  11382. </DIV>
  11383. \ No newline at end of file
  11384. Index: webif/config/menu_streamrelay.html
  11385. ===================================================================
  11386. --- webif/config/menu_streamrelay.html (revision 0)
  11387. +++ webif/config/menu_streamrelay.html (working copy)
  11388. @@ -0,0 +1 @@
  11389. + <LI CLASS="##CMENUACTIVE17##"><A HREF="config.html?part=streamrelay">Stream Relay</A></LI>
  11390. Index: webif/config/streamrelay.html
  11391. ===================================================================
  11392. --- webif/config/streamrelay.html (revision 0)
  11393. +++ webif/config/streamrelay.html (working copy)
  11394. @@ -0,0 +1,26 @@
  11395. + <input name="part" type="hidden" value="streamrelay">
  11396. + <TABLE CLASS="config">
  11397. + <TR><TH COLSPAN="2">Edit Stream Relay Config</TH></TR>
  11398. + <TR><TD><A>Mode (disable to use direct dvbapi decryption)</A></TD>
  11399. + <TD>
  11400. + <select name="stream_relay_enabled">
  11401. + <option value="0" ##STREAMRELAYENABLEDSELECTED0##>0 - disabled (use DVBAPI)</option>
  11402. + <option value="1" ##STREAMRELAYENABLEDSELECTED1##>1 - enabled (use Stream Relay)</option>
  11403. + </select>
  11404. + </TD>
  11405. + </TR>
  11406. + <TR><TD><A>Process EMM from stream </A></TD>
  11407. + <TD>
  11408. + <select name="stream_emm_enabled">
  11409. + <option value="0" ##STREAMEMMENABLEDSELECTED0##>0 - disabled </option>
  11410. + <option value="1" ##STREAMEMMENABLEDSELECTED1##>1 - enabled </option>
  11411. + </select>
  11412. + </TD>
  11413. + </TR>
  11414. + <TR><TD><A>Source Stream Host:</A></TD><TD><input name="stream_source_host" type="text" maxlength="15" value="##STREAM_SOURCE_HOST##"></TD></TR>
  11415. + <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>
  11416. + <TR><TD><A>Source Stream User:</A></TD><TD><input name="stream_source_auth_user" type="text" value="##STREAM_SOURCE_AUTH_USER##"></TD></TR>
  11417. + <TR><TD><A>Source Stream Password:</A></TD><TD><input name="stream_source_auth_password" type="text" value="##STREAM_SOURCE_AUTH_PASSWORD##"></TD></TR>
  11418. + <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>
  11419. + <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>
  11420. +
  11421. Index: webif/files/menu.html
  11422. ===================================================================
  11423. --- webif/files/menu.html (revision 11209)
  11424. +++ webif/files/menu.html (working copy)
  11425. @@ -9,7 +9,7 @@
  11426. ##TPLFILEMENUANTICASC## <!-- CMENUACTIVE6 -->
  11427. <LI CLASS="##CMENUACTIVE7##"><A HREF="files.html?file=logfile">logfile</A></LI>
  11428. <LI CLASS="##CMENUACTIVE8##"><A HREF="files.html?file=userfile">userfile</A></LI>
  11429. - <LI CLASS="##CMENUACTIVE9## ##CMENUACTIVE10## ##CMENUACTIVE11## ##CMENUACTIVE12## ##CMENUACTIVE13## ##CMENUACTIVE14## ##CMENUACTIVE15## ##CMENUACTIVE16## ##CMENUACTIVE17## ##CMENUACTIVE18##"><A HREF="#" class="drop">other file<b class="subcaret"></b></A>
  11430. + <LI CLASS="##CMENUACTIVE9## ##CMENUACTIVE10## ##CMENUACTIVE11## ##CMENUACTIVE12## ##CMENUACTIVE13## ##CMENUACTIVE14## ##CMENUACTIVE15## ##CMENUACTIVE16## ##CMENUACTIVE17## ##CMENUACTIVE18## ##CMENUACTIVE19##"><A HREF="#" class="drop">other file<b class="subcaret"></b></A>
  11431. <UL CLASS="dropdown_nav">
  11432. <LI CLASS="##CMENUACTIVE9##"><A HREF="files.html?file=oscam.services">oscam.services</A></LI>
  11433. <LI CLASS="##CMENUACTIVE10##"><A HREF="files.html?file=oscam.provid">oscam.provid</A></LI>
  11434. @@ -21,6 +21,7 @@
  11435. ##VIEW_FILEMENUCSS## <!-- CMENUACTIVE16 -->
  11436. ##TPLFILEMENUTWIN## <!-- CMENUACTIVE17 -->
  11437. ##TPLFILEMENUCONSTCW## <!-- CMENUACTIVE18 -->
  11438. +##TPLFILEMENUSOFTCAMKEY## <!-- CMENUACTIVE19 -->
  11439. </UL>
  11440. </LI>
  11441. </UL>
  11442. Index: webif/files/menu_softcamkey.html
  11443. ===================================================================
  11444. --- webif/files/menu_softcamkey.html (revision 0)
  11445. +++ webif/files/menu_softcamkey.html (working copy)
  11446. @@ -0,0 +1 @@
  11447. + <LI CLASS="##CMENUACTIVE19##"><A HREF="files.html?file=SoftCam.Key">SoftCam.Key</A></LI>
  11448. Index: webif/pages_index.txt
  11449. ===================================================================
  11450. --- webif/pages_index.txt (revision 11209)
  11451. +++ webif/pages_index.txt (working copy)
  11452. @@ -80,11 +80,13 @@
  11453. CONFIGMENUNEWCAMD config/menu_newcamd.html MODULE_NEWCAMD
  11454. CONFIGMENURADEGAST config/menu_radegast.html MODULE_RADEGAST
  11455. CONFIGMENUSCAM config/menu_scam.html MODULE_SCAM
  11456. +CONFIGMENUSTREAMRELAY config/menu_streamrelay.html WITH_EMU
  11457. CONFIGMENUSERIAL config/menu_serial.html MODULE_SERIAL
  11458. CONFIGMONITOR config/monitor.html MODULE_MONITOR
  11459. CONFIGNEWCAMD config/newcamd.html MODULE_NEWCAMD
  11460. CONFIGRADEGAST config/radegast.html MODULE_RADEGAST
  11461. CONFIGSCAM config/scam.html MODULE_SCAM
  11462. +CONFIGSTREAMRELAY config/streamrelay.html WITH_EMU
  11463. CONFIGSERIAL config/serial.html MODULE_SERIAL
  11464. CONFIGSERIALDEVICEBIT config/serial_devices.html MODULE_SERIAL
  11465. CONFIGWEBIF config/webif.html
  11466. @@ -117,6 +119,7 @@
  11467. FILEMENUDVBAPI files/menu_dvbapi.html HAVE_DVBAPI
  11468. FILEMENUFAKECWS files/menu_fakecws.html CS_CACHEEX
  11469. FILEMENUTWIN files/menu_twin.html MODULE_SERIAL
  11470. +FILEMENUSOFTCAMKEY files/menu_softcamkey.html WITH_EMU
  11471.  
  11472. AUTOCONF ghttp/autoconf.html MODULE_GHTTP
  11473. PREAUTOCONF ghttp/pre_autoconf.html MODULE_GHTTP
  11474. @@ -181,6 +184,7 @@
  11475. READEREDITCACHEEXBIT readerconfig/readerconfig_cacheexbit.html CS_CACHEEX
  11476. READERCONFIGCAMD35BIT readerconfig/readerconfig_camd35bit.html MODULE_CAMD35
  11477. READERCONFIGCCCAMBIT readerconfig/readerconfig_cccambit.html MODULE_CCCAM
  11478. +READERCONFIGEMUBIT readerconfig/readerconfig_emubit.html WITH_EMU
  11479. READERCONFIGCS378XBIT readerconfig/readerconfig_cs378xbit.html MODULE_CAMD35_TCP
  11480. READERCONFIGGBOXBIT readerconfig/readerconfig_gboxbit.html MODULE_GBOX
  11481. READERCONFIGGHTTPBIT readerconfig/readerconfig_ghttpbit.html MODULE_GHTTP
  11482. Index: webif/readerconfig/readerconfig_emubit.html
  11483. ===================================================================
  11484. --- webif/readerconfig/readerconfig_emubit.html (revision 0)
  11485. +++ webif/readerconfig/readerconfig_emubit.html (working copy)
  11486. @@ -0,0 +1 @@
  11487. + <TR><TD><A>AU providers:</A></TD><TD><textarea name="emu_auproviders" rows="3" class="bt">##EMUAUPROVIDERS##</textarea></TD></TR>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement